mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 06:05:40 +12:00
Add Vulkan Descriptor-Update batching
Allows multiple descriptor operations to be batched up and dispatched in one API call rather than scattered through out the code base.
This commit is contained in:
parent
72c77e41b4
commit
4b7bd9df3d
3 changed files with 162 additions and 0 deletions
|
@ -241,12 +241,14 @@ if(ENABLE_VULKAN)
|
|||
set(RENDERER_VK_INCLUDE_FILES include/renderer_vk/renderer_vk.hpp
|
||||
include/renderer_vk/vk_api.hpp include/renderer_vk/vk_debug.hpp
|
||||
include/renderer_vk/vk_descriptor_heap.hpp
|
||||
include/renderer_vk/vk_descriptor_update_batch.hpp
|
||||
include/renderer_vk/vk_memory.hpp include/renderer_vk/vk_pica.hpp
|
||||
)
|
||||
|
||||
set(RENDERER_VK_SOURCE_FILES src/core/renderer_vk/renderer_vk.cpp
|
||||
src/core/renderer_vk/vk_api.cpp src/core/renderer_vk/vk_debug.cpp
|
||||
src/core/renderer_vk/vk_descriptor_heap.cpp
|
||||
src/core/renderer_vk/vk_descriptor_update_batch.cpp
|
||||
src/core/renderer_vk/vk_memory.cpp src/core/renderer_vk/vk_pica.cpp
|
||||
)
|
||||
|
||||
|
|
62
include/renderer_vk/vk_descriptor_update_batch.hpp
Normal file
62
include/renderer_vk/vk_descriptor_update_batch.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
#include "helpers.hpp"
|
||||
#include "vk_api.hpp"
|
||||
|
||||
namespace Vulkan {
|
||||
// Implements a re-usable structure for batching up descriptor writes with a
|
||||
// finite amount of space for both convenience and to reduce the overall amount
|
||||
// of API calls to `vkUpdateDescriptorSets`
|
||||
class DescriptorUpdateBatch {
|
||||
private:
|
||||
const vk::Device device;
|
||||
|
||||
const usize descriptorWriteMax;
|
||||
const usize descriptorCopyMax;
|
||||
|
||||
using DescriptorInfoUnion = std::variant<vk::DescriptorImageInfo, vk::DescriptorBufferInfo, vk::BufferView>;
|
||||
|
||||
// Todo: Maybe some kind of hash so that these structures can be re-used
|
||||
// among descriptor writes.
|
||||
std::unique_ptr<DescriptorInfoUnion[]> descriptorInfos;
|
||||
std::unique_ptr<vk::WriteDescriptorSet[]> descriptorWrites;
|
||||
std::unique_ptr<vk::CopyDescriptorSet[]> descriptorCopies;
|
||||
|
||||
usize descriptorWriteEnd = 0;
|
||||
usize descriptorCopyEnd = 0;
|
||||
|
||||
DescriptorUpdateBatch(vk::Device device, usize descriptorWriteMax, usize descriptorCopyMax)
|
||||
: device(device), descriptorWriteMax(descriptorWriteMax), descriptorCopyMax(descriptorCopyMax) {}
|
||||
|
||||
public:
|
||||
~DescriptorUpdateBatch() = default;
|
||||
|
||||
DescriptorUpdateBatch(DescriptorUpdateBatch&&) = default;
|
||||
|
||||
void flush();
|
||||
|
||||
void addImage(
|
||||
vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::ImageView imageView, vk::ImageLayout imageLayout = vk::ImageLayout::eGeneral
|
||||
);
|
||||
void addSampler(vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::Sampler sampler);
|
||||
|
||||
void addImageSampler(
|
||||
vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::ImageView imageView, vk::Sampler sampler,
|
||||
vk::ImageLayout imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal
|
||||
);
|
||||
void addBuffer(
|
||||
vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::Buffer buffer, vk::DeviceSize offset, vk::DeviceSize size = VK_WHOLE_SIZE
|
||||
);
|
||||
|
||||
void copyBinding(
|
||||
vk::DescriptorSet sourceDescriptor, vk::DescriptorSet targetDescriptor, u8 sourceBinding, u8 targetBinding, u8 sourceArrayElement = 0,
|
||||
u8 targetArrayElement = 0, u8 descriptorCount = 1
|
||||
);
|
||||
|
||||
static std::optional<DescriptorUpdateBatch> create(vk::Device device, usize descriptorWriteMax = 256, usize descriptorCopyMax = 256);
|
||||
};
|
||||
} // namespace Vulkan
|
98
src/core/renderer_vk/vk_descriptor_update_batch.cpp
Normal file
98
src/core/renderer_vk/vk_descriptor_update_batch.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "renderer_vk/vk_descriptor_update_batch.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <span>
|
||||
|
||||
namespace Vulkan {
|
||||
|
||||
void DescriptorUpdateBatch::flush() {
|
||||
device.updateDescriptorSets({std::span(descriptorWrites.get(), descriptorWriteEnd)}, {std::span(descriptorCopies.get(), descriptorCopyEnd)});
|
||||
|
||||
descriptorWriteEnd = 0;
|
||||
descriptorCopyEnd = 0;
|
||||
}
|
||||
|
||||
void DescriptorUpdateBatch::addImage(vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::ImageView imageView, vk::ImageLayout imageLayout) {
|
||||
if (descriptorWriteEnd >= descriptorWriteMax) {
|
||||
flush();
|
||||
}
|
||||
|
||||
const auto& imageInfo = descriptorInfos[descriptorWriteEnd].emplace<vk::DescriptorImageInfo>(vk::Sampler(), imageView, imageLayout);
|
||||
|
||||
descriptorWrites[descriptorWriteEnd] =
|
||||
vk::WriteDescriptorSet(targetDescriptor, targetBinding, 0, 1, vk::DescriptorType::eSampledImage, &imageInfo, nullptr, nullptr);
|
||||
|
||||
++descriptorWriteEnd;
|
||||
}
|
||||
|
||||
void DescriptorUpdateBatch::addSampler(vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::Sampler sampler) {
|
||||
if (descriptorWriteEnd >= descriptorWriteMax) {
|
||||
flush();
|
||||
}
|
||||
|
||||
const auto& imageInfo = descriptorInfos[descriptorWriteEnd].emplace<vk::DescriptorImageInfo>(sampler, vk::ImageView(), vk::ImageLayout());
|
||||
|
||||
descriptorWrites[descriptorWriteEnd] =
|
||||
vk::WriteDescriptorSet(targetDescriptor, targetBinding, 0, 1, vk::DescriptorType::eSampler, &imageInfo, nullptr, nullptr);
|
||||
|
||||
++descriptorWriteEnd;
|
||||
}
|
||||
|
||||
void DescriptorUpdateBatch::addImageSampler(
|
||||
vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::ImageView imageView, vk::Sampler sampler, vk::ImageLayout imageLayout
|
||||
) {
|
||||
if (descriptorWriteEnd >= descriptorWriteMax) {
|
||||
flush();
|
||||
}
|
||||
|
||||
const auto& imageInfo = descriptorInfos[descriptorWriteEnd].emplace<vk::DescriptorImageInfo>(sampler, imageView, imageLayout);
|
||||
|
||||
descriptorWrites[descriptorWriteEnd] =
|
||||
vk::WriteDescriptorSet(targetDescriptor, targetBinding, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
|
||||
|
||||
++descriptorWriteEnd;
|
||||
}
|
||||
|
||||
void DescriptorUpdateBatch::addBuffer(
|
||||
vk::DescriptorSet targetDescriptor, u8 targetBinding, vk::Buffer buffer, vk::DeviceSize offset, vk::DeviceSize size
|
||||
) {
|
||||
if (descriptorWriteEnd >= descriptorWriteMax) {
|
||||
flush();
|
||||
}
|
||||
|
||||
const auto& bufferInfo = descriptorInfos[descriptorWriteEnd].emplace<vk::DescriptorBufferInfo>(buffer, offset, size);
|
||||
|
||||
descriptorWrites[descriptorWriteEnd] =
|
||||
vk::WriteDescriptorSet(targetDescriptor, targetBinding, 0, 1, vk::DescriptorType::eStorageImage, nullptr, &bufferInfo, nullptr);
|
||||
|
||||
++descriptorWriteEnd;
|
||||
}
|
||||
|
||||
void DescriptorUpdateBatch::copyBinding(
|
||||
vk::DescriptorSet sourceDescriptor, vk::DescriptorSet targetDescriptor, u8 sourceBinding, u8 targetBinding, u8 sourceArrayElement,
|
||||
u8 targetArrayElement, u8 descriptorCount
|
||||
) {
|
||||
if (descriptorCopyEnd >= descriptorCopyMax) {
|
||||
flush();
|
||||
}
|
||||
|
||||
descriptorCopies[descriptorCopyEnd] = vk::CopyDescriptorSet(
|
||||
sourceDescriptor, sourceBinding, sourceArrayElement, targetDescriptor, targetBinding, targetArrayElement, descriptorCount
|
||||
);
|
||||
|
||||
++descriptorCopyEnd;
|
||||
}
|
||||
|
||||
std::optional<DescriptorUpdateBatch> DescriptorUpdateBatch::create(vk::Device device, usize descriptorWriteMax, usize descriptorCopyMax)
|
||||
|
||||
{
|
||||
DescriptorUpdateBatch newDescriptorUpdateBatch(device, descriptorWriteMax, descriptorCopyMax);
|
||||
|
||||
newDescriptorUpdateBatch.descriptorInfos = std::make_unique<DescriptorInfoUnion[]>(descriptorWriteMax);
|
||||
newDescriptorUpdateBatch.descriptorWrites = std::make_unique<vk::WriteDescriptorSet[]>(descriptorWriteMax);
|
||||
newDescriptorUpdateBatch.descriptorCopies = std::make_unique<vk::CopyDescriptorSet[]>(descriptorCopyMax);
|
||||
|
||||
return {std::move(newDescriptorUpdateBatch)};
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
Loading…
Add table
Reference in a new issue