mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-04-27 04:41:45 +00:00
refactor(cleanup): rewrite main pass in new abstraction
This commit is contained in:
parent
c3d6cdfc28
commit
f3536b0895
27 changed files with 790 additions and 1674 deletions
|
|
@ -1,81 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace LSFG_3_1::Shaders {
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
///
|
||||
/// Delta shader.
|
||||
///
|
||||
class Delta {
|
||||
public:
|
||||
Delta() = default;
|
||||
|
||||
///
|
||||
/// Initialize the shaderchain.
|
||||
///
|
||||
/// @param inImgs1 Three sets of four RGBA images, corresponding to a frame count % 3.
|
||||
/// @param inImg2 Second Input image
|
||||
/// @param optImg1 Optional image for non-first passes.
|
||||
/// @param optImg2 Second optional image for non-first passes.
|
||||
/// @param optImg3 Third optional image for non-first passes.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Delta(Vulkan& vk, std::array<std::array<Core::Image, 4>, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg1,
|
||||
std::optional<Core::Image> optImg2,
|
||||
std::optional<Core::Image> optImg3);
|
||||
|
||||
///
|
||||
/// Dispatch the shaderchain.
|
||||
///
|
||||
void Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx);
|
||||
|
||||
/// Get the first output image
|
||||
[[nodiscard]] const auto& getOutImage1() const { return this->outImg1; }
|
||||
/// Get the second output image
|
||||
[[nodiscard]] const auto& getOutImage2() const { return this->outImg2; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Delta(const Delta&) noexcept = default;
|
||||
Delta& operator=(const Delta&) noexcept = default;
|
||||
Delta(Delta&&) noexcept = default;
|
||||
Delta& operator=(Delta&&) noexcept = default;
|
||||
~Delta() = default;
|
||||
private:
|
||||
std::array<Core::ShaderModule, 10> shaderModules;
|
||||
std::array<Core::Pipeline, 10> pipelines;
|
||||
std::array<Core::Sampler, 3> samplers;
|
||||
struct DeltaPass {
|
||||
Core::Buffer buffer;
|
||||
std::array<Core::DescriptorSet, 3> firstDescriptorSet;
|
||||
std::array<Core::DescriptorSet, 8> descriptorSets;
|
||||
std::array<Core::DescriptorSet, 3> sixthDescriptorSet;
|
||||
};
|
||||
std::vector<DeltaPass> passes;
|
||||
|
||||
std::array<std::array<Core::Image, 4>, 3> inImgs1;
|
||||
Core::Image inImg2;
|
||||
std::optional<Core::Image> optImg1, optImg2, optImg3;
|
||||
std::array<Core::Image, 4> tempImgs1;
|
||||
std::array<Core::Image, 4> tempImgs2;
|
||||
Core::Image outImg1, outImg2;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace LSFG_3_1::Shaders {
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
///
|
||||
/// Gamma shader.
|
||||
///
|
||||
class Gamma {
|
||||
public:
|
||||
Gamma() = default;
|
||||
|
||||
///
|
||||
/// Initialize the shaderchain.
|
||||
///
|
||||
/// @param inImgs1 Three sets of four RGBA images, corresponding to a frame count % 3.
|
||||
/// @param inImg2 Second Input image
|
||||
/// @param optImg Optional image for non-first passes.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Gamma(Vulkan& vk, std::array<std::array<Core::Image, 4>, 3> inImgs1,
|
||||
Core::Image inImg2, std::optional<Core::Image> optImg);
|
||||
|
||||
///
|
||||
/// Dispatch the shaderchain.
|
||||
///
|
||||
void Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx);
|
||||
|
||||
/// Get the output image
|
||||
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Gamma(const Gamma&) noexcept = default;
|
||||
Gamma& operator=(const Gamma&) noexcept = default;
|
||||
Gamma(Gamma&&) noexcept = default;
|
||||
Gamma& operator=(Gamma&&) noexcept = default;
|
||||
~Gamma() = default;
|
||||
private:
|
||||
std::array<Core::ShaderModule, 5> shaderModules;
|
||||
std::array<Core::Pipeline, 5> pipelines;
|
||||
std::array<Core::Sampler, 3> samplers;
|
||||
struct GammaPass {
|
||||
Core::Buffer buffer;
|
||||
std::array<Core::DescriptorSet, 3> firstDescriptorSet;
|
||||
std::array<Core::DescriptorSet, 4> descriptorSets;
|
||||
};
|
||||
std::vector<GammaPass> passes;
|
||||
|
||||
std::array<std::array<Core::Image, 4>, 3> inImgs1;
|
||||
Core::Image inImg2;
|
||||
std::optional<Core::Image> optImg;
|
||||
std::array<Core::Image, 4> tempImgs1;
|
||||
std::array<Core::Image, 4> tempImgs2;
|
||||
Core::Image outImg;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace LSFG_3_1::Shaders {
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
///
|
||||
/// Generate shader.
|
||||
///
|
||||
class Generate {
|
||||
public:
|
||||
Generate() = default;
|
||||
|
||||
///
|
||||
/// Initialize the shaderchain.
|
||||
///
|
||||
/// @param inImg1 Input image 1.
|
||||
/// @param inImg2 Input image 2.
|
||||
/// @param inImg3 Input image 3.
|
||||
/// @param inImg4 Input image 4.
|
||||
/// @param inImg5 Input image 5.
|
||||
/// @param fds File descriptors for the output images.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Generate(Vulkan& vk,
|
||||
Core::Image inImg1, Core::Image inImg2,
|
||||
Core::Image inImg3, Core::Image inImg4, Core::Image inImg5,
|
||||
const std::vector<int>& fds, VkFormat format);
|
||||
|
||||
///
|
||||
/// Dispatch the shaderchain.
|
||||
///
|
||||
void Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx);
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Generate(const Generate&) noexcept = default;
|
||||
Generate& operator=(const Generate&) noexcept = default;
|
||||
Generate(Generate&&) noexcept = default;
|
||||
Generate& operator=(Generate&&) noexcept = default;
|
||||
~Generate() = default;
|
||||
private:
|
||||
Core::ShaderModule shaderModule;
|
||||
Core::Pipeline pipeline;
|
||||
std::array<Core::Sampler, 2> samplers;
|
||||
struct GeneratePass {
|
||||
Core::Buffer buffer;
|
||||
std::array<Core::DescriptorSet, 2> descriptorSet;
|
||||
};
|
||||
std::vector<GeneratePass> passes;
|
||||
|
||||
Core::Image inImg1, inImg2;
|
||||
Core::Image inImg3, inImg4, inImg5;
|
||||
std::vector<Core::Image> outImgs;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,340 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "v3_1/shaders/delta.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace LSFG_3_1::Shaders;
|
||||
|
||||
Delta::Delta(Vulkan& vk, std::array<std::array<Core::Image, 4>, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg1,
|
||||
std::optional<Core::Image> optImg2,
|
||||
std::optional<Core::Image> optImg3)
|
||||
: inImgs1(std::move(inImgs1)), inImg2(std::move(inImg2)),
|
||||
optImg1(std::move(optImg1)), optImg2(std::move(optImg2)),
|
||||
optImg3(std::move(optImg3)) {
|
||||
// create resources
|
||||
this->shaderModules = {{
|
||||
vk.shaders.getShader(vk.device, "delta[0]",
|
||||
{ { 1 , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 9, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[1]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[2]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[3]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[4]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[5]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 10, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[6]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[7]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[8]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "delta[9]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } })
|
||||
}};
|
||||
this->pipelines = {{
|
||||
vk.shaders.getPipeline(vk.device, "delta[0]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[1]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[2]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[3]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[4]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[5]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[6]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[7]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[8]"),
|
||||
vk.shaders.getPipeline(vk.device, "delta[9]")
|
||||
}};
|
||||
this->samplers.at(0) = vk.resources.getSampler(vk.device);
|
||||
this->samplers.at(1) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, true);
|
||||
this->samplers.at(2) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS, false);
|
||||
|
||||
// create internal images/outputs
|
||||
const VkExtent2D extent = this->inImgs1.at(0).at(0).getExtent();
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
this->tempImgs1.at(i) = Core::Image(vk.device, extent);
|
||||
this->tempImgs2.at(i) = Core::Image(vk.device, extent);
|
||||
}
|
||||
|
||||
this->outImg1 = Core::Image(vk.device,
|
||||
{ extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
this->outImg2 = Core::Image(vk.device,
|
||||
{ extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
|
||||
// hook up shaders
|
||||
for (size_t pass_idx = 0; pass_idx < vk.generationCount; pass_idx++) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
pass.buffer = vk.resources.getBuffer(vk.device,
|
||||
static_cast<float>(pass_idx + 1) / static_cast<float>(vk.generationCount + 1),
|
||||
false, !this->optImg1.has_value());
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
pass.firstDescriptorSet.at(i) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(0));
|
||||
pass.firstDescriptorSet.at(i).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at((i + 2) % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at(i % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1)
|
||||
.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))
|
||||
.build();
|
||||
}
|
||||
pass.descriptorSets.at(0) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(1));
|
||||
pass.descriptorSets.at(0).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.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)
|
||||
.build();
|
||||
pass.descriptorSets.at(1) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(2));
|
||||
pass.descriptorSets.at(1).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
|
||||
.build();
|
||||
pass.descriptorSets.at(2) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(3));
|
||||
pass.descriptorSets.at(2).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
|
||||
.build();
|
||||
pass.descriptorSets.at(3) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(4));
|
||||
pass.descriptorSets.at(3).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg1)
|
||||
.build();
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
pass.sixthDescriptorSet.at(i) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(5));
|
||||
pass.sixthDescriptorSet.at(i).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at((i + 2) % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at(i % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2.at(1))
|
||||
.build();
|
||||
}
|
||||
pass.descriptorSets.at(4) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(6));
|
||||
pass.descriptorSets.at(4).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1))
|
||||
.build();
|
||||
pass.descriptorSets.at(5) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(7));
|
||||
pass.descriptorSets.at(5).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2.at(1))
|
||||
.build();
|
||||
pass.descriptorSets.at(6) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(8));
|
||||
pass.descriptorSets.at(6).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1))
|
||||
.build();
|
||||
pass.descriptorSets.at(7) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(9));
|
||||
pass.descriptorSets.at(7).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.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->optImg3)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg2)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
void Delta::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx) {
|
||||
auto& pass = this->passes.at(pass_idx);
|
||||
|
||||
// first shader
|
||||
const auto extent = this->tempImgs1.at(0).getExtent();
|
||||
const uint32_t threadsX = (extent.width + 7) >> 3;
|
||||
const uint32_t threadsY = (extent.height + 7) >> 3;
|
||||
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImgs1.at((frameCount + 2) % 3))
|
||||
.addW2R(this->inImgs1.at(frameCount % 3))
|
||||
.addW2R(this->optImg1)
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.addR2W(this->tempImgs1.at(2))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(0).bind(buf);
|
||||
pass.firstDescriptorSet.at(frameCount % 3).bind(buf, this->pipelines.at(0));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// second shader
|
||||
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);
|
||||
pass.descriptorSets.at(0).bind(buf, this->pipelines.at(1));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// third shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addR2W(this->tempImgs1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(2).bind(buf);
|
||||
pass.descriptorSets.at(1).bind(buf, this->pipelines.at(2));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fourth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1)
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(3).bind(buf);
|
||||
pass.descriptorSets.at(2).bind(buf, this->pipelines.at(3));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fifth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addW2R(this->optImg1)
|
||||
.addW2R(this->inImg2)
|
||||
.addR2W(this->outImg1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(4).bind(buf);
|
||||
pass.descriptorSets.at(3).bind(buf, this->pipelines.at(4));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// sixth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImgs1.at((frameCount + 2) % 3))
|
||||
.addW2R(this->inImgs1.at(frameCount % 3))
|
||||
.addW2R(this->optImg1)
|
||||
.addW2R(this->optImg2)
|
||||
.addR2W(this->tempImgs2.at(0))
|
||||
.addR2W(this->tempImgs2.at(1))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(5).bind(buf);
|
||||
pass.sixthDescriptorSet.at(frameCount % 3).bind(buf, this->pipelines.at(5));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// seventh shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2.at(0))
|
||||
.addW2R(this->tempImgs2.at(1))
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(6).bind(buf);
|
||||
pass.descriptorSets.at(4).bind(buf, this->pipelines.at(6));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// eighth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1.at(0))
|
||||
.addW2R(this->tempImgs1.at(1))
|
||||
.addR2W(this->tempImgs2.at(0))
|
||||
.addR2W(this->tempImgs2.at(1))
|
||||
.build();
|
||||
this->pipelines.at(7).bind(buf);
|
||||
pass.descriptorSets.at(5).bind(buf, this->pipelines.at(7));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// ninth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2.at(0))
|
||||
.addW2R(this->tempImgs2.at(1))
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(8).bind(buf);
|
||||
pass.descriptorSets.at(6).bind(buf, this->pipelines.at(8));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// tenth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1.at(0))
|
||||
.addW2R(this->tempImgs1.at(1))
|
||||
.addW2R(this->optImg3)
|
||||
.addR2W(this->outImg2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(9).bind(buf);
|
||||
pass.descriptorSets.at(7).bind(buf, this->pipelines.at(9));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
}
|
||||
|
|
@ -1,193 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "v3_1/shaders/gamma.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace LSFG_3_1::Shaders;
|
||||
|
||||
Gamma::Gamma(Vulkan& vk, std::array<std::array<Core::Image, 4>, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg)
|
||||
: inImgs1(std::move(inImgs1)), inImg2(std::move(inImg2)),
|
||||
optImg(std::move(optImg)) {
|
||||
// create resources
|
||||
this->shaderModules = {{
|
||||
vk.shaders.getShader(vk.device, "gamma[0]",
|
||||
{ { 1 , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 9, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "gamma[1]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "gamma[2]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "gamma[3]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "gamma[4]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } })
|
||||
}};
|
||||
this->pipelines = {{
|
||||
vk.shaders.getPipeline(vk.device, "gamma[0]"),
|
||||
vk.shaders.getPipeline(vk.device, "gamma[1]"),
|
||||
vk.shaders.getPipeline(vk.device, "gamma[2]"),
|
||||
vk.shaders.getPipeline(vk.device, "gamma[3]"),
|
||||
vk.shaders.getPipeline(vk.device, "gamma[4]")
|
||||
}};
|
||||
this->samplers.at(0) = vk.resources.getSampler(vk.device);
|
||||
this->samplers.at(1) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, true);
|
||||
this->samplers.at(2) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS, false);
|
||||
|
||||
// create internal images/outputs
|
||||
const VkExtent2D extent = this->inImgs1.at(0).at(0).getExtent();
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
this->tempImgs1.at(i) = Core::Image(vk.device, extent);
|
||||
this->tempImgs2.at(i) = Core::Image(vk.device, extent);
|
||||
}
|
||||
|
||||
this->outImg = Core::Image(vk.device,
|
||||
{ extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
|
||||
// hook up shaders
|
||||
for (size_t pass_idx = 0; pass_idx < vk.generationCount; pass_idx++) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
pass.buffer = vk.resources.getBuffer(vk.device,
|
||||
static_cast<float>(pass_idx + 1) / static_cast<float>(vk.generationCount + 1),
|
||||
!this->optImg.has_value());
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
pass.firstDescriptorSet.at(i) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(0));
|
||||
pass.firstDescriptorSet.at(i).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at((i + 2) % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at(i % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
|
||||
.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))
|
||||
.build();
|
||||
}
|
||||
pass.descriptorSets.at(0) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(1));
|
||||
pass.descriptorSets.at(0).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.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)
|
||||
.build();
|
||||
pass.descriptorSets.at(1) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(2));
|
||||
pass.descriptorSets.at(1).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
|
||||
.build();
|
||||
pass.descriptorSets.at(2) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(3));
|
||||
pass.descriptorSets.at(2).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
|
||||
.build();
|
||||
pass.descriptorSets.at(3) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(4));
|
||||
pass.descriptorSets.at(3).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx) {
|
||||
auto& pass = this->passes.at(pass_idx);
|
||||
|
||||
// first shader
|
||||
const auto extent = this->tempImgs1.at(0).getExtent();
|
||||
const uint32_t threadsX = (extent.width + 7) >> 3;
|
||||
const uint32_t threadsY = (extent.height + 7) >> 3;
|
||||
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImgs1.at((frameCount + 2) % 3))
|
||||
.addW2R(this->inImgs1.at(frameCount % 3))
|
||||
.addW2R(this->optImg)
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.addR2W(this->tempImgs1.at(2))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(0).bind(buf);
|
||||
pass.firstDescriptorSet.at(frameCount % 3).bind(buf, this->pipelines.at(0));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// second shader
|
||||
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);
|
||||
pass.descriptorSets.at(0).bind(buf, this->pipelines.at(1));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// third shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addR2W(this->tempImgs1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(2).bind(buf);
|
||||
pass.descriptorSets.at(1).bind(buf, this->pipelines.at(2));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fourth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1)
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(3).bind(buf);
|
||||
pass.descriptorSets.at(2).bind(buf, this->pipelines.at(3));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fifth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addW2R(this->optImg)
|
||||
.addW2R(this->inImg2)
|
||||
.addR2W(this->outImg)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(4).bind(buf);
|
||||
pass.descriptorSets.at(3).bind(buf, this->pipelines.at(4));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "v3_1/shaders/generate.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace LSFG_3_1::Shaders;
|
||||
|
||||
Generate::Generate(Vulkan& vk,
|
||||
Core::Image inImg1, Core::Image inImg2,
|
||||
Core::Image inImg3, Core::Image inImg4, Core::Image inImg5,
|
||||
const std::vector<int>& fds, VkFormat format)
|
||||
: inImg1(std::move(inImg1)), inImg2(std::move(inImg2)),
|
||||
inImg3(std::move(inImg3)), inImg4(std::move(inImg4)),
|
||||
inImg5(std::move(inImg5)) {
|
||||
// create resources
|
||||
this->shaderModule = vk.shaders.getShader(vk.device, "generate",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } });
|
||||
this->pipeline = vk.shaders.getPipeline(vk.device, "generate");
|
||||
this->samplers.at(0) = vk.resources.getSampler(vk.device);
|
||||
this->samplers.at(1) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS);
|
||||
|
||||
// create internal images/outputs
|
||||
const VkExtent2D extent = this->inImg1.getExtent();
|
||||
for (size_t i = 0; i < vk.generationCount; i++)
|
||||
this->outImgs.emplace_back(vk.device, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT, fds.empty() ? -1 : fds.at(i));
|
||||
|
||||
// hook up shaders
|
||||
for (size_t i = 0; i < vk.generationCount; i++) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
pass.buffer = vk.resources.getBuffer(vk.device,
|
||||
static_cast<float>(i + 1) / static_cast<float>(vk.generationCount + 1));
|
||||
for (size_t j = 0; j < 2; j++) {
|
||||
pass.descriptorSet.at(j) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModule);
|
||||
pass.descriptorSet.at(j).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, j == 0 ? this->inImg2 : this->inImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, j == 0 ? this->inImg1 : 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->outImgs.at(i))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Generate::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx) {
|
||||
auto& pass = this->passes.at(pass_idx);
|
||||
|
||||
// first pass
|
||||
const auto extent = this->inImg1.getExtent();
|
||||
const uint32_t threadsX = (extent.width + 15) >> 4;
|
||||
const uint32_t threadsY = (extent.height + 15) >> 4;
|
||||
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImg1)
|
||||
.addW2R(this->inImg2)
|
||||
.addW2R(this->inImg3)
|
||||
.addW2R(this->inImg4)
|
||||
.addW2R(this->inImg5)
|
||||
.addR2W(this->outImgs.at(pass_idx))
|
||||
.build();
|
||||
|
||||
this->pipeline.bind(buf);
|
||||
pass.descriptorSet.at(frameCount % 2).bind(buf, this->pipeline);
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace LSFG_3_1P::Shaders {
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
///
|
||||
/// Delta shader.
|
||||
///
|
||||
class Delta {
|
||||
public:
|
||||
Delta() = default;
|
||||
|
||||
///
|
||||
/// Initialize the shaderchain.
|
||||
///
|
||||
/// @param inImgs1 Three sets of two RGBA images, corresponding to a frame count % 3.
|
||||
/// @param inImg2 Second Input image
|
||||
/// @param optImg1 Optional image for non-first passes.
|
||||
/// @param optImg2 Second optional image for non-first passes.
|
||||
/// @param optImg3 Third optional image for non-first passes.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Delta(Vulkan& vk, std::array<std::array<Core::Image, 2>, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg1,
|
||||
std::optional<Core::Image> optImg2,
|
||||
std::optional<Core::Image> optImg3);
|
||||
|
||||
///
|
||||
/// Dispatch the shaderchain.
|
||||
///
|
||||
void Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx);
|
||||
|
||||
/// Get the first output image
|
||||
[[nodiscard]] const auto& getOutImage1() const { return this->outImg1; }
|
||||
/// Get the second output image
|
||||
[[nodiscard]] const auto& getOutImage2() const { return this->outImg2; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Delta(const Delta&) noexcept = default;
|
||||
Delta& operator=(const Delta&) noexcept = default;
|
||||
Delta(Delta&&) noexcept = default;
|
||||
Delta& operator=(Delta&&) noexcept = default;
|
||||
~Delta() = default;
|
||||
private:
|
||||
std::array<Core::ShaderModule, 10> shaderModules;
|
||||
std::array<Core::Pipeline, 10> pipelines;
|
||||
std::array<Core::Sampler, 3> samplers;
|
||||
struct DeltaPass {
|
||||
Core::Buffer buffer;
|
||||
std::array<Core::DescriptorSet, 3> firstDescriptorSet;
|
||||
std::array<Core::DescriptorSet, 8> descriptorSets;
|
||||
std::array<Core::DescriptorSet, 3> sixthDescriptorSet;
|
||||
};
|
||||
std::vector<DeltaPass> passes;
|
||||
|
||||
std::array<std::array<Core::Image, 2>, 3> inImgs1;
|
||||
Core::Image inImg2;
|
||||
std::optional<Core::Image> optImg1, optImg2, optImg3;
|
||||
std::array<Core::Image, 3> tempImgs1;
|
||||
std::array<Core::Image, 2> tempImgs2;
|
||||
Core::Image outImg1, outImg2;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace LSFG_3_1P::Shaders {
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
///
|
||||
/// Gamma shader.
|
||||
///
|
||||
class Gamma {
|
||||
public:
|
||||
Gamma() = default;
|
||||
|
||||
///
|
||||
/// Initialize the shaderchain.
|
||||
///
|
||||
/// @param inImgs1 Three sets of two RGBA images, corresponding to a frame count % 3.
|
||||
/// @param inImg2 Second Input image
|
||||
/// @param optImg Optional image for non-first passes.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Gamma(Vulkan& vk, std::array<std::array<Core::Image, 2>, 3> inImgs1,
|
||||
Core::Image inImg2, std::optional<Core::Image> optImg);
|
||||
|
||||
///
|
||||
/// Dispatch the shaderchain.
|
||||
///
|
||||
void Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx);
|
||||
|
||||
/// Get the output image
|
||||
[[nodiscard]] const auto& getOutImage() const { return this->outImg; }
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Gamma(const Gamma&) noexcept = default;
|
||||
Gamma& operator=(const Gamma&) noexcept = default;
|
||||
Gamma(Gamma&&) noexcept = default;
|
||||
Gamma& operator=(Gamma&&) noexcept = default;
|
||||
~Gamma() = default;
|
||||
private:
|
||||
std::array<Core::ShaderModule, 5> shaderModules;
|
||||
std::array<Core::Pipeline, 5> pipelines;
|
||||
std::array<Core::Sampler, 3> samplers;
|
||||
struct GammaPass {
|
||||
Core::Buffer buffer;
|
||||
std::array<Core::DescriptorSet, 3> firstDescriptorSet;
|
||||
std::array<Core::DescriptorSet, 4> descriptorSets;
|
||||
};
|
||||
std::vector<GammaPass> passes;
|
||||
|
||||
std::array<std::array<Core::Image, 2>, 3> inImgs1;
|
||||
Core::Image inImg2;
|
||||
std::optional<Core::Image> optImg;
|
||||
std::array<Core::Image, 3> tempImgs1;
|
||||
std::array<Core::Image, 2> tempImgs2;
|
||||
Core::Image outImg;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/buffer.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/descriptorset.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "common/utils.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace LSFG_3_1P::Shaders {
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
///
|
||||
/// Generate shader.
|
||||
///
|
||||
class Generate {
|
||||
public:
|
||||
Generate() = default;
|
||||
|
||||
///
|
||||
/// Initialize the shaderchain.
|
||||
///
|
||||
/// @param inImg1 Input image 1.
|
||||
/// @param inImg2 Input image 2.
|
||||
/// @param inImg3 Input image 3.
|
||||
/// @param inImg4 Input image 4.
|
||||
/// @param inImg5 Input image 5.
|
||||
/// @param fds File descriptors for the output images.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Generate(Vulkan& vk,
|
||||
Core::Image inImg1, Core::Image inImg2,
|
||||
Core::Image inImg3, Core::Image inImg4, Core::Image inImg5,
|
||||
const std::vector<int>& fds, VkFormat format);
|
||||
|
||||
///
|
||||
/// Dispatch the shaderchain.
|
||||
///
|
||||
void Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx);
|
||||
|
||||
/// Trivially copyable, moveable and destructible
|
||||
Generate(const Generate&) noexcept = default;
|
||||
Generate& operator=(const Generate&) noexcept = default;
|
||||
Generate(Generate&&) noexcept = default;
|
||||
Generate& operator=(Generate&&) noexcept = default;
|
||||
~Generate() = default;
|
||||
private:
|
||||
Core::ShaderModule shaderModule;
|
||||
Core::Pipeline pipeline;
|
||||
std::array<Core::Sampler, 2> samplers;
|
||||
struct GeneratePass {
|
||||
Core::Buffer buffer;
|
||||
std::array<Core::DescriptorSet, 2> descriptorSet;
|
||||
};
|
||||
std::vector<GeneratePass> passes;
|
||||
|
||||
Core::Image inImg1, inImg2;
|
||||
Core::Image inImg3, inImg4, inImg5;
|
||||
std::vector<Core::Image> outImgs;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,322 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "v3_1p/shaders/delta.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace LSFG_3_1P::Shaders;
|
||||
|
||||
Delta::Delta(Vulkan& vk, std::array<std::array<Core::Image, 2>, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg1,
|
||||
std::optional<Core::Image> optImg2,
|
||||
std::optional<Core::Image> optImg3)
|
||||
: inImgs1(std::move(inImgs1)), inImg2(std::move(inImg2)),
|
||||
optImg1(std::move(optImg1)), optImg2(std::move(optImg2)),
|
||||
optImg3(std::move(optImg3)) {
|
||||
// create resources
|
||||
this->shaderModules = {{
|
||||
vk.shaders.getShader(vk.device, "p_delta[0]",
|
||||
{ { 1 , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[1]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[2]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[3]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[4]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[5]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[6]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[7]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[8]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_delta[9]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } })
|
||||
}};
|
||||
this->pipelines = {{
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[0]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[1]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[2]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[3]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[4]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[5]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[6]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[7]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[8]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_delta[9]")
|
||||
}};
|
||||
this->samplers.at(0) = vk.resources.getSampler(vk.device);
|
||||
this->samplers.at(1) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, true);
|
||||
this->samplers.at(2) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS, false);
|
||||
|
||||
// create internal images/outputs
|
||||
const VkExtent2D extent = this->inImgs1.at(0).at(0).getExtent();
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
this->tempImgs1.at(i) = Core::Image(vk.device, extent);
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
this->tempImgs2.at(i) = Core::Image(vk.device, extent);
|
||||
|
||||
this->outImg1 = Core::Image(vk.device,
|
||||
{ extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
this->outImg2 = Core::Image(vk.device,
|
||||
{ extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
|
||||
// hook up shaders
|
||||
for (size_t pass_idx = 0; pass_idx < vk.generationCount; pass_idx++) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
pass.buffer = vk.resources.getBuffer(vk.device,
|
||||
static_cast<float>(pass_idx + 1) / static_cast<float>(vk.generationCount + 1),
|
||||
false, !this->optImg1.has_value());
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
pass.firstDescriptorSet.at(i) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(0));
|
||||
pass.firstDescriptorSet.at(i).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at((i + 2) % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at(i % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
|
||||
.build();
|
||||
}
|
||||
pass.descriptorSets.at(0) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(1));
|
||||
pass.descriptorSets.at(0).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
|
||||
.build();
|
||||
pass.descriptorSets.at(1) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(2));
|
||||
pass.descriptorSets.at(1).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1))
|
||||
.build();
|
||||
pass.descriptorSets.at(2) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(3));
|
||||
pass.descriptorSets.at(2).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
|
||||
.build();
|
||||
pass.descriptorSets.at(3) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(4));
|
||||
pass.descriptorSets.at(3).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg1)
|
||||
.build();
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
pass.sixthDescriptorSet.at(i) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(5));
|
||||
pass.sixthDescriptorSet.at(i).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at((i + 2) % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at(i % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2.at(0))
|
||||
.build();
|
||||
}
|
||||
pass.descriptorSets.at(4) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(6));
|
||||
pass.descriptorSets.at(4).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0))
|
||||
.build();
|
||||
pass.descriptorSets.at(5) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(7));
|
||||
pass.descriptorSets.at(5).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2.at(0))
|
||||
.build();
|
||||
pass.descriptorSets.at(6) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(8));
|
||||
pass.descriptorSets.at(6).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0))
|
||||
.build();
|
||||
pass.descriptorSets.at(7) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(9));
|
||||
pass.descriptorSets.at(7).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg3)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg2)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
void Delta::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx) {
|
||||
auto& pass = this->passes.at(pass_idx);
|
||||
|
||||
// first shader
|
||||
const auto extent = this->tempImgs1.at(0).getExtent();
|
||||
const uint32_t threadsX = (extent.width + 7) >> 3;
|
||||
const uint32_t threadsY = (extent.height + 7) >> 3;
|
||||
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImgs1.at((frameCount + 2) % 3))
|
||||
.addW2R(this->inImgs1.at(frameCount % 3))
|
||||
.addW2R(this->optImg1)
|
||||
.addR2W(this->tempImgs1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(0).bind(buf);
|
||||
pass.firstDescriptorSet.at(frameCount % 3).bind(buf, this->pipelines.at(0));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// second shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1)
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(1).bind(buf);
|
||||
pass.descriptorSets.at(0).bind(buf, this->pipelines.at(1));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// third shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addR2W(this->tempImgs1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(2).bind(buf);
|
||||
pass.descriptorSets.at(1).bind(buf, this->pipelines.at(2));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fourth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1)
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(3).bind(buf);
|
||||
pass.descriptorSets.at(2).bind(buf, this->pipelines.at(3));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fifth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addW2R(this->optImg1)
|
||||
.addW2R(this->inImg2)
|
||||
.addR2W(this->outImg1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(4).bind(buf);
|
||||
pass.descriptorSets.at(3).bind(buf, this->pipelines.at(4));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// sixth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImgs1.at((frameCount + 2) % 3))
|
||||
.addW2R(this->inImgs1.at(frameCount % 3))
|
||||
.addW2R(this->optImg1)
|
||||
.addW2R(this->optImg2)
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(5).bind(buf);
|
||||
pass.sixthDescriptorSet.at(frameCount % 3).bind(buf, this->pipelines.at(5));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// seventh shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(6).bind(buf);
|
||||
pass.descriptorSets.at(4).bind(buf, this->pipelines.at(6));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// eighth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1.at(0))
|
||||
.addW2R(this->tempImgs1.at(1))
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
this->pipelines.at(7).bind(buf);
|
||||
pass.descriptorSets.at(5).bind(buf, this->pipelines.at(7));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// ninth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(8).bind(buf);
|
||||
pass.descriptorSets.at(6).bind(buf, this->pipelines.at(8));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// tenth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1.at(0))
|
||||
.addW2R(this->tempImgs1.at(1))
|
||||
.addW2R(this->optImg3)
|
||||
.addR2W(this->outImg2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(9).bind(buf);
|
||||
pass.descriptorSets.at(7).bind(buf, this->pipelines.at(9));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
}
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "v3_1p/shaders/gamma.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace LSFG_3_1P::Shaders;
|
||||
|
||||
Gamma::Gamma(Vulkan& vk, std::array<std::array<Core::Image, 2>, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg)
|
||||
: inImgs1(std::move(inImgs1)), inImg2(std::move(inImg2)),
|
||||
optImg(std::move(optImg)) {
|
||||
// create resources
|
||||
this->shaderModules = {{
|
||||
vk.shaders.getShader(vk.device, "p_gamma[0]",
|
||||
{ { 1 , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_gamma[1]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_gamma[2]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_gamma[3]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
|
||||
vk.shaders.getShader(vk.device, "p_gamma[4]",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } })
|
||||
}};
|
||||
this->pipelines = {{
|
||||
vk.shaders.getPipeline(vk.device, "p_gamma[0]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_gamma[1]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_gamma[2]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_gamma[3]"),
|
||||
vk.shaders.getPipeline(vk.device, "p_gamma[4]")
|
||||
}};
|
||||
this->samplers.at(0) = vk.resources.getSampler(vk.device);
|
||||
this->samplers.at(1) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, true);
|
||||
this->samplers.at(2) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS, false);
|
||||
|
||||
// create internal images/outputs
|
||||
const VkExtent2D extent = this->inImgs1.at(0).at(0).getExtent();
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
this->tempImgs1.at(i) = Core::Image(vk.device, extent);
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
this->tempImgs2.at(i) = Core::Image(vk.device, extent);
|
||||
|
||||
this->outImg = Core::Image(vk.device,
|
||||
{ extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
|
||||
// hook up shaders
|
||||
for (size_t pass_idx = 0; pass_idx < vk.generationCount; pass_idx++) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
pass.buffer = vk.resources.getBuffer(vk.device,
|
||||
static_cast<float>(pass_idx + 1) / static_cast<float>(vk.generationCount + 1),
|
||||
!this->optImg.has_value());
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
pass.firstDescriptorSet.at(i) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(0));
|
||||
pass.firstDescriptorSet.at(i).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at((i + 2) % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1.at(i % 3))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
|
||||
.build();
|
||||
}
|
||||
pass.descriptorSets.at(0) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(1));
|
||||
pass.descriptorSets.at(0).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
|
||||
.build();
|
||||
pass.descriptorSets.at(1) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(2));
|
||||
pass.descriptorSets.at(1).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1))
|
||||
.build();
|
||||
pass.descriptorSets.at(2) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(3));
|
||||
pass.descriptorSets.at(2).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1.at(1))
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
|
||||
.build();
|
||||
pass.descriptorSets.at(3) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModules.at(4));
|
||||
pass.descriptorSets.at(3).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(0))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers.at(2))
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
|
||||
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx) {
|
||||
auto& pass = this->passes.at(pass_idx);
|
||||
|
||||
// first shader
|
||||
const auto extent = this->tempImgs1.at(0).getExtent();
|
||||
const uint32_t threadsX = (extent.width + 7) >> 3;
|
||||
const uint32_t threadsY = (extent.height + 7) >> 3;
|
||||
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImgs1.at((frameCount + 2) % 3))
|
||||
.addW2R(this->inImgs1.at(frameCount % 3))
|
||||
.addW2R(this->optImg)
|
||||
.addR2W(this->tempImgs1)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(0).bind(buf);
|
||||
pass.firstDescriptorSet.at(frameCount % 3).bind(buf, this->pipelines.at(0));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// second shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1)
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(1).bind(buf);
|
||||
pass.descriptorSets.at(0).bind(buf, this->pipelines.at(1));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// third shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addR2W(this->tempImgs1.at(0))
|
||||
.addR2W(this->tempImgs1.at(1))
|
||||
.build();
|
||||
|
||||
this->pipelines.at(2).bind(buf);
|
||||
pass.descriptorSets.at(1).bind(buf, this->pipelines.at(2));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fourth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs1.at(0))
|
||||
.addW2R(this->tempImgs1.at(1))
|
||||
.addR2W(this->tempImgs2)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(3).bind(buf);
|
||||
pass.descriptorSets.at(2).bind(buf, this->pipelines.at(3));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
|
||||
// fifth shader
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->tempImgs2)
|
||||
.addW2R(this->optImg)
|
||||
.addW2R(this->inImg2)
|
||||
.addR2W(this->outImg)
|
||||
.build();
|
||||
|
||||
this->pipelines.at(4).bind(buf);
|
||||
pass.descriptorSets.at(3).bind(buf, this->pipelines.at(4));
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "v3_1p/shaders/generate.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace LSFG_3_1P::Shaders;
|
||||
|
||||
Generate::Generate(Vulkan& vk,
|
||||
Core::Image inImg1, Core::Image inImg2,
|
||||
Core::Image inImg3, Core::Image inImg4, Core::Image inImg5,
|
||||
const std::vector<int>& fds, VkFormat format)
|
||||
: inImg1(std::move(inImg1)), inImg2(std::move(inImg2)),
|
||||
inImg3(std::move(inImg3)), inImg4(std::move(inImg4)),
|
||||
inImg5(std::move(inImg5)) {
|
||||
// create resources
|
||||
this->shaderModule = vk.shaders.getShader(vk.device, "generate",
|
||||
{ { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_SAMPLER },
|
||||
{ 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } });
|
||||
this->pipeline = vk.shaders.getPipeline(vk.device, "generate");
|
||||
this->samplers.at(0) = vk.resources.getSampler(vk.device);
|
||||
this->samplers.at(1) = vk.resources.getSampler(vk.device,
|
||||
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS);
|
||||
|
||||
// create internal images/outputs
|
||||
const VkExtent2D extent = this->inImg1.getExtent();
|
||||
for (size_t i = 0; i < vk.generationCount; i++)
|
||||
this->outImgs.emplace_back(vk.device, extent, format,
|
||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT, fds.empty() ? -1 : fds.at(i));
|
||||
|
||||
// hook up shaders
|
||||
for (size_t i = 0; i < vk.generationCount; i++) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
pass.buffer = vk.resources.getBuffer(vk.device,
|
||||
static_cast<float>(i + 1) / static_cast<float>(vk.generationCount + 1));
|
||||
for (size_t j = 0; j < 2; j++) {
|
||||
pass.descriptorSet.at(j) = Core::DescriptorSet(vk.device, vk.descriptorPool,
|
||||
this->shaderModule);
|
||||
pass.descriptorSet.at(j).update(vk.device)
|
||||
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, pass.buffer)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLER, this->samplers)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, j == 0 ? this->inImg2 : this->inImg1)
|
||||
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, j == 0 ? this->inImg1 : 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->outImgs.at(i))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Generate::Dispatch(const Core::CommandBuffer& buf, uint64_t frameCount, uint64_t pass_idx) {
|
||||
auto& pass = this->passes.at(pass_idx);
|
||||
|
||||
// first pass
|
||||
const auto extent = this->inImg1.getExtent();
|
||||
const uint32_t threadsX = (extent.width + 15) >> 4;
|
||||
const uint32_t threadsY = (extent.height + 15) >> 4;
|
||||
|
||||
Utils::BarrierBuilder(buf)
|
||||
.addW2R(this->inImg1)
|
||||
.addW2R(this->inImg2)
|
||||
.addW2R(this->inImg3)
|
||||
.addW2R(this->inImg4)
|
||||
.addW2R(this->inImg5)
|
||||
.addR2W(this->outImgs.at(pass_idx))
|
||||
.build();
|
||||
|
||||
this->pipeline.bind(buf);
|
||||
pass.descriptorSet.at(frameCount % 2).bind(buf, this->pipeline);
|
||||
buf.dispatch(threadsX, threadsY, 1);
|
||||
}
|
||||
|
|
@ -7,6 +7,11 @@ set(BACKEND_SOURCES
|
|||
"src/shaderchains/alpha1.cpp"
|
||||
"src/shaderchains/beta0.cpp"
|
||||
"src/shaderchains/beta1.cpp"
|
||||
"src/shaderchains/delta0.cpp"
|
||||
"src/shaderchains/delta1.cpp"
|
||||
"src/shaderchains/gamma0.cpp"
|
||||
"src/shaderchains/gamma1.cpp"
|
||||
"src/shaderchains/generate.cpp"
|
||||
"src/shaderchains/mipmaps.cpp"
|
||||
"src/lsfgvk.cpp")
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,8 @@ using namespace ls;
|
|||
|
||||
ConstantBuffer ls::getDefaultConstantBuffer(
|
||||
size_t index, size_t total,
|
||||
bool hdr, float invFlow,
|
||||
bool isFirst, bool isFirst2) {
|
||||
bool hdr, float invFlow) {
|
||||
return ConstantBuffer {
|
||||
.firstIter = isFirst ? 1U : 0U,
|
||||
.firstIterS = isFirst2 ? 1U : 0U,
|
||||
.advancedColorKind = hdr ? 2U : 0U,
|
||||
.hdrSupport = hdr ? 1U : 0U,
|
||||
.resolutionInvScale = invFlow,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -19,6 +20,7 @@ namespace ls {
|
|||
ls::R<const extr::ShaderRegistry> shaders; // safe back reference
|
||||
|
||||
vk::Buffer constantBuffer;
|
||||
std::vector<vk::Buffer> constantBuffers;
|
||||
vk::Sampler bnbSampler; //!< border, no compare, black
|
||||
vk::Sampler bnwSampler; //!< border, no compare, white
|
||||
vk::Sampler eabSampler; //!< edge, always compare, black
|
||||
|
|
@ -50,13 +52,10 @@ namespace ls {
|
|||
/// @param total total amount of images
|
||||
/// @param hdr whether HDR is enabled
|
||||
/// @param invFlow inverted flow scale value
|
||||
/// @param isFirst whether this is the first iteration
|
||||
/// @param isFirst2 whether this is the first iteration (second flag)
|
||||
/// @return prefilled constant buffer
|
||||
ConstantBuffer getDefaultConstantBuffer(
|
||||
size_t index, size_t total,
|
||||
bool hdr, float invFlow,
|
||||
bool isFirst, bool isFirst2 // TODO: figure out if necessary
|
||||
bool hdr, float invFlow
|
||||
);
|
||||
|
||||
/// round down a VkExtent2D
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "extraction/shader_registry.hpp"
|
||||
#include "helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/errors.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
#include "lsfg-vk-common/vulkan/timeline_semaphore.hpp"
|
||||
|
|
@ -11,6 +13,11 @@
|
|||
#include "shaderchains/alpha1.hpp"
|
||||
#include "shaderchains/beta0.hpp"
|
||||
#include "shaderchains/beta1.hpp"
|
||||
#include "shaderchains/delta0.hpp"
|
||||
#include "shaderchains/delta1.hpp"
|
||||
#include "shaderchains/gamma0.hpp"
|
||||
#include "shaderchains/gamma1.hpp"
|
||||
#include "shaderchains/generate.hpp"
|
||||
#include "shaderchains/mipmaps.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -82,6 +89,7 @@ namespace lsfgvk {
|
|||
private:
|
||||
std::pair<vk::Image, vk::Image> sourceImages;
|
||||
std::vector<vk::Image> destImages;
|
||||
vk::Image blackImage;
|
||||
|
||||
vk::TimelineSemaphore syncSemaphore; // imported
|
||||
vk::TimelineSemaphore prepassSemaphore;
|
||||
|
|
@ -98,6 +106,15 @@ namespace lsfgvk {
|
|||
std::array<chains::Alpha1, 7> alpha1;
|
||||
chains::Beta0 beta0;
|
||||
chains::Beta1 beta1;
|
||||
struct Pass {
|
||||
std::vector<chains::Gamma0> gamma0;
|
||||
std::vector<chains::Gamma1> gamma1;
|
||||
|
||||
std::vector<chains::Delta0> delta0;
|
||||
std::vector<chains::Delta1> delta1;
|
||||
ls::lazy<chains::Generate> generate;
|
||||
};
|
||||
std::vector<Pass> passes;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -236,6 +253,16 @@ namespace {
|
|||
throw lsfgvk::error("Unable to import destination images", e);
|
||||
}
|
||||
}
|
||||
/// create a black image
|
||||
vk::Image createBlackImage(const vk::Vulkan& vk) {
|
||||
try {
|
||||
return{vk,
|
||||
{ .width = 4, .height = 4 }
|
||||
};
|
||||
} catch (const std::exception& e) {
|
||||
throw lsfgvk::error("Unable to create black image", e);
|
||||
}
|
||||
}
|
||||
/// import timeline semaphore
|
||||
vk::TimelineSemaphore importTimelineSemaphore(const vk::Vulkan& vk, int syncFd) {
|
||||
try {
|
||||
|
|
@ -273,12 +300,23 @@ namespace {
|
|||
const auto& shaders = instance.getShaderRegistry();
|
||||
|
||||
try {
|
||||
std::vector<vk::Buffer> constantBuffers{};
|
||||
constantBuffers.reserve(count);
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
constantBuffers.emplace_back(vk,
|
||||
ls::getDefaultConstantBuffer(
|
||||
i, count,
|
||||
hdr, flow
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
.vk = std::ref(vk),
|
||||
.shaders = std::ref(shaders),
|
||||
.constantBuffer{vk,
|
||||
ls::getDefaultConstantBuffer(0, 1,
|
||||
hdr, flow, false, false)},
|
||||
ls::getDefaultConstantBuffer(0, 1, hdr, flow)},
|
||||
.constantBuffers{std::move(constantBuffers)},
|
||||
.bnbSampler{vk, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, false},
|
||||
.bnwSampler{vk, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, true},
|
||||
.eabSampler{vk, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_COMPARE_OP_ALWAYS, false},
|
||||
|
|
@ -305,6 +343,7 @@ ContextImpl::ContextImpl(const InstanceImpl& instance,
|
|||
extent, hdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM)),
|
||||
destImages(importImages(instance.getVulkan(), destFds,
|
||||
extent, hdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM)),
|
||||
blackImage(createBlackImage(instance.getVulkan())),
|
||||
syncSemaphore(importTimelineSemaphore(instance.getVulkan(), syncFd)),
|
||||
prepassSemaphore(createPrepassSemaphore(instance.getVulkan())),
|
||||
cmdbufs(createCommandBuffers(instance.getVulkan(), 16)),
|
||||
|
|
@ -330,8 +369,80 @@ ContextImpl::ContextImpl(const InstanceImpl& instance,
|
|||
},
|
||||
beta0(ctx, alpha1.at(0).getImages()),
|
||||
beta1(ctx, beta0.getImages()) {
|
||||
// build main passes
|
||||
for (size_t i = 0; i < destImages.size(); ++i) {
|
||||
auto& pass = this->passes.emplace_back();
|
||||
|
||||
pass.gamma0.reserve(7);
|
||||
pass.gamma1.reserve(7);
|
||||
pass.delta0.reserve(3);
|
||||
pass.delta1.reserve(3);
|
||||
for (size_t j = 0; j < 7; j++) {
|
||||
if (j == 0) { // first pass has no prior data
|
||||
pass.gamma0.emplace_back(ctx, i,
|
||||
this->alpha1.at(6 - j).getImages(),
|
||||
this->blackImage
|
||||
);
|
||||
pass.gamma1.emplace_back(ctx, i,
|
||||
pass.gamma0.at(j).getImages(),
|
||||
this->blackImage,
|
||||
this->beta1.getImages().at(5)
|
||||
);
|
||||
} else { // other passes use prior data
|
||||
pass.gamma0.emplace_back(ctx, i,
|
||||
this->alpha1.at(6 - j).getImages(),
|
||||
pass.gamma1.at(j - 1).getImage()
|
||||
);
|
||||
pass.gamma1.emplace_back(ctx, i,
|
||||
pass.gamma0.at(j).getImages(),
|
||||
pass.gamma1.at(j - 1).getImage(),
|
||||
this->beta1.getImages().at(6 - j)
|
||||
);
|
||||
}
|
||||
|
||||
if (j == 4) { // first special pass has no prior data
|
||||
pass.delta0.emplace_back(ctx, i,
|
||||
this->alpha1.at(6 - j).getImages(),
|
||||
this->blackImage,
|
||||
pass.gamma1.at(j - 1).getImage(),
|
||||
this->blackImage
|
||||
);
|
||||
pass.delta1.emplace_back(ctx, i,
|
||||
pass.delta0.at(j - 4).getImages0(),
|
||||
pass.delta0.at(j - 4).getImages1(),
|
||||
this->blackImage,
|
||||
this->beta1.getImages().at(6 - j),
|
||||
this->blackImage
|
||||
);
|
||||
} else if (j > 4) { // further passes do
|
||||
pass.delta0.emplace_back(ctx, i,
|
||||
this->alpha1.at(6 - j).getImages(),
|
||||
pass.delta1.at(j - 5).getImage0(),
|
||||
pass.gamma1.at(j - 1).getImage(),
|
||||
this->beta1.getImages().at(6 - j)
|
||||
);
|
||||
pass.delta1.emplace_back(ctx, i,
|
||||
pass.delta0.at(j - 4).getImages0(),
|
||||
pass.delta0.at(j - 4).getImages1(),
|
||||
pass.delta1.at(j - 5).getImage0(),
|
||||
this->beta1.getImages().at(6 - j),
|
||||
pass.delta1.at(j - 5).getImage1()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pass.generate.emplace(ctx, i,
|
||||
this->sourceImages,
|
||||
pass.gamma1.at(6).getImage(),
|
||||
pass.delta1.at(2).getImage0(),
|
||||
pass.delta1.at(2).getImage1(),
|
||||
this->destImages.at(i)
|
||||
);
|
||||
}
|
||||
|
||||
// initialize all images
|
||||
const vk::CommandBuffer cmdbuf{ctx.vk};
|
||||
cmdbuf.prepareImage(this->blackImage);
|
||||
mipmaps.prepare(cmdbuf);
|
||||
for (size_t i = 0; i < 7; ++i) {
|
||||
alpha0.at(i).prepare(cmdbuf);
|
||||
|
|
@ -339,6 +450,16 @@ ContextImpl::ContextImpl(const InstanceImpl& instance,
|
|||
}
|
||||
beta0.prepare(cmdbuf);
|
||||
beta1.prepare(cmdbuf);
|
||||
for (const auto& pass : this->passes) {
|
||||
for (size_t i = 0; i < 7; ++i) {
|
||||
pass.gamma0.at(i).prepare(cmdbuf);
|
||||
pass.gamma1.at(i).prepare(cmdbuf);
|
||||
|
||||
if (i < 4) continue;
|
||||
pass.delta0.at(i - 4).prepare(cmdbuf);
|
||||
pass.delta1.at(i - 4).prepare(cmdbuf);
|
||||
}
|
||||
}
|
||||
cmdbuf.submit(ctx.vk); // wait for completion
|
||||
}
|
||||
|
||||
|
|
@ -387,11 +508,20 @@ void Context::scheduleFrames() {
|
|||
this->idx++;
|
||||
|
||||
// schedule main passes
|
||||
for (size_t i = 0; i < this->destImages.size(); ++i) {
|
||||
for (size_t i = 0; i < this->destImages.size(); i++) {
|
||||
vk::CommandBuffer& cmdbuf = this->cmdbufs.at(this->cmdbuf_idx++ % this->cmdbufs.size());
|
||||
cmdbuf = vk::CommandBuffer(this->ctx.vk);
|
||||
|
||||
// (...)
|
||||
const auto& pass = this->passes.at(i);
|
||||
for (size_t j = 0; j < 7; j++) {
|
||||
pass.gamma0.at(j).render(cmdbuf, this->fidx);
|
||||
pass.gamma1.at(j).render(cmdbuf);
|
||||
|
||||
if (j < 4) continue;
|
||||
pass.delta0.at(j - 4).render(cmdbuf, this->fidx);
|
||||
pass.delta1.at(j - 4).render(cmdbuf);
|
||||
}
|
||||
pass.generate->render(cmdbuf, this->fidx);
|
||||
|
||||
cmdbuf.submit(this->ctx.vk,
|
||||
this->prepassSemaphore, this->idx - 1,
|
||||
|
|
|
|||
73
lsfg-vk-backend/src/shaderchains/delta0.cpp
Normal file
73
lsfg-vk-backend/src/shaderchains/delta0.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "delta0.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace chains;
|
||||
|
||||
Delta0::Delta0(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<std::vector<vk::Image>>& sourceImages,
|
||||
const vk::Image& additionalInput0,
|
||||
const vk::Image& additionalInput1,
|
||||
const vk::Image& additionalInput2) {
|
||||
const size_t m = ctx.perf ? 1 : 2; // multiplier
|
||||
const VkExtent2D extent = sourceImages.at(0).at(0).getExtent();
|
||||
|
||||
// create output images
|
||||
this->images0.reserve(3);
|
||||
for(size_t i = 0; i < 3; i++)
|
||||
this->images0.emplace_back(ctx.vk, extent);
|
||||
this->images1.reserve(m);
|
||||
for (size_t i = 0; i < m; i++)
|
||||
this->images1.emplace_back(ctx.vk, extent);
|
||||
|
||||
// create descriptor sets
|
||||
const auto& shaders = (ctx.perf ?
|
||||
ctx.shaders.get().performance : ctx.shaders.get().quality).delta;
|
||||
|
||||
this->sets0.reserve(3);
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
this->sets0.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(sourceImages.at((i + 2) % 3))
|
||||
.sampleds(sourceImages.at(i % 3))
|
||||
.sampled(additionalInput0)
|
||||
.storages(this->images0)
|
||||
.sampler(ctx.bnwSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, shaders.at(0)));
|
||||
|
||||
this->sets1.reserve(3);
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
this->sets1.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(sourceImages.at((i + 2) % 3))
|
||||
.sampleds(sourceImages.at(i % 3))
|
||||
.sampled(additionalInput1)
|
||||
.sampled(additionalInput2)
|
||||
.storages(this->images1)
|
||||
.sampler(ctx.bnwSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, shaders.at(5)));
|
||||
|
||||
// store dispatch extents
|
||||
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
|
||||
}
|
||||
|
||||
void Delta0::prepare(const vk::CommandBuffer& cmd) const {
|
||||
for (const auto& img : this->images0)
|
||||
cmd.prepareImage(img);
|
||||
for (const auto& img : this->images1)
|
||||
cmd.prepareImage(img);
|
||||
}
|
||||
|
||||
void Delta0::render(const vk::CommandBuffer& cmd, size_t idx) const {
|
||||
this->sets0[idx % 3].dispatch(cmd, dispatchExtent);
|
||||
this->sets1[idx % 3].dispatch(cmd, dispatchExtent);
|
||||
}
|
||||
55
lsfg-vk-backend/src/shaderchains/delta0.hpp
Normal file
55
lsfg-vk-backend/src/shaderchains/delta0.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/managed_shader.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace ctx { struct Ctx; }
|
||||
|
||||
namespace chains {
|
||||
/// delta shaderchain
|
||||
class Delta0 {
|
||||
public:
|
||||
/// create a delta shaderchain
|
||||
/// @param ctx context
|
||||
/// @param idx generated frame index
|
||||
/// @param sourceImages source images
|
||||
/// @param additionalInput0 additional input image
|
||||
/// @param additionalInput1 additional input image
|
||||
/// @param additionalInput2 additional input image
|
||||
Delta0(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<std::vector<vk::Image>>& sourceImages,
|
||||
const vk::Image& additionalInput0,
|
||||
const vk::Image& additionalInput1,
|
||||
const vk::Image& additionalInput2);
|
||||
|
||||
/// prepare the shaderchain initially
|
||||
/// @param cmd command buffer
|
||||
void prepare(const vk::CommandBuffer& cmd) const;
|
||||
|
||||
/// render the delta shaderchain
|
||||
/// @param cmd command buffer
|
||||
/// @param idx frame index
|
||||
void render(const vk::CommandBuffer& cmd, size_t idx) const;
|
||||
|
||||
/// get the generated images
|
||||
/// @return vector of images
|
||||
[[nodiscard]] const auto& getImages0() const { return this->images0; }
|
||||
|
||||
/// get the other generated images
|
||||
/// @return vector of images
|
||||
[[nodiscard]] const auto& getImages1() const { return this->images1; }
|
||||
private:
|
||||
std::vector<vk::Image> images0;
|
||||
std::vector<vk::Image> images1;
|
||||
|
||||
std::vector<ls::ManagedShader> sets0;
|
||||
std::vector<ls::ManagedShader> sets1;
|
||||
VkExtent2D dispatchExtent{};
|
||||
};
|
||||
}
|
||||
107
lsfg-vk-backend/src/shaderchains/delta1.cpp
Normal file
107
lsfg-vk-backend/src/shaderchains/delta1.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "delta1.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace chains;
|
||||
|
||||
Delta1::Delta1(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<vk::Image>& sourceImages0,
|
||||
const std::vector<vk::Image>& sourceImages1,
|
||||
const vk::Image& additionalInput0,
|
||||
const vk::Image& additionalInput1,
|
||||
const vk::Image& additionalInput2) {
|
||||
const size_t m = ctx.perf ? 1 : 2; // multiplier
|
||||
const VkExtent2D extent = sourceImages0.at(0).getExtent();
|
||||
|
||||
// create temporary & output images
|
||||
for (size_t i = 0; i < (2 * m); i++) {
|
||||
this->tempImages0.emplace_back(ctx.vk, extent);
|
||||
this->tempImages1.emplace_back(ctx.vk, extent);
|
||||
}
|
||||
this->image0.emplace(ctx.vk,
|
||||
VkExtent2D { extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
);
|
||||
this->image1.emplace(ctx.vk,
|
||||
VkExtent2D { extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
);
|
||||
|
||||
// create descriptor sets
|
||||
const auto& shaders = (ctx.perf ?
|
||||
ctx.shaders.get().performance : ctx.shaders.get().quality).delta;
|
||||
this->sets.reserve(4 + 4);
|
||||
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(sourceImages0)
|
||||
.storages(this->tempImages0)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(1)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages0)
|
||||
.storages(this->tempImages1)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(2)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages1)
|
||||
.storages(this->tempImages0)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(3)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages0)
|
||||
.sampled(additionalInput0)
|
||||
.sampled(additionalInput1)
|
||||
.storage(*this->image0)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, shaders.at(4)));
|
||||
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(sourceImages1)
|
||||
.storages(this->tempImages0, 0, m)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(6)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages0, 0, m)
|
||||
.storages(this->tempImages1, 0, m)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(7)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages1, 0, m)
|
||||
.storages(this->tempImages0, 0, m)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(8)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages0, 0, m)
|
||||
.sampled(additionalInput2)
|
||||
.storage(*this->image1)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, shaders.at(9)));
|
||||
|
||||
// store dispatch extents
|
||||
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
|
||||
}
|
||||
|
||||
void Delta1::prepare(const vk::CommandBuffer& cmd) const {
|
||||
for (size_t i = 0; i < this->tempImages0.size(); i++) {
|
||||
cmd.prepareImage(this->tempImages0.at(i));
|
||||
cmd.prepareImage(this->tempImages1.at(i));
|
||||
}
|
||||
cmd.prepareImage(*this->image0);
|
||||
cmd.prepareImage(*this->image1);
|
||||
}
|
||||
|
||||
void Delta1::render(const vk::CommandBuffer& cmd) const {
|
||||
for (const auto& set : this->sets)
|
||||
set.dispatch(cmd, dispatchExtent);
|
||||
}
|
||||
58
lsfg-vk-backend/src/shaderchains/delta1.hpp
Normal file
58
lsfg-vk-backend/src/shaderchains/delta1.hpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/managed_shader.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace ctx { struct Ctx; }
|
||||
|
||||
namespace chains {
|
||||
/// gamma shaderchain
|
||||
class Delta1 {
|
||||
public:
|
||||
/// create a gamma shaderchain
|
||||
/// @param ctx context
|
||||
/// @param idx generated frame index
|
||||
/// @param sourceImages0 source images
|
||||
/// @param sourceImages1 source images
|
||||
/// @param additionalInput0 additional input image
|
||||
/// @param additionalInput1 additional input image
|
||||
/// @param additionalInput2 additional input image
|
||||
Delta1(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<vk::Image>& sourceImages0,
|
||||
const std::vector<vk::Image>& sourceImages1,
|
||||
const vk::Image& additionalInput0,
|
||||
const vk::Image& additionalInput1,
|
||||
const vk::Image& additionalInput2);
|
||||
|
||||
/// prepare the shaderchain initially
|
||||
/// @param cmd command buffer
|
||||
void prepare(const vk::CommandBuffer& cmd) const;
|
||||
|
||||
/// render the gamma shaderchain
|
||||
/// @param cmd command buffer
|
||||
void render(const vk::CommandBuffer& cmd) const;
|
||||
|
||||
/// get the first generated image
|
||||
/// @return image
|
||||
[[nodiscard]] const auto& getImage0() const { return *this->image0; }
|
||||
|
||||
/// get the second generated image
|
||||
/// @return image
|
||||
[[nodiscard]] const auto& getImage1() const { return *this->image1; }
|
||||
private:
|
||||
std::vector<vk::Image> tempImages0;
|
||||
std::vector<vk::Image> tempImages1;
|
||||
ls::lazy<vk::Image> image0;
|
||||
ls::lazy<vk::Image> image1;
|
||||
|
||||
std::vector<ls::ManagedShader> sets;
|
||||
VkExtent2D dispatchExtent{};
|
||||
};
|
||||
}
|
||||
50
lsfg-vk-backend/src/shaderchains/gamma0.cpp
Normal file
50
lsfg-vk-backend/src/shaderchains/gamma0.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include "gamma0.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace chains;
|
||||
|
||||
Gamma0::Gamma0(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<std::vector<vk::Image>>& sourceImages,
|
||||
const vk::Image& additionalInput) {
|
||||
const VkExtent2D extent = sourceImages.at(0).at(0).getExtent();
|
||||
|
||||
// create output images
|
||||
this->images.reserve(3);
|
||||
for(size_t i = 0; i < 3; i++)
|
||||
this->images.emplace_back(ctx.vk, extent);
|
||||
|
||||
// create descriptor sets
|
||||
const auto& shader = (ctx.perf ?
|
||||
ctx.shaders.get().performance : ctx.shaders.get().quality).gamma.at(0);
|
||||
this->sets.reserve(3);
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(sourceImages.at((i + 2) % 3))
|
||||
.sampleds(sourceImages.at(i % 3))
|
||||
.sampled(additionalInput)
|
||||
.storages(this->images)
|
||||
.sampler(ctx.bnwSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, shader));
|
||||
|
||||
// store dispatch extents
|
||||
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
|
||||
}
|
||||
|
||||
void Gamma0::prepare(const vk::CommandBuffer& cmd) const {
|
||||
for (const auto& img : this->images)
|
||||
cmd.prepareImage(img);
|
||||
}
|
||||
|
||||
void Gamma0::render(const vk::CommandBuffer& cmd, size_t idx) const {
|
||||
this->sets[idx % 3].dispatch(cmd, dispatchExtent);
|
||||
}
|
||||
45
lsfg-vk-backend/src/shaderchains/gamma0.hpp
Normal file
45
lsfg-vk-backend/src/shaderchains/gamma0.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/managed_shader.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace ctx { struct Ctx; }
|
||||
|
||||
namespace chains {
|
||||
/// gamma shaderchain
|
||||
class Gamma0 {
|
||||
public:
|
||||
/// create a gamma shaderchain
|
||||
/// @param ctx context
|
||||
/// @param idx generated frame index
|
||||
/// @param sourceImages source images
|
||||
/// @param additionalInput additional input image
|
||||
Gamma0(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<std::vector<vk::Image>>& sourceImages,
|
||||
const vk::Image& additionalInput);
|
||||
|
||||
/// prepare the shaderchain initially
|
||||
/// @param cmd command buffer
|
||||
void prepare(const vk::CommandBuffer& cmd) const;
|
||||
|
||||
/// render the gamma shaderchain
|
||||
/// @param cmd command buffer
|
||||
/// @param idx frame index
|
||||
void render(const vk::CommandBuffer& cmd, size_t idx) const;
|
||||
|
||||
/// get the generated images
|
||||
/// @return vector of images
|
||||
[[nodiscard]] const auto& getImages() const { return this->images; }
|
||||
private:
|
||||
std::vector<vk::Image> images;
|
||||
|
||||
std::vector<ls::ManagedShader> sets;
|
||||
VkExtent2D dispatchExtent{};
|
||||
};
|
||||
}
|
||||
75
lsfg-vk-backend/src/shaderchains/gamma1.cpp
Normal file
75
lsfg-vk-backend/src/shaderchains/gamma1.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "gamma1.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace chains;
|
||||
|
||||
Gamma1::Gamma1(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<vk::Image>& sourceImages,
|
||||
const vk::Image& additionalInput0,
|
||||
const vk::Image& additionalInput1) {
|
||||
const size_t m = ctx.perf ? 1 : 2; // multiplier
|
||||
const VkExtent2D extent = sourceImages.at(0).getExtent();
|
||||
|
||||
// create temporary & output images
|
||||
for (size_t i = 0; i < (2 * m); i++) {
|
||||
this->tempImages0.emplace_back(ctx.vk, extent);
|
||||
this->tempImages1.emplace_back(ctx.vk, extent);
|
||||
}
|
||||
this->image.emplace(ctx.vk,
|
||||
VkExtent2D { extent.width, extent.height },
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
);
|
||||
|
||||
// create descriptor sets
|
||||
const auto& shaders = (ctx.perf ?
|
||||
ctx.shaders.get().performance : ctx.shaders.get().quality).gamma;
|
||||
this->sets.reserve(4);
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(sourceImages)
|
||||
.storages(this->tempImages0)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(1)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages0)
|
||||
.storages(this->tempImages1)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(2)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages1)
|
||||
.storages(this->tempImages0)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.build(ctx.vk, shaders.at(3)));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampleds(this->tempImages0)
|
||||
.sampled(additionalInput0)
|
||||
.sampled(additionalInput1)
|
||||
.storage(*this->image)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, shaders.at(4)));
|
||||
|
||||
// store dispatch extents
|
||||
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
|
||||
}
|
||||
|
||||
void Gamma1::prepare(const vk::CommandBuffer& cmd) const {
|
||||
for (size_t i = 0; i < this->tempImages0.size(); i++) {
|
||||
cmd.prepareImage(this->tempImages0.at(i));
|
||||
cmd.prepareImage(this->tempImages1.at(i));
|
||||
}
|
||||
cmd.prepareImage(*this->image);
|
||||
}
|
||||
|
||||
void Gamma1::render(const vk::CommandBuffer& cmd) const {
|
||||
for (const auto& set : this->sets)
|
||||
set.dispatch(cmd, dispatchExtent);
|
||||
}
|
||||
49
lsfg-vk-backend/src/shaderchains/gamma1.hpp
Normal file
49
lsfg-vk-backend/src/shaderchains/gamma1.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/managed_shader.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace ctx { struct Ctx; }
|
||||
|
||||
namespace chains {
|
||||
/// gamma shaderchain
|
||||
class Gamma1 {
|
||||
public:
|
||||
/// create a gamma shaderchain
|
||||
/// @param ctx context
|
||||
/// @param idx generated frame index
|
||||
/// @param sourceImages source images
|
||||
/// @param additionalInput0 additional input image
|
||||
/// @param additionalInput1 additional input image
|
||||
Gamma1(const ls::Ctx& ctx, size_t idx,
|
||||
const std::vector<vk::Image>& sourceImages,
|
||||
const vk::Image& additionalInput0,
|
||||
const vk::Image& additionalInput1);
|
||||
|
||||
/// prepare the shaderchain initially
|
||||
/// @param cmd command buffer
|
||||
void prepare(const vk::CommandBuffer& cmd) const;
|
||||
|
||||
/// render the gamma shaderchain
|
||||
/// @param cmd command buffer
|
||||
void render(const vk::CommandBuffer& cmd) const;
|
||||
|
||||
/// get the generated image
|
||||
/// @return image
|
||||
[[nodiscard]] const auto& getImage() const { return *this->image; }
|
||||
private:
|
||||
std::vector<vk::Image> tempImages0;
|
||||
std::vector<vk::Image> tempImages1;
|
||||
ls::lazy<vk::Image> image;
|
||||
|
||||
std::vector<ls::ManagedShader> sets;
|
||||
VkExtent2D dispatchExtent{};
|
||||
};
|
||||
}
|
||||
52
lsfg-vk-backend/src/shaderchains/generate.cpp
Normal file
52
lsfg-vk-backend/src/shaderchains/generate.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include "generate.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/helpers/pointers.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
using namespace chains;
|
||||
|
||||
Generate::Generate(const ls::Ctx& ctx, size_t idx,
|
||||
const std::pair<vk::Image, vk::Image>& sourceImages,
|
||||
const vk::Image& inputImage1,
|
||||
const vk::Image& inputImage2,
|
||||
const vk::Image& inputImage3,
|
||||
const vk::Image& outputImage) {
|
||||
// create descriptor sets
|
||||
this->sets.reserve(2);
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampled(sourceImages.second)
|
||||
.sampled(sourceImages.first)
|
||||
.sampled(inputImage1)
|
||||
.sampled(inputImage2)
|
||||
.sampled(inputImage3)
|
||||
.storage(outputImage)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, ctx.shaders.get().generate));
|
||||
this->sets.emplace_back(ls::ManagedShaderBuilder()
|
||||
.sampled(sourceImages.first)
|
||||
.sampled(sourceImages.second)
|
||||
.sampled(inputImage1)
|
||||
.sampled(inputImage2)
|
||||
.sampled(inputImage3)
|
||||
.storage(outputImage)
|
||||
.sampler(ctx.bnbSampler)
|
||||
.sampler(ctx.eabSampler)
|
||||
.buffer(ctx.constantBuffers.at(idx))
|
||||
.build(ctx.vk, ctx.shaders.get().generate));
|
||||
|
||||
// store dispatch extent
|
||||
this->dispatchExtent = ls::add_shift_extent(ctx.sourceExtent, 15, 4);
|
||||
}
|
||||
|
||||
void Generate::render(const vk::CommandBuffer& cmd, size_t idx) const {
|
||||
this->sets[idx % 2].dispatch(cmd, this->dispatchExtent);
|
||||
}
|
||||
41
lsfg-vk-backend/src/shaderchains/generate.hpp
Normal file
41
lsfg-vk-backend/src/shaderchains/generate.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "../helpers/managed_shader.hpp"
|
||||
#include "../helpers/utils.hpp"
|
||||
#include "lsfg-vk-common/vulkan/command_buffer.hpp"
|
||||
#include "lsfg-vk-common/vulkan/image.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace ctx { struct Ctx; }
|
||||
|
||||
namespace chains {
|
||||
/// generate shaderchain
|
||||
class Generate {
|
||||
public:
|
||||
/// create a generate shaderchain
|
||||
/// @param ctx context
|
||||
/// @param idx generated frame index
|
||||
/// @param sourceImages pair of source images
|
||||
/// @param inputImage1 input image 1
|
||||
/// @param inputImage2 input image 2
|
||||
/// @param inputImage3 input image 3
|
||||
Generate(const ls::Ctx& ctx, size_t idx,
|
||||
const std::pair<vk::Image, vk::Image>& sourceImages,
|
||||
const vk::Image& inputImage1,
|
||||
const vk::Image& inputImage2,
|
||||
const vk::Image& inputImage3,
|
||||
const vk::Image& outputImage);
|
||||
|
||||
/// render the generate shaderchain
|
||||
/// @param cmd command buffer
|
||||
/// @param idx frame index
|
||||
void render(const vk::CommandBuffer& cmd, size_t idx) const;
|
||||
private:
|
||||
std::vector<ls::ManagedShader> sets;
|
||||
VkExtent2D dispatchExtent{};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ls {
|
||||
|
|
@ -8,6 +9,47 @@ namespace ls {
|
|||
template<typename T>
|
||||
using R = std::reference_wrapper<T>;
|
||||
|
||||
/// helper (eyecandy) alias for std::optional
|
||||
template<typename T>
|
||||
class lazy {
|
||||
public:
|
||||
/// default constructor
|
||||
lazy() = default;
|
||||
|
||||
/// emplace value
|
||||
/// @param args constructor arguments
|
||||
/// @return reference to constructed value
|
||||
/// @throws std::logic_error if value already present
|
||||
template<typename... Args>
|
||||
T& emplace(Args&&... args) {
|
||||
if (this->opt.has_value())
|
||||
throw std::logic_error("lazy: value already present");
|
||||
|
||||
this->opt.emplace(std::forward<Args>(args)...);
|
||||
return *this->opt;
|
||||
}
|
||||
|
||||
/// get reference to value
|
||||
/// @return reference to value
|
||||
/// @throws std::logic_error if no value present
|
||||
const T& operator*() const {
|
||||
if (!this->opt.has_value())
|
||||
throw std::logic_error("lazy: no value present");
|
||||
return *this->opt;
|
||||
}
|
||||
|
||||
/// get pointer to value
|
||||
/// @return pointer to value
|
||||
/// @throws std::logic_error if no value present
|
||||
const T* operator->() const {
|
||||
if (!this->opt.has_value())
|
||||
throw std::logic_error("lazy: no value present");
|
||||
return &(*this->opt);
|
||||
}
|
||||
private:
|
||||
std::optional<T> opt{};
|
||||
};
|
||||
|
||||
/// simplified alternative to std::optional<std::unique_ptr>
|
||||
template<typename T>
|
||||
class owned_ptr {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue