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

View file

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

View file

@ -78,23 +78,24 @@ void CommandBuffer::bindDescriptorSet(const Pipeline& pipeline, const Descriptor
} }
void CommandBuffer::insertBarrier( void CommandBuffer::insertBarrier(
const std::vector<VkImage>& images) const { const std::vector<Core::Image>& images) const {
if (*this->state != CommandBufferState::Recording) if (*this->state != CommandBufferState::Recording)
throw std::logic_error("Command buffer is not in Recording state"); throw std::logic_error("Command buffer is not in Recording state");
std::vector<VkImageMemoryBarrier2> barriers(images.size()); std::vector<VkImageMemoryBarrier2> barriers;
for (size_t i = 0; i < images.size(); i++) { barriers.reserve(images.size());
barriers[i] = { for (const auto& image : images) {
barriers.push_back({
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.image = images[i], .image = image.handle(),
.subresourceRange = { .subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1, .levelCount = 1,
.layerCount = 1 .layerCount = 1
} }
}; });
} }
const VkDependencyInfo dependencyInfo = { const VkDependencyInfo dependencyInfo = {
@ -106,8 +107,8 @@ void CommandBuffer::insertBarrier(
} }
void CommandBuffer::insertBarrier( void CommandBuffer::insertBarrier(
const std::vector<std::optional<Core::Image>>& readableImages, const std::vector<std::optional<Core::Image>>& sampledImages,
const std::vector<Core::Image>& writableImages) const { const std::vector<Core::Image>& storageImages) const {
if (*this->state != CommandBufferState::Recording) if (*this->state != CommandBufferState::Recording)
throw std::logic_error("Command buffer is not in Recording state"); 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; std::vector<VkImageMemoryBarrier2> barriers;
barriers.reserve(totalImages); barriers.reserve(totalImages);
for (const auto& image : readableImages) { for (const auto& image : sampledImages) {
if (!image.has_value()) if (!image.has_value())
continue; continue;
VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier); VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier);
@ -136,7 +137,7 @@ void CommandBuffer::insertBarrier(
barrier.image = image->handle(); barrier.image = image->handle();
} }
for (const auto& image : writableImages) { for (const auto& image : storageImages) {
VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier); VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier);
barrier.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT; barrier.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_2_SHADER_WRITE_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"); throw std::logic_error("Command buffer is not in Full state");
// create wait semaphores and values // create wait semaphores and values
std::vector<VkSemaphore> waitSemaphores(waitTimelines.size() + wait.size()); std::vector<VkSemaphore> waitSemaphores;
std::vector<uint64_t> waitSemaphoreValues(waitTimelines.size() + wait.size()); waitSemaphores.reserve(waitTimelines.size() + wait.size());
std::vector<uint64_t> waitSemaphoreValues;
waitSemaphoreValues.reserve(waitTimelines.size() + wait.size());
for (const auto& entry : waitTimelines) { for (const auto& entry : waitTimelines) {
waitSemaphores.push_back(entry.first.handle()); waitSemaphores.push_back(entry.first.handle());
waitSemaphoreValues.push_back(entry.second); waitSemaphoreValues.push_back(entry.second);
@ -225,8 +228,10 @@ void CommandBuffer::submit(const Device& device, std::optional<Fence> fence,
waitSemaphores.push_back(semaphore.handle()); waitSemaphores.push_back(semaphore.handle());
// create signal semaphores and values // create signal semaphores and values
std::vector<VkSemaphore> signalSemaphores(signalTimelines.size() + signal.size()); std::vector<VkSemaphore> signalSemaphores;
std::vector<uint64_t> signalSemaphoreValues(signalTimelines.size() + signal.size()); signalSemaphores.reserve(signalTimelines.size() + signal.size());
std::vector<uint64_t> signalSemaphoreValues;
signalSemaphoreValues.reserve(signalTimelines.size() + signal.size());
for (const auto& entry : signalTimelines) { for (const auto& entry : signalTimelines) {
signalSemaphores.push_back(entry.first.handle()); signalSemaphores.push_back(entry.first.handle());
signalSemaphoreValues.push_back(entry.second); 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) { for (const auto& img : sampledImages) {
entries.push_back({ entries.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSetHandle, .dstSet = descriptorSetHandle,
.dstBinding = static_cast<uint32_t>(inputIdx++), .dstBinding = static_cast<uint32_t>(sampledIdx++),
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.pImageInfo = &(imageInfos.emplace_back(VkDescriptorImageInfo{ .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) for (const auto& img : storageImages)
entries.push_back({ entries.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSetHandle, .dstSet = descriptorSetHandle,
.dstBinding = static_cast<uint32_t>(outputIdx++), .dstBinding = static_cast<uint32_t>(storageIdx++),
.descriptorCount = 1, .descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &(imageInfos.emplace_back(VkDescriptorImageInfo{ .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); layoutBindings.reserve(buffers + samplers + sampledImages + storageImages);
for (size_t i = 0; i < buffers; i++) for (size_t i = 0; i < buffers; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding { layoutBindings.push_back({
.binding = static_cast<uint32_t>(i), .binding = static_cast<uint32_t>(i),
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1, .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++) for (size_t i = 0; i < samplers; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding { layoutBindings.push_back({
.binding = static_cast<uint32_t>(i + 16), .binding = static_cast<uint32_t>(i + 16),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
.descriptorCount = 1, .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++) for (size_t i = 0; i < sampledImages; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding { layoutBindings.push_back({
.binding = static_cast<uint32_t>(i + 32), .binding = static_cast<uint32_t>(i + 32),
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 1, .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++) for (size_t i = 0; i < storageImages; i++)
layoutBindings.emplace_back(VkDescriptorSetLayoutBinding { layoutBindings.push_back({
.binding = static_cast<uint32_t>(i + 48), .binding = static_cast<uint32_t>(i + 48),
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.descriptorCount = 1, .descriptorCount = 1,

View file

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