From 50f5153374a7ea89eb1daac957aff6eb8a016ab4 Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Mon, 30 Jun 2025 05:27:41 +0200 Subject: [PATCH] initial extract, magic & merge shaderchains --- include/shaderchains/extract.hpp | 4 +- include/shaderchains/magic.hpp | 8 +-- include/shaderchains/merge.hpp | 10 ++-- src/shaderchains/extract.cpp | 65 ++++++++++++++++++++++++ src/shaderchains/magic.cpp | 84 ++++++++++++++++++++++++++++++++ src/shaderchains/merge.cpp | 69 ++++++++++++++++++++++++++ 6 files changed, 229 insertions(+), 11 deletions(-) create mode 100644 src/shaderchains/extract.cpp create mode 100644 src/shaderchains/magic.cpp create mode 100644 src/shaderchains/merge.cpp diff --git a/include/shaderchains/extract.hpp b/include/shaderchains/extract.hpp index b8677de..e70a8e0 100644 --- a/include/shaderchains/extract.hpp +++ b/include/shaderchains/extract.hpp @@ -33,8 +33,8 @@ namespace Vulkan::Shaderchains { /// @throws ls::vulkan_error if resource creation fails. /// Extract(const Device& device, const Core::DescriptorPool& pool, - const Core::Image& inImg1, - const Core::Image& inImg2, + Core::Image inImg1, + Core::Image inImg2, VkExtent2D outExtent); /// diff --git a/include/shaderchains/magic.hpp b/include/shaderchains/magic.hpp index 188df72..2d5f1cb 100644 --- a/include/shaderchains/magic.hpp +++ b/include/shaderchains/magic.hpp @@ -34,10 +34,10 @@ namespace Vulkan::Shaderchains { /// @throws ls::vulkan_error if resource creation fails. /// Magic(const Device& device, const Core::DescriptorPool& pool, - const std::array& temporalImgs, - const std::array& inImgs1, - const Core::Image& inImg2, - const Core::Image& inImg3, + const std::vector& temporalImgs, + const std::vector& inImgs1, + Core::Image inImg2, + Core::Image inImg3, const std::optional& optImg); /// diff --git a/include/shaderchains/merge.hpp b/include/shaderchains/merge.hpp index 520cd47..aeb229a 100644 --- a/include/shaderchains/merge.hpp +++ b/include/shaderchains/merge.hpp @@ -34,11 +34,11 @@ namespace Vulkan::Shaderchains { /// @throws ls::vulkan_error if resource creation fails. /// Merge(const Device& device, const Core::DescriptorPool& pool, - const Core::Image& inImg1, - const Core::Image& inImg2, - const Core::Image& inImg3, - const Core::Image& inImg4, - const Core::Image& inImg5); + Core::Image inImg1, + Core::Image inImg2, + Core::Image inImg3, + Core::Image inImg4, + Core::Image inImg5); /// /// Dispatch the shaderchain. diff --git a/src/shaderchains/extract.cpp b/src/shaderchains/extract.cpp new file mode 100644 index 0000000..3b12f92 --- /dev/null +++ b/src/shaderchains/extract.cpp @@ -0,0 +1,65 @@ +#include "shaderchains/extract.hpp" +#include "utils.hpp" +#include + +using namespace Vulkan::Shaderchains; + +Extract::Extract(const Device& device, const Core::DescriptorPool& pool, + Core::Image inImg1, + Core::Image inImg2, + VkExtent2D outExtent) + : inImg1(std::move(inImg1)), + inImg2(std::move(inImg2)) { + // create internal resources + this->shaderModule = Core::ShaderModule(device, "rsc/shaders/extract.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); + this->pipeline = Core::Pipeline(device, this->shaderModule); + this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); + + const Globals::FgBuffer data = Globals::fgBuffer; + this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + this->whiteImg = Core::Image(device, + { outExtent.width, outExtent.height }, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + // create output images + this->outImg = Core::Image(device, + { outExtent.width, outExtent.height }, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + // update descriptor set + this->descriptorSet.update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg1) + .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 Extract::Dispatch(const Core::CommandBuffer& buf) { + auto extent = this->whiteImg.getExtent(); + const uint32_t threadsX = (extent.width + 7) >> 3; + const uint32_t threadsY = (extent.height + 7) >> 3; + + // FIXME: clear to white + + Utils::insertBarrier( + buf, + { this->whiteImg, this->inImg1, this->inImg2 }, + { this->outImg } + ); + + this->pipeline.bind(buf); + this->descriptorSet.bind(buf, this->pipeline); + buf.dispatch(threadsX, threadsY, 1); +} diff --git a/src/shaderchains/magic.cpp b/src/shaderchains/magic.cpp new file mode 100644 index 0000000..3f641d4 --- /dev/null +++ b/src/shaderchains/magic.cpp @@ -0,0 +1,84 @@ +#include "shaderchains/magic.hpp" +#include "utils.hpp" + +using namespace Vulkan::Shaderchains; + +Magic::Magic(const Device& device, const Core::DescriptorPool& pool, + const std::vector& temporalImgs, + const std::vector& inImgs1, + Core::Image inImg2, + Core::Image inImg3, + const std::optional& optImg) + : temporalImgs(temporalImgs), inImgs1(inImgs1), + inImg2(std::move(inImg2)), inImg3(std::move(inImg3)), optImg(optImg) { + // create internal resources + this->shaderModule = Core::ShaderModule(device, "rsc/shaders/magic.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 4+4+2+1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 3+3+2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); + this->pipeline = Core::Pipeline(device, this->shaderModule); + this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); + + Globals::FgBuffer data = Globals::fgBuffer; + data.firstIterS = !optImg.has_value(); + this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + auto extent = temporalImgs.at(0).getExtent(); + + // create output images + for (size_t i = 0; i < 2; i++) + this->outImgs1.at(i) = Core::Image(device, + { extent.width, extent.height }, + 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 < 3; i++) + this->outImgs2.at(i) = Core::Image(device, + { extent.width, extent.height }, + 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 < 3; i++) + this->outImgs3.at(i) = Core::Image(device, + { extent.width, extent.height }, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + // update descriptor set + this->descriptorSet.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->inImg2) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *this->optImg) // FIXME: invalid resource + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs3) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs2) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs1) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); +} + +void Magic::Dispatch(const Core::CommandBuffer& buf) { + auto extent = this->temporalImgs.at(0).getExtent(); + const uint32_t threadsX = (extent.width + 7) >> 3; + const uint32_t threadsY = (extent.height + 7) >> 3; + + Utils::insertBarrier( + buf, + { this->temporalImgs.at(0), this->temporalImgs.at(1), + this->temporalImgs.at(2), this->temporalImgs.at(3), + this->inImgs1.at(0), this->inImgs1.at(1), + this->inImgs1.at(2), this->inImgs1.at(3), + this->inImg2, this->inImg3, *this->optImg }, // FIXME: invalid resource + { this->outImgs3.at(0), this->outImgs3.at(1), this->outImgs3.at(2), + this->outImgs2.at(0), this->outImgs2.at(1), this->outImgs2.at(2), + this->outImgs1.at(0), this->outImgs1.at(1) } + ); + + this->pipeline.bind(buf); + this->descriptorSet.bind(buf, this->pipeline); + buf.dispatch(threadsX, threadsY, 1); +} diff --git a/src/shaderchains/merge.cpp b/src/shaderchains/merge.cpp new file mode 100644 index 0000000..590779b --- /dev/null +++ b/src/shaderchains/merge.cpp @@ -0,0 +1,69 @@ +#include "shaderchains/merge.hpp" +#include "utils.hpp" +#include + +using namespace Vulkan::Shaderchains; + +Merge::Merge(const Device& device, const Core::DescriptorPool& pool, + Core::Image inImg1, + Core::Image inImg2, + Core::Image inImg3, + Core::Image inImg4, + Core::Image inImg5) + : inImg1(std::move(inImg1)), + inImg2(std::move(inImg2)), + inImg3(std::move(inImg3)), + inImg4(std::move(inImg4)), + inImg5(std::move(inImg5)) { + // create internal resources + this->shaderModule = Core::ShaderModule(device, "rsc/shaders/merge.spv", + { { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, + { 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); + this->pipeline = Core::Pipeline(device, this->shaderModule); + this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); + + const Globals::FgBuffer data = Globals::fgBuffer; + this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + auto extent = this->inImg1.getExtent(); + + // create output image + this->outImg = Core::Image(device, + { extent.width, extent.height }, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + + // update descriptor set + this->descriptorSet.update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg1) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg4) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg5) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) + .build(); +} + +void Merge::Dispatch(const Core::CommandBuffer& buf) { + auto extent = this->inImg1.getExtent(); + const uint32_t threadsX = (extent.width + 15) >> 4; + const uint32_t threadsY = (extent.height + 15) >> 4; + + // FIXME: clear to white + + Utils::insertBarrier( + buf, + { this->inImg1, this->inImg2, this->inImg3, + this->inImg4, this->inImg5 }, + { this->outImg } + ); + + this->pipeline.bind(buf); + this->descriptorSet.bind(buf, this->pipeline); + buf.dispatch(threadsX, threadsY, 1); +}