more refactors and fixes

This commit is contained in:
PancakeTAS 2025-06-30 06:52:42 +02:00
parent 50f5153374
commit faff05fb4f
No known key found for this signature in database
18 changed files with 364 additions and 248 deletions

View file

@ -77,6 +77,7 @@ namespace Vulkan::Core {
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Image& image); DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Image& image);
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Sampler& sampler); DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Sampler& sampler);
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Buffer& buffer); DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Buffer& buffer);
DescriptorSetUpdateBuilder& add(VkDescriptorType type); // empty entry
/// Add a list of resources to the descriptor set update. /// Add a list of resources to the descriptor set update.
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector<Image>& images) { DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector<Image>& images) {
@ -97,6 +98,14 @@ namespace Vulkan::Core {
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::array<Buffer, N>& buffers) { DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::array<Buffer, N>& buffers) {
for (const auto& buffer : buffers) this->add(type, buffer); return *this; } for (const auto& buffer : buffers) this->add(type, buffer); return *this; }
/// Add an optional resource to the descriptor set update.
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional<Image>& image) {
if (image.has_value()) this->add(type, *image); return *this; }
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional<Sampler>& sampler) {
if (sampler.has_value()) this->add(type, *sampler); return *this; }
DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::optional<Buffer>& buffer) {
if (buffer.has_value()) this->add(type, *buffer); return *this; }
/// Finish building the descriptor set update. /// Finish building the descriptor set update.
void build() const; void build() const;
private: private:

View file

@ -9,6 +9,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -28,7 +30,7 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Alpha(const Device& device, const Core::DescriptorPool& pool, Alpha(const Device& device, const Core::DescriptorPool& pool,
const Core::Image& inImg); Core::Image inImg);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -49,17 +51,17 @@ namespace Vulkan::Shaderchains {
Alpha& operator=(Alpha&&) noexcept = default; Alpha& operator=(Alpha&&) noexcept = default;
~Alpha() = default; ~Alpha() = default;
private: private:
std::vector<Core::ShaderModule> shaderModules{4}; std::array<Core::ShaderModule, 4> shaderModules;
std::vector<Core::Pipeline> pipelines{4}; std::array<Core::Pipeline, 4> pipelines;
std::vector<Core::DescriptorSet> descriptorSets{4}; std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Image inImg; Core::Image inImg;
std::vector<Core::Image> tempImgs1{2}; // half-size std::array<Core::Image, 2> tempImgs1; // half-size
std::vector<Core::Image> tempImgs2{2}; // half-size std::array<Core::Image, 2> tempImgs2; // half-size
std::vector<Core::Image> tempImgs3{4}; // quarter-size std::array<Core::Image, 4> tempImgs3; // quarter-size
std::vector<Core::Image> outImgs{4}; // quarter-size std::array<Core::Image, 4> outImgs; // quarter-size
}; };
} }

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -31,8 +33,8 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Beta(const Device& device, const Core::DescriptorPool& pool, Beta(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& temporalImgs, std::array<Core::Image, 8> temporalImgs,
const std::vector<Core::Image>& inImgs); std::array<Core::Image, 4> inImgs);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -53,18 +55,18 @@ namespace Vulkan::Shaderchains {
Beta& operator=(Beta&&) noexcept = default; Beta& operator=(Beta&&) noexcept = default;
~Beta() = default; ~Beta() = default;
private: private:
std::vector<Core::ShaderModule> shaderModules{5}; std::array<Core::ShaderModule, 5> shaderModules;
std::vector<Core::Pipeline> pipelines{5}; std::array<Core::Pipeline, 5> pipelines;
std::vector<Core::DescriptorSet> descriptorSets{5}; std::array<Core::DescriptorSet, 5> descriptorSets;
Core::Buffer buffer; Core::Buffer buffer;
std::vector<Core::Image> temporalImgs{8}; std::array<Core::Image, 8> temporalImgs;
std::vector<Core::Image> inImgs{4}; std::array<Core::Image, 4> inImgs;
std::vector<Core::Image> tempImgs1{2}; std::array<Core::Image, 2> tempImgs1;
std::vector<Core::Image> tempImgs2{2}; std::array<Core::Image, 2> tempImgs2;
std::vector<Core::Image> outImgs{6}; std::array<Core::Image, 6> outImgs;
}; };
} }

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -31,8 +33,8 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Delta(const Device& device, const Core::DescriptorPool& pool, Delta(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& inImgs, std::array<Core::Image, 2> inImgs,
const std::optional<Core::Image>& optImg); std::optional<Core::Image> optImg);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -53,16 +55,16 @@ namespace Vulkan::Shaderchains {
Delta& operator=(Delta&&) noexcept = default; Delta& operator=(Delta&&) noexcept = default;
~Delta() = default; ~Delta() = default;
private: private:
std::vector<Core::ShaderModule> shaderModules{4}; std::array<Core::ShaderModule, 4> shaderModules;
std::vector<Core::Pipeline> pipelines{4}; std::array<Core::Pipeline, 4> pipelines;
std::vector<Core::DescriptorSet> descriptorSets{4}; std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Buffer buffer; Core::Buffer buffer;
std::vector<Core::Image> inImg{2}; std::array<Core::Image, 2> inImg;
std::optional<Core::Image> optImg; std::optional<Core::Image> optImg;
std::vector<Core::Image> tempImgs1{2}; std::array<Core::Image, 2> tempImgs1;
std::vector<Core::Image> tempImgs2{2}; std::array<Core::Image, 2> tempImgs2;
Core::Image outImg; Core::Image outImg;
}; };

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -29,7 +31,7 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Downsample(const Device& device, const Core::DescriptorPool& pool, Downsample(const Device& device, const Core::DescriptorPool& pool,
const Core::Image& inImg); Core::Image inImg);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -57,7 +59,7 @@ namespace Vulkan::Shaderchains {
Core::Image inImg; Core::Image inImg;
std::vector<Core::Image> outImgs{7}; std::array<Core::Image, 7> outImgs;
}; };
} }

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -32,9 +34,9 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Epsilon(const Device& device, const Core::DescriptorPool& pool, Epsilon(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& inImgs1, std::array<Core::Image, 3> inImgs1,
const Core::Image& inImg2, Core::Image inImg2,
const std::optional<Core::Image>& optImg); std::optional<Core::Image> optImg);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -55,17 +57,17 @@ namespace Vulkan::Shaderchains {
Epsilon& operator=(Epsilon&&) noexcept = default; Epsilon& operator=(Epsilon&&) noexcept = default;
~Epsilon() = default; ~Epsilon() = default;
private: private:
std::vector<Core::ShaderModule> shaderModules{4}; std::array<Core::ShaderModule, 4> shaderModules;
std::vector<Core::Pipeline> pipelines{4}; std::array<Core::Pipeline, 4> pipelines;
std::vector<Core::DescriptorSet> descriptorSets{4}; std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Buffer buffer; Core::Buffer buffer;
std::vector<Core::Image> inImgs1{3}; std::array<Core::Image, 3> inImgs1;
Core::Image inImg2; Core::Image inImg2;
std::optional<Core::Image> optImg; std::optional<Core::Image> optImg;
std::vector<Core::Image> tempImgs1{4}; std::array<Core::Image, 4> tempImgs1;
std::vector<Core::Image> tempImgs2{4}; std::array<Core::Image, 4> tempImgs2;
Core::Image outImg; Core::Image outImg;
}; };

View file

@ -9,7 +9,6 @@
#include "core/pipeline.hpp" #include "core/pipeline.hpp"
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <vulkan/vulkan_core.h>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -37,11 +39,11 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Gamma(const Device& device, const Core::DescriptorPool& pool, Gamma(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& temporalImgs, std::array<Core::Image, 4> temporalImgs,
const std::vector<Core::Image>& inImgs1, std::array<Core::Image, 4> inImgs1,
const Core::Image& inImg2, Core::Image inImg2,
const std::optional<Core::Image>& optImg1, std::optional<Core::Image> optImg1,
const std::optional<Core::Image>& optImg2, std::optional<Core::Image> optImg2,
VkExtent2D outExtent); VkExtent2D outExtent);
/// ///
@ -65,19 +67,19 @@ namespace Vulkan::Shaderchains {
Gamma& operator=(Gamma&&) noexcept = default; Gamma& operator=(Gamma&&) noexcept = default;
~Gamma() = default; ~Gamma() = default;
private: private:
std::vector<Core::ShaderModule> shaderModules{6}; std::array<Core::ShaderModule, 6> shaderModules;
std::vector<Core::Pipeline> pipelines{6}; std::array<Core::Pipeline, 6> pipelines;
std::vector<Core::DescriptorSet> descriptorSets{6}; std::array<Core::DescriptorSet, 6> descriptorSets;
Core::Buffer buffer; Core::Buffer buffer;
std::vector<Core::Image> temporalImgs{4}; std::array<Core::Image, 4> temporalImgs;
std::vector<Core::Image> inImgs1{4}; std::array<Core::Image, 4> inImgs1;
Core::Image inImg2; Core::Image inImg2;
Core::Image optImg1; // specified or created black Core::Image optImg1; // specified or created black
std::optional<Core::Image> optImg2; std::optional<Core::Image> optImg2;
std::vector<Core::Image> tempImgs1{4}; std::array<Core::Image, 4> tempImgs1;
std::vector<Core::Image> tempImgs2{4}; std::array<Core::Image, 4> tempImgs2;
Core::Image whiteImg; Core::Image whiteImg;
Core::Image outImg1; Core::Image outImg1;

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -34,11 +36,11 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Magic(const Device& device, const Core::DescriptorPool& pool, Magic(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& temporalImgs, std::array<Core::Image, 4>& temporalImgs,
const std::vector<Core::Image>& inImgs1, std::array<Core::Image, 4>& inImgs1,
Core::Image inImg2, Core::Image inImg2,
Core::Image inImg3, Core::Image inImg3,
const std::optional<Core::Image>& optImg); std::optional<Core::Image> optImg);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -68,15 +70,15 @@ namespace Vulkan::Shaderchains {
Core::DescriptorSet descriptorSet; Core::DescriptorSet descriptorSet;
Core::Buffer buffer; Core::Buffer buffer;
std::vector<Core::Image> temporalImgs{4}; std::array<Core::Image, 4> temporalImgs;
std::vector<Core::Image> inImgs1{4}; std::array<Core::Image, 4> inImgs1;
Core::Image inImg2; Core::Image inImg2;
Core::Image inImg3; Core::Image inImg3;
std::optional<Core::Image> optImg; std::optional<Core::Image> optImg;
std::vector<Core::Image> outImgs1{3}; std::array<Core::Image, 3> outImgs1;
std::vector<Core::Image> outImgs2{3}; std::array<Core::Image, 3> outImgs2;
std::vector<Core::Image> outImgs3{3}; std::array<Core::Image, 3> outImgs3;
}; };
} }

View file

@ -10,6 +10,8 @@
#include "core/shadermodule.hpp" #include "core/shadermodule.hpp"
#include "device.hpp" #include "device.hpp"
#include <array>
namespace Vulkan::Shaderchains { namespace Vulkan::Shaderchains {
/// ///
@ -32,9 +34,9 @@ namespace Vulkan::Shaderchains {
/// @throws ls::vulkan_error if resource creation fails. /// @throws ls::vulkan_error if resource creation fails.
/// ///
Zeta(const Device& device, const Core::DescriptorPool& pool, Zeta(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& inImgs1, std::array<Core::Image, 3> inImgs1,
const Core::Image& inImg2, Core::Image inImg2,
const Core::Image& inImg3); Core::Image inImg3);
/// ///
/// Dispatch the shaderchain. /// Dispatch the shaderchain.
@ -55,17 +57,17 @@ namespace Vulkan::Shaderchains {
Zeta& operator=(Zeta&&) noexcept = default; Zeta& operator=(Zeta&&) noexcept = default;
~Zeta() = default; ~Zeta() = default;
private: private:
std::vector<Core::ShaderModule> shaderModules{4}; std::array<Core::ShaderModule, 4> shaderModules;
std::vector<Core::Pipeline> pipelines{4}; std::array<Core::Pipeline, 4> pipelines;
std::vector<Core::DescriptorSet> descriptorSets{4}; std::array<Core::DescriptorSet, 4> descriptorSets;
Core::Buffer buffer; Core::Buffer buffer;
std::vector<Core::Image> inImgs1{3}; std::array<Core::Image, 3> inImgs1;
Core::Image inImg2; Core::Image inImg2;
Core::Image inImg3; Core::Image inImg3;
std::vector<Core::Image> tempImgs1{4}; std::array<Core::Image, 4> tempImgs1;
std::vector<Core::Image> tempImgs2{4}; std::array<Core::Image, 4> tempImgs2;
Core::Image outImg; Core::Image outImg;
}; };

View file

@ -4,6 +4,7 @@
#include "core/commandbuffer.hpp" #include "core/commandbuffer.hpp"
#include "core/image.hpp" #include "core/image.hpp"
#include "core/sampler.hpp" #include "core/sampler.hpp"
#include "device.hpp"
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
@ -14,16 +15,47 @@ namespace Vulkan::Utils {
/// ///
/// Insert memory barriers for images in a command buffer. /// Insert memory barriers for images in a command buffer.
/// ///
/// @param buffer Command buffer to insert barriers into
/// @param r2wImages Images that are being read and will be written to
/// @param w2rImages Images that are being written to and will be read from
///
/// @throws std::logic_error if the command buffer is not in Recording state /// @throws std::logic_error if the command buffer is not in Recording state
/// ///
void insertBarrier( class BarrierBuilder {
const Vulkan::Core::CommandBuffer& buffer, public:
std::vector<Vulkan::Core::Image> w2rImages, /// Create a barrier builder.
std::vector<Vulkan::Core::Image> r2wImages); BarrierBuilder(const Core::CommandBuffer& buffer)
: commandBuffer(&buffer) {
this->barriers.reserve(16); // this is performance critical
}
// Add a resource to the barrier builder.
BarrierBuilder& addR2W(Core::Image& image);
BarrierBuilder& addW2R(Core::Image& image);
// Add an optional resource to the barrier builder.
BarrierBuilder& addR2W(std::optional<Core::Image>& image) {
if (image.has_value()) this->addR2W(*image); return *this; }
BarrierBuilder& addW2R(std::optional<Core::Image>& image) {
if (image.has_value()) this->addW2R(*image); return *this; }
/// Add a list of resources to the barrier builder.
BarrierBuilder& addR2W(std::vector<Core::Image>& images) {
for (auto& image : images) this->addR2W(image); return *this; }
BarrierBuilder& addW2R(std::vector<Core::Image>& images) {
for (auto& image : images) this->addW2R(image); return *this; }
/// Add an array of resources to the barrier builder.
template<std::size_t N>
BarrierBuilder& addR2W(std::array<Core::Image, N>& images) {
for (auto& image : images) this->addR2W(image); return *this; }
template<std::size_t N>
BarrierBuilder& addW2R(std::array<Core::Image, N>& images) {
for (auto& image : images) this->addW2R(image); return *this; }
/// Finish building the barrier
void build() const;
private:
const Core::CommandBuffer* commandBuffer;
std::vector<VkImageMemoryBarrier2> barriers;
};
/// ///
/// Upload a DDS file to a Vulkan image. /// Upload a DDS file to a Vulkan image.
@ -36,9 +68,19 @@ namespace Vulkan::Utils {
/// @throws std::system_error If the file cannot be opened or read. /// @throws std::system_error If the file cannot be opened or read.
/// @throws ls:vulkan_error If the Vulkan image cannot be created or updated. /// @throws ls:vulkan_error If the Vulkan image cannot be created or updated.
/// ///
void uploadImage(const Vulkan::Device& device, void uploadImage(const Device& device,
const Vulkan::Core::CommandPool& commandPool, const Core::CommandPool& commandPool,
Vulkan::Core::Image& image, const std::string& path); Core::Image& image, const std::string& path);
///
/// Clear a texture to white during setup.
///
/// @param device The Vulkan device.
/// @param image The image to clear.
///
/// @throws ls::vulkan_error If the Vulkan image cannot be cleared.
///
void clearWhiteImage(const Device& device, Core::Image& image);
} }

View file

@ -87,6 +87,19 @@ DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType typ
return *this; return *this;
} }
DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type) {
this->entries.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = this->descriptorSet->handle(),
.dstBinding = static_cast<uint32_t>(this->entries.size()),
.descriptorCount = 0,
.descriptorType = type,
.pImageInfo = nullptr,
.pBufferInfo = nullptr
});
return *this;
}
void DescriptorSetUpdateBuilder::build() const { void DescriptorSetUpdateBuilder::build() const {
if (this->entries.empty()) return; if (this->entries.empty()) return;

View file

@ -4,7 +4,8 @@
using namespace Vulkan::Shaderchains; using namespace Vulkan::Shaderchains;
Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool, Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool,
const Core::Image& inImage) : inImage(inImage) { Core::Image inImg)
: inImg(std::move(inImg)) {
this->shaderModules = {{ this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/alpha/0.spv", Core::ShaderModule(device, "rsc/shaders/alpha/0.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, { { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
@ -30,32 +31,37 @@ Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool,
this->shaderModules.at(i)); this->shaderModules.at(i));
} }
auto extent = inImage.getExtent(); const auto extent = this->inImg.getExtent();
auto halfWidth = (extent.width + 1) >> 1;
auto halfHeight = (extent.height + 1) >> 1;
auto quarterWidth = (extent.width + 3) >> 2;
auto quarterHeight = (extent.height + 3) >> 2;
const VkExtent2D halfExtent = {
.width = (extent.width + 1) >> 1,
.height = (extent.height + 1) >> 1
};
for (size_t i = 0; i < 2; i++) { for (size_t i = 0; i < 2; i++) {
this->tempTex1.at(i) = Core::Image(device, this->tempImgs1.at(i) = Core::Image(device,
{ halfWidth, halfHeight }, halfExtent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
this->tempTex2.at(i) = Core::Image(device, this->tempImgs2.at(i) = Core::Image(device,
{ halfWidth, halfHeight }, halfExtent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
} }
const VkExtent2D quarterExtent = {
.width = (extent.width + 3) >> 2,
.height = (extent.height + 3) >> 2
};
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
this->tempTex3.at(i) = Core::Image(device, this->tempImgs3.at(i) = Core::Image(device,
{ quarterWidth, quarterHeight }, quarterExtent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
this->outImages.at(i) = Core::Image(device, this->outImgs.at(i) = Core::Image(device,
{ quarterWidth, quarterHeight }, quarterExtent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
@ -63,79 +69,73 @@ Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool,
this->descriptorSets.at(0).update(device) this->descriptorSets.at(0).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, inImage) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempTex1) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1)
.build(); .build();
this->descriptorSets.at(1).update(device) this->descriptorSets.at(1).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempTex1) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempTex2) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2)
.build(); .build();
this->descriptorSets.at(2).update(device) this->descriptorSets.at(2).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempTex2) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempTex3) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs3)
.build(); .build();
this->descriptorSets.at(3).update(device) this->descriptorSets.at(3).update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempTex3) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs3)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImages) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs)
.build(); .build();
} }
void Alpha::Dispatch(const Core::CommandBuffer& buf) { void Alpha::Dispatch(const Core::CommandBuffer& buf) {
const auto halfExtent = this->tempTex1.at(0).getExtent(); const auto halfExtent = this->tempImgs1.at(0).getExtent();
const auto quarterExtent = this->tempTex3.at(0).getExtent(); const auto quarterExtent = this->tempImgs3.at(0).getExtent();
// first pass // first pass
Utils::insertBarrier( uint32_t threadsX = (halfExtent.width + 7) >> 3;
buf, uint32_t threadsY = (halfExtent.height + 7) >> 3;
{ this->inImage },
this->tempTex1 Utils::BarrierBuilder(buf)
); .addW2R(this->inImg)
.addR2W(this->tempImgs1)
.build();
this->pipelines.at(0).bind(buf); this->pipelines.at(0).bind(buf);
this->descriptorSets.at(0).bind(buf, this->pipelines.at(0)); this->descriptorSets.at(0).bind(buf, this->pipelines.at(0));
uint32_t threadsX = (halfExtent.width + 7) >> 3;
uint32_t threadsY = (halfExtent.height + 7) >> 3;
buf.dispatch(threadsX, threadsY, 1); buf.dispatch(threadsX, threadsY, 1);
// second pass // second pass
Utils::insertBarrier( Utils::BarrierBuilder(buf)
buf, .addW2R(this->tempImgs1)
this->tempTex1, .addR2W(this->tempImgs2)
this->tempTex2 .build();
);
this->pipelines.at(1).bind(buf); this->pipelines.at(1).bind(buf);
this->descriptorSets.at(1).bind(buf, this->pipelines.at(1)); this->descriptorSets.at(1).bind(buf, this->pipelines.at(1));
buf.dispatch(threadsX, threadsY, 1); buf.dispatch(threadsX, threadsY, 1);
// third pass // third pass
Utils::insertBarrier( threadsX = (quarterExtent.width + 7) >> 3;
buf, threadsY = (quarterExtent.height + 7) >> 3;
this->tempTex2,
this->tempTex3 Utils::BarrierBuilder(buf)
); .addW2R(this->tempImgs2)
.addR2W(this->tempImgs3)
.build();
this->pipelines.at(2).bind(buf); this->pipelines.at(2).bind(buf);
this->descriptorSets.at(2).bind(buf, this->pipelines.at(2)); this->descriptorSets.at(2).bind(buf, this->pipelines.at(2));
threadsX = (quarterExtent.width + 7) >> 3;
threadsY = (quarterExtent.height + 7) >> 3;
buf.dispatch(threadsX, threadsY, 1); buf.dispatch(threadsX, threadsY, 1);
// fourth pass // fourth pass
Utils::insertBarrier( Utils::BarrierBuilder(buf)
buf, .addW2R(this->tempImgs3)
this->tempTex3, .addR2W(this->outImgs)
this->outImages .build();
);
this->pipelines.at(3).bind(buf); this->pipelines.at(3).bind(buf);
this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); this->descriptorSets.at(3).bind(buf, this->pipelines.at(3));
buf.dispatch(threadsX, threadsY, 1); buf.dispatch(threadsX, threadsY, 1);
} }

View file

@ -4,8 +4,8 @@
using namespace Vulkan::Shaderchains; using namespace Vulkan::Shaderchains;
Downsample::Downsample(const Device& device, const Core::DescriptorPool& pool, Downsample::Downsample(const Device& device, const Core::DescriptorPool& pool,
const Core::Image& inImage) : inImage(inImage) { Core::Image inImg)
// create internal resources : inImg(std::move(inImg)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/downsample.spv", this->shaderModule = Core::ShaderModule(device, "rsc/shaders/downsample.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, { { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, { 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
@ -13,39 +13,35 @@ Downsample::Downsample(const Device& device, const Core::DescriptorPool& pool,
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } });
this->pipeline = Core::Pipeline(device, this->shaderModule); this->pipeline = Core::Pipeline(device, this->shaderModule);
this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule);
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
const Globals::FgBuffer data = Globals::fgBuffer; auto extent = this->inImg.getExtent();
this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
auto extent = inImage.getExtent();
// create output images
for (size_t i = 0; i < 7; i++) for (size_t i = 0; i < 7; i++)
this->outImages.at(i) = Core::Image(device, this->outImgs.at(i) = Core::Image(device,
{ extent.width >> i, extent.height >> i }, { extent.width >> i, extent.height >> i },
VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
// update descriptor set
this->descriptorSet.update(device) this->descriptorSet.update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, inImage) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImages) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs)
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer)
.build(); .build();
} }
void Downsample::Dispatch(const Core::CommandBuffer& buf) { void Downsample::Dispatch(const Core::CommandBuffer& buf) {
auto extent = inImage.getExtent(); auto extent = this->inImg.getExtent();
// first pass
const uint32_t threadsX = (extent.width + 63) >> 6; const uint32_t threadsX = (extent.width + 63) >> 6;
const uint32_t threadsY = (extent.height + 63) >> 6; const uint32_t threadsY = (extent.height + 63) >> 6;
Utils::insertBarrier( Utils::BarrierBuilder(buf)
buf, .addW2R(this->inImg)
{ this->inImage }, .addR2W(this->outImgs)
this->outImages .build();
);
this->pipeline.bind(buf); this->pipeline.bind(buf);
this->descriptorSet.bind(buf, this->pipeline); this->descriptorSet.bind(buf, this->pipeline);

View file

@ -1,6 +1,5 @@
#include "shaderchains/extract.hpp" #include "shaderchains/extract.hpp"
#include "utils.hpp" #include "utils.hpp"
#include <vulkan/vulkan_core.h>
using namespace Vulkan::Shaderchains; using namespace Vulkan::Shaderchains;
@ -10,7 +9,6 @@ Extract::Extract(const Device& device, const Core::DescriptorPool& pool,
VkExtent2D outExtent) VkExtent2D outExtent)
: inImg1(std::move(inImg1)), : inImg1(std::move(inImg1)),
inImg2(std::move(inImg2)) { inImg2(std::move(inImg2)) {
// create internal resources
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/extract.spv", this->shaderModule = Core::ShaderModule(device, "rsc/shaders/extract.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, { { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, { 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
@ -18,24 +16,19 @@ Extract::Extract(const Device& device, const Core::DescriptorPool& pool,
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } });
this->pipeline = Core::Pipeline(device, this->shaderModule); this->pipeline = Core::Pipeline(device, this->shaderModule);
this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule);
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
const Globals::FgBuffer data = Globals::fgBuffer;
this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
this->whiteImg = Core::Image(device, this->whiteImg = Core::Image(device,
{ outExtent.width, outExtent.height }, outExtent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
// create output images
this->outImg = Core::Image(device, this->outImg = Core::Image(device,
{ outExtent.width, outExtent.height }, outExtent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
// update descriptor set
this->descriptorSet.update(device) this->descriptorSet.update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg)
@ -44,20 +37,24 @@ Extract::Extract(const Device& device, const Core::DescriptorPool& pool,
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg)
.add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer)
.build(); .build();
// clear white image
Utils::clearWhiteImage(device, this->whiteImg);
} }
void Extract::Dispatch(const Core::CommandBuffer& buf) { void Extract::Dispatch(const Core::CommandBuffer& buf) {
auto extent = this->whiteImg.getExtent(); auto extent = this->whiteImg.getExtent();
// first pass
const uint32_t threadsX = (extent.width + 7) >> 3; const uint32_t threadsX = (extent.width + 7) >> 3;
const uint32_t threadsY = (extent.height + 7) >> 3; const uint32_t threadsY = (extent.height + 7) >> 3;
// FIXME: clear to white Utils::BarrierBuilder(buf)
.addW2R(this->whiteImg)
Utils::insertBarrier( .addW2R(this->inImg1)
buf, .addW2R(this->inImg2)
{ this->whiteImg, this->inImg1, this->inImg2 }, .addR2W(this->outImg)
{ this->outImg } .build();
);
this->pipeline.bind(buf); this->pipeline.bind(buf);
this->descriptorSet.bind(buf, this->pipeline); this->descriptorSet.bind(buf, this->pipeline);

View file

@ -4,14 +4,15 @@
using namespace Vulkan::Shaderchains; using namespace Vulkan::Shaderchains;
Magic::Magic(const Device& device, const Core::DescriptorPool& pool, Magic::Magic(const Device& device, const Core::DescriptorPool& pool,
const std::vector<Core::Image>& temporalImgs, std::array<Core::Image, 4>& temporalImgs,
const std::vector<Core::Image>& inImgs1, std::array<Core::Image, 4>& inImgs1,
Core::Image inImg2, Core::Image inImg2,
Core::Image inImg3, Core::Image inImg3,
const std::optional<Core::Image>& optImg) std::optional<Core::Image> optImg)
: temporalImgs(temporalImgs), inImgs1(inImgs1), : temporalImgs(std::move(temporalImgs)),
inImg2(std::move(inImg2)), inImg3(std::move(inImg3)), optImg(optImg) { inImgs1(std::move(inImgs1)),
// create internal resources inImg2(std::move(inImg2)), inImg3(std::move(inImg3)),
optImg(std::move(optImg)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/magic.spv", this->shaderModule = Core::ShaderModule(device, "rsc/shaders/magic.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, { { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4+4+2+1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, { 4+4+2+1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
@ -26,34 +27,32 @@ Magic::Magic(const Device& device, const Core::DescriptorPool& pool,
auto extent = temporalImgs.at(0).getExtent(); auto extent = temporalImgs.at(0).getExtent();
// create output images
for (size_t i = 0; i < 2; i++) for (size_t i = 0; i < 2; i++)
this->outImgs1.at(i) = Core::Image(device, this->outImgs1.at(i) = Core::Image(device,
{ extent.width, extent.height }, extent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
this->outImgs2.at(i) = Core::Image(device, this->outImgs2.at(i) = Core::Image(device,
{ extent.width, extent.height }, extent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
this->outImgs3.at(i) = Core::Image(device, this->outImgs3.at(i) = Core::Image(device,
{ extent.width, extent.height }, extent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
// update descriptor set
this->descriptorSet.update(device) this->descriptorSet.update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->temporalImgs) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->temporalImgs)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImgs1)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *this->optImg) // FIXME: invalid resource .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs3) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs3)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs2) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs2)
.add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs1) .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs1)
@ -63,20 +62,21 @@ Magic::Magic(const Device& device, const Core::DescriptorPool& pool,
void Magic::Dispatch(const Core::CommandBuffer& buf) { void Magic::Dispatch(const Core::CommandBuffer& buf) {
auto extent = this->temporalImgs.at(0).getExtent(); auto extent = this->temporalImgs.at(0).getExtent();
// first pass
const uint32_t threadsX = (extent.width + 7) >> 3; const uint32_t threadsX = (extent.width + 7) >> 3;
const uint32_t threadsY = (extent.height + 7) >> 3; const uint32_t threadsY = (extent.height + 7) >> 3;
Utils::insertBarrier( Utils::BarrierBuilder(buf)
buf, .addW2R(this->temporalImgs)
{ this->temporalImgs.at(0), this->temporalImgs.at(1), .addW2R(this->inImgs1)
this->temporalImgs.at(2), this->temporalImgs.at(3), .addW2R(this->inImg2)
this->inImgs1.at(0), this->inImgs1.at(1), .addW2R(this->inImg3)
this->inImgs1.at(2), this->inImgs1.at(3), .addW2R(this->optImg)
this->inImg2, this->inImg3, *this->optImg }, // FIXME: invalid resource .addR2W(this->outImgs3)
{ this->outImgs3.at(0), this->outImgs3.at(1), this->outImgs3.at(2), .addR2W(this->outImgs2)
this->outImgs2.at(0), this->outImgs2.at(1), this->outImgs2.at(2), .addR2W(this->outImgs1)
this->outImgs1.at(0), this->outImgs1.at(1) } .build();
);
this->pipeline.bind(buf); this->pipeline.bind(buf);
this->descriptorSet.bind(buf, this->pipeline); this->descriptorSet.bind(buf, this->pipeline);

View file

@ -15,7 +15,6 @@ Merge::Merge(const Device& device, const Core::DescriptorPool& pool,
inImg3(std::move(inImg3)), inImg3(std::move(inImg3)),
inImg4(std::move(inImg4)), inImg4(std::move(inImg4)),
inImg5(std::move(inImg5)) { inImg5(std::move(inImg5)) {
// create internal resources
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/merge.spv", this->shaderModule = Core::ShaderModule(device, "rsc/shaders/merge.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER }, { { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }, { 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
@ -23,20 +22,16 @@ Merge::Merge(const Device& device, const Core::DescriptorPool& pool,
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } });
this->pipeline = Core::Pipeline(device, this->shaderModule); this->pipeline = Core::Pipeline(device, this->shaderModule);
this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule);
this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
const Globals::FgBuffer data = Globals::fgBuffer;
this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
auto extent = this->inImg1.getExtent(); auto extent = this->inImg1.getExtent();
// create output image
this->outImg = Core::Image(device, this->outImg = Core::Image(device,
{ extent.width, extent.height }, extent,
VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
// update descriptor set
this->descriptorSet.update(device) this->descriptorSet.update(device)
.add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder)
.add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg1) .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg1)
@ -51,17 +46,19 @@ Merge::Merge(const Device& device, const Core::DescriptorPool& pool,
void Merge::Dispatch(const Core::CommandBuffer& buf) { void Merge::Dispatch(const Core::CommandBuffer& buf) {
auto extent = this->inImg1.getExtent(); auto extent = this->inImg1.getExtent();
// first pass
const uint32_t threadsX = (extent.width + 15) >> 4; const uint32_t threadsX = (extent.width + 15) >> 4;
const uint32_t threadsY = (extent.height + 15) >> 4; const uint32_t threadsY = (extent.height + 15) >> 4;
// FIXME: clear to white Utils::BarrierBuilder(buf)
.addW2R(this->inImg1)
Utils::insertBarrier( .addW2R(this->inImg2)
buf, .addW2R(this->inImg3)
{ this->inImg1, this->inImg2, this->inImg3, .addW2R(this->inImg4)
this->inImg4, this->inImg5 }, .addW2R(this->inImg5)
{ this->outImg } .addR2W(this->outImg)
); .build();
this->pipeline.bind(buf); this->pipeline.bind(buf);
this->descriptorSet.bind(buf, this->pipeline); this->descriptorSet.bind(buf, this->pipeline);

View file

@ -3,18 +3,13 @@
#include <format> #include <format>
#include <fstream> #include <fstream>
#include <vulkan/vulkan_core.h>
using namespace Vulkan; using namespace Vulkan;
using namespace Vulkan::Utils;
void Utils::insertBarrier( BarrierBuilder& BarrierBuilder::addR2W(Core::Image& image) {
const Core::CommandBuffer& buffer, this->barriers.emplace_back(VkImageMemoryBarrier2 {
std::vector<Core::Image> w2rImages,
std::vector<Core::Image> r2wImages) {
std::vector<VkImageMemoryBarrier2> barriers(r2wImages.size() + w2rImages.size());
size_t index = 0;
for (auto& image : r2wImages) {
barriers[index++] = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT, .srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
@ -28,11 +23,14 @@ void Utils::insertBarrier(
.levelCount = 1, .levelCount = 1,
.layerCount = 1 .layerCount = 1
} }
}; });
image.setLayout(VK_IMAGE_LAYOUT_GENERAL); image.setLayout(VK_IMAGE_LAYOUT_GENERAL);
}
for (auto& image : w2rImages) { return *this;
barriers[index++] = { }
BarrierBuilder& BarrierBuilder::addW2R(Core::Image& image) {
this->barriers.emplace_back(VkImageMemoryBarrier2 {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
@ -46,15 +44,19 @@ void Utils::insertBarrier(
.levelCount = 1, .levelCount = 1,
.layerCount = 1 .layerCount = 1
} }
}; });
image.setLayout(VK_IMAGE_LAYOUT_GENERAL); image.setLayout(VK_IMAGE_LAYOUT_GENERAL);
}
return *this;
}
void BarrierBuilder::build() const {
const VkDependencyInfo dependencyInfo = { const VkDependencyInfo dependencyInfo = {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.imageMemoryBarrierCount = static_cast<uint32_t>(barriers.size()), .imageMemoryBarrierCount = static_cast<uint32_t>(this->barriers.size()),
.pImageMemoryBarriers = barriers.data() .pImageMemoryBarriers = this->barriers.data()
}; };
vkCmdPipelineBarrier2(buffer.handle(), &dependencyInfo); vkCmdPipelineBarrier2(this->commandBuffer->handle(), &dependencyInfo);
} }
void Utils::uploadImage(const Device& device, const Core::CommandPool& commandPool, void Utils::uploadImage(const Device& device, const Core::CommandPool& commandPool,
@ -129,6 +131,51 @@ void Utils::uploadImage(const Device& device, const Core::CommandPool& commandPo
throw ls::vulkan_error(VK_TIMEOUT, "Upload operation timed out"); throw ls::vulkan_error(VK_TIMEOUT, "Upload operation timed out");
} }
void Utils::clearWhiteImage(const Device& device, Core::Image& image) {
Core::Fence fence(device);
const Core::CommandPool cmdPool(device);
Core::CommandBuffer cmdBuf(device, cmdPool);
cmdBuf.begin();
const VkImageMemoryBarrier2 barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = image.getLayout(),
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.image = image.handle(),
.subresourceRange = {
.aspectMask = image.getAspectFlags(),
.levelCount = 1,
.layerCount = 1
}
};
const VkDependencyInfo dependencyInfo = {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &barrier
};
image.setLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkCmdPipelineBarrier2(cmdBuf.handle(), &dependencyInfo);
const VkClearColorValue clearColor = {{ 1.0F, 1.0F, 1.0F, 1.0F }};
const VkImageSubresourceRange subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1
};
vkCmdClearColorImage(cmdBuf.handle(),
image.handle(), image.getLayout(),
&clearColor,
1, &subresourceRange);
cmdBuf.end();
cmdBuf.submit(device.getComputeQueue(), fence);
if (!fence.wait(device))
throw ls::vulkan_error(VK_TIMEOUT, "Failed to wait for clearing fence.");
}
Core::Sampler Globals::samplerClampBorder; Core::Sampler Globals::samplerClampBorder;
Core::Sampler Globals::samplerClampEdge; Core::Sampler Globals::samplerClampEdge;
Globals::FgBuffer Globals::fgBuffer; Globals::FgBuffer Globals::fgBuffer;