mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
refactor: rework abstraction for descriptor sets
This commit is contained in:
parent
b86291b951
commit
1b367f7743
7 changed files with 238 additions and 280 deletions
|
|
@ -1,128 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorpool.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
|
||||
namespace LSFG::Core {
|
||||
|
||||
class DescriptorSetUpdateBuilder;
|
||||
|
||||
///
|
||||
/// C++ wrapper class for a Vulkan descriptor set.
|
||||
///
|
||||
/// This class manages the lifetime of a Vulkan descriptor set.
|
||||
///
|
||||
class DescriptorSet {
|
||||
public:
|
||||
DescriptorSet() noexcept = default;
|
||||
|
||||
///
|
||||
/// Create the descriptor set.
|
||||
///
|
||||
/// @param device Vulkan device
|
||||
/// @param pool Descriptor pool to allocate from
|
||||
/// @param shaderModule Shader module to use for the descriptor set
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
DescriptorSet(const Core::Device& device,
|
||||
const DescriptorPool& pool, const ShaderModule& shaderModule);
|
||||
|
||||
///
|
||||
/// Update the descriptor set with resources.
|
||||
///
|
||||
/// @param device Vulkan device
|
||||
///
|
||||
[[nodiscard]] DescriptorSetUpdateBuilder update(const Core::Device& device) const;
|
||||
|
||||
///
|
||||
/// Bind a descriptor set to a command buffer.
|
||||
///
|
||||
/// @param commandBuffer Command buffer to bind the descriptor set to.
|
||||
/// @param pipeline Pipeline to bind the descriptor set to.
|
||||
///
|
||||
void bind(const CommandBuffer& commandBuffer, const Pipeline& pipeline) const;
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->descriptorSet; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
DescriptorSet(const DescriptorSet&) noexcept = default;
|
||||
DescriptorSet& operator=(const DescriptorSet&) noexcept = default;
|
||||
DescriptorSet(DescriptorSet&&) noexcept = default;
|
||||
DescriptorSet& operator=(DescriptorSet&&) noexcept = default;
|
||||
~DescriptorSet() = default;
|
||||
private:
|
||||
std::shared_ptr<VkDescriptorSet> descriptorSet;
|
||||
};
|
||||
|
||||
///
|
||||
/// Builder class for updating a descriptor set.
|
||||
///
|
||||
class DescriptorSetUpdateBuilder {
|
||||
friend class DescriptorSet;
|
||||
public:
|
||||
/// Add a resource to the descriptor set update.
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Image& image);
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Sampler& sampler);
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Buffer& buffer);
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type); // empty entry
|
||||
|
||||
/// Add a list of resources to the descriptor set update.
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector<Image>& images) {
|
||||
for (const auto& image : images) this->add(type, image); return *this; }
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector<Sampler>& samplers) {
|
||||
for (const auto& sampler : samplers) this->add(type, sampler); return *this; }
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector<Buffer>& buffers) {
|
||||
for (const auto& buffer : buffers) this->add(type, buffer); return *this; }
|
||||
|
||||
/// Add an array of resources
|
||||
template<std::size_t N>
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::array<Image, N>& images) {
|
||||
for (const auto& image : images) this->add(type, image); return *this; }
|
||||
template<std::size_t N>
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::array<Sampler, N>& samplers) {
|
||||
for (const auto& sampler : samplers) this->add(type, sampler); return *this; }
|
||||
template<std::size_t N>
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::array<Buffer, N>& buffers) {
|
||||
for (const auto& buffer : buffers) this->add(type, buffer); return *this; }
|
||||
|
||||
/// Add an optional resource to the descriptor set update.
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional<Image>& image) {
|
||||
if (image.has_value()) this->add(type, *image); else this->add(type); return *this; }
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional<Sampler>& sampler) {
|
||||
if (sampler.has_value()) this->add(type, *sampler); else this->add(type); return *this; }
|
||||
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional<Buffer>& buffer) {
|
||||
if (buffer.has_value()) this->add(type, *buffer); else this->add(type); return *this; }
|
||||
|
||||
/// Finish building the descriptor set update.
|
||||
void build();
|
||||
private:
|
||||
const DescriptorSet* descriptorSet;
|
||||
const Core::Device* device;
|
||||
|
||||
DescriptorSetUpdateBuilder(const DescriptorSet& descriptorSet, const Core::Device& device)
|
||||
: descriptorSet(&descriptorSet), device(&device) {}
|
||||
|
||||
std::vector<VkWriteDescriptorSet> entries;
|
||||
size_t bufferIdx{0};
|
||||
size_t samplerIdx{16};
|
||||
size_t inputIdx{32};
|
||||
size_t outputIdx{48};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/device.hpp"
|
||||
#include "core/descriptorpool.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/buffer.hpp"
|
||||
#include "common/exception.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
DescriptorSet::DescriptorSet(const Core::Device& device,
|
||||
const DescriptorPool& pool, const ShaderModule& shaderModule) {
|
||||
// create descriptor set
|
||||
VkDescriptorSetLayout layout = shaderModule.getLayout();
|
||||
const VkDescriptorSetAllocateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = pool.handle(),
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &layout
|
||||
};
|
||||
VkDescriptorSet descriptorSetHandle{};
|
||||
auto res = vkAllocateDescriptorSets(device.handle(), &desc, &descriptorSetHandle);
|
||||
if (res != VK_SUCCESS || descriptorSetHandle == VK_NULL_HANDLE)
|
||||
throw LSFG::vulkan_error(res, "Unable to allocate descriptor set");
|
||||
|
||||
/// store set in shared ptr
|
||||
this->descriptorSet = std::shared_ptr<VkDescriptorSet>(
|
||||
new VkDescriptorSet(descriptorSetHandle),
|
||||
[dev = device.handle(), pool = pool](VkDescriptorSet* setHandle) {
|
||||
vkFreeDescriptorSets(dev, pool.handle(), 1, setHandle);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DescriptorSetUpdateBuilder DescriptorSet::update(const Core::Device& device) const {
|
||||
return { *this, device };
|
||||
}
|
||||
|
||||
void DescriptorSet::bind(const CommandBuffer& commandBuffer, const Pipeline& pipeline) const {
|
||||
VkDescriptorSet descriptorSetHandle = this->handle();
|
||||
vkCmdBindDescriptorSets(commandBuffer.handle(),
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getLayout(),
|
||||
0, 1, &descriptorSetHandle, 0, nullptr);
|
||||
}
|
||||
|
||||
// updater class
|
||||
|
||||
DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type, const Image& image) {
|
||||
size_t* idx{type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? &this->outputIdx : &this->inputIdx};
|
||||
this->entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = this->descriptorSet->handle(),
|
||||
.dstBinding = static_cast<uint32_t>(*idx),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = type,
|
||||
.pImageInfo = new VkDescriptorImageInfo {
|
||||
.imageView = image.getView(),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
},
|
||||
.pBufferInfo = nullptr
|
||||
});
|
||||
(*idx)++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type, const Sampler& sampler) {
|
||||
this->entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = this->descriptorSet->handle(),
|
||||
.dstBinding = static_cast<uint32_t>(this->samplerIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = type,
|
||||
.pImageInfo = new VkDescriptorImageInfo {
|
||||
.sampler = sampler.handle(),
|
||||
},
|
||||
.pBufferInfo = nullptr
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type, const Buffer& buffer) {
|
||||
this->entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = this->descriptorSet->handle(),
|
||||
.dstBinding = static_cast<uint32_t>(this->bufferIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = type,
|
||||
.pImageInfo = nullptr,
|
||||
.pBufferInfo = new VkDescriptorBufferInfo {
|
||||
.buffer = buffer.handle(),
|
||||
.range = buffer.getSize()
|
||||
}
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type) {
|
||||
size_t* idx{};
|
||||
switch (type) {
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
idx = &this->inputIdx;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
idx = &this->outputIdx;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
idx = &this->samplerIdx;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
idx = &this->bufferIdx;
|
||||
break;
|
||||
default:
|
||||
throw LSFG::vulkan_error(VK_ERROR_UNKNOWN, "Unsupported descriptor type");
|
||||
}
|
||||
this->entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = this->descriptorSet->handle(),
|
||||
.dstBinding = static_cast<uint32_t>(*idx),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = type,
|
||||
.pImageInfo = new VkDescriptorImageInfo {
|
||||
},
|
||||
.pBufferInfo = nullptr
|
||||
});
|
||||
(*idx)++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void DescriptorSetUpdateBuilder::build() {
|
||||
vkUpdateDescriptorSets(this->device->handle(),
|
||||
static_cast<uint32_t>(this->entries.size()),
|
||||
this->entries.data(), 0, nullptr);
|
||||
|
||||
// NOLINTBEGIN
|
||||
for (const auto& entry : this->entries) {
|
||||
delete entry.pImageInfo;
|
||||
delete entry.pBufferInfo;
|
||||
}
|
||||
// NOLINTEND
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "vk/core/commandpool.hpp"
|
||||
#include "vk/core/descriptorset.hpp"
|
||||
#include "vk/core/semaphore.hpp"
|
||||
#include "vk/core/pipeline.hpp"
|
||||
#include "vk/core/device.hpp"
|
||||
|
|
@ -65,8 +66,16 @@ namespace VK::Core {
|
|||
///
|
||||
void bindPipeline(const Pipeline& pipeline) const;
|
||||
|
||||
// TODO: Method for binding a descriptor set.
|
||||
// TODO: Rework abstraction for descriptor sets.
|
||||
///
|
||||
/// Bind a descriptor set to the command buffer.
|
||||
///
|
||||
/// @param pipeline Vulkan compute pipeline
|
||||
/// @param set Vulkan descriptor set
|
||||
///
|
||||
/// @throws std::logic_error if the command buffer is not in Recording state
|
||||
///
|
||||
void bindDescriptorSet(const Pipeline& pipeline, const DescriptorSet& set) const;
|
||||
|
||||
// TODO: Method for inserting a pipeline barrier.
|
||||
// TODO: Rework abstraction for barriers.
|
||||
// TODO: Method for copying a buffer to an image
|
||||
|
|
|
|||
122
framegen/include/vk/core/descriptorset.hpp
Normal file
122
framegen/include/vk/core/descriptorset.hpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#pragma once
|
||||
|
||||
#include "vk/core/descriptorpool.hpp"
|
||||
#include "vk/core/shadermodule.hpp"
|
||||
#include "vk/core/sampler.hpp"
|
||||
#include "vk/core/device.hpp"
|
||||
#include "vk/core/buffer.hpp"
|
||||
#include "vk/core/image.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace VK::Core {
|
||||
|
||||
/// Helper class to wrap VkDescriptorImageInfo
|
||||
class ImageInfo {
|
||||
public:
|
||||
ImageInfo() noexcept = default; // skipping images is allowed
|
||||
|
||||
ImageInfo(const Image& image) noexcept
|
||||
: info{
|
||||
.imageView = image.getView(),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
} {}
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return &this->info; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
ImageInfo(const ImageInfo&) noexcept = default;
|
||||
ImageInfo& operator=(const ImageInfo&) noexcept = default;
|
||||
ImageInfo(ImageInfo&&) noexcept = default;
|
||||
ImageInfo& operator=(ImageInfo&&) noexcept = default;
|
||||
~ImageInfo() = default;
|
||||
private:
|
||||
VkDescriptorImageInfo info{};
|
||||
};
|
||||
|
||||
/// Helper class to wrap VkDescriptorImageInfo for samplers
|
||||
class SamplerInfo {
|
||||
public:
|
||||
SamplerInfo(const Sampler& sampler) noexcept
|
||||
: info{
|
||||
.sampler = sampler.handle(),
|
||||
} {}
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return &this->info; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
SamplerInfo(const SamplerInfo&) noexcept = default;
|
||||
SamplerInfo& operator=(const SamplerInfo&) noexcept = default;
|
||||
SamplerInfo(SamplerInfo&&) noexcept = default;
|
||||
SamplerInfo& operator=(SamplerInfo&&) noexcept = default;
|
||||
~SamplerInfo() = default;
|
||||
private:
|
||||
VkDescriptorImageInfo info{};
|
||||
};
|
||||
|
||||
/// Helper class to wrap VkDescriptorBufferInfo
|
||||
class BufferInfo {
|
||||
public:
|
||||
BufferInfo(const Buffer& buffer) noexcept
|
||||
: info{
|
||||
.buffer = buffer.handle(),
|
||||
.range = buffer.getSize()
|
||||
} {}
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return &this->info; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
BufferInfo(const BufferInfo&) noexcept = default;
|
||||
BufferInfo& operator=(const BufferInfo&) noexcept = default;
|
||||
BufferInfo(BufferInfo&&) noexcept = default;
|
||||
BufferInfo& operator=(BufferInfo&&) noexcept = default;
|
||||
~BufferInfo() = default;
|
||||
private:
|
||||
VkDescriptorBufferInfo info{};
|
||||
};
|
||||
|
||||
///
|
||||
/// C++ wrapper class for a Vulkan descriptor set.
|
||||
///
|
||||
/// This class manages the lifetime of a Vulkan descriptor set.
|
||||
///
|
||||
class DescriptorSet {
|
||||
public:
|
||||
DescriptorSet() noexcept = default;
|
||||
|
||||
///
|
||||
/// Create the descriptor set.
|
||||
///
|
||||
/// @param device Vulkan device
|
||||
/// @param pool Descriptor pool to allocate from
|
||||
/// @param shaderModule Shader module to use for the descriptor set
|
||||
///
|
||||
/// @throws VK::vulkan_error if object creation fails.
|
||||
///
|
||||
DescriptorSet(const Device& device,
|
||||
const DescriptorPool& pool, const ShaderModule& shaderModule,
|
||||
const std::vector<ImageInfo>& sampledImages,
|
||||
const std::vector<ImageInfo>& storageImages,
|
||||
const std::vector<SamplerInfo>& samplers,
|
||||
const std::vector<BufferInfo>& uniformBuffers);
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->descriptorSet; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
DescriptorSet(const DescriptorSet&) noexcept = default;
|
||||
DescriptorSet& operator=(const DescriptorSet&) noexcept = default;
|
||||
DescriptorSet(DescriptorSet&&) noexcept = default;
|
||||
DescriptorSet& operator=(DescriptorSet&&) noexcept = default;
|
||||
~DescriptorSet() = default;
|
||||
private:
|
||||
std::shared_ptr<VkDescriptorSet> descriptorSet;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -20,6 +20,8 @@ namespace VK::Core {
|
|||
///
|
||||
class Device {
|
||||
public:
|
||||
Device() noexcept = default;
|
||||
|
||||
///
|
||||
/// Create the device.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -62,6 +62,16 @@ void CommandBuffer::bindPipeline(const Pipeline& pipeline) const {
|
|||
vkCmdBindPipeline(*this->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.handle());
|
||||
}
|
||||
|
||||
void CommandBuffer::bindDescriptorSet(const Pipeline& pipeline, const DescriptorSet& set) const {
|
||||
if (*this->state != CommandBufferState::Recording)
|
||||
throw std::logic_error("Command buffer is not in Recording state");
|
||||
|
||||
VkDescriptorSet descriptorSetHandle = set.handle();
|
||||
vkCmdBindDescriptorSets(*this->commandBuffer,
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getLayout(),
|
||||
0, 1, &descriptorSetHandle, 0, nullptr);
|
||||
}
|
||||
|
||||
void CommandBuffer::dispatch(uint32_t x, uint32_t y, uint32_t z) const {
|
||||
if (*this->state != CommandBufferState::Recording)
|
||||
throw std::logic_error("Command buffer is not in Recording state");
|
||||
|
|
|
|||
93
framegen/src/vk/core/descriptorset.cpp
Normal file
93
framegen/src/vk/core/descriptorset.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include <cstddef>
|
||||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "vk/core/descriptorset.hpp"
|
||||
#include "vk/core/device.hpp"
|
||||
#include "vk/core/descriptorpool.hpp"
|
||||
#include "vk/exception.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace VK::Core;
|
||||
|
||||
DescriptorSet::DescriptorSet(const Device& device,
|
||||
const DescriptorPool& pool, const ShaderModule& shaderModule,
|
||||
const std::vector<ImageInfo>& sampledImages,
|
||||
const std::vector<ImageInfo>& storageImages,
|
||||
const std::vector<SamplerInfo>& samplers,
|
||||
const std::vector<BufferInfo>& uniformBuffers) {
|
||||
// create descriptor set
|
||||
VkDescriptorSetLayout layout = shaderModule.getLayout();
|
||||
const VkDescriptorSetAllocateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = pool.handle(),
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &layout
|
||||
};
|
||||
VkDescriptorSet descriptorSetHandle{};
|
||||
auto res = vkAllocateDescriptorSets(device.handle(), &desc, &descriptorSetHandle);
|
||||
if (res != VK_SUCCESS || descriptorSetHandle == VK_NULL_HANDLE)
|
||||
throw VK::vulkan_error(res, "Unable to allocate descriptor set");
|
||||
|
||||
// create descriptor writes
|
||||
const size_t totalEntries =
|
||||
storageImages.size() + samplers.size() + uniformBuffers.size() + sampledImages.size();
|
||||
std::vector<VkWriteDescriptorSet> entries(totalEntries);
|
||||
|
||||
size_t bufferIdx{0};
|
||||
for (const auto& buf : uniformBuffers)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSetHandle,
|
||||
.dstBinding = static_cast<uint32_t>(bufferIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pBufferInfo = buf.handle()
|
||||
});
|
||||
|
||||
size_t samplerIdx{16};
|
||||
for (const auto& samp : samplers)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSetHandle,
|
||||
.dstBinding = static_cast<uint32_t>(samplerIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.pImageInfo = samp.handle()
|
||||
});
|
||||
|
||||
size_t inputIdx{32};
|
||||
for (const auto& img : sampledImages)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSetHandle,
|
||||
.dstBinding = static_cast<uint32_t>(inputIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.pImageInfo = img.handle()
|
||||
});
|
||||
|
||||
size_t outputIdx{48};
|
||||
for (const auto& img : storageImages)
|
||||
entries.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSetHandle,
|
||||
.dstBinding = static_cast<uint32_t>(outputIdx++),
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.pImageInfo = img.handle()
|
||||
});
|
||||
|
||||
// update descriptor set
|
||||
vkUpdateDescriptorSets(device.handle(),
|
||||
static_cast<uint32_t>(entries.size()), entries.data(), 0, nullptr);
|
||||
|
||||
// store set in shared ptr
|
||||
this->descriptorSet = std::shared_ptr<VkDescriptorSet>(
|
||||
new VkDescriptorSet(descriptorSetHandle),
|
||||
[dev = device.handle(), pool = pool](VkDescriptorSet* setHandle) {
|
||||
vkFreeDescriptorSets(dev, pool.handle(), 1, setHandle);
|
||||
}
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue