switch namespace and initial draft for lsfg main

This commit is contained in:
PancakeTAS 2025-07-01 03:17:40 +02:00
parent 64331fbb9a
commit 3a7864ee19
No known key found for this signature in database
51 changed files with 525 additions and 307 deletions

View file

@ -7,7 +7,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan buffer.
@ -25,7 +25,7 @@ namespace Vulkan::Core {
/// @param data Initial data for the buffer, also specifies the size of the buffer.
/// @param usage Usage flags for the buffer
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
template<typename T>
Buffer(const Device& device, const T& data, VkBufferUsageFlags usage)
@ -41,7 +41,7 @@ namespace Vulkan::Core {
/// @param size Size of the buffer in bytes
/// @param usage Usage flags for the buffer
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Buffer(const Device& device, const void* data, size_t size, VkBufferUsageFlags usage)
: size(size) {

View file

@ -12,7 +12,7 @@
#include <vector>
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
/// State of the command buffer.
enum class CommandBufferState {
@ -43,7 +43,7 @@ namespace Vulkan::Core {
/// @param device Vulkan device
/// @param pool Vulkan command pool
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
CommandBuffer(const Device& device, const CommandPool& pool);
@ -51,7 +51,7 @@ namespace Vulkan::Core {
/// Begin recording commands in the command buffer.
///
/// @throws std::logic_error if the command buffer is in Empty state
/// @throws ls::vulkan_error if beginning the command buffer fails.
/// @throws LSFG::vulkan_error if beginning the command buffer fails.
///
void begin();
@ -70,7 +70,7 @@ namespace Vulkan::Core {
/// End recording commands in the command buffer.
///
/// @throws std::logic_error if the command buffer is not in Recording state
/// @throws ls::vulkan_error if ending the command buffer fails.
/// @throws LSFG::vulkan_error if ending the command buffer fails.
///
void end();
@ -85,7 +85,7 @@ namespace Vulkan::Core {
/// @param signalSemaphoreValues Values for the semaphores to signal
///
/// @throws std::logic_error if the command buffer is not in Full state.
/// @throws ls::vulkan_error if submission fails.
/// @throws LSFG::vulkan_error if submission fails.
///
void submit(VkQueue queue, std::optional<Fence> fence,
const std::vector<Semaphore>& waitSemaphores = {},

View file

@ -7,7 +7,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan command pool.
@ -23,7 +23,7 @@ namespace Vulkan::Core {
///
/// @param device Vulkan device
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
CommandPool(const Device& device);

View file

@ -7,7 +7,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan descriptor pool.
@ -23,7 +23,7 @@ namespace Vulkan::Core {
///
/// @param device Vulkan device
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
DescriptorPool(const Device& device);

View file

@ -14,7 +14,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
class DescriptorSetUpdateBuilder;
@ -34,7 +34,7 @@ namespace Vulkan::Core {
/// @param pool Descriptor pool to allocate from
/// @param shaderModule Shader module to use for the descriptor set
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
DescriptorSet(const Device& device,
const DescriptorPool& pool, const ShaderModule& shaderModule);

View file

@ -7,7 +7,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan fence.
@ -23,7 +23,7 @@ namespace Vulkan::Core {
///
/// @param device Vulkan device
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Fence(const Device& device);
@ -32,7 +32,7 @@ namespace Vulkan::Core {
///
/// @param device Vulkan device
///
/// @throws ls::vulkan_error if resetting fails.
/// @throws LSFG::vulkan_error if resetting fails.
///
void reset(const Device& device) const;
@ -43,7 +43,7 @@ namespace Vulkan::Core {
/// @param timeout The timeout in nanoseconds, or UINT64_MAX for no timeout.
/// @returns true if the fence signaled, false if it timed out.
///
/// @throws ls::vulkan_error if waiting fails.
/// @throws LSFG::vulkan_error if waiting fails.
///
[[nodiscard]] bool wait(const Device& device, uint64_t timeout = UINT64_MAX) const;

View file

@ -7,7 +7,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan image.
@ -27,7 +27,7 @@ namespace Vulkan::Core {
/// @param usage Usage flags for the image
/// @param aspectFlags Aspect flags for the image view
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Image(const Device& device, VkExtent2D extent, VkFormat format,
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags);

View file

@ -9,7 +9,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan pipeline.
@ -26,7 +26,7 @@ namespace Vulkan::Core {
/// @param device Vulkan device
/// @param shader Shader module to use for the pipeline.
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Pipeline(const Device& device, const ShaderModule& shader);

View file

@ -7,7 +7,7 @@
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan sampler.
@ -24,7 +24,7 @@ namespace Vulkan::Core {
/// @param device Vulkan device
/// @param mode Address mode for the sampler.
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Sampler(const Device& device, VkSamplerAddressMode mode);

View file

@ -8,7 +8,7 @@
#include <optional>
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan semaphore.
@ -25,7 +25,7 @@ namespace Vulkan::Core {
/// @param device Vulkan device
/// @param initial Optional initial value for creating a timeline semaphore.
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Semaphore(const Device& device, std::optional<uint32_t> initial = std::nullopt);
@ -36,7 +36,7 @@ namespace Vulkan::Core {
/// @param value The value to signal the semaphore to.
///
/// @throws std::logic_error if the semaphore is not a timeline semaphore.
/// @throws ls::vulkan_error if signaling fails.
/// @throws LSFG::vulkan_error if signaling fails.
///
void signal(const Device& device, uint64_t value) const;
@ -49,7 +49,7 @@ namespace Vulkan::Core {
/// @returns true if the semaphore reached the value, false if it timed out.
///
/// @throws std::logic_error if the semaphore is not a timeline semaphore.
/// @throws ls::vulkan_error if waiting fails.
/// @throws LSFG::vulkan_error if waiting fails.
///
[[nodiscard]] bool wait(const Device& device, uint64_t value, uint64_t timeout = UINT64_MAX) const;

View file

@ -10,7 +10,7 @@
#include <vector>
#include <memory>
namespace Vulkan::Core {
namespace LSFG::Core {
///
/// C++ wrapper class for a Vulkan shader module.
@ -29,7 +29,7 @@ namespace Vulkan::Core {
/// @param descriptorTypes Descriptor types used in the shader.
///
/// @throws std::system_error if the shader file cannot be opened or read.
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
ShaderModule(const Device& device, const std::string& path,
const std::vector<std::pair<size_t, VkDescriptorType>>& descriptorTypes);

View file

@ -2,12 +2,13 @@
#define DEVICE_HPP
#include "instance.hpp"
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <memory>
namespace Vulkan {
namespace LSFG {
///
/// C++ wrapper class for a Vulkan device.
@ -21,9 +22,9 @@ namespace Vulkan {
///
/// @param instance Vulkan instance
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Device(const Vulkan::Instance& instance);
Device(const Instance& instance);
/// Get the Vulkan handle.
[[nodiscard]] auto handle() const { return *this->device; }

View file

@ -5,7 +5,7 @@
#include <memory>
namespace Vulkan {
namespace LSFG {
///
/// C++ wrapper class for a Vulkan instance.
@ -17,7 +17,7 @@ namespace Vulkan {
///
/// Create the instance.
///
/// @throws ls::vulkan_error if object creation fails.
/// @throws LSFG::vulkan_error if object creation fails.
///
Instance();

128
include/lsfg.hpp Normal file
View file

@ -0,0 +1,128 @@
#ifndef LSFG_HPP
#define LSFG_HPP
#include "core/commandpool.hpp"
#include "core/descriptorpool.hpp"
#include "core/image.hpp"
#include "device.hpp"
#include "instance.hpp"
#include "shaderchains/alpha.hpp"
#include "shaderchains/beta.hpp"
#include "shaderchains/delta.hpp"
#include "shaderchains/downsample.hpp"
#include "shaderchains/epsilon.hpp"
#include "shaderchains/extract.hpp"
#include "shaderchains/gamma.hpp"
#include "shaderchains/magic.hpp"
#include "shaderchains/merge.hpp"
#include "shaderchains/zeta.hpp"
#include "utils.hpp"
namespace LSFG {
class Generator;
/// LSFG context.
class Context {
friend class Generator; // FIXME: getters, I'm lazy
public:
///
/// Initialize the LSFG Vulkan instance.
///
/// @throws LSFG::vulkan_error if the Vulkan objects cannot be created.
///
Context() { Globals::initializeGlobals(device); } // FIXME: no need for globals
///
/// Create a generator instance.
///
/// @throws LSFG::vulkan_error if the generator cannot be created.
///
const Generator& create();
///
/// Present a generator instance.
///
/// @throws LSFG::vulkan_error if the generator fails to present.
///
void present(const Generator& gen);
/// Trivial copyable, moveable and destructible
Context(const Context&) = default;
Context& operator=(const Context&) = default;
Context(Context&&) = default;
Context& operator=(Context&&) = default;
~Context() { Globals::uninitializeGlobals(); }
private:
Instance instance;
Device device{instance};
Core::DescriptorPool descPool{device};
Core::CommandPool cmdPool{device};
};
/// Per-swapchain instance of LSFG.
class Generator {
public:
///
/// Create a generator instance.
///
/// @param context The LSFG context to use.
///
Generator(const Context& context);
///
/// Present.
///
/// @throws LSFG::vulkan_error if the generator fails to present.
///
void present(const Context& context);
// Trivially copyable, moveable and destructible
Generator(const Generator&) = default;
Generator(Generator&&) = default;
Generator& operator=(const Generator&) = default;
Generator& operator=(Generator&&) = default;
~Generator() = default;
private:
Core::Image fullFrame0, fullFrame1; // next/prev for fc % 2 == 0
uint64_t fc{0};
Shaderchains::Downsample downsampleChain; // FIXME: get rid of default constructors (+ core)
std::array<Shaderchains::Alpha, 7> alphaChains;
Shaderchains::Beta betaChain;
std::array<Shaderchains::Gamma, 4> gammaChains;
std::array<Shaderchains::Magic, 3> magicChains;
std::array<Shaderchains::Delta, 3> deltaChains;
std::array<Shaderchains::Epsilon, 3> epsilonChains;
std::array<Shaderchains::Zeta, 3> zetaChains;
std::array<Shaderchains::Extract, 2> extractChains;
Shaderchains::Merge mergeChain;
};
/// Simple exception class for Vulkan errors.
class vulkan_error : public std::runtime_error {
public:
///
/// Construct a vulkan_error with a message and a Vulkan result code.
///
/// @param result The Vulkan result code associated with the error.
/// @param message The error message.
///
explicit vulkan_error(VkResult result, const std::string& message);
/// Get the Vulkan result code associated with this error.
[[nodiscard]] VkResult error() const { return this->result; }
// Trivially copyable, moveable and destructible
vulkan_error(const vulkan_error&) = default;
vulkan_error(vulkan_error&&) = default;
vulkan_error& operator=(const vulkan_error&) = default;
vulkan_error& operator=(vulkan_error&&) = default;
~vulkan_error() noexcept override;
private:
VkResult result;
};
}
#endif // LSFG_HPP

View file

@ -11,7 +11,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain alpha.
@ -20,6 +20,8 @@ namespace Vulkan::Shaderchains {
///
class Alpha {
public:
Alpha() = default;
///
/// Initialize the shaderchain.
///
@ -27,7 +29,7 @@ namespace Vulkan::Shaderchains {
/// @param pool The descriptor pool to allocate in.
/// @param inImg The input image to process
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Alpha(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg);

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain beta.
@ -22,6 +22,8 @@ namespace Vulkan::Shaderchains {
///
class Beta {
public:
Beta() = default;
///
/// Initialize the shaderchain.
///
@ -30,7 +32,7 @@ namespace Vulkan::Shaderchains {
/// @param temporalImgs The temporal images to use for processing.
/// @param inImgs The input images to process
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Beta(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 8> temporalImgs,

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain delta.
@ -22,6 +22,8 @@ namespace Vulkan::Shaderchains {
///
class Delta {
public:
Delta() = default;
///
/// Initialize the shaderchain.
///
@ -30,7 +32,7 @@ namespace Vulkan::Shaderchains {
/// @param inImgs The input images to process.
/// @param optImg An optional additional input from the previous pass.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Delta(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 2> inImgs,

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Downsample shader.
@ -21,6 +21,8 @@ namespace Vulkan::Shaderchains {
///
class Downsample {
public:
Downsample() = default;
///
/// Initialize the shaderchain.
///
@ -28,7 +30,7 @@ namespace Vulkan::Shaderchains {
/// @param pool The descriptor pool to allocate in.
/// @param inImg The input image to downsample.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Downsample(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg);

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain epsilon.
@ -22,6 +22,8 @@ namespace Vulkan::Shaderchains {
///
class Epsilon {
public:
Epsilon() = default;
///
/// Initialize the shaderchain.
///
@ -31,7 +33,7 @@ namespace Vulkan::Shaderchains {
/// @param inImg2 The second type image to process.
/// @param optImg An optional additional input from the previous pass.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Epsilon(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,

View file

@ -10,7 +10,7 @@
#include "core/shadermodule.hpp"
#include "device.hpp"
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain extract.
@ -20,6 +20,8 @@ namespace Vulkan::Shaderchains {
///
class Extract {
public:
Extract() = default;
///
/// Initialize the shaderchain.
///
@ -29,7 +31,7 @@ namespace Vulkan::Shaderchains {
/// @param inImg2 The second type image to process.
/// @param outExtent The extent of the output image.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Extract(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg1,

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain gamma.
@ -24,6 +24,8 @@ namespace Vulkan::Shaderchains {
///
class Gamma {
public:
Gamma() = default;
///
/// Initialize the shaderchain.
///
@ -36,7 +38,7 @@ namespace Vulkan::Shaderchains {
/// @param optImg2 An optional additional input image for processing non-first passes.
/// @param outExtent The extent of the output image.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Gamma(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> temporalImgs,

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain magic.
@ -22,6 +22,8 @@ namespace Vulkan::Shaderchains {
///
class Magic {
public:
Magic() = default;
///
/// Initialize the shaderchain.
///
@ -33,7 +35,7 @@ namespace Vulkan::Shaderchains {
/// @param inImg3 The third input image to process, next step up the resolution.
/// @param optImg An optional additional input from the previous pass.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Magic(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> temporalImgs,

View file

@ -10,7 +10,7 @@
#include "core/shadermodule.hpp"
#include "device.hpp"
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain merge.
@ -20,6 +20,8 @@ namespace Vulkan::Shaderchains {
///
class Merge {
public:
Merge() = default;
///
/// Initialize the shaderchain.
///
@ -31,7 +33,7 @@ namespace Vulkan::Shaderchains {
/// @param inImg4 The second related input texture
/// @param inImg5 The third related input texture
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Merge(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg1,

View file

@ -12,7 +12,7 @@
#include <array>
namespace Vulkan::Shaderchains {
namespace LSFG::Shaderchains {
///
/// Shader chain zeta.
@ -22,6 +22,8 @@ namespace Vulkan::Shaderchains {
///
class Zeta {
public:
Zeta() = default;
///
/// Initialize the shaderchain.
///
@ -31,7 +33,7 @@ namespace Vulkan::Shaderchains {
/// @param inImg2 The second type image to process.
/// @param inImg3 The third type image to process.
///
/// @throws ls::vulkan_error if resource creation fails.
/// @throws LSFG::vulkan_error if resource creation fails.
///
Zeta(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,

View file

@ -10,7 +10,7 @@
#include <string>
#include <array>
namespace Vulkan::Utils {
namespace LSFG::Utils {
///
/// Insert memory barriers for images in a command buffer.
@ -79,13 +79,13 @@ namespace Vulkan::Utils {
/// @param image The image to clear.
/// @param white If true, the image will be cleared to white, otherwise to black.
///
/// @throws ls::vulkan_error If the Vulkan image cannot be cleared.
/// @throws LSFG::vulkan_error If the Vulkan image cannot be cleared.
///
void clearImage(const Device& device, Core::Image& image, bool white = false);
}
namespace Vulkan::Globals {
namespace LSFG::Globals {
/// Global sampler with address mode set to clamp to border.
extern Core::Sampler samplerClampBorder;
@ -118,32 +118,4 @@ namespace Vulkan::Globals {
}
namespace ls {
/// Simple exception class for Vulkan errors.
class vulkan_error : public std::runtime_error {
public:
///
/// Construct a vulkan_error with a message and a Vulkan result code.
///
/// @param result The Vulkan result code associated with the error.
/// @param message The error message.
///
explicit vulkan_error(VkResult result, const std::string& message);
/// Get the Vulkan result code associated with this error.
[[nodiscard]] VkResult error() const { return this->result; }
// Trivially copyable, moveable and destructible
vulkan_error(const vulkan_error&) = default;
vulkan_error(vulkan_error&&) = default;
vulkan_error& operator=(const vulkan_error&) = default;
vulkan_error& operator=(vulkan_error&&) = default;
~vulkan_error() noexcept override;
private:
VkResult result;
};
}
#endif // UTILS_HPP

View file

@ -1,10 +1,10 @@
#include "core/buffer.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
#include <algorithm>
#include <optional>
using namespace Vulkan::Core;
using namespace LSFG::Core;
void Buffer::construct(const Device& device, const void* data, VkBufferUsageFlags usage) {
// create buffer
@ -17,7 +17,7 @@ void Buffer::construct(const Device& device, const void* data, VkBufferUsageFlag
VkBuffer bufferHandle{};
auto res = vkCreateBuffer(device.handle(), &desc, nullptr, &bufferHandle);
if (res != VK_SUCCESS || bufferHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Failed to create Vulkan buffer");
throw LSFG::vulkan_error(res, "Failed to create Vulkan buffer");
// find memory type
VkPhysicalDeviceMemoryProperties memProps;
@ -38,7 +38,7 @@ void Buffer::construct(const Device& device, const void* data, VkBufferUsageFlag
} // NOLINTEND
}
if (!memType.has_value())
throw ls::vulkan_error(VK_ERROR_UNKNOWN, "Unable to find memory type for buffer");
throw LSFG::vulkan_error(VK_ERROR_UNKNOWN, "Unable to find memory type for buffer");
#pragma clang diagnostic pop
// allocate and bind memory
@ -50,17 +50,17 @@ void Buffer::construct(const Device& device, const void* data, VkBufferUsageFlag
VkDeviceMemory memoryHandle{};
res = vkAllocateMemory(device.handle(), &allocInfo, nullptr, &memoryHandle);
if (res != VK_SUCCESS || memoryHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Failed to allocate memory for Vulkan buffer");
throw LSFG::vulkan_error(res, "Failed to allocate memory for Vulkan buffer");
res = vkBindBufferMemory(device.handle(), bufferHandle, memoryHandle, 0);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Failed to bind memory to Vulkan buffer");
throw LSFG::vulkan_error(res, "Failed to bind memory to Vulkan buffer");
// upload data to buffer
uint8_t* buf{};
res = vkMapMemory(device.handle(), memoryHandle, 0, this->size, 0, reinterpret_cast<void**>(&buf));
if (res != VK_SUCCESS || buf == nullptr)
throw ls::vulkan_error(res, "Failed to map memory for Vulkan buffer");
throw LSFG::vulkan_error(res, "Failed to map memory for Vulkan buffer");
std::copy_n(reinterpret_cast<const uint8_t*>(data), this->size, buf);
vkUnmapMemory(device.handle(), memoryHandle);

View file

@ -1,7 +1,7 @@
#include "core/commandbuffer.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
CommandBuffer::CommandBuffer(const Device& device, const CommandPool& pool) {
// create command buffer
@ -14,7 +14,7 @@ CommandBuffer::CommandBuffer(const Device& device, const CommandPool& pool) {
VkCommandBuffer commandBufferHandle{};
auto res = vkAllocateCommandBuffers(device.handle(), &desc, &commandBufferHandle);
if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to allocate command buffer");
throw LSFG::vulkan_error(res, "Unable to allocate command buffer");
// store command buffer in shared ptr
this->state = std::make_shared<CommandBufferState>(CommandBufferState::Empty);
@ -36,7 +36,7 @@ void CommandBuffer::begin() {
};
auto res = vkBeginCommandBuffer(*this->commandBuffer, &beginInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Unable to begin command buffer");
throw LSFG::vulkan_error(res, "Unable to begin command buffer");
*this->state = CommandBufferState::Recording;
}
@ -54,7 +54,7 @@ void CommandBuffer::end() {
auto res = vkEndCommandBuffer(*this->commandBuffer);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Unable to end command buffer");
throw LSFG::vulkan_error(res, "Unable to end command buffer");
*this->state = CommandBufferState::Full;
}
@ -104,7 +104,7 @@ void CommandBuffer::submit(VkQueue queue, std::optional<Fence> fence,
};
auto res = vkQueueSubmit(queue, 1, &submitInfo, fence ? fence->handle() : VK_NULL_HANDLE);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Unable to submit command buffer");
throw LSFG::vulkan_error(res, "Unable to submit command buffer");
*this->state = CommandBufferState::Submitted;
}

View file

@ -1,7 +1,7 @@
#include "core/commandpool.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
CommandPool::CommandPool(const Device& device) {
// create command pool
@ -12,7 +12,7 @@ CommandPool::CommandPool(const Device& device) {
VkCommandPool commandPoolHandle{};
auto res = vkCreateCommandPool(device.handle(), &desc, nullptr, &commandPoolHandle);
if (res != VK_SUCCESS || commandPoolHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to create command pool");
throw LSFG::vulkan_error(res, "Unable to create command pool");
// store command pool in shared ptr
this->commandPool = std::shared_ptr<VkCommandPool>(

View file

@ -1,9 +1,9 @@
#include "core/descriptorpool.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
#include <array>
using namespace Vulkan::Core;
using namespace LSFG::Core;
DescriptorPool::DescriptorPool(const Device& device) {
// create descriptor pool
@ -23,7 +23,7 @@ DescriptorPool::DescriptorPool(const Device& device) {
VkDescriptorPool poolHandle{};
auto res = vkCreateDescriptorPool(device.handle(), &desc, nullptr, &poolHandle);
if (res != VK_SUCCESS || poolHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to create descriptor pool");
throw LSFG::vulkan_error(res, "Unable to create descriptor pool");
// store pool in shared ptr
this->descriptorPool = std::shared_ptr<VkDescriptorPool>(

View file

@ -1,8 +1,7 @@
#include "core/descriptorset.hpp"
#include "utils.hpp"
#include <algorithm>
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
DescriptorSet::DescriptorSet(const Device& device,
const DescriptorPool& pool, const ShaderModule& shaderModule) {
@ -17,7 +16,7 @@ DescriptorSet::DescriptorSet(const Device& device,
VkDescriptorSet descriptorSetHandle{};
auto res = vkAllocateDescriptorSets(device.handle(), &desc, &descriptorSetHandle);
if (res != VK_SUCCESS || descriptorSetHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to allocate descriptor set");
throw LSFG::vulkan_error(res, "Unable to allocate descriptor set");
/// store set in shared ptr
this->descriptorSet = std::shared_ptr<VkDescriptorSet>(

View file

@ -1,7 +1,7 @@
#include "core/fence.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
Fence::Fence(const Device& device) {
// create fence
@ -11,7 +11,7 @@ Fence::Fence(const Device& device) {
VkFence fenceHandle{};
auto res = vkCreateFence(device.handle(), &desc, nullptr, &fenceHandle);
if (res != VK_SUCCESS || fenceHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to create fence");
throw LSFG::vulkan_error(res, "Unable to create fence");
// store fence in shared ptr
this->fence = std::shared_ptr<VkFence>(
@ -26,14 +26,14 @@ void Fence::reset(const Device& device) const {
VkFence fenceHandle = this->handle();
auto res = vkResetFences(device.handle(), 1, &fenceHandle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Unable to reset fence");
throw LSFG::vulkan_error(res, "Unable to reset fence");
}
bool Fence::wait(const Device& device, uint64_t timeout) const {
VkFence fenceHandle = this->handle();
auto res = vkWaitForFences(device.handle(), 1, &fenceHandle, VK_TRUE, timeout);
if (res != VK_SUCCESS && res != VK_TIMEOUT)
throw ls::vulkan_error(res, "Unable to wait for fence");
throw LSFG::vulkan_error(res, "Unable to wait for fence");
return res == VK_SUCCESS;
}

View file

@ -1,9 +1,9 @@
#include "core/image.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
#include <optional>
using namespace Vulkan::Core;
using namespace LSFG::Core;
Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags)
@ -27,7 +27,7 @@ Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
VkImage imageHandle{};
auto res = vkCreateImage(device.handle(), &desc, nullptr, &imageHandle);
if (res != VK_SUCCESS || imageHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Failed to create Vulkan image");
throw LSFG::vulkan_error(res, "Failed to create Vulkan image");
// find memory type
VkPhysicalDeviceMemoryProperties memProps;
@ -47,7 +47,7 @@ Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
} // NOLINTEND
}
if (!memType.has_value())
throw ls::vulkan_error(VK_ERROR_UNKNOWN, "Unable to find memory type for image");
throw LSFG::vulkan_error(VK_ERROR_UNKNOWN, "Unable to find memory type for image");
#pragma clang diagnostic pop
// allocate and bind memory
@ -59,11 +59,11 @@ Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
VkDeviceMemory memoryHandle{};
res = vkAllocateMemory(device.handle(), &allocInfo, nullptr, &memoryHandle);
if (res != VK_SUCCESS || memoryHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Failed to allocate memory for Vulkan image");
throw LSFG::vulkan_error(res, "Failed to allocate memory for Vulkan image");
res = vkBindImageMemory(device.handle(), imageHandle, memoryHandle, 0);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Failed to bind memory to Vulkan image");
throw LSFG::vulkan_error(res, "Failed to bind memory to Vulkan image");
// create image view
const VkImageViewCreateInfo viewDesc{
@ -87,7 +87,7 @@ Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
VkImageView viewHandle{};
res = vkCreateImageView(device.handle(), &viewDesc, nullptr, &viewHandle);
if (res != VK_SUCCESS || viewHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Failed to create image view");
throw LSFG::vulkan_error(res, "Failed to create image view");
// store objects in shared ptr
this->layout = std::make_shared<VkImageLayout>(VK_IMAGE_LAYOUT_UNDEFINED);

View file

@ -1,7 +1,7 @@
#include "core/pipeline.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
Pipeline::Pipeline(const Device& device, const ShaderModule& shader) {
// create pipeline layout
@ -14,7 +14,7 @@ Pipeline::Pipeline(const Device& device, const ShaderModule& shader) {
VkPipelineLayout layoutHandle{};
auto res = vkCreatePipelineLayout(device.handle(), &layoutDesc, nullptr, &layoutHandle);
if (res != VK_SUCCESS || !layoutHandle)
throw ls::vulkan_error(res, "Failed to create pipeline layout");
throw LSFG::vulkan_error(res, "Failed to create pipeline layout");
// create pipeline
const VkPipelineShaderStageCreateInfo shaderStageInfo{
@ -32,7 +32,7 @@ Pipeline::Pipeline(const Device& device, const ShaderModule& shader) {
res = vkCreateComputePipelines(device.handle(),
VK_NULL_HANDLE, 1, &pipelineDesc, nullptr, &pipelineHandle);
if (res != VK_SUCCESS || !pipelineHandle)
throw ls::vulkan_error(res, "Failed to create compute pipeline");
throw LSFG::vulkan_error(res, "Failed to create compute pipeline");
// store layout and pipeline in shared ptr
this->layout = std::shared_ptr<VkPipelineLayout>(

View file

@ -1,7 +1,7 @@
#include "core/sampler.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
Sampler::Sampler(const Device& device, VkSamplerAddressMode mode) {
// create sampler
@ -18,7 +18,7 @@ Sampler::Sampler(const Device& device, VkSamplerAddressMode mode) {
VkSampler samplerHandle{};
auto res = vkCreateSampler(device.handle(), &desc, nullptr, &samplerHandle);
if (res != VK_SUCCESS || samplerHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to create sampler");
throw LSFG::vulkan_error(res, "Unable to create sampler");
// store sampler in shared ptr
this->sampler = std::shared_ptr<VkSampler>(

View file

@ -1,7 +1,7 @@
#include "core/semaphore.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
using namespace Vulkan::Core;
using namespace LSFG::Core;
Semaphore::Semaphore(const Device& device, std::optional<uint32_t> initial) {
// create semaphore
@ -17,7 +17,7 @@ Semaphore::Semaphore(const Device& device, std::optional<uint32_t> initial) {
VkSemaphore semaphoreHandle{};
auto res = vkCreateSemaphore(device.handle(), &desc, nullptr, &semaphoreHandle);
if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to create semaphore");
throw LSFG::vulkan_error(res, "Unable to create semaphore");
// store semaphore in shared ptr
this->isTimeline = initial.has_value();
@ -40,7 +40,7 @@ void Semaphore::signal(const Device& device, uint64_t value) const {
};
auto res = vkSignalSemaphore(device.handle(), &signalInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Unable to signal semaphore");
throw LSFG::vulkan_error(res, "Unable to signal semaphore");
}
bool Semaphore::wait(const Device& device, uint64_t value, uint64_t timeout) const {
@ -56,7 +56,7 @@ bool Semaphore::wait(const Device& device, uint64_t value, uint64_t timeout) con
};
auto res = vkWaitSemaphores(device.handle(), &waitInfo, timeout);
if (res != VK_SUCCESS && res != VK_TIMEOUT)
throw ls::vulkan_error(res, "Unable to wait for semaphore");
throw LSFG::vulkan_error(res, "Unable to wait for semaphore");
return res == VK_SUCCESS;
}

View file

@ -1,9 +1,9 @@
#include "core/shadermodule.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
#include <fstream>
using namespace Vulkan::Core;
using namespace LSFG::Core;
ShaderModule::ShaderModule(const Device& device, const std::string& path,
const std::vector<std::pair<size_t, VkDescriptorType>>& descriptorTypes) {
@ -31,7 +31,7 @@ ShaderModule::ShaderModule(const Device& device, const std::string& path,
VkShaderModule shaderModuleHandle{};
auto res = vkCreateShaderModule(device.handle(), &createInfo, nullptr, &shaderModuleHandle);
if (res != VK_SUCCESS || !shaderModuleHandle)
throw ls::vulkan_error(res, "Failed to create shader module");
throw LSFG::vulkan_error(res, "Failed to create shader module");
// create descriptor set layout
std::vector<VkDescriptorSetLayoutBinding> layoutBindings;
@ -53,7 +53,7 @@ ShaderModule::ShaderModule(const Device& device, const std::string& path,
VkDescriptorSetLayout descriptorSetLayout{};
res = vkCreateDescriptorSetLayout(device.handle(), &layoutDesc, nullptr, &descriptorSetLayout);
if (res != VK_SUCCESS || !descriptorSetLayout)
throw ls::vulkan_error(res, "Failed to create descriptor set layout");
throw LSFG::vulkan_error(res, "Failed to create descriptor set layout");
// store module and layout in shared ptr
this->shaderModule = std::shared_ptr<VkShaderModule>(

View file

@ -1,11 +1,10 @@
#include "device.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
#include <optional>
#include <vector>
#include <vulkan/vulkan_core.h>
using namespace Vulkan;
using namespace LSFG;
const std::vector<const char*> requiredExtensions = {
"VK_KHR_external_memory_fd",
@ -17,12 +16,12 @@ Device::Device(const Instance& instance) {
uint32_t deviceCount{};
auto res = vkEnumeratePhysicalDevices(instance.handle(), &deviceCount, nullptr);
if (res != VK_SUCCESS || deviceCount == 0)
throw ls::vulkan_error(res, "Failed to enumerate physical devices");
throw LSFG::vulkan_error(res, "Failed to enumerate physical devices");
std::vector<VkPhysicalDevice> devices(deviceCount);
res = vkEnumeratePhysicalDevices(instance.handle(), &deviceCount, devices.data());
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Failed to get physical devices");
throw LSFG::vulkan_error(res, "Failed to get physical devices");
// find first discrete GPU
std::optional<VkPhysicalDevice> physicalDevice;
@ -36,7 +35,7 @@ Device::Device(const Instance& instance) {
}
}
if (!physicalDevice)
throw ls::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No discrete GPU found");
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No discrete GPU found");
// find queue family indices
uint32_t familyCount{};
@ -51,7 +50,7 @@ Device::Device(const Instance& instance) {
computeFamilyIdx = i;
}
if (!computeFamilyIdx)
throw ls::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No compute queue family found");
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No compute queue family found");
// create logical device
const float queuePriority{1.0F}; // highest priority
@ -87,7 +86,7 @@ Device::Device(const Instance& instance) {
VkDevice deviceHandle{};
res = vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);
if (res != VK_SUCCESS | deviceHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Failed to create logical device");
throw LSFG::vulkan_error(res, "Failed to create logical device");
// get compute queue
VkQueue queueHandle{};

View file

@ -1,9 +1,9 @@
#include "instance.hpp"
#include "utils.hpp"
#include "lsfg.hpp"
#include <vector>
using namespace Vulkan;
using namespace LSFG;
const std::vector<const char*> requiredExtensions = {
@ -34,7 +34,7 @@ Instance::Instance() {
VkInstance instanceHandle{};
auto res = vkCreateInstance(&createInfo, nullptr, &instanceHandle);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "Failed to create Vulkan instance");
throw LSFG::vulkan_error(res, "Failed to create Vulkan instance");
// store in shared ptr
this->instance = std::shared_ptr<VkInstance>(

106
src/lsfg.cpp Normal file
View file

@ -0,0 +1,106 @@
#include "lsfg.hpp"
#include "core/commandbuffer.hpp"
#include <format>
using namespace LSFG;
Generator::Generator(const Context& context) {
// TODO: temporal frames
// create shader chains
this->downsampleChain = Shaderchains::Downsample(context.device, context.descPool,
this->fullFrame0, this->fullFrame1);
for (size_t i = 0; i < 7; i++)
this->alphaChains.at(i) = Shaderchains::Alpha(context.device, context.descPool,
this->downsampleChain.getOutImages().at(i), i == 0);
this->betaChain = Shaderchains::Beta(context.device, context.descPool,
this->alphaChains.at(0).getOutImages0(),
this->alphaChains.at(0).getOutImages1(),
this->alphaChains.at(0).getOutImages2());
for (size_t i = 0; i < 7; i++) {
if (i < 4) {
this->gammaChains.at(i) = Shaderchains::Gamma(context.device, context.descPool,
this->alphaChains.at(6 - i).getOutImages1(),
this->alphaChains.at(6 - i).getOutImages0(),
this->betaChain.getOutImages().at(std::min(5UL, 6 - i)),
i == 0 ? std::nullopt
: std::optional{this->gammaChains.at(i - 1).getOutImage2()},
i == 0 ? std::nullopt
: std::optional{this->gammaChains.at(i - 1).getOutImage1()},
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent()
);
} else {
// this->magicChains.at(i - 4) = Shaderchains::Magic(context.device, context.descPool,
// this->alphaChains.at(6 - i).getOutImages(),
// i == 4 ? this->gammaChains.at(i - 1).getOutImage2()
// : this->extractChains.at(i - 5).getOutImage(),
// i == 4 ? this->gammaChains.at(i - 1).getOutImage1()
// : this->zetaChains.at(i - 5).getOutImage(),
// i == 4 ? std::nullopt : std::optional{this->epsilonChains.at(i - 5).getOutImage()}
// );
this->deltaChains.at(i - 4) = Shaderchains::Delta(context.device, context.descPool,
this->magicChains.at(i - 4).getOutImages1(),
i == 4 ? std::nullopt
: std::optional{this->deltaChains.at(i - 5).getOutImage()}
);
this->epsilonChains.at(i - 4) = Shaderchains::Epsilon(context.device, context.descPool,
this->magicChains.at(i - 4).getOutImages2(),
this->betaChain.getOutImages().at(6 - i),
i == 4 ? std::nullopt
: std::optional{this->epsilonChains.at(i - 5).getOutImage()}
);
this->zetaChains.at(i - 4) = Shaderchains::Zeta(context.device, context.descPool,
this->magicChains.at(i - 4).getOutImages3(),
i == 4 ? this->gammaChains.at(i - 1).getOutImage1()
: this->zetaChains.at(i - 5).getOutImage(),
this->betaChain.getOutImages().at(6 - i)
);
if (i >= 6)
continue; // no extract for i >= 6
this->extractChains.at(i - 4) = Shaderchains::Extract(context.device, context.descPool,
this->zetaChains.at(i - 4).getOutImage(),
this->epsilonChains.at(i - 4).getOutImage(),
this->extractChains.at(i - 5).getOutImage().getExtent()
);
}
}
this->mergeChain = Shaderchains::Merge(context.device, context.descPool,
this->fullFrame0,
this->fullFrame1,
this->zetaChains.at(2).getOutImage(),
this->epsilonChains.at(2).getOutImage(),
this->deltaChains.at(2).getOutImage()
);
}
void Generator::present(const Context& context) {
Core::CommandBuffer cmdBuffer(context.device, context.cmdPool);
cmdBuffer.begin();
this->downsampleChain.Dispatch(cmdBuffer, fc);
for (size_t i = 0; i < 7; i++)
this->alphaChains.at(6 - i).Dispatch(cmdBuffer, fc);
this->betaChain.Dispatch(cmdBuffer, fc);
for (size_t i = 0; i < 4; i++)
this->gammaChains.at(i).Dispatch(cmdBuffer);
for (size_t i = 0; i < 3; i++) {
this->magicChains.at(i).Dispatch(cmdBuffer);
this->deltaChains.at(i).Dispatch(cmdBuffer);
this->epsilonChains.at(i).Dispatch(cmdBuffer);
this->zetaChains.at(i).Dispatch(cmdBuffer);
if (i < 2)
this->extractChains.at(i).Dispatch(cmdBuffer);
}
this->mergeChain.Dispatch(cmdBuffer, fc);
cmdBuffer.end();
// TODO: submit logic
fc++;
}
vulkan_error::vulkan_error(VkResult result, const std::string& message)
: std::runtime_error(std::format("{} (error {})", message, static_cast<int32_t>(result))), result(result) {}
vulkan_error::~vulkan_error() noexcept = default;

View file

@ -25,7 +25,7 @@
#include <unistd.h>
#include <vector>
using namespace Vulkan;
using namespace LSFG;
int main() {
// attempt to load renderdoc
@ -43,12 +43,12 @@ int main() {
}
// initialize application
const Instance instance;
const Device device(instance);
const Core::DescriptorPool descriptorPool(device);
const Core::CommandPool commandPool(device);
// const Instance instance;
// const Device device(instance);
// const Core::DescriptorPool descriptorPool(device);
// const Core::CommandPool commandPool(device);
Globals::initializeGlobals(device);
// Globals::initializeGlobals(device);
// create downsample shader chain
Core::Image inputImage(
@ -58,156 +58,156 @@ int main() {
);
Utils::uploadImage(device, commandPool, inputImage, "rsc/images/source.dds");
Shaderchains::Downsample downsample(device, descriptorPool, inputImage);
// Shaderchains::Downsample downsample(device, descriptorPool, inputImage);
// create alpha shader chains
std::vector<Shaderchains::Alpha> alphas;
alphas.reserve(7);
for (size_t i = 0; i < 7; ++i)
alphas.emplace_back(device, descriptorPool, downsample.getOutImages().at(i));
// std::vector<Shaderchains::Alpha> alphas;
// alphas.reserve(7);
// for (size_t i = 0; i < 7; ++i)
// alphas.emplace_back(device, descriptorPool, downsample.getOutImages().at(i));
// create beta shader chain
std::array<Core::Image, 8> betaTemporalImages;
auto betaInExtent = alphas.at(0).getOutImages().at(0).getExtent();
for (size_t i = 0; i < 8; ++i) {
betaTemporalImages.at(i) = Core::Image(
device, betaInExtent, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
VK_IMAGE_ASPECT_COLOR_BIT
);
Utils::uploadImage(device, commandPool, betaTemporalImages.at(i),
std::format("rsc/images/temporal_beta/{}.dds", i));
}
// // create beta shader chain
// std::array<Core::Image, 8> betaTemporalImages;
// auto betaInExtent = alphas.at(0).getOutImages().at(0).getExtent();
// for (size_t i = 0; i < 8; ++i) {
// betaTemporalImages.at(i) = Core::Image(
// device, betaInExtent, VK_FORMAT_R8G8B8A8_UNORM,
// VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
// VK_IMAGE_USAGE_TRANSFER_DST_BIT,
// VK_IMAGE_ASPECT_COLOR_BIT
// );
// Utils::uploadImage(device, commandPool, betaTemporalImages.at(i),
// std::format("rsc/images/temporal_beta/{}.dds", i));
// }
Shaderchains::Beta beta(device, descriptorPool,
betaTemporalImages,
alphas.at(0).getOutImages()
// Shaderchains::Beta beta(device, descriptorPool,
// betaTemporalImages,
// alphas.at(0).getOutImages()
);
// create gamma to zeta shader chains
std::vector<Shaderchains::Gamma> gammas;
std::vector<Shaderchains::Magic> magics;
std::vector<Shaderchains::Delta> deltas;
std::vector<Shaderchains::Epsilon> epsilons;
std::vector<Shaderchains::Zeta> zetas;
std::vector<Shaderchains::Extract> extracts;
std::array<std::array<Core::Image, 4>, 7> otherTemporalImages;
for (size_t i = 0; i < 7; i++) {
auto otherInExtent = alphas.at(6 - i).getOutImages().at(0).getExtent();
for (size_t j = 0; j < 4; j++) {
otherTemporalImages.at(i).at(j) = Core::Image(
device, otherInExtent, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
VK_IMAGE_ASPECT_COLOR_BIT
);
Utils::uploadImage(device, commandPool, otherTemporalImages.at(i).at(j),
std::format("rsc/images/temporal_other/{}.{}.dds", i, j));
}
if (i < 4) {
auto gammaOutExtent = alphas.at(6 - i - 1).getOutImages().at(0).getExtent();
gammas.emplace_back(device, descriptorPool,
otherTemporalImages.at(i),
alphas.at(6 - i).getOutImages(),
beta.getOutImages().at(std::min(static_cast<size_t>(5), 6 - i)), // smallest twice
i == 0 ? std::nullopt : std::optional{gammas.at(i - 1).getOutImage2()},
i == 0 ? std::nullopt : std::optional{gammas.at(i - 1).getOutImage1()},
gammaOutExtent);
} else {
magics.emplace_back(device, descriptorPool,
otherTemporalImages.at(i),
alphas.at(6 - i).getOutImages(),
i == 4 ? gammas.at(i - 1).getOutImage2() : extracts.at(i - 5).getOutImage(),
i == 4 ? gammas.at(i - 1).getOutImage1() : zetas.at(i - 5).getOutImage(),
i == 4 ? std::nullopt : std::optional{epsilons.at(i - 5).getOutImage()}
);
deltas.emplace_back(device, descriptorPool,
magics.at(i - 4).getOutImages1(),
i == 4 ? std::nullopt : std::optional{deltas.at(i - 5).getOutImage()}
);
epsilons.emplace_back(device, descriptorPool,
magics.at(i - 4).getOutImages2(),
beta.getOutImages().at(6 - i),
i == 4 ? std::nullopt : std::optional{epsilons.at(i - 5).getOutImage()}
);
zetas.emplace_back(device, descriptorPool,
magics.at(i - 4).getOutImages3(),
i == 4 ? gammas.at(i - 1).getOutImage1() : zetas.at(i - 5).getOutImage(),
beta.getOutImages().at(6 - i)
);
if (i < 6) {
auto extractOutExtent = alphas.at(6 - i - 1).getOutImages().at(0).getExtent();
extracts.emplace_back(device, descriptorPool,
zetas.at(i - 4).getOutImage(),
epsilons.at(i - 4).getOutImage(),
extractOutExtent);
}
}
}
// std::vector<Shaderchains::Gamma> gammas;
// std::vector<Shaderchains::Magic> magics;
// std::vector<Shaderchains::Delta> deltas;
// std::vector<Shaderchains::Epsilon> epsilons;
// std::vector<Shaderchains::Zeta> zetas;
// std::vector<Shaderchains::Extract> extracts;
// std::array<std::array<Core::Image, 4>, 7> otherTemporalImages;
// for (size_t i = 0; i < 7; i++) {
// auto otherInExtent = alphas.at(6 - i).getOutImages().at(0).getExtent();
// for (size_t j = 0; j < 4; j++) {
// otherTemporalImages.at(i).at(j) = Core::Image(
// device, otherInExtent, VK_FORMAT_R8G8B8A8_UNORM,
// VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
// VK_IMAGE_USAGE_TRANSFER_DST_BIT,
// VK_IMAGE_ASPECT_COLOR_BIT
// );
// Utils::uploadImage(device, commandPool, otherTemporalImages.at(i).at(j),
// std::format("rsc/images/temporal_other/{}.{}.dds", i, j));
// }
// if (i < 4) {
// auto gammaOutExtent = alphas.at(6 - i - 1).getOutImages().at(0).getExtent();
// gammas.emplace_back(device, descriptorPool,
// otherTemporalImages.at(i),
// alphas.at(6 - i).getOutImages(),
// beta.getOutImages().at(std::min(static_cast<size_t>(5), 6 - i)), // smallest twice
// i == 0 ? std::nullopt : std::optional{gammas.at(i - 1).getOutImage2()},
// i == 0 ? std::nullopt : std::optional{gammas.at(i - 1).getOutImage1()},
// gammaOutExtent);
// } else {
// magics.emplace_back(device, descriptorPool,
// otherTemporalImages.at(i),
// alphas.at(6 - i).getOutImages(),
// i == 4 ? gammas.at(i - 1).getOutImage2() : extracts.at(i - 5).getOutImage(),
// i == 4 ? gammas.at(i - 1).getOutImage1() : zetas.at(i - 5).getOutImage(),
// i == 4 ? std::nullopt : std::optional{epsilons.at(i - 5).getOutImage()}
// );
// deltas.emplace_back(device, descriptorPool,
// magics.at(i - 4).getOutImages1(),
// i == 4 ? std::nullopt : std::optional{deltas.at(i - 5).getOutImage()}
// );
// epsilons.emplace_back(device, descriptorPool,
// magics.at(i - 4).getOutImages2(),
// beta.getOutImages().at(6 - i),
// i == 4 ? std::nullopt : std::optional{epsilons.at(i - 5).getOutImage()}
// );
// zetas.emplace_back(device, descriptorPool,
// magics.at(i - 4).getOutImages3(),
// i == 4 ? gammas.at(i - 1).getOutImage1() : zetas.at(i - 5).getOutImage(),
// beta.getOutImages().at(6 - i)
// );
// if (i < 6) {
// auto extractOutExtent = alphas.at(6 - i - 1).getOutImages().at(0).getExtent();
// extracts.emplace_back(device, descriptorPool,
// zetas.at(i - 4).getOutImage(),
// epsilons.at(i - 4).getOutImage(),
// extractOutExtent);
// }
// }
// }
// create merge shader chain
Core::Image inputImagePrev(
device, { 2560, 1411 }, VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
VK_IMAGE_ASPECT_COLOR_BIT
);
Utils::uploadImage(device, commandPool, inputImagePrev, "rsc/images/source_prev.dds");
Shaderchains::Merge merge(device, descriptorPool,
inputImagePrev,
inputImage,
zetas.at(2).getOutImage(),
epsilons.at(2).getOutImage(),
deltas.at(2).getOutImage()
);
// // create merge shader chain
// Core::Image inputImagePrev(
// device, { 2560, 1411 }, VK_FORMAT_R8G8B8A8_UNORM,
// VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
// VK_IMAGE_ASPECT_COLOR_BIT
// );
// Utils::uploadImage(device, commandPool, inputImagePrev, "rsc/images/source_prev.dds");
// Shaderchains::Merge merge(device, descriptorPool,
// inputImagePrev,
// inputImage,
// zetas.at(2).getOutImage(),
// epsilons.at(2).getOutImage(),
// deltas.at(2).getOutImage()
// );
for (int i = 0; i < 1000; i++) {
const Core::Fence fence(device);
// for (int i = 0; i < 1000; i++) {
// const Core::Fence fence(device);
// start the rendering pipeline
if (rdoc)
rdoc->StartFrameCapture(nullptr, nullptr);
// // start the rendering pipeline
// if (rdoc)
// rdoc->StartFrameCapture(nullptr, nullptr);
Core::CommandBuffer commandBuffer(device, commandPool);
commandBuffer.begin();
// Core::CommandBuffer commandBuffer(device, commandPool);
// commandBuffer.begin();
downsample.Dispatch(commandBuffer);
for (size_t i = 0; i < 7; i++)
alphas.at(6 - i).Dispatch(commandBuffer);
beta.Dispatch(commandBuffer);
for (size_t i = 0; i < 4; i++)
gammas.at(i).Dispatch(commandBuffer);
for (size_t i = 0; i < 3; i++) {
magics.at(i).Dispatch(commandBuffer);
deltas.at(i).Dispatch(commandBuffer);
epsilons.at(i).Dispatch(commandBuffer);
zetas.at(i).Dispatch(commandBuffer);
if (i < 2)
extracts.at(i).Dispatch(commandBuffer);
}
merge.Dispatch(commandBuffer);
// downsample.Dispatch(commandBuffer);
// for (size_t i = 0; i < 7; i++)
// alphas.at(6 - i).Dispatch(commandBuffer);
// beta.Dispatch(commandBuffer);
// for (size_t i = 0; i < 4; i++)
// gammas.at(i).Dispatch(commandBuffer);
// for (size_t i = 0; i < 3; i++) {
// magics.at(i).Dispatch(commandBuffer);
// deltas.at(i).Dispatch(commandBuffer);
// epsilons.at(i).Dispatch(commandBuffer);
// zetas.at(i).Dispatch(commandBuffer);
// if (i < 2)
// extracts.at(i).Dispatch(commandBuffer);
// }
// merge.Dispatch(commandBuffer);
// finish the rendering pipeline
commandBuffer.end();
// // finish the rendering pipeline
// commandBuffer.end();
commandBuffer.submit(device.getComputeQueue(), fence);
if (!fence.wait(device)) {
Globals::uninitializeGlobals();
// commandBuffer.submit(device.getComputeQueue(), fence);
// if (!fence.wait(device)) {
// Globals::uninitializeGlobals();
std::cerr << "Application failed due to timeout" << '\n';
return 1;
}
// std::cerr << "Application failed due to timeout" << '\n';
// return 1;
// }
if (rdoc)
rdoc->EndFrameCapture(nullptr, nullptr);
// if (rdoc)
// rdoc->EndFrameCapture(nullptr, nullptr);
// sleep 8 ms
usleep(8000);
}
// // sleep 8 ms
// usleep(8000);
// }
usleep(1000 * 100); // give renderdoc time to capture
// usleep(1000 * 100); // give renderdoc time to capture
Globals::uninitializeGlobals();
// Globals::uninitializeGlobals();
std::cerr << "Application finished" << '\n';
return 0;

View file

@ -1,7 +1,7 @@
#include "shaderchains/alpha.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg)

View file

@ -1,7 +1,7 @@
#include "shaderchains/beta.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Beta::Beta(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 8> temporalImgs,

View file

@ -1,7 +1,7 @@
#include "shaderchains/delta.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Delta::Delta(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 2> inImgs,

View file

@ -1,7 +1,7 @@
#include "shaderchains/downsample.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Downsample::Downsample(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg)

View file

@ -1,7 +1,7 @@
#include "shaderchains/epsilon.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Epsilon::Epsilon(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,

View file

@ -1,7 +1,7 @@
#include "shaderchains/extract.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Extract::Extract(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg1,

View file

@ -1,7 +1,7 @@
#include "shaderchains/gamma.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Gamma::Gamma(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> temporalImgs,

View file

@ -1,7 +1,7 @@
#include "shaderchains/magic.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Magic::Magic(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 4> temporalImgs,

View file

@ -1,8 +1,7 @@
#include "shaderchains/merge.hpp"
#include "utils.hpp"
#include <vulkan/vulkan_core.h>
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Merge::Merge(const Device& device, const Core::DescriptorPool& pool,
Core::Image inImg1,

View file

@ -1,7 +1,7 @@
#include "shaderchains/zeta.hpp"
#include "utils.hpp"
using namespace Vulkan::Shaderchains;
using namespace LSFG::Shaderchains;
Zeta::Zeta(const Device& device, const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,

View file

@ -1,12 +1,11 @@
#include "utils.hpp"
#include "core/buffer.hpp"
#include "lsfg.hpp"
#include <format>
#include <fstream>
#include <vulkan/vulkan_core.h>
using namespace Vulkan;
using namespace Vulkan::Utils;
using namespace LSFG;
using namespace LSFG::Utils;
BarrierBuilder& BarrierBuilder::addR2W(Core::Image& image) {
this->barriers.emplace_back(VkImageMemoryBarrier2 {
@ -128,7 +127,7 @@ void Utils::uploadImage(const Device& device, const Core::CommandPool& commandPo
// wait for the upload to complete
if (!fence.wait(device))
throw ls::vulkan_error(VK_TIMEOUT, "Upload operation timed out");
throw LSFG::vulkan_error(VK_TIMEOUT, "Upload operation timed out");
}
void Utils::clearImage(const Device& device, Core::Image& image, bool white) {
@ -174,7 +173,7 @@ void Utils::clearImage(const Device& device, Core::Image& image, bool white) {
cmdBuf.submit(device.getComputeQueue(), fence);
if (!fence.wait(device))
throw ls::vulkan_error(VK_TIMEOUT, "Failed to wait for clearing fence.");
throw LSFG::vulkan_error(VK_TIMEOUT, "Failed to wait for clearing fence.");
}
Core::Sampler Globals::samplerClampBorder;
@ -203,8 +202,3 @@ void Globals::uninitializeGlobals() noexcept {
// uninitialize global constant buffer
fgBuffer = Globals::FgBuffer();
}
ls::vulkan_error::vulkan_error(VkResult result, const std::string& message)
: std::runtime_error(std::format("{} (error {})", message, static_cast<int32_t>(result))), result(result) {}
ls::vulkan_error::~vulkan_error() noexcept = default;