mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
make it a library
This commit is contained in:
parent
b7ca80adb7
commit
08646483a8
55 changed files with 417 additions and 382 deletions
|
|
@ -22,10 +22,11 @@ file(GLOB SOURCES
|
|||
"src/*.cpp"
|
||||
)
|
||||
|
||||
add_executable(lsfg-vk-base ${SOURCES})
|
||||
add_library(lsfg-vk-base SHARED ${SOURCES})
|
||||
|
||||
target_include_directories(lsfg-vk-base
|
||||
PUBLIC include)
|
||||
PRIVATE include
|
||||
PUBLIC public)
|
||||
target_link_libraries(lsfg-vk-base
|
||||
PUBLIC vulkan)
|
||||
target_compile_options(lsfg-vk-base PRIVATE
|
||||
|
|
|
|||
76
include/context.hpp
Normal file
76
include/context.hpp
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef CONTEXT_HPP
|
||||
#define CONTEXT_HPP
|
||||
|
||||
#include "core/commandpool.hpp"
|
||||
#include "core/descriptorpool.hpp"
|
||||
#include "core/image.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"
|
||||
|
||||
namespace LSFG {
|
||||
|
||||
///
|
||||
/// LSFG context.
|
||||
///
|
||||
class Context {
|
||||
public:
|
||||
///
|
||||
/// Create a generator instance.
|
||||
///
|
||||
/// @param device The Vulkan device to use.
|
||||
/// @param width Width of the input images.
|
||||
/// @param height Height of the input images.
|
||||
/// @param in0 File descriptor for the first input image.
|
||||
/// @param in1 File descriptor for the second input image.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if the generator fails to initialize.
|
||||
///
|
||||
Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1);
|
||||
|
||||
///
|
||||
/// Schedule the next generation.
|
||||
///
|
||||
/// @param device The Vulkan device to use.
|
||||
/// @param inSem Semaphore to wait on before starting the generation.
|
||||
/// @param outSem Semaphore to signal when the generation is complete.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if the generator fails to present.
|
||||
///
|
||||
void present(const Core::Device& device, int inSem, int outSem);
|
||||
|
||||
// Trivially copyable, moveable and destructible
|
||||
Context(const Context&) = default;
|
||||
Context(Context&&) = default;
|
||||
Context& operator=(const Context&) = default;
|
||||
Context& operator=(Context&&) = default;
|
||||
~Context() = default;
|
||||
private:
|
||||
Core::DescriptorPool descPool;
|
||||
Core::CommandPool cmdPool;
|
||||
|
||||
Core::Image inImg_0, inImg_1; // inImg_0 is next (inImg_1 prev) when fc % 2 == 0
|
||||
uint64_t fc{0};
|
||||
|
||||
Shaderchains::Downsample downsampleChain;
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CONTEXT_HPP
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef BUFFER_HPP
|
||||
#define BUFFER_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ namespace LSFG::Core {
|
|||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
template<typename T>
|
||||
Buffer(const Device& device, const T& data, VkBufferUsageFlags usage)
|
||||
Buffer(const Core::Device& device, const T& data, VkBufferUsageFlags usage)
|
||||
: size(sizeof(T)) {
|
||||
construct(device, reinterpret_cast<const void*>(&data), usage);
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
Buffer(const Device& device, const void* data, size_t size, VkBufferUsageFlags usage)
|
||||
Buffer(const Core::Device& device, const void* data, size_t size, VkBufferUsageFlags usage)
|
||||
: size(size) {
|
||||
construct(device, data, usage);
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ namespace LSFG::Core {
|
|||
Buffer& operator=(Buffer&&) noexcept = default;
|
||||
~Buffer() = default;
|
||||
private:
|
||||
void construct(const Device& device, const void* data, VkBufferUsageFlags usage);
|
||||
void construct(const Core::Device& device, const void* data, VkBufferUsageFlags usage);
|
||||
|
||||
std::shared_ptr<VkBuffer> buffer;
|
||||
std::shared_ptr<VkDeviceMemory> memory;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "core/commandpool.hpp"
|
||||
#include "core/fence.hpp"
|
||||
#include "core/semaphore.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
CommandBuffer(const Device& device, const CommandPool& pool);
|
||||
CommandBuffer(const Core::Device& device, const CommandPool& pool);
|
||||
|
||||
///
|
||||
/// Begin recording commands in the command buffer.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef COMMANDPOOL_HPP
|
||||
#define COMMANDPOOL_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
CommandPool(const Device& device);
|
||||
CommandPool(const Core::Device& device);
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->commandPool; }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef DESCRIPTORPOOL_HPP
|
||||
#define DESCRIPTORPOOL_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
DescriptorPool(const Device& device);
|
||||
DescriptorPool(const Core::Device& device);
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->descriptorPool; }
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/pipeline.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
DescriptorSet(const Device& device,
|
||||
DescriptorSet(const Core::Device& device,
|
||||
const DescriptorPool& pool, const ShaderModule& shaderModule);
|
||||
|
||||
///
|
||||
|
|
@ -44,7 +44,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @param device Vulkan device
|
||||
///
|
||||
[[nodiscard]] DescriptorSetUpdateBuilder update(const Device& device) const;
|
||||
[[nodiscard]] DescriptorSetUpdateBuilder update(const Core::Device& device) const;
|
||||
|
||||
///
|
||||
/// Bind a descriptor set to a command buffer.
|
||||
|
|
@ -110,9 +110,9 @@ namespace LSFG::Core {
|
|||
void build();
|
||||
private:
|
||||
const DescriptorSet* descriptorSet;
|
||||
const Device* device;
|
||||
const Core::Device* device;
|
||||
|
||||
DescriptorSetUpdateBuilder(const DescriptorSet& descriptorSet, const Device& device)
|
||||
DescriptorSetUpdateBuilder(const DescriptorSet& descriptorSet, const Core::Device& device)
|
||||
: descriptorSet(&descriptorSet), device(&device) {}
|
||||
|
||||
std::vector<VkWriteDescriptorSet> entries;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#ifndef DEVICE_HPP
|
||||
#define DEVICE_HPP
|
||||
|
||||
#include "instance.hpp"
|
||||
#include "core/instance.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace LSFG {
|
||||
namespace LSFG::Core {
|
||||
|
||||
///
|
||||
/// C++ wrapper class for a Vulkan device.
|
||||
|
|
@ -36,8 +36,8 @@ namespace LSFG {
|
|||
[[nodiscard]] VkQueue getComputeQueue() const { return this->computeQueue; }
|
||||
|
||||
// Trivially copyable, moveable and destructible
|
||||
Device(const Device&) noexcept = default;
|
||||
Device& operator=(const Device&) noexcept = default;
|
||||
Device(const Core::Device&) noexcept = default;
|
||||
Device& operator=(const Core::Device&) noexcept = default;
|
||||
Device(Device&&) noexcept = default;
|
||||
Device& operator=(Device&&) noexcept = default;
|
||||
~Device() = default;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef FENCE_HPP
|
||||
#define FENCE_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
Fence(const Device& device);
|
||||
Fence(const Core::Device& device);
|
||||
|
||||
///
|
||||
/// Reset the fence to an unsignaled state.
|
||||
|
|
@ -34,7 +34,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resetting fails.
|
||||
///
|
||||
void reset(const Device& device) const;
|
||||
void reset(const Core::Device& device) const;
|
||||
|
||||
///
|
||||
/// Wait for the fence
|
||||
|
|
@ -45,7 +45,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if waiting fails.
|
||||
///
|
||||
[[nodiscard]] bool wait(const Device& device, uint64_t timeout = UINT64_MAX) const;
|
||||
[[nodiscard]] bool wait(const Core::Device& device, uint64_t timeout = UINT64_MAX) const;
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->fence; }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IMAGE_HPP
|
||||
#define IMAGE_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
Image(const Device& device, VkExtent2D extent, VkFormat format,
|
||||
Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
||||
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags);
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
namespace LSFG {
|
||||
namespace LSFG::Core {
|
||||
|
||||
///
|
||||
/// C++ wrapper class for a Vulkan instance.
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
Pipeline(const Device& device, const ShaderModule& shader);
|
||||
Pipeline(const Core::Device& device, const ShaderModule& shader);
|
||||
|
||||
///
|
||||
/// Bind the pipeline to a command buffer.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SAMPLER_HPP
|
||||
#define SAMPLER_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
Sampler(const Device& device, VkSamplerAddressMode mode);
|
||||
Sampler(const Core::Device& device, VkSamplerAddressMode mode);
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->sampler; }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SEMAPHORE_HPP
|
||||
#define SEMAPHORE_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ namespace LSFG::Core {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
Semaphore(const Device& device, std::optional<uint32_t> initial = std::nullopt);
|
||||
Semaphore(const Core::Device& device, std::optional<uint32_t> initial = std::nullopt);
|
||||
|
||||
///
|
||||
/// Signal the semaphore to a specific value.
|
||||
|
|
@ -38,7 +38,7 @@ namespace LSFG::Core {
|
|||
/// @throws std::logic_error if the semaphore is not a timeline semaphore.
|
||||
/// @throws LSFG::vulkan_error if signaling fails.
|
||||
///
|
||||
void signal(const Device& device, uint64_t value) const;
|
||||
void signal(const Core::Device& device, uint64_t value) const;
|
||||
|
||||
///
|
||||
/// Wait for the semaphore to reach a specific value.
|
||||
|
|
@ -51,7 +51,7 @@ namespace LSFG::Core {
|
|||
/// @throws std::logic_error if the semaphore is not a timeline semaphore.
|
||||
/// @throws LSFG::vulkan_error if waiting fails.
|
||||
///
|
||||
[[nodiscard]] bool wait(const Device& device, uint64_t value, uint64_t timeout = UINT64_MAX) const;
|
||||
[[nodiscard]] bool wait(const Core::Device& device, uint64_t value, uint64_t timeout = UINT64_MAX) const;
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
[[nodiscard]] auto handle() const { return *this->semaphore; }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SHADERMODULE_HPP
|
||||
#define SHADERMODULE_HPP
|
||||
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ namespace LSFG::Core {
|
|||
/// @throws std::system_error if the shader file cannot be opened or read.
|
||||
/// @throws LSFG::vulkan_error if object creation fails.
|
||||
///
|
||||
ShaderModule(const Device& device, const std::string& path,
|
||||
ShaderModule(const Core::Device& device, const std::string& path,
|
||||
const std::vector<std::pair<size_t, VkDescriptorType>>& descriptorTypes);
|
||||
|
||||
/// Get the Vulkan handle.
|
||||
|
|
|
|||
128
include/lsfg.hpp
128
include/lsfg.hpp
|
|
@ -1,128 +0,0 @@
|
|||
#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 inImg_0, inImg_1; // inImg_0 is next (inImg_1 prev) when 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
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Alpha(const Device& device, const Core::DescriptorPool& pool,
|
||||
Alpha(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg);
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Beta(const Device& device, const Core::DescriptorPool& pool,
|
||||
Beta(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 4> inImgs_0,
|
||||
std::array<Core::Image, 4> inImgs_1,
|
||||
std::array<Core::Image, 4> inImgs_2);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Delta(const Device& device, const Core::DescriptorPool& pool,
|
||||
Delta(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 2> inImgs,
|
||||
std::optional<Core::Image> optImg);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Downsample(const Device& device, const Core::DescriptorPool& pool,
|
||||
Downsample(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg_0, Core::Image inImg_1);
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Epsilon(const Device& device, const Core::DescriptorPool& pool,
|
||||
Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
namespace LSFG::Shaderchains {
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Extract(const Device& device, const Core::DescriptorPool& pool,
|
||||
Extract(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg1,
|
||||
Core::Image inImg2,
|
||||
VkExtent2D outExtent);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Gamma(const Device& device, const Core::DescriptorPool& pool,
|
||||
Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 4> inImgs1_0,
|
||||
std::array<Core::Image, 4> inImgs1_1,
|
||||
std::array<Core::Image, 4> inImgs1_2,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Magic(const Device& device, const Core::DescriptorPool& pool,
|
||||
Magic(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 4> inImgs1_0,
|
||||
std::array<Core::Image, 4> inImgs1_1,
|
||||
std::array<Core::Image, 4> inImgs1_2,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Merge(const Device& device, const Core::DescriptorPool& pool,
|
||||
Merge(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg1,
|
||||
Core::Image inImg2,
|
||||
Core::Image inImg3,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "core/image.hpp"
|
||||
#include "core/pipeline.hpp"
|
||||
#include "core/shadermodule.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ namespace LSFG::Shaderchains {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||
///
|
||||
Zeta(const Device& device, const Core::DescriptorPool& pool,
|
||||
Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
Core::Image inImg3);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@
|
|||
#include "core/commandbuffer.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "core/sampler.hpp"
|
||||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <array>
|
||||
|
||||
|
|
@ -68,7 +67,7 @@ namespace LSFG::Utils {
|
|||
/// @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.
|
||||
///
|
||||
void uploadImage(const Device& device,
|
||||
void uploadImage(const Core::Device& device,
|
||||
const Core::CommandPool& commandPool,
|
||||
Core::Image& image, const std::string& path);
|
||||
|
||||
|
|
@ -81,7 +80,7 @@ namespace LSFG::Utils {
|
|||
///
|
||||
/// @throws LSFG::vulkan_error If the Vulkan image cannot be cleared.
|
||||
///
|
||||
void clearImage(const Device& device, Core::Image& image, bool white = false);
|
||||
void clearImage(const Core::Device& device, Core::Image& image, bool white = false);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +110,7 @@ namespace LSFG::Globals {
|
|||
static_assert(sizeof(FgBuffer) == 48, "FgBuffer must be 48 bytes in size.");
|
||||
|
||||
/// Initialize global resources.
|
||||
void initializeGlobals(const Device& device);
|
||||
void initializeGlobals(const Core::Device& device);
|
||||
|
||||
/// Uninitialize global resources.
|
||||
void uninitializeGlobals() noexcept;
|
||||
|
|
|
|||
79
public/lsfg.hpp
Normal file
79
public/lsfg.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef PUBLIC_LSFG_HPP
|
||||
#define PUBLIC_LSFG_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace LSFG {
|
||||
|
||||
///
|
||||
/// Initialize the LSFG library.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if Vulkan objects fail to initialize.
|
||||
///
|
||||
void initialize();
|
||||
|
||||
///
|
||||
/// Create a new LSFG context on a swapchain.
|
||||
///
|
||||
/// @param width Width of the input images.
|
||||
/// @param height Height of the input images.
|
||||
/// @param in0 File descriptor for the first input image.
|
||||
/// @param in1 File descriptor for the second input image.
|
||||
/// @return A unique identifier for the created context.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if the context cannot be created.
|
||||
///
|
||||
int32_t createContext(uint32_t width, uint32_t height, int in0, int in1);
|
||||
|
||||
///
|
||||
/// Present a context.
|
||||
///
|
||||
/// @param id Unique identifier of the context to present.
|
||||
/// @param inSem Semaphore to wait on before starting the generation.
|
||||
/// @param outSem Semaphore to signal when the generation is complete.
|
||||
///
|
||||
/// @throws LSFG::vulkan_error if the context cannot be presented.
|
||||
///
|
||||
void presentContext(int32_t id, int inSem, int outSem);
|
||||
|
||||
///
|
||||
/// Delete an LSFG context.
|
||||
///
|
||||
/// @param id Unique identifier of the context to delete.
|
||||
///
|
||||
void deleteContext(int32_t id);
|
||||
|
||||
///
|
||||
/// Deinitialize the LSFG library.
|
||||
///
|
||||
void finalize();
|
||||
|
||||
/// 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 // PUBLIC_LSFG_HPP
|
||||
111
src/context.cpp
Normal file
111
src/context.cpp
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include "context.hpp"
|
||||
#include "lsfg.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1) {
|
||||
// create pools
|
||||
this->descPool = Core::DescriptorPool(device);
|
||||
this->cmdPool = Core::CommandPool(device);
|
||||
|
||||
// create shader chains
|
||||
this->downsampleChain = Shaderchains::Downsample(device, this->descPool,
|
||||
this->inImg_0, this->inImg_1);
|
||||
for (size_t i = 0; i < 7; i++)
|
||||
this->alphaChains.at(i) = Shaderchains::Alpha(device, this->descPool,
|
||||
this->downsampleChain.getOutImages().at(i));
|
||||
this->betaChain = Shaderchains::Beta(device, this->descPool,
|
||||
this->alphaChains.at(0).getOutImages0(),
|
||||
this->alphaChains.at(0).getOutImages1(),
|
||||
this->alphaChains.at(0).getOutImages2());
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
if (i < 4) {
|
||||
this->gammaChains.at(i) = Shaderchains::Gamma(device, this->descPool,
|
||||
this->alphaChains.at(6 - i).getOutImages0(),
|
||||
this->alphaChains.at(6 - i).getOutImages1(),
|
||||
this->alphaChains.at(6 - i).getOutImages2(),
|
||||
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(device, this->descPool,
|
||||
this->alphaChains.at(6 - i).getOutImages0(),
|
||||
this->alphaChains.at(6 - i).getOutImages1(),
|
||||
this->alphaChains.at(6 - i).getOutImages2(),
|
||||
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(device, this->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(device, this->descPool,
|
||||
this->magicChains.at(i - 4).getOutImages2(),
|
||||
this->betaChain.getOutImages().at(6 - i),
|
||||
i == 4 ? std::nullopt
|
||||
: std::optional{this->epsilonChains.at(i - 5).getOutImage()}
|
||||
);
|
||||
this->zetaChains.at(i - 4) = Shaderchains::Zeta(device, this->descPool,
|
||||
this->magicChains.at(i - 4).getOutImages3(),
|
||||
i == 4 ? this->gammaChains.at(i - 1).getOutImage1()
|
||||
: this->zetaChains.at(i - 5).getOutImage(),
|
||||
this->betaChain.getOutImages().at(6 - i)
|
||||
);
|
||||
if (i >= 6)
|
||||
continue; // no extract for i >= 6
|
||||
this->extractChains.at(i - 4) = Shaderchains::Extract(device, this->descPool,
|
||||
this->zetaChains.at(i - 4).getOutImage(),
|
||||
this->epsilonChains.at(i - 4).getOutImage(),
|
||||
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent()
|
||||
);
|
||||
}
|
||||
}
|
||||
this->mergeChain = Shaderchains::Merge(device, this->descPool,
|
||||
this->inImg_1,
|
||||
this->inImg_0,
|
||||
this->zetaChains.at(2).getOutImage(),
|
||||
this->epsilonChains.at(2).getOutImage(),
|
||||
this->deltaChains.at(2).getOutImage()
|
||||
);
|
||||
}
|
||||
|
||||
void Context::present(const Core::Device& device, int inSem, int outSem) {
|
||||
Core::CommandBuffer cmdBuffer(device, this->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, fc);
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
this->magicChains.at(i).Dispatch(cmdBuffer, fc);
|
||||
this->deltaChains.at(i).Dispatch(cmdBuffer);
|
||||
this->epsilonChains.at(i).Dispatch(cmdBuffer);
|
||||
this->zetaChains.at(i).Dispatch(cmdBuffer);
|
||||
if (i < 2)
|
||||
this->extractChains.at(i).Dispatch(cmdBuffer);
|
||||
}
|
||||
this->mergeChain.Dispatch(cmdBuffer, fc);
|
||||
|
||||
cmdBuffer.end();
|
||||
|
||||
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;
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
void Buffer::construct(const Device& device, const void* data, VkBufferUsageFlags usage) {
|
||||
void Buffer::construct(const Core::Device& device, const void* data, VkBufferUsageFlags usage) {
|
||||
// create buffer
|
||||
const VkBufferCreateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
CommandBuffer::CommandBuffer(const Device& device, const CommandPool& pool) {
|
||||
CommandBuffer::CommandBuffer(const Core::Device& device, const CommandPool& pool) {
|
||||
// create command buffer
|
||||
const VkCommandBufferAllocateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
CommandPool::CommandPool(const Device& device) {
|
||||
CommandPool::CommandPool(const Core::Device& device) {
|
||||
// create command pool
|
||||
const VkCommandPoolCreateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
DescriptorPool::DescriptorPool(const Device& device) {
|
||||
DescriptorPool::DescriptorPool(const Core::Device& device) {
|
||||
// create descriptor pool
|
||||
const std::array<VkDescriptorPoolSize, 4> pools{{ // arbitrary limits
|
||||
{ .type = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = 4096 },
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
DescriptorSet::DescriptorSet(const Device& device,
|
||||
DescriptorSet::DescriptorSet(const Core::Device& device,
|
||||
const DescriptorPool& pool, const ShaderModule& shaderModule) {
|
||||
// create descriptor set
|
||||
VkDescriptorSetLayout layout = shaderModule.getLayout();
|
||||
|
|
@ -27,7 +27,7 @@ DescriptorSet::DescriptorSet(const Device& device,
|
|||
);
|
||||
}
|
||||
|
||||
DescriptorSetUpdateBuilder DescriptorSet::update(const Device& device) const {
|
||||
DescriptorSetUpdateBuilder DescriptorSet::update(const Core::Device& device) const {
|
||||
return { *this, device };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "device.hpp"
|
||||
#include "core/device.hpp"
|
||||
#include "lsfg.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
using namespace LSFG;
|
||||
using namespace LSFG::Core;
|
||||
|
||||
const std::vector<const char*> requiredExtensions = {
|
||||
"VK_KHR_external_memory_fd",
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
Fence::Fence(const Device& device) {
|
||||
Fence::Fence(const Core::Device& device) {
|
||||
// create fence
|
||||
const VkFenceCreateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
|
||||
|
|
@ -22,14 +22,14 @@ Fence::Fence(const Device& device) {
|
|||
);
|
||||
}
|
||||
|
||||
void Fence::reset(const Device& device) const {
|
||||
void Fence::reset(const Core::Device& device) const {
|
||||
VkFence fenceHandle = this->handle();
|
||||
auto res = vkResetFences(device.handle(), 1, &fenceHandle);
|
||||
if (res != VK_SUCCESS)
|
||||
throw LSFG::vulkan_error(res, "Unable to reset fence");
|
||||
}
|
||||
|
||||
bool Fence::wait(const Device& device, uint64_t timeout) const {
|
||||
bool Fence::wait(const Core::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)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
Image::Image(const Device& device, VkExtent2D extent, VkFormat format,
|
||||
Image::Image(const Core::Device& device, VkExtent2D extent, VkFormat format,
|
||||
VkImageUsageFlags usage, VkImageAspectFlags aspectFlags)
|
||||
: extent(extent), format(format), aspectFlags(aspectFlags) {
|
||||
// create image
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "instance.hpp"
|
||||
#include "core/instance.hpp"
|
||||
#include "lsfg.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace LSFG;
|
||||
using namespace LSFG::Core;
|
||||
|
||||
const std::vector<const char*> requiredExtensions = {
|
||||
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
Pipeline::Pipeline(const Device& device, const ShaderModule& shader) {
|
||||
Pipeline::Pipeline(const Core::Device& device, const ShaderModule& shader) {
|
||||
// create pipeline layout
|
||||
VkDescriptorSetLayout shaderLayout = shader.getLayout();
|
||||
const VkPipelineLayoutCreateInfo layoutDesc{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
Sampler::Sampler(const Device& device, VkSamplerAddressMode mode) {
|
||||
Sampler::Sampler(const Core::Device& device, VkSamplerAddressMode mode) {
|
||||
// create sampler
|
||||
const VkSamplerCreateInfo desc{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
Semaphore::Semaphore(const Device& device, std::optional<uint32_t> initial) {
|
||||
Semaphore::Semaphore(const Core::Device& device, std::optional<uint32_t> initial) {
|
||||
// create semaphore
|
||||
const VkSemaphoreTypeCreateInfo typeInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
|
||||
|
|
@ -29,7 +29,7 @@ Semaphore::Semaphore(const Device& device, std::optional<uint32_t> initial) {
|
|||
);
|
||||
}
|
||||
|
||||
void Semaphore::signal(const Device& device, uint64_t value) const {
|
||||
void Semaphore::signal(const Core::Device& device, uint64_t value) const {
|
||||
if (!this->isTimeline)
|
||||
throw std::logic_error("Invalid timeline semaphore");
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ void Semaphore::signal(const Device& device, uint64_t value) const {
|
|||
throw LSFG::vulkan_error(res, "Unable to signal semaphore");
|
||||
}
|
||||
|
||||
bool Semaphore::wait(const Device& device, uint64_t value, uint64_t timeout) const {
|
||||
bool Semaphore::wait(const Core::Device& device, uint64_t value, uint64_t timeout) const {
|
||||
if (!this->isTimeline)
|
||||
throw std::logic_error("Invalid timeline semaphore");
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
using namespace LSFG::Core;
|
||||
|
||||
ShaderModule::ShaderModule(const Device& device, const std::string& path,
|
||||
ShaderModule::ShaderModule(const Core::Device& device, const std::string& path,
|
||||
const std::vector<std::pair<size_t, VkDescriptorType>>& descriptorTypes) {
|
||||
// read shader bytecode
|
||||
std::ifstream file(path, std::ios::ate | std::ios::binary);
|
||||
|
|
|
|||
166
src/lsfg.cpp
166
src/lsfg.cpp
|
|
@ -1,123 +1,67 @@
|
|||
#include "lsfg.hpp"
|
||||
#include "core/commandbuffer.hpp"
|
||||
#include "core/fence.hpp"
|
||||
#include "core/image.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "core/device.hpp"
|
||||
#include "core/instance.hpp"
|
||||
#include "context.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
Generator::Generator(const Context& context) {
|
||||
// TEST: create temporal images
|
||||
this->inImg_0 = Core::Image(context.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
|
||||
);
|
||||
this->inImg_1 = Core::Image(context.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
|
||||
);
|
||||
// TEST END
|
||||
|
||||
// create shader chains
|
||||
this->downsampleChain = Shaderchains::Downsample(context.device, context.descPool,
|
||||
this->inImg_0, this->inImg_1);
|
||||
for (size_t i = 0; i < 7; i++)
|
||||
this->alphaChains.at(i) = Shaderchains::Alpha(context.device, context.descPool,
|
||||
this->downsampleChain.getOutImages().at(i));
|
||||
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).getOutImages0(),
|
||||
this->alphaChains.at(6 - i).getOutImages1(),
|
||||
this->alphaChains.at(6 - i).getOutImages2(),
|
||||
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).getOutImages0(),
|
||||
this->alphaChains.at(6 - i).getOutImages1(),
|
||||
this->alphaChains.at(6 - i).getOutImages2(),
|
||||
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->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent()
|
||||
);
|
||||
}
|
||||
}
|
||||
this->mergeChain = Shaderchains::Merge(context.device, context.descPool,
|
||||
this->inImg_1,
|
||||
this->inImg_0,
|
||||
this->zetaChains.at(2).getOutImage(),
|
||||
this->epsilonChains.at(2).getOutImage(),
|
||||
this->deltaChains.at(2).getOutImage()
|
||||
);
|
||||
namespace {
|
||||
std::optional<Core::Instance> instance;
|
||||
std::optional<Core::Device> device;
|
||||
std::unordered_map<int32_t, Context> contexts;
|
||||
}
|
||||
|
||||
void Generator::present(const Context& context) {
|
||||
Core::CommandBuffer cmdBuffer(context.device, context.cmdPool);
|
||||
cmdBuffer.begin();
|
||||
void LSFG::initialize() {
|
||||
if (instance.has_value() || device.has_value())
|
||||
return;
|
||||
|
||||
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, fc);
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
this->magicChains.at(i).Dispatch(cmdBuffer, fc);
|
||||
this->deltaChains.at(i).Dispatch(cmdBuffer);
|
||||
this->epsilonChains.at(i).Dispatch(cmdBuffer);
|
||||
this->zetaChains.at(i).Dispatch(cmdBuffer);
|
||||
if (i < 2)
|
||||
this->extractChains.at(i).Dispatch(cmdBuffer);
|
||||
}
|
||||
this->mergeChain.Dispatch(cmdBuffer, fc);
|
||||
instance.emplace();
|
||||
device.emplace(*instance);
|
||||
|
||||
cmdBuffer.end();
|
||||
|
||||
fc++;
|
||||
std::srand(static_cast<uint32_t>(std::time(nullptr)));
|
||||
}
|
||||
|
||||
vulkan_error::vulkan_error(VkResult result, const std::string& message)
|
||||
: std::runtime_error(std::format("{} (error {})", message, static_cast<int32_t>(result))), result(result) {}
|
||||
int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1) {
|
||||
if (!instance.has_value() || !device.has_value())
|
||||
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
|
||||
|
||||
vulkan_error::~vulkan_error() noexcept = default;
|
||||
auto id = std::rand();
|
||||
contexts.emplace(id, Context(*device, width, height, in0, in1));
|
||||
return id;
|
||||
}
|
||||
|
||||
void LSFG::presentContext(int32_t id, int inSem, int outSem) {
|
||||
if (!instance.has_value() || !device.has_value())
|
||||
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
|
||||
|
||||
auto it = contexts.find(id);
|
||||
if (it == contexts.end())
|
||||
throw LSFG::vulkan_error(VK_ERROR_DEVICE_LOST, "No such context");
|
||||
|
||||
Context& context = it->second;
|
||||
context.present(*device, inSem, outSem);
|
||||
}
|
||||
|
||||
void LSFG::deleteContext(int32_t id) {
|
||||
if (!instance.has_value() || !device.has_value())
|
||||
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
|
||||
|
||||
auto it = contexts.find(id);
|
||||
if (it == contexts.end())
|
||||
throw LSFG::vulkan_error(VK_ERROR_DEVICE_LOST, "No such context");
|
||||
|
||||
contexts.erase(it);
|
||||
}
|
||||
|
||||
void LSFG::finalize() {
|
||||
if (!instance.has_value() && !device.has_value())
|
||||
return;
|
||||
|
||||
instance.reset();
|
||||
device.reset();
|
||||
}
|
||||
|
|
|
|||
47
src/main.cpp
47
src/main.cpp
|
|
@ -1,47 +0,0 @@
|
|||
#include "lsfg.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <renderdoc_app.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace LSFG;
|
||||
|
||||
int main() {
|
||||
// attempt to load renderdoc
|
||||
RENDERDOC_API_1_6_0* rdoc = nullptr;
|
||||
if (void* mod_renderdoc = dlopen("/usr/lib/librenderdoc.so", RTLD_NOLOAD | RTLD_NOW)) {
|
||||
std::cerr << "Found RenderDoc library, setting up frame capture." << '\n';
|
||||
|
||||
auto GetAPI = reinterpret_cast<pRENDERDOC_GetAPI>(dlsym(mod_renderdoc, "RENDERDOC_GetAPI"));
|
||||
const int ret = GetAPI(eRENDERDOC_API_Version_1_6_0, reinterpret_cast<void**>(&rdoc));
|
||||
if (ret == 0) {
|
||||
std::cerr << "Unable to initialize RenderDoc API. Is your RenderDoc up to date?" << '\n';
|
||||
rdoc = nullptr;
|
||||
}
|
||||
usleep(1000 * 100); // give renderdoc time to load
|
||||
}
|
||||
|
||||
// initialize test application
|
||||
LSFG::Context context;
|
||||
auto gen = LSFG::Generator(context);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (rdoc)
|
||||
rdoc->StartFrameCapture(nullptr, nullptr);
|
||||
|
||||
gen.present(context);
|
||||
|
||||
if (rdoc)
|
||||
rdoc->EndFrameCapture(nullptr, nullptr);
|
||||
|
||||
// sleep 8 ms
|
||||
usleep(8000);
|
||||
}
|
||||
|
||||
usleep(1000 * 100);
|
||||
|
||||
std::cerr << "Application finished" << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Alpha::Alpha(const Device& device, const Core::DescriptorPool& pool,
|
||||
Alpha::Alpha(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg)
|
||||
: inImg(std::move(inImg)) {
|
||||
this->shaderModules = {{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Beta::Beta(const Device& device, const Core::DescriptorPool& pool,
|
||||
Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 4> inImgs_0,
|
||||
std::array<Core::Image, 4> inImgs_1,
|
||||
std::array<Core::Image, 4> inImgs_2)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Delta::Delta(const Device& device, const Core::DescriptorPool& pool,
|
||||
Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 2> inImgs,
|
||||
std::optional<Core::Image> optImg)
|
||||
: inImgs(std::move(inImgs)),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Downsample::Downsample(const Device& device, const Core::DescriptorPool& pool,
|
||||
Downsample::Downsample(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg_0, Core::Image inImg_1)
|
||||
: inImg_0(std::move(inImg_0)),
|
||||
inImg_1(std::move(inImg_1)) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Epsilon::Epsilon(const Device& device, const Core::DescriptorPool& pool,
|
||||
Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
std::optional<Core::Image> optImg)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Extract::Extract(const Device& device, const Core::DescriptorPool& pool,
|
||||
Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg1,
|
||||
Core::Image inImg2,
|
||||
VkExtent2D outExtent)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Gamma::Gamma(const Device& device, const Core::DescriptorPool& pool,
|
||||
Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 4> inImgs1_0,
|
||||
std::array<Core::Image, 4> inImgs1_1,
|
||||
std::array<Core::Image, 4> inImgs1_2,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Magic::Magic(const Device& device, const Core::DescriptorPool& pool,
|
||||
Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 4> inImgs1_0,
|
||||
std::array<Core::Image, 4> inImgs1_1,
|
||||
std::array<Core::Image, 4> inImgs1_2,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Merge::Merge(const Device& device, const Core::DescriptorPool& pool,
|
||||
Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
Core::Image inImg1,
|
||||
Core::Image inImg2,
|
||||
Core::Image inImg3,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using namespace LSFG::Shaderchains;
|
||||
|
||||
Zeta::Zeta(const Device& device, const Core::DescriptorPool& pool,
|
||||
Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||
std::array<Core::Image, 3> inImgs1,
|
||||
Core::Image inImg2,
|
||||
Core::Image inImg3)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ void BarrierBuilder::build() const {
|
|||
vkCmdPipelineBarrier2(this->commandBuffer->handle(), &dependencyInfo);
|
||||
}
|
||||
|
||||
void Utils::uploadImage(const Device& device, const Core::CommandPool& commandPool,
|
||||
void Utils::uploadImage(const Core::Device& device, const Core::CommandPool& commandPool,
|
||||
Core::Image& image, const std::string& path) {
|
||||
// read image bytecode
|
||||
std::ifstream file(path.data(), std::ios::binary | std::ios::ate);
|
||||
|
|
@ -130,7 +130,7 @@ void Utils::uploadImage(const Device& device, const Core::CommandPool& commandPo
|
|||
throw LSFG::vulkan_error(VK_TIMEOUT, "Upload operation timed out");
|
||||
}
|
||||
|
||||
void Utils::clearImage(const Device& device, Core::Image& image, bool white) {
|
||||
void Utils::clearImage(const Core::Device& device, Core::Image& image, bool white) {
|
||||
Core::Fence fence(device);
|
||||
const Core::CommandPool cmdPool(device);
|
||||
Core::CommandBuffer cmdBuf(device, cmdPool);
|
||||
|
|
@ -180,7 +180,7 @@ Core::Sampler Globals::samplerClampBorder;
|
|||
Core::Sampler Globals::samplerClampEdge;
|
||||
Globals::FgBuffer Globals::fgBuffer;
|
||||
|
||||
void Globals::initializeGlobals(const Device& device) {
|
||||
void Globals::initializeGlobals(const Core::Device& device) {
|
||||
// initialize global samplers
|
||||
samplerClampBorder = Core::Sampler(device, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
|
||||
samplerClampEdge = Core::Sampler(device, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue