mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-05-11 03:31:44 +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 "vkhelper.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
@ -12,6 +14,7 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/* Device initialization */
|
/* Device initialization */
|
||||||
|
|
||||||
|
|
@ -170,3 +173,31 @@ vk::UniqueShaderModule vkhelper::createShaderModule(
|
||||||
};
|
};
|
||||||
return device.createShaderModuleUnique(shaderInfo, nullptr, dld);
|
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>
|
#include <vulkan/vulkan_structs.hpp>
|
||||||
// IWYU pragma: end_exports
|
// IWYU pragma: end_exports
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace vkhelper {
|
namespace vkhelper {
|
||||||
|
|
||||||
|
|
@ -116,4 +118,21 @@ namespace vkhelper {
|
||||||
const std::span<const uint32_t>& code
|
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