From 42a692cd6206ff0e67e34e65a6aca26b71213622 Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Mon, 30 Jun 2025 07:49:11 +0200 Subject: [PATCH] remaining shaderchains --- include/core/descriptorset.hpp | 6 +- include/shaderchains/delta.hpp | 2 +- include/shaderchains/gamma.hpp | 2 +- include/shaderchains/magic.hpp | 6 +- src/shaderchains/alpha.cpp | 16 +-- src/shaderchains/beta.cpp | 161 +++++++++++++++++++++++ src/shaderchains/delta.cpp | 138 ++++++++++++++++++++ src/shaderchains/epsilon.cpp | 139 ++++++++++++++++++++ src/shaderchains/gamma.cpp | 227 +++++++++++++++++++++++++++++++++ src/shaderchains/magic.cpp | 8 +- src/shaderchains/zeta.cpp | 139 ++++++++++++++++++++ 11 files changed, 824 insertions(+), 20 deletions(-) create mode 100644 src/shaderchains/beta.cpp create mode 100644 src/shaderchains/delta.cpp create mode 100644 src/shaderchains/epsilon.cpp create mode 100644 src/shaderchains/gamma.cpp create mode 100644 src/shaderchains/zeta.cpp diff --git a/include/core/descriptorset.hpp b/include/core/descriptorset.hpp index 3bbacbb..4f0d2b3 100644 --- a/include/core/descriptorset.hpp +++ b/include/core/descriptorset.hpp @@ -100,11 +100,11 @@ namespace Vulkan::Core { /// Add an optional resource to the descriptor set update. DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional& image) { - if (image.has_value()) this->add(type, *image); return *this; } + if (image.has_value()) this->add(type, *image); else this->add(type); return *this; } DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional& sampler) { - if (sampler.has_value()) this->add(type, *sampler); return *this; } + if (sampler.has_value()) this->add(type, *sampler); else this->add(type); return *this; } DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional& buffer) { - if (buffer.has_value()) this->add(type, *buffer); return *this; } + if (buffer.has_value()) this->add(type, *buffer); else this->add(type); return *this; } /// Finish building the descriptor set update. void build() const; diff --git a/include/shaderchains/delta.hpp b/include/shaderchains/delta.hpp index c880e90..dcb561b 100644 --- a/include/shaderchains/delta.hpp +++ b/include/shaderchains/delta.hpp @@ -60,7 +60,7 @@ namespace Vulkan::Shaderchains { std::array descriptorSets; Core::Buffer buffer; - std::array inImg; + std::array inImgs; std::optional optImg; std::array tempImgs1; diff --git a/include/shaderchains/gamma.hpp b/include/shaderchains/gamma.hpp index dad16c0..d819760 100644 --- a/include/shaderchains/gamma.hpp +++ b/include/shaderchains/gamma.hpp @@ -42,7 +42,7 @@ namespace Vulkan::Shaderchains { std::array temporalImgs, std::array inImgs1, Core::Image inImg2, - std::optional optImg1, + std::optional& optImg1, std::optional optImg2, VkExtent2D outExtent); diff --git a/include/shaderchains/magic.hpp b/include/shaderchains/magic.hpp index 6de4525..7c21cb8 100644 --- a/include/shaderchains/magic.hpp +++ b/include/shaderchains/magic.hpp @@ -36,8 +36,8 @@ namespace Vulkan::Shaderchains { /// @throws ls::vulkan_error if resource creation fails. /// Magic(const Device& device, const Core::DescriptorPool& pool, - std::array& temporalImgs, - std::array& inImgs1, + std::array temporalImgs, + std::array inImgs1, Core::Image inImg2, Core::Image inImg3, std::optional optImg); @@ -76,7 +76,7 @@ namespace Vulkan::Shaderchains { Core::Image inImg3; std::optional optImg; - std::array outImgs1; + std::array outImgs1; std::array outImgs2; std::array outImgs3; }; diff --git a/src/shaderchains/alpha.cpp b/src/shaderchains/alpha.cpp index 8bd270e..325dc2c 100644 --- a/src/shaderchains/alpha.cpp +++ b/src/shaderchains/alpha.cpp @@ -9,20 +9,20 @@ Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool, this->shaderModules = {{ Core::ShaderModule(device, "rsc/shaders/alpha/0.spv", { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, - { 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, - { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }), + { 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }), Core::ShaderModule(device, "rsc/shaders/alpha/1.spv", { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, - { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, - { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }), + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }), Core::ShaderModule(device, "rsc/shaders/alpha/2.spv", { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, - { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, - { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }), + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }), Core::ShaderModule(device, "rsc/shaders/alpha/3.spv", { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, - { 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, - { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }) + { 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }) }}; for (size_t i = 0; i < 4; i++) { this->pipelines.at(i) = Core::Pipeline(device, diff --git a/src/shaderchains/beta.cpp b/src/shaderchains/beta.cpp new file mode 100644 index 0000000..0e4659e --- /dev/null +++ b/src/shaderchains/beta.cpp @@ -0,0 +1,161 @@ +#include "shaderchains/beta.hpp" +#include "utils.hpp" + +using namespace Vulkan::Shaderchains; + +Beta::Beta(const Device& device, const Core::DescriptorPool& pool, + std::array temporalImgs, + std::array inImgs) + : temporalImgs(std::move(temporalImgs)), + inImgs(std::move(inImgs)) { + this->shaderModules = {{ + Core::ShaderModule(device, "rsc/shaders/beta/0.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 8+4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/beta/1.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/beta/2.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/beta/3.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/beta/4.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }) + }}; + for (size_t i = 0; i < 5; i++) { + this->pipelines.at(i) = Core::Pipeline(device, + this->shaderModules.at(i)); + this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, + this->shaderModules.at(i)); + } + this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + const auto extent = this->temporalImgs.at(0).getExtent(); + + for (size_t i = 0; i < 2; i++) { + this->tempImgs1.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + this->tempImgs2.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + + for (size_t i = 0; i < 6; i++) { + this->outImgs.at(i) = Core::Image(device, + { extent.width >> i, extent.height >> i }, + VK_FORMAT_R8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + + this->descriptorSets.at(0).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->temporalImgs) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(1).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(2).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(3).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(4).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); +} + +void Beta::Dispatch(const Core::CommandBuffer& buf) { + const auto extent = this->tempImgs1.at(0).getExtent(); + + // first pass + uint32_t threadsX = (extent.width + 7) >> 3; + uint32_t threadsY = (extent.height + 7) >> 3; + + Utils::BarrierBuilder(buf) + .addW2R(this->temporalImgs) + .addW2R(this->inImgs) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(0).bind(buf); + this->descriptorSets.at(0).bind(buf, this->pipelines.at(0)); + buf.dispatch(threadsX, threadsY, 1); + + // second pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(1).bind(buf); + this->descriptorSets.at(1).bind(buf, this->pipelines.at(1)); + buf.dispatch(threadsX, threadsY, 1); + + // third pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(2).bind(buf); + this->descriptorSets.at(2).bind(buf, this->pipelines.at(2)); + buf.dispatch(threadsX, threadsY, 1); + + // fourth pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(3).bind(buf); + this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); + buf.dispatch(threadsX, threadsY, 1); + + // fifth pass + threadsX = (extent.width + 31) >> 5; + threadsY = (extent.height + 31) >> 5; + + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addR2W(this->outImgs) + .build(); + + this->pipelines.at(4).bind(buf); + this->descriptorSets.at(4).bind(buf, this->pipelines.at(4)); + buf.dispatch(threadsX, threadsY, 1); +} diff --git a/src/shaderchains/delta.cpp b/src/shaderchains/delta.cpp new file mode 100644 index 0000000..340d00a --- /dev/null +++ b/src/shaderchains/delta.cpp @@ -0,0 +1,138 @@ +#include "shaderchains/delta.hpp" +#include "utils.hpp" + +using namespace Vulkan::Shaderchains; + +Delta::Delta(const Device& device, const Core::DescriptorPool& pool, + std::array inImgs, + std::optional optImg) + : inImgs(std::move(inImgs)), + optImg(std::move(optImg)) { + this->shaderModules = {{ + Core::ShaderModule(device, "rsc/shaders/delta/0.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/delta/1.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/delta/2.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/delta/3.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }) + }}; + for (size_t i = 0; i < 4; i++) { + this->pipelines.at(i) = Core::Pipeline(device, + this->shaderModules.at(i)); + this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, + this->shaderModules.at(i)); + } + + Globals::FgBuffer data = Globals::fgBuffer; + data.firstIterS = !this->optImg.has_value(); + this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + const auto extent = this->inImgs.at(0).getExtent(); + + for (size_t i = 0; i < 2; i++) { + this->tempImgs1.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + this->tempImgs2.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + + this->outImg = Core::Image(device, + extent, + VK_FORMAT_R16G16B16A16_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + this->descriptorSets.at(0).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(1).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(2).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(3).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); +} + +void Delta::Dispatch(const Core::CommandBuffer& buf) { + const auto extent = this->tempImgs1.at(0).getExtent(); + + // first pass + const uint32_t threadsX = (extent.width + 7) >> 3; + const uint32_t threadsY = (extent.height + 7) >> 3; + + Utils::BarrierBuilder(buf) + .addW2R(this->inImgs) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(0).bind(buf); + this->descriptorSets.at(0).bind(buf, this->pipelines.at(0)); + buf.dispatch(threadsX, threadsY, 1); + + // second pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(1).bind(buf); + this->descriptorSets.at(1).bind(buf, this->pipelines.at(1)); + buf.dispatch(threadsX, threadsY, 1); + + // third pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(2).bind(buf); + this->descriptorSets.at(2).bind(buf, this->pipelines.at(2)); + buf.dispatch(threadsX, threadsY, 1); + + // fourth pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addW2R(this->optImg) + .addR2W(this->outImg) + .build(); + + this->pipelines.at(3).bind(buf); + this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); + buf.dispatch(threadsX, threadsY, 1); +} diff --git a/src/shaderchains/epsilon.cpp b/src/shaderchains/epsilon.cpp new file mode 100644 index 0000000..77d4269 --- /dev/null +++ b/src/shaderchains/epsilon.cpp @@ -0,0 +1,139 @@ +#include "shaderchains/epsilon.hpp" +#include "utils.hpp" + +using namespace Vulkan::Shaderchains; + +Epsilon::Epsilon(const Device& device, const Core::DescriptorPool& pool, + std::array inImgs1, + Core::Image inImg2, + std::optional optImg) + : inImgs1(std::move(inImgs1)), + inImg2(std::move(inImg2)), + optImg(std::move(optImg)) { + this->shaderModules = {{ + Core::ShaderModule(device, "rsc/shaders/epsilon/0.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/epsilon/1.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/epsilon/2.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/epsilon/3.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }) + }}; + for (size_t i = 0; i < 4; i++) { + this->pipelines.at(i) = Core::Pipeline(device, + this->shaderModules.at(i)); + this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, + this->shaderModules.at(i)); + } + this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + const auto extent = this->inImgs1.at(0).getExtent(); + + for (size_t i = 0; i < 4; i++) { + this->tempImgs1.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + this->tempImgs2.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + + this->outImg = Core::Image(device, + extent, + VK_FORMAT_R16G16B16A16_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + this->descriptorSets.at(0).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(1).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(2).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(3).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); +} + +void Epsilon::Dispatch(const Core::CommandBuffer& buf) { + const auto extent = this->tempImgs1.at(0).getExtent(); + + // first pass + const uint32_t threadsX = (extent.width + 7) >> 3; + const uint32_t threadsY = (extent.height + 7) >> 3; + + Utils::BarrierBuilder(buf) + .addW2R(this->inImgs1) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(0).bind(buf); + this->descriptorSets.at(0).bind(buf, this->pipelines.at(0)); + buf.dispatch(threadsX, threadsY, 1); + + // second pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(1).bind(buf); + this->descriptorSets.at(1).bind(buf, this->pipelines.at(1)); + buf.dispatch(threadsX, threadsY, 1); + + // third pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(2).bind(buf); + this->descriptorSets.at(2).bind(buf, this->pipelines.at(2)); + buf.dispatch(threadsX, threadsY, 1); + + // fourth pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addW2R(this->optImg) + .addW2R(this->inImg2) + .addR2W(this->outImg) + .build(); + + this->pipelines.at(3).bind(buf); + this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); + buf.dispatch(threadsX, threadsY, 1); +} diff --git a/src/shaderchains/gamma.cpp b/src/shaderchains/gamma.cpp new file mode 100644 index 0000000..bef9de0 --- /dev/null +++ b/src/shaderchains/gamma.cpp @@ -0,0 +1,227 @@ +#include "shaderchains/gamma.hpp" +#include "utils.hpp" + +using namespace Vulkan::Shaderchains; + +Gamma::Gamma(const Device& device, const Core::DescriptorPool& pool, + std::array temporalImgs, + std::array inImgs1, + Core::Image inImg2, + std::optional& optImg1, + std::optional optImg2, + VkExtent2D outExtent) + : temporalImgs(std::move(temporalImgs)), + inImgs1(std::move(inImgs1)), + inImg2(std::move(inImg2)), + optImg2(std::move(optImg2)) { + this->shaderModules = {{ + Core::ShaderModule(device, "rsc/shaders/gamma/0.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 8+4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/gamma/1.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/gamma/2.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/gamma/3.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/gamma/4.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/gamma/5.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }) + }}; + for (size_t i = 0; i < 6; i++) { + this->pipelines.at(i) = Core::Pipeline(device, + this->shaderModules.at(i)); + this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, + this->shaderModules.at(i)); + } + + Globals::FgBuffer data = Globals::fgBuffer; + data.firstIter = !optImg1.has_value(); + this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + const auto extent = this->temporalImgs.at(0).getExtent(); + + this->optImg1 = optImg1.value_or(Core::Image(device, extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + VK_IMAGE_ASPECT_COLOR_BIT)); + + for (size_t i = 0; i < 4; i++) { + this->tempImgs1.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + this->tempImgs2.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + this->whiteImg = Core::Image(device, outExtent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + this->outImg1 = Core::Image(device, + extent, + VK_FORMAT_R16G16B16A16_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + this->outImg2 = Core::Image(device, + outExtent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + this->descriptorSets.at(0).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->temporalImgs) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0)) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1)) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(2)) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(1).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(0)) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(1)) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(2)) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(2).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(3).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(4).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(5).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->outImg1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + + // clear white image + Utils::clearWhiteImage(device, this->whiteImg); +} + +void Gamma::Dispatch(const Core::CommandBuffer& buf) { + const auto extent = this->tempImgs1.at(0).getExtent(); + + // first pass + uint32_t threadsX = (extent.width + 7) >> 3; + uint32_t threadsY = (extent.height + 7) >> 3; + + Utils::BarrierBuilder(buf) + .addW2R(this->temporalImgs) + .addW2R(this->inImgs1) + .addW2R(this->optImg1) + .addW2R(this->optImg2) + .addR2W(this->tempImgs1.at(0)) + .addR2W(this->tempImgs1.at(1)) + .addR2W(this->tempImgs1.at(2)) + .build(); + + this->pipelines.at(0).bind(buf); + this->descriptorSets.at(0).bind(buf, this->pipelines.at(0)); + buf.dispatch(threadsX, threadsY, 1); + + // second pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1.at(0)) + .addW2R(this->tempImgs1.at(1)) + .addW2R(this->tempImgs1.at(2)) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(1).bind(buf); + this->descriptorSets.at(1).bind(buf, this->pipelines.at(1)); + buf.dispatch(threadsX, threadsY, 1); + + // third pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(2).bind(buf); + this->descriptorSets.at(2).bind(buf, this->pipelines.at(2)); + buf.dispatch(threadsX, threadsY, 1); + + // fourth pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(3).bind(buf); + this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); + buf.dispatch(threadsX, threadsY, 1); + + // fifth pass + threadsX = (extent.width + 31) >> 5; + threadsY = (extent.height + 31) >> 5; + + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addW2R(this->optImg2) + .addW2R(this->inImg2) + .addR2W(this->outImg1) + .build(); + + this->pipelines.at(4).bind(buf); + this->descriptorSets.at(4).bind(buf, this->pipelines.at(4)); + buf.dispatch(threadsX, threadsY, 1); + + // sixth pass + threadsX = (extent.width + 3) >> 2; + threadsY = (extent.height + 3) >> 2; + + Utils::BarrierBuilder(buf) + .addW2R(this->whiteImg) + .addW2R(this->outImg1) + .addR2W(this->outImg2) + .build(); + + this->pipelines.at(5).bind(buf); + this->descriptorSets.at(5).bind(buf, this->pipelines.at(5)); + buf.dispatch(threadsX, threadsY, 1); +} diff --git a/src/shaderchains/magic.cpp b/src/shaderchains/magic.cpp index da77a8c..4eb1c42 100644 --- a/src/shaderchains/magic.cpp +++ b/src/shaderchains/magic.cpp @@ -4,8 +4,8 @@ using namespace Vulkan::Shaderchains; Magic::Magic(const Device& device, const Core::DescriptorPool& pool, - std::array& temporalImgs, - std::array& inImgs1, + std::array temporalImgs, + std::array inImgs1, Core::Image inImg2, Core::Image inImg3, std::optional optImg) @@ -22,10 +22,10 @@ Magic::Magic(const Device& device, const Core::DescriptorPool& pool, this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); Globals::FgBuffer data = Globals::fgBuffer; - data.firstIterS = !optImg.has_value(); + data.firstIterS = !this->optImg.has_value(); this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - auto extent = temporalImgs.at(0).getExtent(); + auto extent = this->temporalImgs.at(0).getExtent(); for (size_t i = 0; i < 2; i++) this->outImgs1.at(i) = Core::Image(device, diff --git a/src/shaderchains/zeta.cpp b/src/shaderchains/zeta.cpp new file mode 100644 index 0000000..d614a53 --- /dev/null +++ b/src/shaderchains/zeta.cpp @@ -0,0 +1,139 @@ +#include "shaderchains/zeta.hpp" +#include "utils.hpp" + +using namespace Vulkan::Shaderchains; + +Zeta::Zeta(const Device& device, const Core::DescriptorPool& pool, + std::array inImgs1, + Core::Image inImg2, + Core::Image inImg3) + : inImgs1(std::move(inImgs1)), + inImg2(std::move(inImg2)), + inImg3(std::move(inImg3)) { + this->shaderModules = {{ + Core::ShaderModule(device, "rsc/shaders/zeta/0.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/zeta/1.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/zeta/2.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }), + Core::ShaderModule(device, "rsc/shaders/zeta/3.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }) + }}; + for (size_t i = 0; i < 4; i++) { + this->pipelines.at(i) = Core::Pipeline(device, + this->shaderModules.at(i)); + this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, + this->shaderModules.at(i)); + } + this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + const auto extent = this->inImgs1.at(0).getExtent(); + + for (size_t i = 0; i < 4; i++) { + this->tempImgs1.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + this->tempImgs2.at(i) = Core::Image(device, + extent, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + + this->outImg = Core::Image(device, + extent, + VK_FORMAT_R16G16B16A16_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + this->descriptorSets.at(0).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(1).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(2).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); + this->descriptorSets.at(3).update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); +} + +void Zeta::Dispatch(const Core::CommandBuffer& buf) { + const auto extent = this->tempImgs1.at(0).getExtent(); + + // first pass + const uint32_t threadsX = (extent.width + 7) >> 3; + const uint32_t threadsY = (extent.height + 7) >> 3; + + Utils::BarrierBuilder(buf) + .addW2R(this->inImgs1) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(0).bind(buf); + this->descriptorSets.at(0).bind(buf, this->pipelines.at(0)); + buf.dispatch(threadsX, threadsY, 1); + + // second pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addR2W(this->tempImgs2) + .build(); + + this->pipelines.at(1).bind(buf); + this->descriptorSets.at(1).bind(buf, this->pipelines.at(1)); + buf.dispatch(threadsX, threadsY, 1); + + // third pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs2) + .addR2W(this->tempImgs1) + .build(); + + this->pipelines.at(2).bind(buf); + this->descriptorSets.at(2).bind(buf, this->pipelines.at(2)); + buf.dispatch(threadsX, threadsY, 1); + + // fourth pass + Utils::BarrierBuilder(buf) + .addW2R(this->tempImgs1) + .addW2R(this->inImg2) + .addW2R(this->inImg3) + .addR2W(this->outImg) + .build(); + + this->pipelines.at(3).bind(buf); + this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); + buf.dispatch(threadsX, threadsY, 1); +}