mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-10 19:21:42 +00:00
feat(bindless): Build descriptor layout for pipelines
This commit is contained in:
parent
75a186c10e
commit
8e7dd4e4aa
4 changed files with 237 additions and 0 deletions
112
lsfg-vk-backend/src/modules/pipeline.cpp
Normal file
112
lsfg-vk-backend/src/modules/pipeline.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#include "pipeline.hpp"
|
||||
#include "library.hpp"
|
||||
#include "modules/pipeline/signature.hpp"
|
||||
#include "modules/pipeline/signature/helpers.hpp"
|
||||
#include "modules/pipeline/signature/image.hpp"
|
||||
#include "utility/logger.hpp"
|
||||
#include "utility/vkhelper.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace lsfgvk::pipeline;
|
||||
|
||||
namespace {
|
||||
/// Helper method to apply extent operations
|
||||
vk::Extent2D apply(
|
||||
const vk::Extent2D& base,
|
||||
const vk::Extent2D& flow,
|
||||
const ExtentOp& op
|
||||
) {
|
||||
vk::Extent2D result{op.flow() ? flow : base};
|
||||
for (const auto& [add, shift] : op.operations()) {
|
||||
result.width = (result.width + add) >> shift;
|
||||
result.height = (result.height + add) >> shift;
|
||||
}
|
||||
return { result.width, result.height };
|
||||
}
|
||||
}
|
||||
|
||||
Pipeline::Pipeline(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
const vk::Queue& queue,
|
||||
uint32_t queueFamilyIndex,
|
||||
const library::ShaderLibrary& library,
|
||||
const PipelineSignature& signature,
|
||||
vk::Extent2D extent,
|
||||
float flow,
|
||||
bool perf,
|
||||
bool hdr
|
||||
) {
|
||||
LOG_DEBUG("Building pipeline for "
|
||||
<< extent.width << "x" << extent.height
|
||||
<< " at " << flow << " flow")
|
||||
|
||||
// Build the Vulkan descriptor set layout
|
||||
uint32_t sampledImageCount{};
|
||||
uint32_t storageImageCount{};
|
||||
|
||||
std::vector<vk::DescriptorSetLayoutBinding> bindings;
|
||||
bindings.reserve(4 + signature.descriptors.size());
|
||||
|
||||
bindings.push_back({
|
||||
.binding = 0,
|
||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute
|
||||
});
|
||||
|
||||
for (uint32_t i = 1; i <= 3; i++) {
|
||||
bindings.push_back({
|
||||
.binding = i,
|
||||
.descriptorType = vk::DescriptorType::eSampler,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t bindingIdx{4};
|
||||
for (const auto& binding : signature.descriptors) {
|
||||
uint32_t descriptorCount{static_cast<uint32_t>(binding.resources.size())};
|
||||
if (descriptorCount == 1) {
|
||||
const auto& image{signature.images.at(binding.resources.front())};
|
||||
if (image.flags & ImageFlag::Mipmaps)
|
||||
descriptorCount = image.count;
|
||||
}
|
||||
|
||||
bindings.push_back({
|
||||
.binding = bindingIdx++,
|
||||
.descriptorType = binding.type == BindingType::StorageImage ?
|
||||
vk::DescriptorType::eStorageImage : vk::DescriptorType::eSampledImage,
|
||||
.descriptorCount = descriptorCount,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute
|
||||
});
|
||||
|
||||
if (binding.type == BindingType::StorageImage)
|
||||
storageImageCount += descriptorCount;
|
||||
else
|
||||
sampledImageCount += descriptorCount;
|
||||
}
|
||||
|
||||
auto [layout, pipelineLayout] = vkhelper::createLayout(
|
||||
dld,
|
||||
device,
|
||||
bindings,
|
||||
sizeof(PushConstants)
|
||||
);
|
||||
this->m_layout = {
|
||||
.layout = std::move(layout),
|
||||
.pipelineLayout = std::move(pipelineLayout)
|
||||
};
|
||||
|
||||
LOG_DEBUG(" Built descriptor set layout with " << bindings.size() << " bindings ("
|
||||
<< sampledImageCount << " sampled images, "
|
||||
<< storageImageCount << " storage images)")
|
||||
|
||||
LOG_DEBUG("Finished building pipeline")
|
||||
}
|
||||
75
lsfg-vk-backend/src/modules/pipeline.hpp
Normal file
75
lsfg-vk-backend/src/modules/pipeline.hpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "library.hpp"
|
||||
#include "pipeline/signature.hpp"
|
||||
#include "utility/vkhelper.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace lsfgvk::pipeline {
|
||||
|
||||
// TODO: Improve API design
|
||||
|
||||
/// Struct for the uniform buffer
|
||||
struct UniformBuffer {
|
||||
float timestamp;
|
||||
uint32_t iteration;
|
||||
uint32_t advancedColorKind;
|
||||
uint32_t hdrSupport;
|
||||
float resolutionInvScale;
|
||||
float uiThreshold;
|
||||
};
|
||||
|
||||
/// Struct for push constants
|
||||
struct PushConstants {
|
||||
uint32_t specialFlag;
|
||||
uint32_t subiteration;
|
||||
};
|
||||
|
||||
///
|
||||
/// Vulkan pipeline created from a signature
|
||||
///
|
||||
class Pipeline {
|
||||
public:
|
||||
///
|
||||
/// Create a new pipeline
|
||||
///
|
||||
/// @param dld Vulkan dispatch loader
|
||||
/// @param dev Vulkan device
|
||||
/// @param physdev Vulkan physical device
|
||||
/// @param queue Vulkan compute queue
|
||||
/// @param queueFamilyIndex Compute queue family index
|
||||
/// @param library Shader library
|
||||
/// @param signature Pipeline signature
|
||||
/// @param extent Base extent
|
||||
/// @param flow Flow scale
|
||||
/// @param perf Performance mode
|
||||
/// @param hdr HDR variant
|
||||
/// @throws std::runtime_error on failure
|
||||
///
|
||||
explicit Pipeline(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& dev,
|
||||
const vk::PhysicalDevice& physdev,
|
||||
const vk::Queue& queue,
|
||||
uint32_t queueFamilyIndex,
|
||||
const library::ShaderLibrary& library,
|
||||
const PipelineSignature& signature,
|
||||
vk::Extent2D extent,
|
||||
float flow,
|
||||
bool perf,
|
||||
bool hdr
|
||||
);
|
||||
|
||||
private:
|
||||
/// Vulkan descriptor set & pipeline layout
|
||||
struct Layout {
|
||||
vk::UniqueDescriptorSetLayout layout;
|
||||
vk::UniquePipelineLayout pipelineLayout;
|
||||
};
|
||||
Layout m_layout;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@
|
|||
#include "vkhelper.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
|
|
@ -12,6 +14,7 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/* Device initialization */
|
||||
|
||||
|
|
@ -170,3 +173,31 @@ vk::UniqueShaderModule vkhelper::createShaderModule(
|
|||
};
|
||||
return device.createShaderModuleUnique(shaderInfo, nullptr, dld);
|
||||
}
|
||||
|
||||
std::pair<vk::UniqueDescriptorSetLayout, vk::UniquePipelineLayout> vkhelper::createLayout(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const std::vector<vk::DescriptorSetLayoutBinding>& bindings,
|
||||
size_t pushConstantSize
|
||||
) {
|
||||
const vk::DescriptorSetLayoutCreateInfo layoutInfo{
|
||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
|
||||
.bindingCount = static_cast<uint32_t>(bindings.size()),
|
||||
.pBindings = bindings.data()
|
||||
};
|
||||
auto descriptorSetLayout{device.createDescriptorSetLayoutUnique(layoutInfo, nullptr, dld)};
|
||||
|
||||
const vk::PushConstantRange pushConstantRange{
|
||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||
.size = static_cast<uint32_t>(pushConstantSize)
|
||||
};
|
||||
const vk::PipelineLayoutCreateInfo pipelineLayoutInfo{
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &*descriptorSetLayout,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &pushConstantRange
|
||||
};
|
||||
auto pipelineLayout{device.createPipelineLayoutUnique(pipelineLayoutInfo, nullptr, dld)};
|
||||
|
||||
return { std::move(descriptorSetLayout), std::move(pipelineLayout) };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@
|
|||
#include <vulkan/vulkan_structs.hpp>
|
||||
// IWYU pragma: end_exports
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace vkhelper {
|
||||
|
||||
|
|
@ -116,4 +118,21 @@ namespace vkhelper {
|
|||
const std::span<const uint32_t>& code
|
||||
);
|
||||
|
||||
///
|
||||
/// Create a Vulkan descriptor set layout
|
||||
///
|
||||
/// @param dld Dynamic dispatch loader
|
||||
/// @param device Vulkan device
|
||||
/// @param bindings List of descriptor set layout bindings
|
||||
/// @param pushConstantSize Size of push constant range
|
||||
/// @return RAII-wrapped Vulkan descriptor set & pipeline layout
|
||||
/// @throws std::runtime_error on failure
|
||||
///
|
||||
std::pair<vk::UniqueDescriptorSetLayout, vk::UniquePipelineLayout> createLayout(
|
||||
const vk::detail::DispatchLoaderDynamic& dld,
|
||||
const vk::Device& device,
|
||||
const std::vector<vk::DescriptorSetLayoutBinding>& bindings,
|
||||
size_t pushConstantSize
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue