mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-10 03:01:40 +00:00
feat(bindless): Define constructs for pipeline building
This commit is contained in:
parent
602f571c1d
commit
f1147c3ae4
4 changed files with 338 additions and 0 deletions
119
lsfg-vk-backend/src/modules/pipeline/signature.hpp
Normal file
119
lsfg-vk-backend/src/modules/pipeline/signature.hpp
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "signature/helpers.hpp"
|
||||
#include "signature/image.hpp"
|
||||
#include "signature/pass.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace lsfgvk::pipeline {
|
||||
|
||||
/// Type of a descriptor set binding
|
||||
enum class BindingType : uint8_t {
|
||||
SampledImage,
|
||||
StorageImage
|
||||
};
|
||||
|
||||
/// Signature of a descriptor set binding
|
||||
struct BindingSignature {
|
||||
/// Type of binding
|
||||
BindingType type{ BindingType::SampledImage };
|
||||
/// Resources attached to binding
|
||||
inplace_vector<size_t, 16> resources;
|
||||
};
|
||||
|
||||
/// Signature of a pipeline stage
|
||||
struct StageSignature {
|
||||
/// Passes executed this stage
|
||||
inplace_vector<size_t, 8> passes;
|
||||
};
|
||||
|
||||
///
|
||||
/// Signature of a compute pipeline
|
||||
///
|
||||
struct PipelineSignature {
|
||||
/// Shader names used by the pipeline (and if there are hdr variants)
|
||||
inplace_vector<std::pair<std::string_view, bool>, 32> shaders;
|
||||
/// Images used by the pipeline
|
||||
inplace_vector<ImageSignature, 192> images;
|
||||
/// Ordered set of bindings for the descriptor set
|
||||
inplace_vector<BindingSignature, 192> descriptors;
|
||||
/// Indexable list of all passes
|
||||
inplace_vector<PassSignature, 100> passes;
|
||||
/// Ordered list of stages, excecuted in sequence
|
||||
inplace_vector<StageSignature, 100> stages;
|
||||
/// Stage index where the command buffers are split
|
||||
inplace_vector<size_t, 4> splitIndices;
|
||||
};
|
||||
|
||||
///
|
||||
/// The signature of a compute pipeline
|
||||
///
|
||||
class PipelineSignatureBuilder {
|
||||
public:
|
||||
///
|
||||
/// Create a new empty signature builder
|
||||
///
|
||||
explicit PipelineSignatureBuilder() = default;
|
||||
|
||||
///
|
||||
/// Register an image
|
||||
///
|
||||
/// @param image Image signature
|
||||
/// @return Handle to the image
|
||||
///
|
||||
consteval size_t registerImage(ImageSignature image) {
|
||||
this->m_images.push_back(std::move(image));
|
||||
return this->m_images.size() - 1;
|
||||
}
|
||||
|
||||
///
|
||||
/// Append a pass
|
||||
///
|
||||
/// @param pass Pass signature
|
||||
/// @return Handle to the pass
|
||||
///
|
||||
consteval size_t appendPass(PassSignature pass) {
|
||||
this->m_passes.push_back(std::move(pass));
|
||||
return this->m_passes.size() - 1;
|
||||
}
|
||||
|
||||
///
|
||||
/// Split the command buffer
|
||||
///
|
||||
consteval void split() {
|
||||
this->m_splitIndices.emplace_back(this->m_passes.size());
|
||||
}
|
||||
|
||||
///
|
||||
/// Compute a pipeline signature
|
||||
///
|
||||
/// @throws const char* on failure
|
||||
/// @return Pipeline siganture
|
||||
///
|
||||
consteval PipelineSignature finalize() {
|
||||
PipelineSignature s{};
|
||||
|
||||
/* TODO */
|
||||
|
||||
return s;
|
||||
}
|
||||
private:
|
||||
std::vector<ImageSignature> m_images;
|
||||
std::vector<PassSignature> m_passes;
|
||||
std::vector<size_t> m_splitIndices;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
|
|
@ -90,4 +91,39 @@ namespace lsfgvk::pipeline {
|
|||
#pragma clang diagnostic pop
|
||||
};
|
||||
|
||||
/// Sequence of operations to apply to the base extent
|
||||
class ExtentOp {
|
||||
public:
|
||||
/// Default constructor for no operations and no flow scaling
|
||||
constexpr ExtentOp() = default;
|
||||
/// Constructor for no operations aside from flow scale
|
||||
constexpr ExtentOp(bool flow) : m_flow(flow) {}
|
||||
/// Constructor for a single operation
|
||||
constexpr ExtentOp(bool flow, uint32_t add, uint32_t shift)
|
||||
: m_flow(flow), m_operations({{add, shift}}) {}
|
||||
/// Constructor for a single operation starting from the flow base extent
|
||||
constexpr ExtentOp(uint32_t add, uint32_t shift)
|
||||
: m_flow(true), m_operations({{add, shift}}) {}
|
||||
// Combine two extents
|
||||
constexpr ExtentOp operator+(const ExtentOp& other) const {
|
||||
ExtentOp result{*this};
|
||||
for (const auto& [add, shift] : other.m_operations)
|
||||
result.m_operations.emplace_back(add, shift);
|
||||
return result;
|
||||
}
|
||||
// Combine two extends
|
||||
constexpr ExtentOp operator+=(const ExtentOp& other) {
|
||||
for (const auto& [add, shift] : other.m_operations)
|
||||
this->m_operations.emplace_back(add, shift);
|
||||
return *this;
|
||||
}
|
||||
/// Get the flow value
|
||||
[[nodiscard]] constexpr auto flow() const { return this->m_flow; }
|
||||
/// Get the operations
|
||||
[[nodiscard]] constexpr const auto& operations() const { return this->m_operations; }
|
||||
private:
|
||||
bool m_flow{false};
|
||||
inplace_vector<std::pair<uint32_t, uint32_t>, 8> m_operations;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
95
lsfg-vk-backend/src/modules/pipeline/signature/image.hpp
Normal file
95
lsfg-vk-backend/src/modules/pipeline/signature/image.hpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace lsfgvk::pipeline {
|
||||
|
||||
/// All supported image formats
|
||||
enum class Format : char {
|
||||
/// Invalid format
|
||||
Invalid = 0,
|
||||
/// 8-bit unsigned normalized RGBA format
|
||||
RGBA8888 = 37, // VK_FORMAT_R8G8B8A8_UNORM
|
||||
/// 8-bit unsigned normalized R format
|
||||
R8 = 9, // VK_FORMAT_R8_UNORM
|
||||
/// 16-bit signed floating point RGBA format
|
||||
RGBA16161616 = 97, // VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
};
|
||||
|
||||
/// All supported image flags
|
||||
enum class ImageFlag : char {
|
||||
/// No special flags
|
||||
None = 0,
|
||||
/// Instead of using a single image array, create several individual images with halving
|
||||
/// extends for each mip level.
|
||||
///
|
||||
/// This will cause the image to show up as Texture2D[], rather than Texture2DArray
|
||||
/// and must therefore not be used in full with passes where the "Aggregate" flag is set.
|
||||
Mipmaps = 1 << 0,
|
||||
/// Indicate that the image is pinned & not transient
|
||||
Pinned = 1 << 1,
|
||||
/// Indicate that this image is written to externally
|
||||
ExternalInput = 1 << 2,
|
||||
/// Indicate that this image is read from externally
|
||||
ExternalOutput = 1 << 3,
|
||||
/// Indicate that a separate format should be used for HDR
|
||||
HdrVariant = 1 << 4
|
||||
};
|
||||
|
||||
/// Helper type for operating on image flags
|
||||
class ImageFlags {
|
||||
public:
|
||||
/// Default constructor
|
||||
constexpr ImageFlags() = default;
|
||||
/// Create from single image flag
|
||||
constexpr ImageFlags(ImageFlag flag) : m_flags(static_cast<int>(flag)) {}
|
||||
/// Check any set of flags
|
||||
constexpr operator bool() const { return m_flags != 0; }
|
||||
/// Combine with another flag
|
||||
constexpr ImageFlags operator|(ImageFlag flag) const {
|
||||
return{this->m_flags | static_cast<int>(flag)};
|
||||
}
|
||||
/// Match with another flag
|
||||
constexpr ImageFlags operator&(ImageFlag flag) const {
|
||||
return{this->m_flags & static_cast<int>(flag)};
|
||||
}
|
||||
/// Match with another flag instance
|
||||
constexpr ImageFlags operator&(ImageFlags other) const {
|
||||
return{this->m_flags & other.m_flags};
|
||||
}
|
||||
private:
|
||||
int m_flags{static_cast<int>(ImageFlag::None)};
|
||||
|
||||
// Create from number
|
||||
constexpr ImageFlags(int flags) : m_flags(flags) {}
|
||||
};
|
||||
|
||||
/// Compine two image flags
|
||||
constexpr ImageFlags operator|(ImageFlag lhs, ImageFlag rhs) {
|
||||
return ImageFlags(lhs) | rhs;
|
||||
}
|
||||
|
||||
/// Signature for an image
|
||||
struct ImageSignature {
|
||||
/// Format of the image
|
||||
Format format{ Format::RGBA8888 };
|
||||
/// Optional second format for HDR variants
|
||||
Format hdrFormat{ Format::RGBA16161616 };
|
||||
/// Optional flags for the image
|
||||
ImageFlags flags{ ImageFlag::None };
|
||||
/// Operation applied to the base extent for calculating the image extent
|
||||
ExtentOp extentOp;
|
||||
/// Amount of layers in the image
|
||||
uint32_t count{1};
|
||||
|
||||
/// Lifetime of the image (set by pipeline builder)
|
||||
std::pair<size_t, size_t> lifetime;
|
||||
};
|
||||
|
||||
}
|
||||
88
lsfg-vk-backend/src/modules/pipeline/signature/pass.hpp
Normal file
88
lsfg-vk-backend/src/modules/pipeline/signature/pass.hpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace lsfgvk::pipeline {
|
||||
|
||||
/// All supported pass flags
|
||||
enum class PassFlag : char {
|
||||
/// No special flags
|
||||
None = 0,
|
||||
/// Indicates the shader will be reused several times and resources must be
|
||||
/// aggregated into arrays and indexed via push constants.
|
||||
Aggregate = 1 << 0,
|
||||
/// Indicate that the special flag is set via push constant.
|
||||
Special = 1 << 1,
|
||||
/// Indicate that there are two variants for 8-bit and 16-bit foramtrs
|
||||
HdrVariant = 1 << 2
|
||||
};
|
||||
|
||||
/// Helper type for operating on pass flags
|
||||
class PassFlags {
|
||||
public:
|
||||
/// Default constructor
|
||||
constexpr PassFlags() = default;
|
||||
/// Create from single pass flag
|
||||
constexpr PassFlags(PassFlag flag) : m_flags(static_cast<int>(flag)) {}
|
||||
/// Check any set of flags
|
||||
constexpr operator bool() const { return m_flags != 0; }
|
||||
/// Combine with another flag
|
||||
constexpr PassFlags operator|(PassFlag flag) const {
|
||||
return{this->m_flags | static_cast<int>(flag)};
|
||||
}
|
||||
/// Match with another flag
|
||||
constexpr PassFlags operator&(PassFlag flag) const {
|
||||
return{this->m_flags & static_cast<int>(flag)};
|
||||
}
|
||||
private:
|
||||
int m_flags{static_cast<int>(PassFlag::None)};
|
||||
|
||||
// Create from number
|
||||
constexpr PassFlags(int flags) : m_flags(flags) {}
|
||||
};
|
||||
|
||||
/// Combine two pass flags
|
||||
constexpr PassFlags operator|(PassFlag lhs, PassFlag rhs) {
|
||||
return PassFlags(lhs) | rhs;
|
||||
}
|
||||
|
||||
/// A pointer to an image, or a specific layer inside that image
|
||||
class Resource {
|
||||
public:
|
||||
/// Default constructor
|
||||
constexpr Resource() = default;
|
||||
/// Constructor for a full image
|
||||
constexpr Resource(size_t idx) : m_idx(idx) {}
|
||||
/// Constructor for a single layer
|
||||
constexpr Resource(size_t idx, uint32_t layer) : m_idx(idx), m_layer(layer) {}
|
||||
/// Get the flow value
|
||||
[[nodiscard]] constexpr auto idx() const { return this->m_idx; }
|
||||
/// Get the operations
|
||||
[[nodiscard]] constexpr auto layer() const { return this->m_layer; }
|
||||
private:
|
||||
std::optional<size_t> m_idx{0};
|
||||
std::optional<uint32_t> m_layer;
|
||||
};
|
||||
|
||||
/// Signature of a shader pass
|
||||
struct PassSignature {
|
||||
/// Name of the shader
|
||||
std::string_view shader;
|
||||
/// Optional flags of this pass
|
||||
PassFlags flags{ PassFlag::None };
|
||||
/// Resources to read from
|
||||
inplace_vector<Resource, 8> inputs;
|
||||
/// Resources to write to
|
||||
inplace_vector<Resource, 8> outputs;
|
||||
/// Operation applied to the base extent for calculating the dispatch extent
|
||||
ExtentOp dispatchOp;
|
||||
};
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue