Skip to content

Commit

Permalink
Remove DescriptorSetLayouts and DescriptorSets. Use singular version …
Browse files Browse the repository at this point in the history
…instead (less overhead, template-based strong type constraint.)
  • Loading branch information
stripe2933 committed Aug 1, 2024
1 parent 49cbad7 commit f7c245f
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 136 deletions.
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ target_sources(vku PUBLIC
interface/commands.cppm
interface/constants.cppm
interface/descriptors/mod.cppm
interface/descriptors/DescriptorSetLayouts.cppm
interface/descriptors/DescriptorSets.cppm
interface/descriptors/DescriptorSetLayout.cppm
interface/descriptors/DescriptorSet.cppm
interface/descriptors/PoolSizes.cppm
interface/details/mod.cppm
interface/details/concepts.cppm
interface/details/functional.cppm
interface/details/ranges.cppm
interface/images/mod.cppm
interface/images/AllocatedImage.cppm
Expand Down
81 changes: 81 additions & 0 deletions interface/descriptors/DescriptorSet.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
module;

#ifndef VKU_USE_STD_MODULE
#include <cstdint>
#include <compare>
#include <tuple>
#include <utility>
#endif

#include <vulkan/vulkan_hpp_macros.hpp>

export module vku:descriptors.DescriptorSet;

#ifdef VKU_USE_STD_MODULE
import std;
#endif
export import :descriptors.DescriptorSetLayout;
import :details;
import :utils;

template <vk::DescriptorType> struct WriteDescriptorInfo;
template <> struct WriteDescriptorInfo<vk::DescriptorType::eSampler> { using type = vk::DescriptorImageInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eCombinedImageSampler> { using type = vk::DescriptorImageInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eSampledImage> { using type = vk::DescriptorImageInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eStorageImage> { using type = vk::DescriptorImageInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eUniformTexelBuffer> { using type = vk::BufferView; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eStorageTexelBuffer> { using type = vk::BufferView; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eUniformBuffer> { using type = vk::DescriptorBufferInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eStorageBuffer> { using type = vk::DescriptorBufferInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eUniformBufferDynamic> { using type = vk::DescriptorBufferInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eStorageBufferDynamic> { using type = vk::DescriptorBufferInfo; };
template <> struct WriteDescriptorInfo<vk::DescriptorType::eInputAttachment> { using type = vk::DescriptorImageInfo; };
template <vk::DescriptorType Type> using WriteDescriptorInfo_t = typename WriteDescriptorInfo<Type>::type;

namespace vku {
export template <concepts::derived_from_value_specialization_of<DescriptorSetLayout> Layout>
class DescriptorSet : public vk::DescriptorSet {
public:
DescriptorSet() noexcept = default;
DescriptorSet(const DescriptorSet&) noexcept = default;
DescriptorSet(DescriptorSet&&) noexcept = default;
DescriptorSet& operator=(const DescriptorSet&) noexcept = default;
DescriptorSet& operator=(DescriptorSet&&) noexcept = default;

template <std::uint32_t Binding>
[[nodiscard]] auto getWrite(const vk::ArrayProxyNoTemporaries<const WriteDescriptorInfo_t<get<Binding>(Layout::bindingTypes)>> &descriptorInfos) const noexcept -> vk::WriteDescriptorSet {
constexpr auto attachInfo = multilambda {
[](vk::WriteDescriptorSet writeDescriptorSet, const vk::ArrayProxyNoTemporaries<const vk::DescriptorImageInfo> &descriptorInfos) {
return writeDescriptorSet.setImageInfo(descriptorInfos);
},
[](vk::WriteDescriptorSet writeDescriptorSet, const vk::ArrayProxyNoTemporaries<const vk::BufferView> &descriptorInfos) {
return writeDescriptorSet.setTexelBufferView(descriptorInfos);
},
[](vk::WriteDescriptorSet writeDescriptorSet, const vk::ArrayProxyNoTemporaries<const vk::DescriptorBufferInfo> &descriptorInfos) {
return writeDescriptorSet.setBufferInfo(descriptorInfos);
},
};

return attachInfo(vk::WriteDescriptorSet { *this, Binding, 0, {}, get<Binding>(Layout::bindingTypes) }, descriptorInfos);
}

template <concepts::derived_from_value_specialization_of<DescriptorSetLayout>... Layouts>
friend auto allocateDescriptorSets(vk::Device, vk::DescriptorPool, std::tuple<const Layouts&...>) -> std::tuple<DescriptorSet<Layouts>...>;

private:
explicit DescriptorSet(vk::DescriptorSet descriptorSet) noexcept : vk::DescriptorSet { descriptorSet } {}
};

export template <concepts::derived_from_value_specialization_of<DescriptorSetLayout>... Layouts>
[[nodiscard]] auto allocateDescriptorSets(
vk::Device device,
vk::DescriptorPool pool,
std::tuple<const Layouts&...> layouts
) -> std::tuple<DescriptorSet<Layouts>...> {
return std::apply([&](const auto &...layout) {
return std::apply([&](auto... rawSet) {
return std::tuple { DescriptorSet<Layouts> { rawSet }... };
}, device.allocateDescriptorSets({ pool, unsafeProxy({ *layout... }) }) | ranges::to_array<sizeof...(Layouts)>());
}, layouts);
}
}
54 changes: 54 additions & 0 deletions interface/descriptors/DescriptorSetLayout.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
module;

#include <cassert>
#ifndef VKU_USE_STD_MODULE
#include <cstdint>
#include <array>
#include <compare>
#endif

export module vku:descriptors.DescriptorSetLayout;

#ifdef VKU_USE_STD_MODULE
import std;
#endif
export import vulkan_hpp;
export import :descriptors.PoolSizes;
import :details;

#define INDEX_SEQ(Is, N, ...) [&]<std::size_t ...Is>(std::index_sequence<Is...>) __VA_ARGS__ (std::make_index_sequence<N>{})

namespace vku {
export template <vk::DescriptorType... BindingTypes>
struct DescriptorSetLayout : vk::raii::DescriptorSetLayout {
static constexpr std::uint32_t bindingCount = sizeof...(BindingTypes);
static constexpr std::array bindingTypes = { BindingTypes... };

DescriptorSetLayout(
const vk::raii::Device &device [[clang::lifetimebound]],
const vk::DescriptorSetLayoutCreateInfo &createInfo
) : vk::raii::DescriptorSetLayout { device, createInfo } {
assert(createInfo.bindingCount == bindingCount && "The binding count must match the template parameter count.");
INDEX_SEQ(Is, bindingCount, {
assert(((createInfo.pBindings[Is].descriptorType == BindingTypes) && ...) && "The descriptor types must match the template parameter.");
});
}

[[nodiscard]] static auto getPoolSize() noexcept -> PoolSizes {
PoolSizes poolSizes;
poolSizes.setCount = 1;
(++poolSizes.typeCounts[BindingTypes], ...);
return poolSizes;
}
};

export template <concepts::derived_from_value_specialization_of<DescriptorSetLayout>... Layouts>
[[nodiscard]] auto getPoolSizes() noexcept -> PoolSizes {
return (Layouts::getPoolSize() + ...);
}

export template <concepts::derived_from_value_specialization_of<DescriptorSetLayout>... Layouts>
[[nodiscard]] auto getPoolSizes(const Layouts &...) noexcept -> PoolSizes {
return (Layouts::getPoolSize() + ...);
}
}
49 changes: 0 additions & 49 deletions interface/descriptors/DescriptorSetLayouts.cppm

This file was deleted.

53 changes: 0 additions & 53 deletions interface/descriptors/DescriptorSets.cppm

This file was deleted.

43 changes: 13 additions & 30 deletions interface/descriptors/PoolSizes.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ export module vku:descriptors.PoolSizes;
import std;
#endif
export import vulkan_hpp;
import :descriptors.DescriptorSetLayouts;
import :details;
import :utils.RefHolder;

namespace vku {
export class PoolSizes {
public:
PoolSizes() = default;
explicit PoolSizes(concepts::derived_from_value_specialization_of<DescriptorSetLayouts> auto const &layouts);
PoolSizes(const PoolSizes&) = default;
export struct PoolSizes {
std::uint32_t setCount;
std::unordered_map<vk::DescriptorType, std::uint32_t> typeCounts;

PoolSizes() noexcept = default;
PoolSizes(const PoolSizes&) noexcept = default;
PoolSizes(PoolSizes&&) noexcept = default;

// Addition/scalar multiplication operators.
Expand All @@ -37,10 +37,6 @@ namespace vku {
auto operator*=(std::uint32_t multiplier) noexcept -> PoolSizes&;

[[nodiscard]] auto getDescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlags flags = {}) const noexcept -> RefHolder<vk::DescriptorPoolCreateInfo, std::vector<vk::DescriptorPoolSize>>;

private:
std::uint32_t setCount;
std::unordered_map<vk::DescriptorType, std::uint32_t> descriptorTypeCountMap;
};
}

Expand All @@ -50,47 +46,34 @@ namespace vku {

// module :private;

vku::PoolSizes::PoolSizes(
concepts::derived_from_value_specialization_of<DescriptorSetLayouts> auto const &layouts
) : setCount { std::remove_cvref_t<decltype(layouts)>::setCount } {
std::apply([this](const auto &...layoutBindings){
const auto accumBindings = [this](std::span<const vk::DescriptorSetLayoutBinding> bindings) {
for (const auto &binding : bindings) {
descriptorTypeCountMap[binding.descriptorType] += binding.descriptorCount;
}
};
(accumBindings(layoutBindings), ...);
}, layouts.layoutBindingsPerSet);
}

auto vku::PoolSizes::operator+(PoolSizes rhs) const noexcept -> PoolSizes {
rhs.setCount += setCount;
for (const auto &[type, count] : descriptorTypeCountMap) {
rhs.descriptorTypeCountMap[type] += count;
for (const auto &[type, count] : typeCounts) {
rhs.typeCounts[type] += count;
}
return rhs;
}

auto vku::PoolSizes::operator+=(const PoolSizes &rhs) noexcept -> PoolSizes & {
setCount += rhs.setCount;
for (const auto &[type, count] : rhs.descriptorTypeCountMap) {
descriptorTypeCountMap[type] += count;
for (const auto &[type, count] : rhs.typeCounts) {
typeCounts[type] += count;
}
return *this;
}

auto vku::PoolSizes::operator*(std::uint32_t multiplier) const noexcept -> PoolSizes {
PoolSizes result { *this };
result.setCount *= multiplier;
for (std::uint32_t &count : result.descriptorTypeCountMap | std::views::values) {
for (std::uint32_t &count : result.typeCounts | std::views::values) {
count *= multiplier;
}
return result;
}

auto vku::PoolSizes::operator*=(std::uint32_t multiplier) noexcept -> PoolSizes & {
setCount *= multiplier;
for (std::uint32_t &count : descriptorTypeCountMap | std::views::values) {
for (std::uint32_t &count : typeCounts | std::views::values) {
count *= multiplier;
}
return *this;
Expand All @@ -107,7 +90,7 @@ auto vku::PoolSizes::getDescriptorPoolCreateInfo(
poolSizes,
};
},
descriptorTypeCountMap
typeCounts
| std::views::transform([](const auto &keyValue) {
return vk::DescriptorPoolSize { keyValue.first, keyValue.second };
})
Expand Down
4 changes: 2 additions & 2 deletions interface/descriptors/mod.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ module;
#endif

export module vku:descriptors;
export import :descriptors.DescriptorSetLayouts;
export import :descriptors.DescriptorSets;
export import :descriptors.DescriptorSetLayout;
export import :descriptors.DescriptorSet;
export import :descriptors.PoolSizes;
8 changes: 8 additions & 0 deletions interface/details/functional.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export module vku:details.functional;

namespace vku::inline functional {
export template <typename ...Fs>
struct multilambda : Fs... {
using Fs::operator()...;
};
}
1 change: 1 addition & 0 deletions interface/details/mod.cppm
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export module vku:details;
export import :details.concepts;
export import :details.functional;
export import :details.ranges;

0 comments on commit f7c245f

Please sign in to comment.