refactor: convenience changes

This commit is contained in:
PancakeTAS 2025-09-01 21:41:35 +02:00
parent 32d35c25fc
commit 41c0083a04
No known key found for this signature in database
6 changed files with 84 additions and 79 deletions

View file

@ -83,19 +83,19 @@ namespace VK::Core {
///
/// @throws std::logic_error if the command buffer is not in Recording state
///
void insertBarrier(const std::vector<VkImage>& images) const;
void insertBarrier(const std::vector<Core::Image>& images) const;
///
/// Insert memory barriers for images in the command buffer.
///
/// @param readableImages Images that will be transitioned from rw to read-only
/// @param writableImages Images that will be transitioned from read-only to rw
/// @param sampledImages Images that will be transitioned from rw to read-only
/// @param storageImages Images that will be transitioned from read-only to rw
///
/// @throws std::logic_error if the command buffer is not in Recording state
///
void insertBarrier(
const std::vector<std::optional<Core::Image>>& readableImages,
const std::vector<Core::Image>& writableImages) const;
const std::vector<std::optional<Core::Image>>& sampledImages,
const std::vector<Core::Image>& storageImages) const;
///
/// Copy a buffer to an image.

View file

@ -30,22 +30,22 @@ namespace VK::Helper {
[[nodiscard]] const auto& all() const { return this->sets; }
/// Get the descriptor set for a specific frame index.
[[nodiscard]] const auto& at(size_t index) const {
[[nodiscard]] const auto& getSetAt(size_t index) const {
return this->set(index).sets;
}
/// Get the readable images for a specific frame index.
[[nodiscard]] const auto& readablesAt(size_t index) const {
return this->set(index).readables;
/// Get the sampled images for a specific frame index.
[[nodiscard]] const auto& getSampledImagesAt(size_t index) const {
return this->set(index).sampled;
}
/// Get the writable images for a specific frame index.
[[nodiscard]] const auto& writablesAt(size_t index) const {
return this->set(index).writables;
/// Get the storage images for a specific frame index.
[[nodiscard]] const auto& getStorageImagesAt(size_t index) const {
return this->set(index).storage;
}
private:
struct Set {
Core::DescriptorSet sets;
std::vector<std::optional<Core::Image>> readables;
std::vector<Core::Image> writables;
std::vector<std::optional<Core::Image>> sampled;
std::vector<Core::Image> storage;
};
std::vector<Set> sets;
@ -87,85 +87,85 @@ namespace VK::Helper {
return *this;
}
/// Add an input image to the descriptor.
MultiSetBuilder& addInput(const Core::Image& image) {
/// Add a sampled image to the descriptor.
MultiSetBuilder& addSampledImage(const Core::Image& image) {
for (auto& recipe : this->recipes)
recipe.inImages.emplace_back(image);
recipe.sampled.emplace_back(image);
return *this;
}
/// Add an optional input image to the descriptor.
MultiSetBuilder& addInput(const std::optional<Core::Image>& image) {
/// Add an optional sampled image to the descriptor.
MultiSetBuilder& addSampledImage(const std::optional<Core::Image>& image) {
for (auto& recipe : this->recipes)
recipe.inImages.emplace_back(image);
recipe.sampled.emplace_back(image);
return *this;
}
/// Add multiple input images to the descriptor.
MultiSetBuilder& addInput(const std::vector<Core::Image>& images) {
/// Add multiple sampled images to the descriptor.
MultiSetBuilder& addSampledImage(const std::vector<Core::Image>& images) {
for (auto& recipe : this->recipes)
for (const auto& img : images)
recipe.inImages.emplace_back(img);
recipe.sampled.emplace_back(img);
return *this;
}
/// Add a temporal input image to the descriptor.
MultiSetBuilder& addInput(const TemporalImage& temporalImage, size_t offset = 0) {
/// Add a temporal sampled image to the descriptor.
MultiSetBuilder& addSampledImage(const TemporalImage& temporalImage, size_t offset = 0) {
for (auto& recipe : this->recipes)
recipe.inImages.emplace_back(temporalImage.at(offset++));
recipe.sampled.emplace_back(temporalImage.at(offset++));
return *this;
}
/// Add a group of input images to the descriptor.
MultiSetBuilder& addInput(const ImageGroup& imageGroup) {
this->addInput(imageGroup.into());
/// Add a group of sampled images to the descriptor.
MultiSetBuilder& addSampledImage(const ImageGroup& imageGroup) {
this->addSampledImage(imageGroup.into());
return *this;
}
/// Add a subgroup of input images to the descriptor.
MultiSetBuilder& addInput(const ImageGroup& imageGroup, size_t start, size_t length) {
this->addInput(imageGroup.subGroup(start, length));
/// Add a subgroup of sampled images to the descriptor.
MultiSetBuilder& addSampledImage(const ImageGroup& imageGroup, size_t start, size_t length) {
this->addSampledImage(imageGroup.subGroup(start, length));
return *this;
}
/// Add all mipmapped images to the descriptor.
MultiSetBuilder& addInput(const Helper::MipmappedImage& mipmappedImage) {
this->addInput(mipmappedImage.into());
MultiSetBuilder& addSampledImage(const Helper::MipmappedImage& mipmappedImage) {
this->addSampledImage(mipmappedImage.into());
return *this;
}
/// Add an output image to the descriptor.
MultiSetBuilder& addOutput(const Core::Image& image) {
/// Add a storage image to the descriptor.
MultiSetBuilder& addStorageImage(const Core::Image& image) {
for (auto& recipe : this->recipes)
recipe.outImages.push_back(image);
recipe.storage.push_back(image);
return *this;
}
/// Add multiple output images to the descriptor.
MultiSetBuilder& addOutput(const std::vector<Core::Image>& images) {
/// Add multiple storage images to the descriptor.
MultiSetBuilder& addStorageImage(const std::vector<Core::Image>& images) {
for (auto& recipe : this->recipes)
for (const auto& img : images)
recipe.outImages.push_back(img);
recipe.storage.push_back(img);
return *this;
}
/// Add a temporal output image to the descriptor.
MultiSetBuilder& addOutput(const TemporalImage& temporalImage, size_t offset = 0) {
/// Add a temporal storage image to the descriptor.
MultiSetBuilder& addStorageImage(const TemporalImage& temporalImage, size_t offset = 0) {
for (auto& recipe : this->recipes)
recipe.outImages.push_back(temporalImage.at(offset++));
recipe.storage.push_back(temporalImage.at(offset++));
return *this;
}
/// Add a group of output images to the descriptor.
MultiSetBuilder& addOutput(const ImageGroup& imageGroup) {
this->addOutput(imageGroup.into());
/// Add a group of storage images to the descriptor.
MultiSetBuilder& addStorageImage(const ImageGroup& imageGroup) {
this->addStorageImage(imageGroup.into());
return *this;
}
/// Add a subgroup of output images to the descriptor.
MultiSetBuilder& addOutput(const ImageGroup& imageGroup, size_t start, size_t length) {
this->addOutput(imageGroup.subGroup(start, length));
/// Add a subgroup of storage images to the descriptor.
MultiSetBuilder& addStorageImage(const ImageGroup& imageGroup, size_t start, size_t length) {
this->addStorageImage(imageGroup.subGroup(start, length));
return *this;
}
/// Add all mipmapped images to the descriptor.
MultiSetBuilder& addOutput(const Helper::MipmappedImage& mipmappedImage) {
this->addOutput(mipmappedImage.into());
MultiSetBuilder& addStorageImage(const Helper::MipmappedImage& mipmappedImage) {
this->addStorageImage(mipmappedImage.into());
return *this;
}
@ -186,8 +186,8 @@ namespace VK::Helper {
std::optional<Core::Buffer> buffer;
std::vector<Core::Sampler> samplers;
struct SetRecipe {
std::vector<std::optional<Core::Image>> inImages;
std::vector<Core::Image> outImages;
std::vector<std::optional<Core::Image>> sampled;
std::vector<Core::Image> storage;
};
std::vector<SetRecipe> recipes;
};

View file

@ -78,23 +78,24 @@ void CommandBuffer::bindDescriptorSet(const Pipeline& pipeline, const Descriptor
}
void CommandBuffer::insertBarrier(
const std::vector<VkImage>& images) const {
const std::vector<Core::Image>& images) const {
if (*this->state != CommandBufferState::Recording)
throw std::logic_error("Command buffer is not in Recording state");
std::vector<VkImageMemoryBarrier2> barriers(images.size());
for (size_t i = 0; i < images.size(); i++) {
barriers[i] = {
std::vector<VkImageMemoryBarrier2> barriers;
barriers.reserve(images.size());
for (const auto& image : images) {
barriers.push_back({
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.image = images[i],
.image = image.handle(),
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1
}
};
});
}
const VkDependencyInfo dependencyInfo = {
@ -106,8 +107,8 @@ void CommandBuffer::insertBarrier(
}
void CommandBuffer::insertBarrier(
const std::vector<std::optional<Core::Image>>& readableImages,
const std::vector<Core::Image>& writableImages) const {
const std::vector<std::optional<Core::Image>>& sampledImages,
const std::vector<Core::Image>& storageImages) const {
if (*this->state != CommandBufferState::Recording)
throw std::logic_error("Command buffer is not in Recording state");
@ -123,11 +124,11 @@ void CommandBuffer::insertBarrier(
}
};
const size_t totalImages = readableImages.size() + writableImages.size();
const size_t totalImages = sampledImages.size() + storageImages.size();
std::vector<VkImageMemoryBarrier2> barriers;
barriers.reserve(totalImages);
for (const auto& image : readableImages) {
for (const auto& image : sampledImages) {
if (!image.has_value())
continue;
VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier);
@ -136,7 +137,7 @@ void CommandBuffer::insertBarrier(
barrier.image = image->handle();
}
for (const auto& image : writableImages) {
for (const auto& image : storageImages) {
VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier);
barrier.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT;
@ -215,8 +216,10 @@ void CommandBuffer::submit(const Device& device, std::optional<Fence> fence,
throw std::logic_error("Command buffer is not in Full state");
// create wait semaphores and values
std::vector<VkSemaphore> waitSemaphores(waitTimelines.size() + wait.size());
std::vector<uint64_t> waitSemaphoreValues(waitTimelines.size() + wait.size());
std::vector<VkSemaphore> waitSemaphores;
waitSemaphores.reserve(waitTimelines.size() + wait.size());
std::vector<uint64_t> waitSemaphoreValues;
waitSemaphoreValues.reserve(waitTimelines.size() + wait.size());
for (const auto& entry : waitTimelines) {
waitSemaphores.push_back(entry.first.handle());
waitSemaphoreValues.push_back(entry.second);
@ -225,8 +228,10 @@ void CommandBuffer::submit(const Device& device, std::optional<Fence> fence,
waitSemaphores.push_back(semaphore.handle());
// create signal semaphores and values
std::vector<VkSemaphore> signalSemaphores(signalTimelines.size() + signal.size());
std::vector<uint64_t> signalSemaphoreValues(signalTimelines.size() + signal.size());
std::vector<VkSemaphore> signalSemaphores;
signalSemaphores.reserve(signalTimelines.size() + signal.size());
std::vector<uint64_t> signalSemaphoreValues;
signalSemaphoreValues.reserve(signalTimelines.size() + signal.size());
for (const auto& entry : signalTimelines) {
signalSemaphores.push_back(entry.first.handle());
signalSemaphoreValues.push_back(entry.second);

View file

@ -74,12 +74,12 @@ DescriptorSet::DescriptorSet(const Device& device,
}))
});
size_t inputIdx{32};
size_t sampledIdx{32};
for (const auto& img : sampledImages) {
entries.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSetHandle,
.dstBinding = static_cast<uint32_t>(inputIdx++),
.dstBinding = static_cast<uint32_t>(sampledIdx++),
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.pImageInfo = &(imageInfos.emplace_back(VkDescriptorImageInfo{
@ -90,12 +90,12 @@ DescriptorSet::DescriptorSet(const Device& device,
});
}
size_t outputIdx{48};
size_t storageIdx{48};
for (const auto& img : storageImages)
entries.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSetHandle,
.dstBinding = static_cast<uint32_t>(outputIdx++),
.dstBinding = static_cast<uint32_t>(storageIdx++),
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &(imageInfos.emplace_back(VkDescriptorImageInfo{

View file

@ -34,7 +34,7 @@ ShaderModule::ShaderModule(const Device& device, const std::vector<uint8_t>& cod
layoutBindings.reserve(buffers + samplers + sampledImages + storageImages);
for (size_t i = 0; i < buffers; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding {
layoutBindings.push_back({
.binding = static_cast<uint32_t>(i),
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
@ -42,7 +42,7 @@ ShaderModule::ShaderModule(const Device& device, const std::vector<uint8_t>& cod
});
for (size_t i = 0; i < samplers; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding {
layoutBindings.push_back({
.binding = static_cast<uint32_t>(i + 16),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = 1,
@ -50,7 +50,7 @@ ShaderModule::ShaderModule(const Device& device, const std::vector<uint8_t>& cod
});
for (size_t i = 0; i < sampledImages; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding {
layoutBindings.push_back({
.binding = static_cast<uint32_t>(i + 32),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 1,
@ -58,7 +58,7 @@ ShaderModule::ShaderModule(const Device& device, const std::vector<uint8_t>& cod
});
for (size_t i = 0; i < storageImages; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding {
layoutBindings.push_back({
.binding = static_cast<uint32_t>(i + 48),
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.descriptorCount = 1,

View file

@ -17,9 +17,9 @@ MultiSet MultiSetBuilder::build(
for (const auto& recipe : this->recipes)
multiset.sets.push_back({
.sets = Core::DescriptorSet(device, pool, shader,
recipe.inImages, recipe.outImages, this->samplers, this->buffer),
.readables = recipe.inImages,
.writables = recipe.outImages
recipe.sampled, recipe.storage, this->samplers, this->buffer),
.sampled = recipe.sampled,
.storage = recipe.storage
});
return multiset;