multi frame generation for backend

This commit is contained in:
PancakeTAS 2025-07-02 13:30:45 +02:00
parent 3a6458ab7a
commit f3b5cfc131
No known key found for this signature in database
22 changed files with 402 additions and 239 deletions

View file

@ -32,22 +32,24 @@ namespace LSFG {
/// @param height Height of the input images.
/// @param in0 File descriptor for the first input image.
/// @param in1 File descriptor for the second input image.
/// @param out File descriptor for the output image.
/// @param outN File descriptor for the output image.
///
/// @throws LSFG::vulkan_error if the generator fails to initialize.
///
Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, int out);
Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN);
///
/// Schedule the next generation.
///
/// @param device The Vulkan device to use.
/// @param inSem Semaphore to wait on before starting the generation.
/// @param outSem Semaphore to signal when the generation is complete.
/// @param outSem Semaphores to signal after each generation is done.
///
/// @throws LSFG::vulkan_error if the generator fails to present.
///
void present(const Core::Device& device, int inSem, int outSem);
void present(const Core::Device& device, int inSem,
const std::vector<int>& outSem);
// Trivially copyable, moveable and destructible
Context(const Context&) = default;
@ -61,8 +63,10 @@ namespace LSFG {
Core::Image inImg_0, inImg_1; // inImg_0 is next (inImg_1 prev) when fc % 2 == 0
std::array<Core::Semaphore, 8> inSemaphores;
std::array<Core::Semaphore, 8> outSemaphores;
std::array<Core::CommandBuffer, 8> cmdBuffers;
std::array<std::vector<Core::Semaphore>, 8> internalSemaphores;
std::vector<std::array<Core::Semaphore, 8>> outSemaphores;
std::array<Core::CommandBuffer, 8> cmdBuffers1;
std::vector<std::array<Core::CommandBuffer, 8>> cmdBuffers2;
uint64_t fc{0};
Shaderchains::Downsample downsampleChain;

View file

@ -32,23 +32,26 @@ namespace LSFG::Shaderchains {
/// @param inImgs_0 The next input images to process (when fc % 3 == 0)
/// @param inImgs_1 The prev input images to process (when fc % 3 == 0)
/// @param inImgs_2 The prev prev input images to process (when fc % 3 == 0)
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Beta(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> inImgs_0,
std::array<Core::Image, 4> inImgs_1,
std::array<Core::Image, 4> inImgs_2);
std::array<Core::Image, 4> inImgs_2,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param fc The frame count, used to select the input images.
/// @param pass The pass number
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc);
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass);
/// Get the output images.
[[nodiscard]] const auto& getOutImages() const { return this->outImgs; }
@ -62,9 +65,10 @@ namespace LSFG::Shaderchains {
private:
std::array<Core::ShaderModule, 5> shaderModules;
std::array<Core::Pipeline, 5> pipelines;
std::array<Core::DescriptorSet, 4> descriptorSets; // first shader has special logic
std::array<Core::DescriptorSet, 3> descriptorSets; // first shader has special logic
std::array<Core::DescriptorSet, 3> specialDescriptorSets;
Core::Buffer buffer;
std::vector<Core::DescriptorSet> nDescriptorSets;
std::vector<Core::Buffer> buffers;
std::array<Core::Image, 4> inImgs_0;
std::array<Core::Image, 4> inImgs_1;

View file

@ -31,21 +31,24 @@ namespace LSFG::Shaderchains {
/// @param pool The descriptor pool to allocate in.
/// @param inImgs The input images to process.
/// @param optImg An optional additional input from the previous pass.
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Delta(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 2> inImgs,
std::optional<Core::Image> optImg);
std::optional<Core::Image> optImg,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf);
void Dispatch(const Core::CommandBuffer& buf, uint64_t pass);
/// Get the output image.
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
@ -59,8 +62,9 @@ namespace LSFG::Shaderchains {
private:
std::array<Core::ShaderModule, 4> shaderModules;
std::array<Core::Pipeline, 4> pipelines;
std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Buffer buffer;
std::array<Core::DescriptorSet, 3> descriptorSets;
std::vector<Core::DescriptorSet> nDescriptorSets;
std::vector<Core::Buffer> buffers;
std::array<Core::Image, 2> inImgs;
std::optional<Core::Image> optImg;

View file

@ -30,11 +30,13 @@ namespace LSFG::Shaderchains {
/// @param pool The descriptor pool to allocate in.
/// @param inImg_0 The next full image to downsample (when fc % 2 == 0)
/// @param inImg_1 The next full image to downsample (when fc % 2 == 1)
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Downsample(const Core::Device& device, const Core::DescriptorPool& pool,
Core::Image inImg_0, Core::Image inImg_1);
Core::Image inImg_0, Core::Image inImg_1,
size_t genc);
///
/// Dispatch the shaderchain.

View file

@ -32,22 +32,25 @@ namespace LSFG::Shaderchains {
/// @param inImgs1 The first set of input images to process.
/// @param inImg2 The second type image to process.
/// @param optImg An optional additional input from the previous pass.
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
std::optional<Core::Image> optImg);
std::optional<Core::Image> optImg,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf);
void Dispatch(const Core::CommandBuffer& buf, uint64_t pass);
/// Get the output image.
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
@ -61,8 +64,9 @@ namespace LSFG::Shaderchains {
private:
std::array<Core::ShaderModule, 4> shaderModules;
std::array<Core::Pipeline, 4> pipelines;
std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Buffer buffer;
std::array<Core::DescriptorSet, 3> descriptorSets;
std::vector<Core::DescriptorSet> nDescriptorSets;
std::vector<Core::Buffer> buffers;
std::array<Core::Image, 3> inImgs1;
Core::Image inImg2;

View file

@ -30,22 +30,25 @@ namespace LSFG::Shaderchains {
/// @param inImg1 The first set of input images to process.
/// @param inImg2 The second type image to process.
/// @param outExtent The extent of the output image.
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Extract(const Core::Device& device, const Core::DescriptorPool& pool,
Core::Image inImg1,
Core::Image inImg2,
VkExtent2D outExtent);
VkExtent2D outExtent,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf);
void Dispatch(const Core::CommandBuffer& buf, uint64_t pass);
/// Get the output image.
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
@ -59,8 +62,8 @@ namespace LSFG::Shaderchains {
private:
Core::ShaderModule shaderModule;
Core::Pipeline pipeline;
Core::DescriptorSet descriptorSet;
Core::Buffer buffer;
std::vector<Core::DescriptorSet> nDescriptorSets;
std::vector<Core::Buffer> buffers;
Core::Image inImg1;
Core::Image inImg2;

View file

@ -38,6 +38,7 @@ namespace LSFG::Shaderchains {
/// @param optImg1 An optional additional input from the previous pass.
/// @param optImg2 An optional additional input image for processing non-first passes.
/// @param outExtent The extent of the output image.
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
@ -48,17 +49,19 @@ namespace LSFG::Shaderchains {
Core::Image inImg2,
std::optional<Core::Image> optImg1,
std::optional<Core::Image> optImg2,
VkExtent2D outExtent);
VkExtent2D outExtent,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param fc The frame count, used to select the input images.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc);
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass);
/// Get the first output image.
[[nodiscard]] const auto& getOutImage1() const { return this->outImg1; }
@ -74,9 +77,11 @@ namespace LSFG::Shaderchains {
private:
std::array<Core::ShaderModule, 6> shaderModules;
std::array<Core::Pipeline, 6> pipelines;
std::array<Core::DescriptorSet, 5> descriptorSets; // first shader has special logic
std::array<Core::DescriptorSet, 3> specialDescriptorSets;
Core::Buffer buffer;
std::array<Core::DescriptorSet, 3> descriptorSets; // first shader has special logic
std::vector<Core::DescriptorSet> n1DescriptorSets;
std::vector<Core::DescriptorSet> n2DescriptorSets;
std::vector<std::array<Core::DescriptorSet, 3>> nSpecialDescriptorSets;
std::vector<Core::Buffer> buffers;
std::array<Core::Image, 4> inImgs1_0;
std::array<Core::Image, 4> inImgs1_1;

View file

@ -35,6 +35,7 @@ namespace LSFG::Shaderchains {
/// @param inImg2 The second input image to process.
/// @param inImg3 The third input image to process, next step up the resolution.
/// @param optImg An optional additional input from the previous pass.
/// @param genc Amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
@ -44,17 +45,19 @@ namespace LSFG::Shaderchains {
std::array<Core::Image, 4> inImgs1_2,
Core::Image inImg2,
Core::Image inImg3,
std::optional<Core::Image> optImg);
std::optional<Core::Image> optImg,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param fc The frame count, used to select the input images.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc);
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass);
/// Get the first set of output images
[[nodiscard]] const auto& getOutImages1() const { return this->outImgs1; }
@ -72,8 +75,8 @@ namespace LSFG::Shaderchains {
private:
Core::ShaderModule shaderModule;
Core::Pipeline pipeline;
std::array<Core::DescriptorSet, 3> descriptorSets;
Core::Buffer buffer;
std::vector<std::array<Core::DescriptorSet, 3>> nDescriptorSets;
std::vector<Core::Buffer> buffers;
std::array<Core::Image, 4> inImgs1_0;
std::array<Core::Image, 4> inImgs1_1;

View file

@ -34,7 +34,8 @@ namespace LSFG::Shaderchains {
/// @param inImg3 The first related input texture
/// @param inImg4 The second related input texture
/// @param inImg5 The third related input texture
/// @param outFd File descriptor for the output image.
/// @param outFds File descriptors for the output images.
/// @param genc The amount of frames to generaten.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
@ -44,20 +45,22 @@ namespace LSFG::Shaderchains {
Core::Image inImg3,
Core::Image inImg4,
Core::Image inImg5,
int outFd);
const std::vector<int>& outFds,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param fc The frame count, used to select the input images.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc);
void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass);
/// Get the output image
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
[[nodiscard]] const auto& getOutImage(size_t pass) const { return this->outImgs.at(pass); }
/// Trivially copyable, moveable and destructible
Merge(const Merge&) noexcept = default;
@ -68,8 +71,8 @@ namespace LSFG::Shaderchains {
private:
Core::ShaderModule shaderModule;
Core::Pipeline pipeline;
std::array<Core::DescriptorSet, 2> descriptorSets; // one for each input combination
Core::Buffer buffer;
std::vector<std::array<Core::DescriptorSet, 2>> nDescriptorSets; // per combo
std::vector<Core::Buffer> buffers;
Core::Image inImg1;
Core::Image inImg2;
@ -77,7 +80,7 @@ namespace LSFG::Shaderchains {
Core::Image inImg4;
Core::Image inImg5;
Core::Image outImg;
std::vector<Core::Image> outImgs;
};
}

View file

@ -32,22 +32,25 @@ namespace LSFG::Shaderchains {
/// @param inImgs1 The first set of input images to process.
/// @param inImg2 The second type image to process.
/// @param inImg3 The third type image to process.
/// @param genc The amount of frames to generate.
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
Core::Image inImg3);
Core::Image inImg3,
size_t genc);
///
/// Dispatch the shaderchain.
///
/// @param buf The command buffer to use for dispatching.
/// @param pass The pass number.
///
/// @throws std::logic_error if the command buffer is not recording.
///
void Dispatch(const Core::CommandBuffer& buf);
void Dispatch(const Core::CommandBuffer& buf, uint64_t pass);
/// Get the output image.
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
@ -61,8 +64,9 @@ namespace LSFG::Shaderchains {
private:
std::array<Core::ShaderModule, 4> shaderModules;
std::array<Core::Pipeline, 4> pipelines;
std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Buffer buffer;
std::array<Core::DescriptorSet, 3> descriptorSets;
std::vector<Core::DescriptorSet> nDescriptorSets;
std::vector<Core::Buffer> buffers;
std::array<Core::Image, 3> inImgs1;
Core::Image inImg2;

View file

@ -3,6 +3,7 @@
#include <stdexcept>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace LSFG {
@ -21,23 +22,24 @@ namespace LSFG {
/// @param height Height of the input images.
/// @param in0 File descriptor for the first input image.
/// @param in1 File descriptor for the second input image.
/// @param out File descriptor for the output image.
/// @param outN File descriptor for each output image. This defines the LSFG level.
/// @return A unique identifier for the created context.
///
/// @throws LSFG::vulkan_error if the context cannot be created.
///
int32_t createContext(uint32_t width, uint32_t height, int in0, int in1, int out);
int32_t createContext(uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN);
///
/// Present a context.
///
/// @param id Unique identifier of the context to present.
/// @param inSem Semaphore to wait on before starting the generation.
/// @param outSem Semaphore to signal when the generation is complete.
/// @param outSem Semaphores to signal once each output image is ready.
///
/// @throws LSFG::vulkan_error if the context cannot be presented.
///
void presentContext(int32_t id, int inSem, int outSem);
void presentContext(int32_t id, int inSem, const std::vector<int>& outSem);
///
/// Delete an LSFG context.

View file

@ -8,7 +8,8 @@
using namespace LSFG;
Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, int out) {
Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN) {
// import images
this->inImg_0 = Core::Image(device, { width, height },
VK_FORMAT_R8G8B8A8_UNORM,
@ -25,16 +26,24 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
this->descPool = Core::DescriptorPool(device);
this->cmdPool = Core::CommandPool(device);
// prepare vectors
for (size_t i = 0; i < 8; i++)
this->internalSemaphores.at(i).resize(outN.size());
for (size_t i = 0; i < outN.size(); i++) {
this->outSemaphores.emplace_back();
this->cmdBuffers2.emplace_back();
}
// create shader chains
this->downsampleChain = Shaderchains::Downsample(device, this->descPool,
this->inImg_0, this->inImg_1);
this->inImg_0, this->inImg_1, outN.size());
for (size_t i = 0; i < 7; i++)
this->alphaChains.at(i) = Shaderchains::Alpha(device, this->descPool,
this->downsampleChain.getOutImages().at(i));
this->betaChain = Shaderchains::Beta(device, this->descPool,
this->alphaChains.at(0).getOutImages0(),
this->alphaChains.at(0).getOutImages1(),
this->alphaChains.at(0).getOutImages2());
this->alphaChains.at(0).getOutImages2(), outN.size());
for (size_t i = 0; i < 7; i++) {
if (i < 4) {
this->gammaChains.at(i) = Shaderchains::Gamma(device, this->descPool,
@ -46,7 +55,8 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
: std::optional{this->gammaChains.at(i - 1).getOutImage2()},
i == 0 ? std::nullopt
: std::optional{this->gammaChains.at(i - 1).getOutImage1()},
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent()
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent(),
outN.size()
);
} else {
this->magicChains.at(i - 4) = Shaderchains::Magic(device, this->descPool,
@ -57,31 +67,36 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
: this->extractChains.at(i - 5).getOutImage(),
i == 4 ? this->gammaChains.at(i - 1).getOutImage1()
: this->zetaChains.at(i - 5).getOutImage(),
i == 4 ? std::nullopt : std::optional{this->epsilonChains.at(i - 5).getOutImage()}
i == 4 ? std::nullopt : std::optional{this->epsilonChains.at(i - 5).getOutImage()},
outN.size()
);
this->deltaChains.at(i - 4) = Shaderchains::Delta(device, this->descPool,
this->magicChains.at(i - 4).getOutImages1(),
i == 4 ? std::nullopt
: std::optional{this->deltaChains.at(i - 5).getOutImage()}
: std::optional{this->deltaChains.at(i - 5).getOutImage()},
outN.size()
);
this->epsilonChains.at(i - 4) = Shaderchains::Epsilon(device, this->descPool,
this->magicChains.at(i - 4).getOutImages2(),
this->betaChain.getOutImages().at(6 - i),
i == 4 ? std::nullopt
: std::optional{this->epsilonChains.at(i - 5).getOutImage()}
: std::optional{this->epsilonChains.at(i - 5).getOutImage()},
outN.size()
);
this->zetaChains.at(i - 4) = Shaderchains::Zeta(device, this->descPool,
this->magicChains.at(i - 4).getOutImages3(),
i == 4 ? this->gammaChains.at(i - 1).getOutImage1()
: this->zetaChains.at(i - 5).getOutImage(),
this->betaChain.getOutImages().at(6 - i)
this->betaChain.getOutImages().at(6 - i),
outN.size()
);
if (i >= 6)
continue; // no extract for i >= 6
this->extractChains.at(i - 4) = Shaderchains::Extract(device, this->descPool,
this->zetaChains.at(i - 4).getOutImage(),
this->epsilonChains.at(i - 4).getOutImage(),
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent()
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent(),
outN.size()
);
}
}
@ -91,41 +106,61 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
this->zetaChains.at(2).getOutImage(),
this->epsilonChains.at(2).getOutImage(),
this->deltaChains.at(2).getOutImage(),
out
outN,
outN.size()
);
}
void Context::present(const Core::Device& device, int inSem, int outSem) {
void Context::present(const Core::Device& device, int inSem,
const std::vector<int>& outSem) {
auto& inSemaphore = this->inSemaphores.at(this->fc % 8);
inSemaphore = Core::Semaphore(device, inSem);
auto& outSemaphore = this->outSemaphores.at(this->fc % 8);
outSemaphore = Core::Semaphore(device, outSem);
auto& internalSemaphores = this->internalSemaphores.at(this->fc % 8);
for (size_t i = 0; i < outSem.size(); i++)
internalSemaphores.at(i) = Core::Semaphore(device);
auto& cmdBuffer = this->cmdBuffers.at(this->fc % 8);
cmdBuffer = Core::CommandBuffer(device, this->cmdPool);
cmdBuffer.begin();
auto& cmdBuffer1 = this->cmdBuffers1.at(this->fc % 8);
cmdBuffer1 = Core::CommandBuffer(device, this->cmdPool);
cmdBuffer1.begin();
this->downsampleChain.Dispatch(cmdBuffer, fc);
this->downsampleChain.Dispatch(cmdBuffer1, fc);
for (size_t i = 0; i < 7; i++)
this->alphaChains.at(6 - i).Dispatch(cmdBuffer, fc);
this->betaChain.Dispatch(cmdBuffer, fc);
for (size_t i = 0; i < 4; i++)
this->gammaChains.at(i).Dispatch(cmdBuffer, fc);
for (size_t i = 0; i < 3; i++) {
this->magicChains.at(i).Dispatch(cmdBuffer, fc);
this->deltaChains.at(i).Dispatch(cmdBuffer);
this->epsilonChains.at(i).Dispatch(cmdBuffer);
this->zetaChains.at(i).Dispatch(cmdBuffer);
if (i < 2)
this->extractChains.at(i).Dispatch(cmdBuffer);
}
this->mergeChain.Dispatch(cmdBuffer, fc);
this->alphaChains.at(6 - i).Dispatch(cmdBuffer1, fc);
cmdBuffer.end();
cmdBuffer1.end();
cmdBuffer.submit(device.getComputeQueue(), std::nullopt,
cmdBuffer1.submit(device.getComputeQueue(), std::nullopt,
{ inSemaphore }, std::nullopt,
{ outSemaphore }, std::nullopt);
internalSemaphores, std::nullopt);
for (size_t pass = 0; pass < outSem.size(); pass++) {
auto& outSemaphore = this->outSemaphores.at(pass).at(this->fc % 8);
outSemaphore = Core::Semaphore(device, outSem.at(pass));
auto& cmdBuffer2 = this->cmdBuffers2.at(pass).at(this->fc % 8);
cmdBuffer2 = Core::CommandBuffer(device, this->cmdPool);
cmdBuffer2.begin();
this->betaChain.Dispatch(cmdBuffer2, fc, pass);
for (size_t i = 0; i < 4; i++)
this->gammaChains.at(i).Dispatch(cmdBuffer2, fc, pass);
for (size_t i = 0; i < 3; i++) {
this->magicChains.at(i).Dispatch(cmdBuffer2, fc, pass);
this->deltaChains.at(i).Dispatch(cmdBuffer2, pass);
this->epsilonChains.at(i).Dispatch(cmdBuffer2, pass);
this->zetaChains.at(i).Dispatch(cmdBuffer2, pass);
if (i < 2)
this->extractChains.at(i).Dispatch(cmdBuffer2, pass);
}
this->mergeChain.Dispatch(cmdBuffer2, fc, pass);
cmdBuffer2.end();
cmdBuffer2.submit(device.getComputeQueue(), std::nullopt,
{ internalSemaphores.at(pass) }, std::nullopt,
{ outSemaphore }, std::nullopt);
}
fc++;
}

View file

@ -28,16 +28,17 @@ void LSFG::initialize() {
std::srand(static_cast<uint32_t>(std::time(nullptr)));
}
int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1, int out) {
int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN) {
if (!instance.has_value() || !device.has_value())
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
auto id = std::rand();
contexts.emplace(id, Context(*device, width, height, in0, in1, out));
contexts.emplace(id, Context(*device, width, height, in0, in1, outN));
return id;
}
void LSFG::presentContext(int32_t id, int inSem, int outSem) {
void LSFG::presentContext(int32_t id, int inSem, const std::vector<int>& outSem) {
if (!instance.has_value() || !device.has_value())
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");

View file

@ -6,7 +6,8 @@ using namespace LSFG::Shaderchains;
Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> inImgs_0,
std::array<Core::Image, 4> inImgs_1,
std::array<Core::Image, 4> inImgs_2)
std::array<Core::Image, 4> inImgs_2,
size_t genc)
: inImgs_0(std::move(inImgs_0)),
inImgs_1(std::move(inImgs_1)),
inImgs_2(std::move(inImgs_2)) {
@ -36,14 +37,21 @@ Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool,
for (size_t i = 0; i < 5; i++) {
this->pipelines.at(i) = Core::Pipeline(device,
this->shaderModules.at(i));
if (i == 0) continue; // first shader has special logic
if (i == 0 || i == 4) continue; // first shader has special logic
this->descriptorSets.at(i - 1) = Core::DescriptorSet(device, pool,
this->shaderModules.at(i));
}
for (size_t i = 0; i < 3; i++)
this->specialDescriptorSets.at(i) = Core::DescriptorSet(device, pool,
this->shaderModules.at(0));
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
for (size_t i = 0; i < genc; i++)
this->nDescriptorSets.emplace_back(device, pool,
this->shaderModules.at(4));
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
const auto extent = this->inImgs_0.at(0).getExtent();
@ -104,15 +112,17 @@ Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool,
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
.build();
this->descriptorSets.at(3).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();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).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->buffers.at(i))
.build();
}
}
void Beta::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
void Beta::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) {
const auto extent = this->tempImgs1.at(0).getExtent();
// first pass
@ -170,6 +180,6 @@ void Beta::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
.build();
this->pipelines.at(4).bind(buf);
this->descriptorSets.at(3).bind(buf, this->pipelines.at(4));
this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(4));
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -5,7 +5,8 @@ using namespace LSFG::Shaderchains;
Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 2> inImgs,
std::optional<Core::Image> optImg)
std::optional<Core::Image> optImg,
size_t genc)
: inImgs(std::move(inImgs)),
optImg(std::move(optImg)) {
this->shaderModules = {{
@ -30,13 +31,19 @@ Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool,
for (size_t i = 0; i < 4; i++) {
this->pipelines.at(i) = Core::Pipeline(device,
this->shaderModules.at(i));
if (i == 3) continue;
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);
for (size_t i = 0; i < genc; i++)
this->nDescriptorSets.emplace_back(device, pool,
this->shaderModules.at(3));
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
data.firstIterS = !this->optImg.has_value();
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
const auto extent = this->inImgs.at(0).getExtent();
@ -74,17 +81,19 @@ Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool,
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
.build();
this->descriptorSets.at(3).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg)
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer)
.build();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg)
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i))
.build();
}
}
void Delta::Dispatch(const Core::CommandBuffer& buf) {
void Delta::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) {
const auto extent = this->tempImgs1.at(0).getExtent();
// first pass
@ -128,6 +137,6 @@ void Delta::Dispatch(const Core::CommandBuffer& buf) {
.build();
this->pipelines.at(3).bind(buf);
this->descriptorSets.at(3).bind(buf, this->pipelines.at(3));
this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(3));
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -4,7 +4,8 @@
using namespace LSFG::Shaderchains;
Downsample::Downsample(const Core::Device& device, const Core::DescriptorPool& pool,
Core::Image inImg_0, Core::Image inImg_1)
Core::Image inImg_0, Core::Image inImg_1,
size_t genc)
: inImg_0(std::move(inImg_0)),
inImg_1(std::move(inImg_1)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/downsample.spv",
@ -15,7 +16,10 @@ Downsample::Downsample(const Core::Device& device, const Core::DescriptorPool& p
this->pipeline = Core::Pipeline(device, this->shaderModule);
for (size_t i = 0; i < 2; i++)
this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, this->shaderModule);
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
auto data = Globals::fgBuffer;
data.timestamp = 1.0F / static_cast<float>(genc + 1);
this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
auto extent = this->inImg_0.getExtent();
for (size_t i = 0; i < 7; i++)

View file

@ -6,7 +6,8 @@ using namespace LSFG::Shaderchains;
Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
std::optional<Core::Image> optImg)
std::optional<Core::Image> optImg,
size_t genc)
: inImgs1(std::move(inImgs1)),
inImg2(std::move(inImg2)),
optImg(std::move(optImg)) {
@ -32,10 +33,18 @@ Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
for (size_t i = 0; i < 4; i++) {
this->pipelines.at(i) = Core::Pipeline(device,
this->shaderModules.at(i));
if (i == 3) continue;
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);
for (size_t i = 0; i < genc; i++)
this->nDescriptorSets.emplace_back(device, pool,
this->shaderModules.at(3));
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
const auto extent = this->inImgs1.at(0).getExtent();
@ -73,18 +82,20 @@ Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
.build();
this->descriptorSets.at(3).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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->buffers.at(i))
.build();
}
}
void Epsilon::Dispatch(const Core::CommandBuffer& buf) {
void Epsilon::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) {
const auto extent = this->tempImgs1.at(0).getExtent();
// first pass
@ -129,6 +140,6 @@ void Epsilon::Dispatch(const Core::CommandBuffer& buf) {
.build();
this->pipelines.at(3).bind(buf);
this->descriptorSets.at(3).bind(buf, this->pipelines.at(3));
this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(3));
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -6,7 +6,8 @@ using namespace LSFG::Shaderchains;
Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool,
Core::Image inImg1,
Core::Image inImg2,
VkExtent2D outExtent)
VkExtent2D outExtent,
size_t genc)
: inImg1(std::move(inImg1)),
inImg2(std::move(inImg2)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/extract.spv",
@ -15,8 +16,14 @@ Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool,
{ 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);
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
for (size_t i = 0; i < genc; i++)
this->nDescriptorSets.emplace_back(device, pool,
this->shaderModule);
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
this->whiteImg = Core::Image(device,
outExtent,
@ -30,21 +37,23 @@ Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT);
this->descriptorSet.update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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->buffers.at(i))
.build();
}
// clear white image
Utils::clearImage(device, this->whiteImg, true);
}
void Extract::Dispatch(const Core::CommandBuffer& buf) {
void Extract::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) {
auto extent = this->whiteImg.getExtent();
// first pass
@ -59,6 +68,6 @@ void Extract::Dispatch(const Core::CommandBuffer& buf) {
.build();
this->pipeline.bind(buf);
this->descriptorSet.bind(buf, this->pipeline);
this->nDescriptorSets.at(pass).bind(buf, this->pipeline);
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -10,7 +10,8 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
Core::Image inImg2,
std::optional<Core::Image> optImg1, // NOLINT
std::optional<Core::Image> optImg2,
VkExtent2D outExtent)
VkExtent2D outExtent,
size_t genc)
: inImgs1_0(std::move(inImgs1_0)),
inImgs1_1(std::move(inImgs1_1)),
inImgs1_2(std::move(inImgs1_2)),
@ -48,17 +49,28 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
for (size_t i = 0; i < 6; i++) {
this->pipelines.at(i) = Core::Pipeline(device,
this->shaderModules.at(i));
if (i == 0) continue; // first shader has special logic
if (i == 0 || i >= 4) continue; // first shader has special logic
this->descriptorSets.at(i - 1) = Core::DescriptorSet(device, pool,
this->shaderModules.at(i));
}
for (size_t i = 0; i < 3; i++)
this->specialDescriptorSets.at(i) = Core::DescriptorSet(device, pool,
this->shaderModules.at(0));
Globals::FgBuffer data = Globals::fgBuffer;
data.firstIter = !optImg1.has_value();
this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
for (size_t i = 0; i < genc; i++)
this->n1DescriptorSets.emplace_back(device, pool,
this->shaderModules.at(4));
for (size_t i = 0; i < genc; i++)
this->n2DescriptorSets.emplace_back(device, pool,
this->shaderModules.at(5));
for (size_t i = 0; i < genc; i++) {
this->nSpecialDescriptorSets.emplace_back();
for (size_t j = 0; j < 3; j++)
this->nSpecialDescriptorSets.at(i).at(j) = Core::DescriptorSet(device, pool,
this->shaderModules.at(0));
}
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
data.firstIter = !optImg1.has_value();
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
const auto extent = this->inImgs1_0.at(0).getExtent();
@ -107,18 +119,20 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
nextImgs1 = &this->inImgs1_2;
prevImgs1 = &this->inImgs1_1;
}
this->specialDescriptorSets.at(fc).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1)
.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();
for (size_t i = 0; i < genc; i++) {
this->nSpecialDescriptorSets.at(i).at(fc).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1)
.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->buffers.at(i))
.build();
}
}
this->descriptorSets.at(0).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
@ -137,23 +151,25 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
.build();
this->descriptorSets.at(3).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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(4).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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();
for (size_t i = 0; i < genc; i++) {
this->n1DescriptorSets.at(i).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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->buffers.at(i))
.build();
this->n2DescriptorSets.at(i).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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->buffers.at(i))
.build();
}
// clear white image and optImg1 if needed
Utils::clearImage(device, this->whiteImg, true);
@ -161,7 +177,7 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
Utils::clearImage(device, this->optImg1);
}
void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) {
const auto extent = this->tempImgs1.at(0).getExtent();
// first pass
@ -188,7 +204,7 @@ void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
.build();
this->pipelines.at(0).bind(buf);
this->specialDescriptorSets.at(fc % 3).bind(buf, this->pipelines.at(0));
this->nSpecialDescriptorSets.at(pass).at(fc % 3).bind(buf, this->pipelines.at(0));
buf.dispatch(threadsX, threadsY, 1);
// second pass
@ -232,7 +248,7 @@ void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
.build();
this->pipelines.at(4).bind(buf);
this->descriptorSets.at(3).bind(buf, this->pipelines.at(4));
this->n1DescriptorSets.at(pass).bind(buf, this->pipelines.at(4));
buf.dispatch(threadsX, threadsY, 1);
// sixth pass
@ -246,6 +262,6 @@ void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
.build();
this->pipelines.at(5).bind(buf);
this->descriptorSets.at(4).bind(buf, this->pipelines.at(5));
this->n2DescriptorSets.at(pass).bind(buf, this->pipelines.at(5));
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -9,7 +9,8 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> inImgs1_2,
Core::Image inImg2,
Core::Image inImg3,
std::optional<Core::Image> optImg)
std::optional<Core::Image> optImg,
size_t genc)
: inImgs1_0(std::move(inImgs1_0)),
inImgs1_1(std::move(inImgs1_1)),
inImgs1_2(std::move(inImgs1_2)),
@ -21,12 +22,17 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool,
{ 3+3+2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } });
this->pipeline = Core::Pipeline(device, this->shaderModule);
for (size_t i = 0; i < 3; i++)
this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, this->shaderModule);
Globals::FgBuffer data = Globals::fgBuffer;
data.firstIterS = !this->optImg.has_value();
this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.emplace_back();
for (size_t j = 0; j < 3; j++)
this->nDescriptorSets.at(i).at(j) = Core::DescriptorSet(device, pool, this->shaderModule);
}
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
data.firstIterS = !this->optImg.has_value();
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
auto extent = this->inImgs1_0.at(0).getExtent();
@ -59,23 +65,25 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool,
nextImgs1 = &this->inImgs1_2;
prevImgs1 = &this->inImgs1_1;
}
this->descriptorSets.at(fc).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
.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();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).at(fc).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
.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->buffers.at(i))
.build();
}
}
}
void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) {
auto extent = this->inImgs1_0.at(0).getExtent();
// first pass
@ -103,6 +111,6 @@ void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
.build();
this->pipeline.bind(buf);
this->descriptorSets.at(fc % 3).bind(buf, this->pipeline);
this->nDescriptorSets.at(pass).at(fc % 3).bind(buf, this->pipeline);
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -9,7 +9,8 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
Core::Image inImg3,
Core::Image inImg4,
Core::Image inImg5,
int outFd)
const std::vector<int>& outFds,
size_t genc)
: inImg1(std::move(inImg1)),
inImg2(std::move(inImg2)),
inImg3(std::move(inImg3)),
@ -21,35 +22,45 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } });
this->pipeline = Core::Pipeline(device, this->shaderModule);
for (size_t i = 0; i < 2; i++)
this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, this->shaderModule);
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.emplace_back();
for (size_t j = 0; j < 2; j++)
this->nDescriptorSets.at(i).at(j) = Core::DescriptorSet(device, pool, this->shaderModule);
}
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
auto extent = this->inImg1.getExtent();
this->outImg = Core::Image(device,
extent,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT,
outFd);
for (size_t i = 0; i < genc; i++)
this->outImgs.emplace_back(device,
extent,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT,
outFds.at(i));
for (size_t fc = 0; fc < 2; fc++) {
this->descriptorSets.at(fc).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg1 : this->inImg2)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg2 : this->inImg1)
.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();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).at(fc).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg1 : this->inImg2)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg2 : this->inImg1)
.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->outImgs.at(i))
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i))
.build();
}
}
}
void Merge::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
void Merge::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) {
auto extent = this->inImg1.getExtent();
// first pass
@ -62,10 +73,10 @@ void Merge::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
.addW2R(this->inImg3)
.addW2R(this->inImg4)
.addW2R(this->inImg5)
.addR2W(this->outImg)
.addR2W(this->outImgs.at(pass))
.build();
this->pipeline.bind(buf);
this->descriptorSets.at(fc % 2).bind(buf, this->pipeline);
this->nDescriptorSets.at(pass).at(fc % 2).bind(buf, this->pipeline);
buf.dispatch(threadsX, threadsY, 1);
}

View file

@ -6,7 +6,8 @@ using namespace LSFG::Shaderchains;
Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
Core::Image inImg3)
Core::Image inImg3,
size_t genc)
: inImgs1(std::move(inImgs1)),
inImg2(std::move(inImg2)),
inImg3(std::move(inImg3)) {
@ -32,10 +33,18 @@ Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
for (size_t i = 0; i < 4; i++) {
this->pipelines.at(i) = Core::Pipeline(device,
this->shaderModules.at(i));
if (i == 3) continue;
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);
for (size_t i = 0; i < genc; i++)
this->nDescriptorSets.emplace_back(device, pool,
this->shaderModules.at(3));
for (size_t i = 0; i < genc; i++) {
auto data = Globals::fgBuffer;
data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1);
this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
}
const auto extent = this->inImgs1.at(0).getExtent();
@ -73,18 +82,20 @@ Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
.build();
this->descriptorSets.at(3).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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();
for (size_t i = 0; i < genc; i++) {
this->nDescriptorSets.at(i).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge)
.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->buffers.at(i) )
.build();
}
}
void Zeta::Dispatch(const Core::CommandBuffer& buf) {
void Zeta::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) {
const auto extent = this->tempImgs1.at(0).getExtent();
// first pass
@ -129,6 +140,6 @@ void Zeta::Dispatch(const Core::CommandBuffer& buf) {
.build();
this->pipelines.at(3).bind(buf);
this->descriptorSets.at(3).bind(buf, this->pipelines.at(3));
this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(3));
buf.dispatch(threadsX, threadsY, 1);
}