allow for multiple lsfg versions to coexist

This commit is contained in:
PancakeTAS 2025-07-12 18:19:18 +02:00
parent dac149c84a
commit 82bcf2bb72
No known key found for this signature in database
62 changed files with 174 additions and 95 deletions

View file

@ -14,6 +14,7 @@ endif()
include(cmake/FetchDXVK.cmake)
include(cmake/FetchPeParse.cmake)
add_subdirectory(lsfg-vk-common)
add_subdirectory(lsfg-vk-v3.1)
# main project
@ -38,7 +39,7 @@ set_target_properties(lsfg-vk PROPERTIES
target_include_directories(lsfg-vk
PRIVATE include)
target_link_libraries(lsfg-vk
PRIVATE lsfg-vk-v3.1 peparse dxvk vulkan)
PRIVATE lsfg-vk-common lsfg-vk-v3.1 peparse dxvk vulkan)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set_target_properties(lsfg-vk PROPERTIES

View file

@ -0,0 +1,59 @@
cmake_minimum_required(VERSION 3.29)
# project
project(lsfg-vk-common
LANGUAGES CXX)
file(GLOB SOURCES
"src/core/*.cpp"
"src/pool/*.cpp"
"src/common/*.cpp"
"src/*.cpp"
)
add_library(lsfg-vk-common STATIC ${SOURCES})
# target
set_target_properties(lsfg-vk-common PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON)
target_include_directories(lsfg-vk-common
PUBLIC include)
target_link_libraries(lsfg-vk-common
PRIVATE vulkan)
target_compile_options(lsfg-vk-common PRIVATE
-fPIC)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set_target_properties(lsfg-vk-common PROPERTIES
INTERPROCEDURAL_OPTIMIZATION ON)
endif()
# diagnostics
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set_target_properties(lsfg-vk-common PROPERTIES
EXPORT_COMPILE_COMMANDS ON)
endif()
if(LSFGVK_EXCESS_DEBUG)
target_compile_options(lsfg-vk-common PRIVATE
-Weverything
# disable compat c++ flags
-Wno-pre-c++20-compat-pedantic
-Wno-pre-c++17-compat
-Wno-c++98-compat-pedantic
-Wno-c++98-compat
# disable other flags
-Wno-missing-designated-field-initializers
-Wno-shadow # allow shadowing
-Wno-switch-enum # ignore missing cases
-Wno-switch-default # ignore missing default
-Wno-padded # ignore automatic padding
-Wno-exit-time-destructors # allow globals
-Wno-global-constructors # allow globals
-Wno-cast-function-type-strict # for vulkan
)
set_target_properties(lsfg-vk-common PROPERTIES
CXX_CLANG_TIDY clang-tidy)
endif()

View file

@ -0,0 +1,34 @@
#pragma once
#include <vulkan/vulkan_core.h>
#include <stdexcept>
#include <string>
namespace LSFG {
/// 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;
};
}

View file

@ -0,0 +1,16 @@
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>
#include <stdexcept>
#include <cstdint>
#include <format>
#include <string>
using namespace LSFG;
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

@ -1,10 +1,10 @@
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/buffer.hpp"
#include "core/image.hpp"
#include "core/device.hpp"
#include "core/commandpool.hpp"
#include "core/fence.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/buffer.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -3,7 +3,7 @@
#include "core/commandpool.hpp"
#include "core/fence.hpp"
#include "core/semaphore.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/commandpool.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/descriptorpool.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -7,7 +7,7 @@
#include "core/image.hpp"
#include "core/sampler.hpp"
#include "core/buffer.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/device.hpp"
#include "core/instance.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/fence.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/image.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,5 +1,5 @@
#include "core/instance.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <cstdint>
#include <memory>

View file

@ -2,7 +2,7 @@
#include "core/device.hpp"
#include "core/shadermodule.hpp"
#include "core/commandbuffer.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/sampler.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/semaphore.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -1,6 +1,6 @@
#include "core/shadermodule.hpp"
#include "core/device.hpp"
#include "lsfg.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -5,8 +5,6 @@ project(lsfg-vk-v3.1
DESCRIPTION "Lossless Scaling Frame Generation v3.1"
LANGUAGES CXX)
option(LDFGVK_EXCESS_DEBUG "Enable excessive debug output" OFF)
file(GLOB SOURCES
"src/core/*.cpp"
"src/pool/*.cpp"
@ -25,7 +23,7 @@ target_include_directories(lsfg-vk-v3.1
PRIVATE include
PUBLIC public)
target_link_libraries(lsfg-vk-v3.1
PRIVATE vulkan)
PUBLIC lsfg-vk-common vulkan)
target_compile_options(lsfg-vk-v3.1 PRIVATE
-fPIC)

View file

@ -7,8 +7,8 @@ The project is intentionally structured as a fully external project, such that i
### Interface
Interfacing with lsfg-vk-v3.1 is done via `lsfg.hpp` header. The internal Vulkan instance is created using `LSFG::initialize()` and requires a specific deviceUUID, as well as parts of the lsfg-vk configuration, including a function loading SPIR-V shaders by name. Cleanup is done via `LSFG::finalize()` after which `LSFG::initialize()` may be called again. Please note that the initialization process is expensive and may take a while. It is recommended to call this function once during the applications lifetime.
Interfacing with lsfg-vk-v3.1 is done via `lsfg.hpp` header. The internal Vulkan instance is created using `LSFG_3_1::initialize()` and requires a specific deviceUUID, as well as parts of the lsfg-vk configuration, including a function loading SPIR-V shaders by name. Cleanup is done via `LSFG_3_1::finalize()` after which `LSFG_3_1::initialize()` may be called again. Please note that the initialization process is expensive and may take a while. It is recommended to call this function once during the applications lifetime.
Once the format and extent of the requested images is determined, `LSFG::createContext()` should be called to initialize a frame generation context. The Vulkan images are created from backing memory, which is passed through the file descriptor arguments. A context can be destroyed using `LSFG::deleteContext()`.
Once the format and extent of the requested images is determined, `LSFG_3_1::createContext()` should be called to initialize a frame generation context. The Vulkan images are created from backing memory, which is passed through the file descriptor arguments. A context can be destroyed using `LSFG_3_1::deleteContext()`.
Presenting the context can be done via `LSFG::presentContext()`. Before calling the function a second time, make sure the outgoing semaphores have been signaled.
Presenting the context can be done via `LSFG_3_1::presentContext()`. Before calling the function a second time, make sure the outgoing semaphores have been signaled.

View file

@ -10,7 +10,7 @@
#include "shaders/gamma.hpp"
#include "shaders/generate.hpp"
#include "shaders/mipmaps.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -6,7 +6,7 @@
#include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <array>
#include <cstdint>

View file

@ -7,7 +7,7 @@
#include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <array>
#include <cstdint>

View file

@ -7,7 +7,7 @@
#include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <array>
#include <cstdint>

View file

@ -7,7 +7,7 @@
#include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <array>
#include <cstdint>

View file

@ -7,7 +7,7 @@
#include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -7,7 +7,7 @@
#include "core/pipeline.hpp"
#include "core/sampler.hpp"
#include "core/shadermodule.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include <array>
#include <cstdint>

View file

@ -3,12 +3,11 @@
#include <vulkan/vulkan_core.h>
#include <functional>
#include <stdexcept>
#include <cstdint>
#include <string>
#include <vector>
namespace LSFG {
namespace LSFG_3_1 {
///
/// Initialize the LSFG library.
@ -64,28 +63,4 @@ namespace LSFG {
///
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;
};
}

View file

@ -1,6 +1,6 @@
#include "context.hpp"
#include "lsfg.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>

View file

@ -4,22 +4,22 @@
#include "core/descriptorpool.hpp"
#include "core/instance.hpp"
#include "pool/shaderpool.hpp"
#include "utils/utils.hpp"
#include "common/exception.hpp"
#include "common/utils.hpp"
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <optional>
#include <cstdlib>
#include <ctime>
#include <format>
#include <optional>
#include <functional>
#include <string>
#include <stdexcept>
#include <unordered_map>
#include <vector>
using namespace LSFG;
using namespace LSFG_3_1;
namespace {
std::optional<Core::Instance> instance;
@ -27,7 +27,7 @@ namespace {
std::unordered_map<int32_t, Context> contexts;
}
void LSFG::initialize(uint64_t deviceUUID,
void LSFG_3_1::initialize(uint64_t deviceUUID,
bool isHdr, float flowScale, uint64_t generationCount,
const std::function<std::vector<uint8_t>(const std::string&)>& loader) {
if (instance.has_value() || device.has_value())
@ -51,41 +51,41 @@ void LSFG::initialize(uint64_t deviceUUID,
std::srand(static_cast<uint32_t>(std::time(nullptr)));
}
int32_t LSFG::createContext(
int32_t LSFG_3_1::createContext(
int in0, int in1, const std::vector<int>& outN,
VkExtent2D extent, VkFormat format) {
if (!instance.has_value() || !device.has_value())
throw vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
const int32_t id = std::rand();
contexts.emplace(id, Context(*device, in0, in1, outN, extent, format));
return id;
}
void LSFG::presentContext(int32_t id, int inSem, const std::vector<int>& outSem) {
void LSFG_3_1::presentContext(int32_t id, int inSem, const std::vector<int>& outSem) {
if (!instance.has_value() || !device.has_value())
throw vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
auto it = contexts.find(id);
if (it == contexts.end())
throw vulkan_error(VK_ERROR_UNKNOWN, "Context not found");
throw LSFG::vulkan_error(VK_ERROR_UNKNOWN, "Context not found");
it->second.present(*device, inSem, outSem);
}
void LSFG::deleteContext(int32_t id) {
void LSFG_3_1::deleteContext(int32_t id) {
if (!instance.has_value() || !device.has_value())
throw vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
auto it = contexts.find(id);
if (it == contexts.end())
throw vulkan_error(VK_ERROR_DEVICE_LOST, "No such context");
throw LSFG::vulkan_error(VK_ERROR_DEVICE_LOST, "No such context");
vkDeviceWaitIdle(device->device.handle());
contexts.erase(it);
}
void LSFG::finalize() {
void LSFG_3_1::finalize() {
if (!instance.has_value() || !device.has_value())
return;
@ -94,8 +94,3 @@ void LSFG::finalize() {
device.reset();
instance.reset();
}
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

@ -1,5 +1,5 @@
#include "shaders/alpha.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/commandbuffer.hpp"
#include "core/image.hpp"

View file

@ -1,5 +1,5 @@
#include "shaders/beta.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/commandbuffer.hpp"
#include "core/image.hpp"

View file

@ -1,5 +1,5 @@
#include "shaders/delta.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/commandbuffer.hpp"
#include "core/image.hpp"

View file

@ -1,5 +1,5 @@
#include "shaders/gamma.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/commandbuffer.hpp"
#include "core/image.hpp"

View file

@ -1,5 +1,5 @@
#include "shaders/generate.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/commandbuffer.hpp"
#include "core/image.hpp"

View file

@ -1,5 +1,5 @@
#include "shaders/mipmaps.hpp"
#include "utils/utils.hpp"
#include "common/utils.hpp"
#include "core/image.hpp"
#include "core/commandbuffer.hpp"

View file

@ -5,6 +5,7 @@
#include "utils/log.hpp"
#include "hooks.hpp"
#include "layer.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>
#include <lsfg.hpp>
@ -75,7 +76,7 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain,
Log::debug("context", "(entering LSFG initialization)");
setenv("DISABLE_LSFG", "1", 1); // NOLINT
Extract::extractShaders();
LSFG::initialize(
LSFG_3_1::initialize(
Utils::getDeviceUUID(info.physicalDevice),
isHdr, 1.0F / flowScale, info.frameGen,
[](const std::string& name) {
@ -90,12 +91,12 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain,
// create lsfg context
Log::debug("context", "(entering LSFG context creation)");
this->lsfgCtxId = std::shared_ptr<int32_t>(
new int32_t(LSFG::createContext(frame_0_fd, frame_1_fd, out_n_fds,
new int32_t(LSFG_3_1::createContext(frame_0_fd, frame_1_fd, out_n_fds,
extent, format)),
[](const int32_t* id) {
Log::info("context",
"(entering LSFG context deletion with id: {})", *id);
LSFG::deleteContext(*id);
LSFG_3_1::deleteContext(*id);
Log::info("context",
"(exiting LSFG context deletion with id: {})", *id);
}
@ -156,7 +157,7 @@ VkResult LsContext::present(const Hooks::DeviceInfo& info, const void* pNext, Vk
Log::debug("context2",
"(entering LSFG present with id: {})", *this->lsfgCtxId);
LSFG::presentContext(*this->lsfgCtxId,
LSFG_3_1::presentContext(*this->lsfgCtxId,
preCopySemaphoreFd,
renderSemaphoreFds);
Log::debug("context2",

View file

@ -3,8 +3,8 @@
#include "layer.hpp"
#include "utils/log.hpp"
#include "utils/utils.hpp"
#include "common/exception.hpp"
#include <lsfg.hpp>
#include <vulkan/vulkan_core.h>
#include <cstdint>

View file

@ -1,9 +1,9 @@
#include "mini/commandbuffer.hpp"
#include "mini/commandpool.hpp"
#include "common/exception.hpp"
#include "layer.hpp"
#include <vulkan/vulkan_core.h>
#include <lsfg.hpp>
#include <cstdint>
#include <memory>

View file

@ -1,7 +1,7 @@
#include "mini/commandpool.hpp"
#include "common/exception.hpp"
#include "layer.hpp"
#include <lsfg.hpp>
#include <vulkan/vulkan_core.h>
#include <cstdint>

View file

@ -1,8 +1,8 @@
#include "mini/image.hpp"
#include "common/exception.hpp"
#include "layer.hpp"
#include <vulkan/vulkan_core.h>
#include <lsfg.hpp>
#include <memory>
#include <cstdint>

View file

@ -1,7 +1,7 @@
#include "mini/semaphore.hpp"
#include "common/exception.hpp"
#include "layer.hpp"
#include <lsfg.hpp>
#include <vulkan/vulkan_core.h>
#include <memory>

View file

@ -55,7 +55,7 @@ namespace {
? std::stoull(std::string(lsfgDeviceUUID), nullptr, 16) : 0x1463ABAC;
Extract::extractShaders();
LSFG::initialize(
LSFG_3_1::initialize(
deviceUUID, // some magic number if not given
isHdr, 1.0F / flowScale, multiplier - 1,
[](const std::string& name) -> std::vector<uint8_t> {
@ -64,7 +64,7 @@ namespace {
return spirv;
}
);
const int32_t ctx = LSFG::createContext(-1, -1, {},
const int32_t ctx = LSFG_3_1::createContext(-1, -1, {},
{ .width = width, .height = height },
isHdr ? VK_FORMAT_R16G16B16A16_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM
);
@ -75,7 +75,7 @@ namespace {
const auto now = std::chrono::high_resolution_clock::now();
const uint64_t iterations = (8 * 500) + 1;
for (uint64_t count = 0; count < iterations; count++) {
LSFG::presentContext(ctx, -1, {});
LSFG_3_1::presentContext(ctx, -1, {});
if (count % 500 == 0)
Log::info("bench", "{:.2f}% done ({}/{})",

View file

@ -1,8 +1,8 @@
#include "utils/utils.hpp"
#include "utils/log.hpp"
#include "common/exception.hpp"
#include "layer.hpp"
#include <lsfg.hpp>
#include <vulkan/vulkan_core.h>
#include <cstdint>