refactor(cleanup): rename namespaces and handle errors more robustly

This commit is contained in:
PancakeTAS 2025-12-23 00:00:31 +01:00
parent 8e685e0794
commit e7bfccd7c1
43 changed files with 317 additions and 271 deletions

View file

@ -9,7 +9,7 @@
#include <utility>
#include <vector>
namespace lsfgvk {
namespace lsfgvk::backend {
class [[gnu::visibility("default")]] ContextImpl;
class [[gnu::visibility("default")]] InstanceImpl;
@ -42,7 +42,7 @@ namespace lsfgvk {
/// Function type for picking a device based on its name and IDs
using DevicePicker = std::function<bool(
const std::string& deviceName,
std::pair<const std::string&, const std::string&> ids, // (vendor ID, device ID) in 0xXXXX format
std::pair<const std::string&, const std::string&> ids, // (vendor ID, device ID) 0xXXXX format
const std::optional<std::string>& pci // (bus:slot.func) if available, no padded zeros
)>;
@ -54,11 +54,11 @@ namespace lsfgvk {
///
/// Create a lsfg-vk instance
///
/// @param devicePicker Function that picks a physical device based on its name or other identifiers.
/// @param devicePicker Function that picks a physical device based on some identifiers.
/// @param shaderDllPath Path to the Lossless.dll file to load shaders from.
/// @param allowLowPrecision Whether to load low-precision (FP16) shaders if supported by the device.
/// @param allowLowPrecision Whether to load low-precision (FP16) shaders if supported.
///
/// @throws lsfgvk::error on failure
/// @throws backend::error on failure
///
Instance(
const DevicePicker& devicePicker,
@ -90,7 +90,7 @@ namespace lsfgvk {
/// @param flow Motion flow factor.
/// @param perf Whether to enable performance mode.
///
/// @throws lsfgvk::error on failure
/// @throws backend::error on failure
///
Context& openContext(
std::pair<int, int> sourceFds,
@ -104,7 +104,7 @@ namespace lsfgvk {
/// Schedule a new set of generated frames.
///
/// @param context Context to use.
/// @throws lsfgvk::error on failure
/// @throws backend::error on failure
///
void scheduleFrames(Context& context);

View file

@ -1,6 +1,6 @@
#include "dll_reader.hpp"
#include "lsfg-vk-common/helpers/errors.hpp"
#include <stdexcept>
#include <unordered_map>
#include <filesystem>
#include <algorithm>
@ -14,7 +14,8 @@
#include <array>
#include <span>
using namespace extr;
using namespace lsfgvk;
using namespace lsfgvk::backend;
/// DOS file header
struct DOSHeader {
@ -78,7 +79,7 @@ namespace {
const T* safe_cast(const std::vector<uint8_t>& data, size_t offset) {
const size_t end = offset + sizeof(T);
if (end > data.size() || end < offset)
throw std::runtime_error("buffer overflow/underflow during safe cast");
throw ls::error("buffer overflow/underflow during safe cast");
return reinterpret_cast<const T*>(&data.at(offset));
}
@ -87,42 +88,42 @@ namespace {
std::span<const T> span_cast(const std::vector<uint8_t>& data, size_t offset, size_t count) {
const size_t end = offset + (count * sizeof(T));
if (end > data.size() || end < offset)
throw std::runtime_error("buffer overflow/underflow during safe cast");
throw ls::error("buffer overflow/underflow during safe cast");
return std::span<const T>(reinterpret_cast<const T*>(&data.at(offset)), count);
}
}
#pragma clang diagnostic pop
std::unordered_map<uint32_t, std::vector<uint8_t>> extr::extractResourcesFromDLL(
std::unordered_map<uint32_t, std::vector<uint8_t>> backend::extractResourcesFromDLL(
const std::filesystem::path& dll) {
std::ifstream file(dll, std::ios::binary | std::ios::ate);
if (!file.is_open())
throw std::runtime_error("failed to open dll file");
throw ls::error("failed to open dll file");
const auto size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> data(static_cast<size_t>(size));
if (!file.read(reinterpret_cast<char*>(data.data()), size))
throw std::runtime_error("failed to read dll file");
throw ls::error("failed to read dll file");
// parse dos header
size_t fileOffset = 0;
const auto* dosHdr = safe_cast<const DOSHeader>(data, 0);
if (dosHdr->magic != 0x5A4D)
throw std::runtime_error("dos header magic number is incorrect");
throw ls::error("dos header magic number is incorrect");
// parse pe header
fileOffset += static_cast<size_t>(dosHdr->pe_offset);
const auto* peHdr = safe_cast<const PEHeader>(data, fileOffset);
if (peHdr->signature != 0x00004550)
throw std::runtime_error("pe header signature is incorrect");
throw ls::error("pe header signature is incorrect");
// parse optional pe header
fileOffset += sizeof(PEHeader);
const auto* peOptHdr = safe_cast<const PEOptionalHeader>(data, fileOffset);
if (peOptHdr->magic != 0x20B)
throw std::runtime_error("pe format is not PE32+");
throw ls::error("pe format is not PE32+");
const auto& [rsrc_rva, rsrc_size] = peOptHdr->resource_table;
// locate section containing resources
@ -137,13 +138,13 @@ std::unordered_map<uint32_t, std::vector<uint8_t>> extr::extractResourcesFromDLL
break;
}
if (!rsrc_offset)
throw std::runtime_error("unable to locate resource section");
throw ls::error("unable to locate resource section");
// parse resource directory
fileOffset = rsrc_offset.value();
const auto* rsrcDir = safe_cast<const ResourceDirectory>(data, fileOffset);
if (rsrcDir->id_count < 3)
throw std::runtime_error("resource directory does not have enough entries");
throw ls::error("resource directory does not have enough entries");
// find resource table with data type
std::optional<size_t> rsrc_tbl_offset;
@ -154,18 +155,18 @@ std::unordered_map<uint32_t, std::vector<uint8_t>> extr::extractResourcesFromDLL
if (rsrcDirEntry.id != 10) // RT_RCDATA
continue;
if ((rsrcDirEntry.offset & 0x80000000) == 0)
throw std::runtime_error("expected resource directory, found data entry");
throw ls::error("expected resource directory, found data entry");
rsrc_tbl_offset.emplace(rsrcDirEntry.offset & 0x7FFFFFFF);
}
if (!rsrc_tbl_offset)
throw std::runtime_error("unabele to locate RT_RCDATA directory");
throw ls::error("unabele to locate RT_RCDATA directory");
// parse data type resource directory
fileOffset = rsrc_offset.value() + rsrc_tbl_offset.value();
const auto* rsrcTbl = safe_cast<const ResourceDirectory>(data, fileOffset);
if (rsrcTbl->id_count < 1)
throw std::runtime_error("RT_RCDATA directory does not have enough entries");
throw ls::error("RT_RCDATA directory does not have enough entries");
// collect all resources
fileOffset += sizeof(ResourceDirectory);
@ -174,30 +175,30 @@ std::unordered_map<uint32_t, std::vector<uint8_t>> extr::extractResourcesFromDLL
std::unordered_map<uint32_t, std::vector<uint8_t>> resources;
for (const auto& rsrcTblEntry : rsrcTblEntries) {
if ((rsrcTblEntry.offset & 0x80000000) == 0)
throw std::runtime_error("expected resource directory, found data entry");
throw ls::error("expected resource directory, found data entry");
// skip over language directory
fileOffset = rsrc_offset.value() + (rsrcTblEntry.offset & 0x7FFFFFFF);
const auto* langDir = safe_cast<const ResourceDirectory>(data, fileOffset);
if (langDir->id_count < 1)
throw std::runtime_error("Incorrect language directory");
throw ls::error("Incorrect language directory");
fileOffset += sizeof(ResourceDirectory);
const auto* langDirEntry = safe_cast<const ResourceDirectoryEntry>(data, fileOffset);
if ((langDirEntry->offset & 0x80000000) != 0)
throw std::runtime_error("expected resource data entry, but found directory");
throw ls::error("expected resource data entry, but found directory");
// parse resource data entry
fileOffset = rsrc_offset.value() + (langDirEntry->offset & 0x7FFFFFFF);
const auto* entry = safe_cast<const ResourceDataEntry>(data, fileOffset);
if (entry->offset < rsrc_rva || entry->offset > (rsrc_rva + rsrc_size))
throw std::runtime_error("resource data entry points outside resource section");
throw ls::error("resource data entry points outside resource section");
// extract resource
std::vector<uint8_t> resource(entry->size);
fileOffset = (entry->offset - rsrc_rva) + rsrc_offset.value();
if (fileOffset + entry->size > data.size())
throw std::runtime_error("resource data entry points outside file");
throw ls::error("resource data entry points outside file");
std::copy_n(&data.at(fileOffset), entry->size, resource.data());
resources.emplace(rsrcTblEntry.id, std::move(resource));
}

View file

@ -5,12 +5,12 @@
#include <unordered_map>
#include <vector>
namespace extr {
namespace lsfgvk::backend {
/// extract all resources from a DLL file
/// @param dll path to the DLL file
/// @return map of resource IDs to their binary data
/// @throws std::runtime_error on various failure points
/// @throws ls::error on various failure points
std::unordered_map<uint32_t, std::vector<uint8_t>> extractResourcesFromDLL(
const std::filesystem::path& dll);

View file

@ -1,16 +1,17 @@
#include "shader_registry.hpp"
#include "lsfg-vk-common/helpers/errors.hpp"
#include "lsfg-vk-common/vulkan/shader.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstddef>
#include <cstdint>
#include <span>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
using namespace extr;
using namespace lsfgvk;
using namespace lsfgvk::backend;
namespace {
/// get the source code for a shader
@ -24,7 +25,7 @@ namespace {
(perf ? OFFSET_PERF : 0) +
(fp16 ? OFFSET_FP16 : 0));
if (it == resources.end())
throw std::runtime_error("unable to find shader with id: " + std::to_string(id));
throw ls::error("unable to find shader with id: " + std::to_string(id));
return it->second;
}
@ -70,7 +71,7 @@ namespace {
}
}
ShaderRegistry extr::buildShaderRegistry(const vk::Vulkan& vk, bool fp16,
ShaderRegistry backend::buildShaderRegistry(const vk::Vulkan& vk, bool fp16,
const std::unordered_map<uint32_t, std::vector<uint8_t>>& resources) {
// patch the generate shader
std::vector<uint8_t> generate_data = getShaderSource(256, fp16, false, resources);

View file

@ -7,7 +7,7 @@
#include <unordered_map>
#include <vector>
namespace extr {
namespace lsfgvk::backend {
/// shader collection struct
struct Shaders {
@ -32,7 +32,7 @@ namespace extr {
/// @param fp16 whether to load fp16 variants
/// @param resources map of resource IDs to their binary data
/// @return constructed shader registry
/// @throws std::runtime_error if shaders are missing
/// @throws ls::error if shaders are missing
/// @throws vk::vulkan_error on Vulkan errors
ShaderRegistry buildShaderRegistry(const vk::Vulkan& vk, bool fp16,
const std::unordered_map<uint32_t, std::vector<uint8_t>>& resources);

View file

@ -5,7 +5,8 @@
#include <cstddef>
#include <cstdint>
using namespace ls;
using namespace lsfgvk;
using namespace lsfgvk::backend;
namespace {
const vk::Limits BASE_LIMITS{
@ -32,7 +33,7 @@ namespace {
};
}
vk::Limits ls::calculateDescriptorPoolLimits(size_t count, bool perf) {
vk::Limits backend::calculateDescriptorPoolLimits(size_t count, bool perf) {
const auto m = static_cast<uint16_t>(count);
vk::Limits a{BASE_LIMITS};

View file

@ -4,7 +4,7 @@
#include <cstddef>
namespace ls {
namespace lsfgvk::backend {
/// calculate limits for descriptor pools
/// @param count number of images
/// @param perf whether performance mode is enabled

View file

@ -14,7 +14,8 @@
#include <vulkan/vulkan_core.h>
using namespace ls;
using namespace lsfgvk;
using namespace lsfgvk::backend;
ManagedShaderBuilder& ManagedShaderBuilder::sampled(const vk::Image& image) {
this->sampledImages.push_back(std::ref(image));

View file

@ -11,7 +11,7 @@
#include <vulkan/vulkan_core.h>
namespace ls {
namespace lsfgvk::backend {
/// managed shader handling dispatch and barriers
/// this class is NOT memory-safe

View file

@ -7,9 +7,10 @@
#include <vulkan/vulkan_core.h>
using namespace ls;
using namespace lsfgvk;
using namespace lsfgvk::backend;
ConstantBuffer ls::getDefaultConstantBuffer(
ConstantBuffer backend::getDefaultConstantBuffer(
size_t index, size_t total,
bool hdr, float invFlow) {
return ConstantBuffer {
@ -21,21 +22,21 @@ ConstantBuffer ls::getDefaultConstantBuffer(
};
}
VkExtent2D ls::shift_extent(VkExtent2D extent, uint32_t i) {
VkExtent2D backend::shift_extent(VkExtent2D extent, uint32_t i) {
return VkExtent2D{
.width = extent.width >> i,
.height = extent.height >> i
};
}
VkExtent2D ls::add_shift_extent(VkExtent2D extent, uint32_t a, uint32_t i) {
VkExtent2D backend::add_shift_extent(VkExtent2D extent, uint32_t a, uint32_t i) {
return VkExtent2D{
.width = (extent.width + a) >> i,
.height = (extent.height + a) >> i
};
}
std::string ls::to_hex_id(uint32_t id) {
std::string backend::to_hex_id(uint32_t id) {
const std::array<char, 17> chars = std::to_array("0123456789ABCDEF");
std::string result = "0x";

View file

@ -15,11 +15,11 @@
#include <vulkan/vulkan_core.h>
namespace ls {
namespace lsfgvk::backend {
/// exposed context data
struct Ctx {
ls::R<const vk::Vulkan> vk; // safe back reference
ls::R<const extr::ShaderRegistry> shaders; // safe back reference
ls::R<const ShaderRegistry> shaders; // safe back reference
vk::DescriptorPool pool;

View file

@ -46,8 +46,15 @@
#endif
using namespace lsfgvk;
using namespace lsfgvk::backend;
namespace lsfgvk::backend {
error::error(const std::string& msg, const std::exception& inner)
: std::runtime_error(msg + "\n- " + inner.what()) {}
error::error(const std::string& msg)
: std::runtime_error(msg) {}
error::~error() = default;
namespace lsfgvk {
/// instance class
class InstanceImpl {
public:
@ -70,7 +77,7 @@ namespace lsfgvk {
#endif
private:
vk::Vulkan vk;
extr::ShaderRegistry shaders;
ShaderRegistry shaders;
#ifdef LSFGVK__RENDERDOC_INTEGRATION
std::optional<RENDERDOC_API_1_6_0> renderdoc;
@ -102,20 +109,20 @@ namespace lsfgvk {
std::vector<vk::CommandBuffer> cmdbufs;
vk::Fence cmdbufFence;
ls::Ctx ctx;
Ctx ctx;
chains::Mipmaps mipmaps;
std::array<chains::Alpha0, 7> alpha0;
std::array<chains::Alpha1, 7> alpha1;
chains::Beta0 beta0;
chains::Beta1 beta1;
Mipmaps mipmaps;
std::array<Alpha0, 7> alpha0;
std::array<Alpha1, 7> alpha1;
Beta0 beta0;
Beta1 beta1;
struct Pass {
std::vector<chains::Gamma0> gamma0;
std::vector<chains::Gamma1> gamma1;
std::vector<Gamma0> gamma0;
std::vector<Gamma1> gamma1;
std::vector<chains::Delta0> delta0;
std::vector<chains::Delta1> delta1;
ls::lazy<chains::Generate> generate;
std::vector<Delta0> delta0;
std::vector<Delta1> delta1;
ls::lazy<Generate> generate;
};
std::vector<Pass> passes;
};
@ -156,8 +163,8 @@ Instance::Instance(
if (devicePicker(
std::string(devname.data()),
{ ls::to_hex_id(props.properties.vendorID),
ls::to_hex_id(props.properties.deviceID) },
{ backend::to_hex_id(props.properties.vendorID),
backend::to_hex_id(props.properties.deviceID) },
has_pci_ext ? std::optional<std::string>{
std::to_string(pciInfo.pciBus) + ":" +
std::to_string(pciInfo.pciDevice) + "." +
@ -199,28 +206,28 @@ namespace {
findCacheFilePath()
};
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to initialize Vulkan", e);
throw backend::error("Unable to initialize Vulkan", e);
}
}
/// build a shader registry
extr::ShaderRegistry createShaderRegistry(vk::Vulkan& vk,
ShaderRegistry createShaderRegistry(vk::Vulkan& vk,
const std::filesystem::path& shaderDllPath,
bool allowLowPrecision) {
std::unordered_map<uint32_t, std::vector<uint8_t>> resources{};
try {
resources = extr::extractResourcesFromDLL(shaderDllPath);
resources = backend::extractResourcesFromDLL(shaderDllPath);
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to parse Lossless Scaling DLL", e);
throw backend::error("Unable to parse Lossless Scaling DLL", e);
}
try {
return extr::buildShaderRegistry(
return backend::buildShaderRegistry(
vk, allowLowPrecision && vk.supportsFP16(),
resources
);
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to build shader registry", e);
throw backend::error("Unable to build shader registry", e);
}
}
#ifdef LSFGVK__RENDERDOC_INTEGRATION
@ -280,7 +287,7 @@ namespace {
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, sourceFds.second)
};
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to import destination images", e);
throw backend::error("Unable to import destination images", e);
}
}
/// import destination images
@ -297,7 +304,7 @@ namespace {
return destImages;
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to import destination images", e);
throw backend::error("Unable to import destination images", e);
}
}
/// create a black image
@ -307,7 +314,7 @@ namespace {
{ .width = 4, .height = 4 }
};
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to create black image", e);
throw backend::error("Unable to create black image", e);
}
}
/// import timeline semaphore
@ -315,7 +322,7 @@ namespace {
try {
return{vk, 0, syncFd};
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to import timeline semaphore", e);
throw backend::error("Unable to import timeline semaphore", e);
}
}
/// create prepass semaphores
@ -323,7 +330,7 @@ namespace {
try {
return{vk, 0};
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to create prepass semaphore", e);
throw backend::error("Unable to create prepass semaphore", e);
}
}
/// create command buffers
@ -337,11 +344,11 @@ namespace {
return cmdbufs;
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to create command buffers", e);
throw backend::error("Unable to create command buffers", e);
}
}
/// create context data
ls::Ctx createCtx(const InstanceImpl& instance, VkExtent2D extent,
Ctx createCtx(const InstanceImpl& instance, VkExtent2D extent,
bool hdr, float flow, bool perf, size_t count) {
const auto& vk = instance.getVulkan();
const auto& shaders = instance.getShaderRegistry();
@ -352,7 +359,7 @@ namespace {
for (size_t i = 0; i < count; ++i)
constantBuffers.emplace_back(vk,
ls::getDefaultConstantBuffer(
backend::getDefaultConstantBuffer(
i, count,
hdr, flow
)
@ -361,9 +368,8 @@ namespace {
return {
.vk = std::ref(vk),
.shaders = std::ref(shaders),
.pool{vk, ls::calculateDescriptorPoolLimits(count, perf)},
.constantBuffer{vk,
ls::getDefaultConstantBuffer(0, 1, hdr, flow)},
.pool{vk, backend::calculateDescriptorPoolLimits(count, perf)},
.constantBuffer{vk, backend::getDefaultConstantBuffer(0, 1, hdr, flow)},
.constantBuffers{std::move(constantBuffers)},
.bnbSampler{vk, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, false},
.bnwSampler{vk, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_COMPARE_OP_NEVER, true},
@ -379,7 +385,7 @@ namespace {
.count = count
};
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to create context", e);
throw backend::error("Unable to create context", e);
}
}
}
@ -399,22 +405,22 @@ ContextImpl::ContextImpl(const InstanceImpl& instance,
ctx(createCtx(instance, extent, hdr, flow, perf, destFds.size())),
mipmaps(ctx, sourceImages),
alpha0{
chains::Alpha0(ctx, mipmaps.getImages().at(0)),
chains::Alpha0(ctx, mipmaps.getImages().at(1)),
chains::Alpha0(ctx, mipmaps.getImages().at(2)),
chains::Alpha0(ctx, mipmaps.getImages().at(3)),
chains::Alpha0(ctx, mipmaps.getImages().at(4)),
chains::Alpha0(ctx, mipmaps.getImages().at(5)),
chains::Alpha0(ctx, mipmaps.getImages().at(6))
Alpha0(ctx, mipmaps.getImages().at(0)),
Alpha0(ctx, mipmaps.getImages().at(1)),
Alpha0(ctx, mipmaps.getImages().at(2)),
Alpha0(ctx, mipmaps.getImages().at(3)),
Alpha0(ctx, mipmaps.getImages().at(4)),
Alpha0(ctx, mipmaps.getImages().at(5)),
Alpha0(ctx, mipmaps.getImages().at(6))
},
alpha1{
chains::Alpha1(ctx, 3, alpha0.at(0).getImages()),
chains::Alpha1(ctx, 2, alpha0.at(1).getImages()),
chains::Alpha1(ctx, 2, alpha0.at(2).getImages()),
chains::Alpha1(ctx, 2, alpha0.at(3).getImages()),
chains::Alpha1(ctx, 2, alpha0.at(4).getImages()),
chains::Alpha1(ctx, 2, alpha0.at(5).getImages()),
chains::Alpha1(ctx, 2, alpha0.at(6).getImages())
Alpha1(ctx, 3, alpha0.at(0).getImages()),
Alpha1(ctx, 2, alpha0.at(1).getImages()),
Alpha1(ctx, 2, alpha0.at(2).getImages()),
Alpha1(ctx, 2, alpha0.at(3).getImages()),
Alpha1(ctx, 2, alpha0.at(4).getImages()),
Alpha1(ctx, 2, alpha0.at(5).getImages()),
Alpha1(ctx, 2, alpha0.at(6).getImages())
},
beta0(ctx, alpha1.at(0).getImages()),
beta1(ctx, beta0.getImages()) {
@ -544,7 +550,7 @@ void Instance::scheduleFrames(Context& context) {
try {
context.scheduleFrames();
} catch (const std::exception& e) {
throw lsfgvk::error("Unable to schedule frames", e);
throw backend::error("Unable to schedule frames", e);
}
#ifdef LSFGVK__RENDERDOC_INTEGRATION
if (impl->getRenderDocAPI()) {
@ -559,7 +565,7 @@ void Instance::scheduleFrames(Context& context) {
void Context::scheduleFrames() {
// wait for previous pre-pass to complete
if (this->fidx && !this->cmdbufFence.wait(this->ctx.vk))
throw lsfgvk::error("Timeout waiting for previous frame to complete");
throw backend::error("Timeout waiting for previous frame to complete");
this->cmdbufFence.reset(this->ctx.vk);
// schedule pre-pass
@ -616,7 +622,7 @@ void Instance::closeContext(const Context& context) {
return ctx.get() == context;
});
if (it == this->m_contexts.end())
throw lsfgvk::error("attempted to close unknown context",
throw backend::error("attempted to close unknown context",
std::runtime_error("no such context"));
const auto& vk = this->m_impl->getVulkan();
@ -626,11 +632,3 @@ void Instance::closeContext(const Context& context) {
}
Instance::~Instance() = default;
error::error(const std::string& msg, const std::exception& inner)
: std::runtime_error(msg + "\n- " + inner.what()) {}
error::error(const std::string& msg)
: std::runtime_error(msg) {}
error::~error() = default;

View file

@ -10,13 +10,13 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Alpha0::Alpha0(const ls::Ctx& ctx,
Alpha0::Alpha0(const Ctx& ctx,
const vk::Image& sourceImage) {
const size_t m = ctx.perf ? 1 : 2; // multiplier
const VkExtent2D halfExtent = ls::add_shift_extent(sourceImage.getExtent(), 1, 1);
const VkExtent2D quarterExtent = ls::add_shift_extent(halfExtent, 1, 1);
const VkExtent2D halfExtent = backend::add_shift_extent(sourceImage.getExtent(), 1, 1);
const VkExtent2D quarterExtent = backend::add_shift_extent(halfExtent, 1, 1);
// create temporary & output images
this->tempImages0.reserve(m);
@ -33,25 +33,25 @@ Alpha0::Alpha0(const ls::Ctx& ctx,
// create descriptor sets
const auto& shaders = ctx.perf ? ctx.shaders.get().performance : ctx.shaders.get().quality;
this->sets.reserve(3);
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampled(sourceImage)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.alpha.at(0)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.storages(this->tempImages1)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.alpha.at(1)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages1)
.storages(this->images)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.alpha.at(2)));
// store dispatch extents
this->dispatchExtent0 = ls::add_shift_extent(halfExtent, 7, 3);
this->dispatchExtent1 = ls::add_shift_extent(quarterExtent, 7, 3);
this->dispatchExtent0 = backend::add_shift_extent(halfExtent, 7, 3);
this->dispatchExtent1 = backend::add_shift_extent(quarterExtent, 7, 3);
}
void Alpha0::prepare(std::vector<VkImage>& images) const {

View file

@ -12,14 +12,14 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// pre-alpha shaderchain
class Alpha0 {
public:
/// create a pre-alpha shaderchain
/// @param ctx context
/// @param sourceImage source image
Alpha0(const ls::Ctx& ctx,
Alpha0(const Ctx& ctx,
const vk::Image& sourceImage);
/// prepare the shaderchain initially
@ -39,7 +39,7 @@ namespace chains {
std::vector<vk::Image> tempImages1;
std::vector<vk::Image> images;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent0{};
VkExtent2D dispatchExtent1{};
};

View file

@ -10,9 +10,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Alpha1::Alpha1(const ls::Ctx& ctx, size_t temporal,
Alpha1::Alpha1(const Ctx& ctx, size_t temporal,
const std::vector<vk::Image>& sourceImages) {
const size_t m = ctx.perf ? 1 : 2; // multiplier
const VkExtent2D quarterExtent = sourceImages.at(0).getExtent();
@ -31,14 +31,14 @@ Alpha1::Alpha1(const ls::Ctx& ctx, size_t temporal,
const auto& shaders = ctx.perf ? ctx.shaders.get().performance : ctx.shaders.get().quality;
this->sets.reserve(temporal);
for (size_t i = 0; i < temporal; i++)
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages)
.storages(this->images.at(i))
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.alpha.at(3)));
// store dispatch extents
this->dispatchExtent = ls::add_shift_extent(quarterExtent, 7, 3);
this->dispatchExtent = backend::add_shift_extent(quarterExtent, 7, 3);
}
void Alpha1::prepare(std::vector<VkImage>& images) const {

View file

@ -12,7 +12,7 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// alpha shaderchain
class Alpha1 {
public:
@ -20,7 +20,7 @@ namespace chains {
/// @param ctx context
/// @param temporal temporal count
/// @param sourceImages source images
Alpha1(const ls::Ctx& ctx, size_t temporal,
Alpha1(const Ctx& ctx, size_t temporal,
const std::vector<vk::Image>& sourceImages);
/// prepare the shaderchain initially
@ -39,7 +39,7 @@ namespace chains {
private:
std::vector<std::vector<vk::Image>> images;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -10,9 +10,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Beta0::Beta0(const ls::Ctx& ctx,
Beta0::Beta0(const Ctx& ctx,
const std::vector<std::vector<vk::Image>>& sourceImages) {
const VkExtent2D extent = sourceImages.at(0).at(0).getExtent();
@ -26,7 +26,7 @@ Beta0::Beta0(const ls::Ctx& ctx,
ctx.shaders.get().performance : ctx.shaders.get().quality).beta.at(0);
this->sets.reserve(sourceImages.size());
for (size_t i = 0; i < sourceImages.size(); i++)
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages.at((i + (sourceImages.size() - 2)) % sourceImages.size()))
.sampleds(sourceImages.at((i + (sourceImages.size() - 1)) % sourceImages.size()))
.sampleds(sourceImages.at(i % sourceImages.size()))
@ -35,7 +35,7 @@ Beta0::Beta0(const ls::Ctx& ctx,
.build(ctx.vk, ctx.pool, shader));
// store dispatch extents
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
this->dispatchExtent = backend::add_shift_extent(extent, 7, 3);
}
void Beta0::prepare(std::vector<VkImage>& images) const {

View file

@ -12,14 +12,14 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// beta shaderchain
class Beta0 {
public:
/// create a beta shaderchain
/// @param ctx context
/// @param sourceImages source images
Beta0(const ls::Ctx& ctx,
Beta0(const Ctx& ctx,
const std::vector<std::vector<vk::Image>>& sourceImages);
/// prepare the shaderchain initially
@ -38,7 +38,7 @@ namespace chains {
private:
std::vector<vk::Image> images;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -11,9 +11,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Beta1::Beta1(const ls::Ctx& ctx,
Beta1::Beta1(const Ctx& ctx,
const std::vector<vk::Image>& sourceImages) {
const VkExtent2D extent = sourceImages.at(0).getExtent();
@ -28,29 +28,29 @@ Beta1::Beta1(const ls::Ctx& ctx,
this->images.reserve(6);
for (uint32_t i = 0; i < 6; i++)
this->images.emplace_back(ctx.vk,
ls::shift_extent(extent, i),
backend::shift_extent(extent, i),
VK_FORMAT_R8_UNORM);
// create descriptor sets
const auto& shaders = (ctx.perf ?
ctx.shaders.get().performance : ctx.shaders.get().quality).beta;
this->sets.reserve(4);
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(1)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.storages(this->tempImages1)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(2)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages1)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(3)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.storages(this->images)
.sampler(ctx.bnbSampler)
@ -58,8 +58,8 @@ Beta1::Beta1(const ls::Ctx& ctx,
.build(ctx.vk, ctx.pool, shaders.at(4)));
// store dispatch extents
this->dispatchExtent0 = ls::add_shift_extent(extent, 7, 3);
this->dispatchExtent1 = ls::add_shift_extent(extent, 31, 5);
this->dispatchExtent0 = backend::add_shift_extent(extent, 7, 3);
this->dispatchExtent1 = backend::add_shift_extent(extent, 31, 5);
}
void Beta1::prepare(std::vector<VkImage>& images) const {

View file

@ -12,14 +12,14 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// beta shaderchain
class Beta1 {
public:
/// create a beta shaderchain
/// @param ctx context
/// @param sourceImages source images
Beta1(const ls::Ctx& ctx,
Beta1(const Ctx& ctx,
const std::vector<vk::Image>& sourceImages);
/// prepare the shaderchain initially
@ -39,7 +39,7 @@ namespace chains {
std::vector<vk::Image> tempImages1;
std::vector<vk::Image> images;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent0{};
VkExtent2D dispatchExtent1{};
};

View file

@ -10,9 +10,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Delta0::Delta0(const ls::Ctx& ctx, size_t idx,
Delta0::Delta0(const Ctx& ctx, size_t idx,
const std::vector<std::vector<vk::Image>>& sourceImages,
const vk::Image& additionalInput0,
const vk::Image& additionalInput1) {
@ -33,7 +33,7 @@ Delta0::Delta0(const ls::Ctx& ctx, size_t idx,
this->sets0.reserve(sourceImages.size());
for (size_t i = 0; i < sourceImages.size(); i++)
this->sets0.emplace_back(ls::ManagedShaderBuilder()
this->sets0.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages.at((i + (sourceImages.size() - 1)) % sourceImages.size()))
.sampleds(sourceImages.at(i % sourceImages.size()))
.sampled(additionalInput0)
@ -45,7 +45,7 @@ Delta0::Delta0(const ls::Ctx& ctx, size_t idx,
this->sets1.reserve(sourceImages.size());
for (size_t i = 0; i < sourceImages.size(); i++)
this->sets1.emplace_back(ls::ManagedShaderBuilder()
this->sets1.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages.at((i + (sourceImages.size() - 1)) % sourceImages.size()))
.sampleds(sourceImages.at(i % sourceImages.size()))
.sampled(additionalInput1)
@ -57,7 +57,7 @@ Delta0::Delta0(const ls::Ctx& ctx, size_t idx,
.build(ctx.vk, ctx.pool, shaders.at(5)));
// store dispatch extents
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
this->dispatchExtent = backend::add_shift_extent(extent, 7, 3);
}
void Delta0::prepare(std::vector<VkImage>& images) const {

View file

@ -12,7 +12,7 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// delta shaderchain
class Delta0 {
public:
@ -22,7 +22,7 @@ namespace chains {
/// @param sourceImages source images
/// @param additionalInput0 additional input image
/// @param additionalInput1 additional input image
Delta0(const ls::Ctx& ctx, size_t idx,
Delta0(const Ctx& ctx, size_t idx,
const std::vector<std::vector<vk::Image>>& sourceImages,
const vk::Image& additionalInput0,
const vk::Image& additionalInput1);
@ -48,8 +48,8 @@ namespace chains {
std::vector<vk::Image> images0;
std::vector<vk::Image> images1;
std::vector<ls::ManagedShader> sets0;
std::vector<ls::ManagedShader> sets1;
std::vector<ManagedShader> sets0;
std::vector<ManagedShader> sets1;
VkExtent2D dispatchExtent{};
};
}

View file

@ -10,9 +10,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Delta1::Delta1(const ls::Ctx& ctx, size_t idx,
Delta1::Delta1(const Ctx& ctx, size_t idx,
const std::vector<vk::Image>& sourceImages0,
const std::vector<vk::Image>& sourceImages1,
const vk::Image& additionalInput0,
@ -40,22 +40,22 @@ Delta1::Delta1(const ls::Ctx& ctx, size_t idx,
ctx.shaders.get().performance : ctx.shaders.get().quality).delta;
this->sets.reserve(4 + 4);
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages0)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(1)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.storages(this->tempImages1)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(2)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages1)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(3)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.sampled(additionalInput0)
.sampled(additionalInput1)
@ -65,22 +65,22 @@ Delta1::Delta1(const ls::Ctx& ctx, size_t idx,
.buffer(ctx.constantBuffers.at(idx))
.build(ctx.vk, ctx.pool, shaders.at(4)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages1)
.storages(this->tempImages0, 0, m)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(6)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0, 0, m)
.storages(this->tempImages1, 0, m)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(7)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages1, 0, m)
.storages(this->tempImages0, 0, m)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(8)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0, 0, m)
.sampled(additionalInput2)
.storage(*this->image1)
@ -90,7 +90,7 @@ Delta1::Delta1(const ls::Ctx& ctx, size_t idx,
.build(ctx.vk, ctx.pool, shaders.at(9)));
// store dispatch extents
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
this->dispatchExtent = backend::add_shift_extent(extent, 7, 3);
}
void Delta1::prepare(std::vector<VkImage>& images) const {

View file

@ -13,7 +13,7 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// gamma shaderchain
class Delta1 {
public:
@ -25,7 +25,7 @@ namespace chains {
/// @param additionalInput0 additional input image
/// @param additionalInput1 additional input image
/// @param additionalInput2 additional input image
Delta1(const ls::Ctx& ctx, size_t idx,
Delta1(const Ctx& ctx, size_t idx,
const std::vector<vk::Image>& sourceImages0,
const std::vector<vk::Image>& sourceImages1,
const vk::Image& additionalInput0,
@ -54,7 +54,7 @@ namespace chains {
ls::lazy<vk::Image> image0;
ls::lazy<vk::Image> image1;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -10,9 +10,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Gamma0::Gamma0(const ls::Ctx& ctx, size_t idx,
Gamma0::Gamma0(const Ctx& ctx, size_t idx,
const std::vector<std::vector<vk::Image>>& sourceImages,
const vk::Image& additionalInput) {
const VkExtent2D extent = sourceImages.at(0).at(0).getExtent();
@ -27,7 +27,7 @@ Gamma0::Gamma0(const ls::Ctx& ctx, size_t idx,
ctx.shaders.get().performance : ctx.shaders.get().quality).gamma.at(0);
this->sets.reserve(sourceImages.size());
for (size_t i = 0; i < sourceImages.size(); i++)
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages.at((i + (sourceImages.size() - 1)) % sourceImages.size()))
.sampleds(sourceImages.at(i % sourceImages.size()))
.sampled(additionalInput)
@ -38,7 +38,7 @@ Gamma0::Gamma0(const ls::Ctx& ctx, size_t idx,
.build(ctx.vk, ctx.pool, shader));
// store dispatch extents
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
this->dispatchExtent = backend::add_shift_extent(extent, 7, 3);
}
void Gamma0::prepare(std::vector<VkImage>& images) const {

View file

@ -12,7 +12,7 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// gamma shaderchain
class Gamma0 {
public:
@ -21,7 +21,7 @@ namespace chains {
/// @param idx generated frame index
/// @param sourceImages source images
/// @param additionalInput additional input image
Gamma0(const ls::Ctx& ctx, size_t idx,
Gamma0(const Ctx& ctx, size_t idx,
const std::vector<std::vector<vk::Image>>& sourceImages,
const vk::Image& additionalInput);
@ -41,7 +41,7 @@ namespace chains {
private:
std::vector<vk::Image> images;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -10,9 +10,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Gamma1::Gamma1(const ls::Ctx& ctx, size_t idx,
Gamma1::Gamma1(const Ctx& ctx, size_t idx,
const std::vector<vk::Image>& sourceImages,
const vk::Image& additionalInput0,
const vk::Image& additionalInput1) {
@ -33,22 +33,22 @@ Gamma1::Gamma1(const ls::Ctx& ctx, size_t idx,
const auto& shaders = (ctx.perf ?
ctx.shaders.get().performance : ctx.shaders.get().quality).gamma;
this->sets.reserve(4);
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(sourceImages)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(1)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.storages(this->tempImages1)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(2)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages1)
.storages(this->tempImages0)
.sampler(ctx.bnbSampler)
.build(ctx.vk, ctx.pool, shaders.at(3)));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampleds(this->tempImages0)
.sampled(additionalInput0)
.sampled(additionalInput1)
@ -59,7 +59,7 @@ Gamma1::Gamma1(const ls::Ctx& ctx, size_t idx,
.build(ctx.vk, ctx.pool, shaders.at(4)));
// store dispatch extents
this->dispatchExtent = ls::add_shift_extent(extent, 7, 3);
this->dispatchExtent = backend::add_shift_extent(extent, 7, 3);
}
void Gamma1::prepare(std::vector<VkImage>& images) const {

View file

@ -13,7 +13,7 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// gamma shaderchain
class Gamma1 {
public:
@ -23,7 +23,7 @@ namespace chains {
/// @param sourceImages source images
/// @param additionalInput0 additional input image
/// @param additionalInput1 additional input image
Gamma1(const ls::Ctx& ctx, size_t idx,
Gamma1(const Ctx& ctx, size_t idx,
const std::vector<vk::Image>& sourceImages,
const vk::Image& additionalInput0,
const vk::Image& additionalInput1);
@ -45,7 +45,7 @@ namespace chains {
std::vector<vk::Image> tempImages1;
ls::lazy<vk::Image> image;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -11,9 +11,9 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Generate::Generate(const ls::Ctx& ctx, size_t idx,
Generate::Generate(const Ctx& ctx, size_t idx,
const std::pair<vk::Image, vk::Image>& sourceImages,
const vk::Image& inputImage1,
const vk::Image& inputImage2,
@ -23,7 +23,7 @@ Generate::Generate(const ls::Ctx& ctx, size_t idx,
const auto& shader = ctx.hdr ?
ctx.shaders.get().generate_hdr : ctx.shaders.get().generate;
this->sets.reserve(2);
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampled(sourceImages.second)
.sampled(sourceImages.first)
.sampled(inputImage1)
@ -34,7 +34,7 @@ Generate::Generate(const ls::Ctx& ctx, size_t idx,
.sampler(ctx.eabSampler)
.buffer(ctx.constantBuffers.at(idx))
.build(ctx.vk, ctx.pool, shader));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampled(sourceImages.first)
.sampled(sourceImages.second)
.sampled(inputImage1)
@ -47,7 +47,7 @@ Generate::Generate(const ls::Ctx& ctx, size_t idx,
.build(ctx.vk, ctx.pool, shader));
// store dispatch extent
this->dispatchExtent = ls::add_shift_extent(ctx.sourceExtent, 15, 4);
this->dispatchExtent = backend::add_shift_extent(ctx.sourceExtent, 15, 4);
}
void Generate::render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const {

View file

@ -13,7 +13,7 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// generate shaderchain
class Generate {
public:
@ -24,7 +24,7 @@ namespace chains {
/// @param inputImage1 input image 1
/// @param inputImage2 input image 2
/// @param inputImage3 input image 3
Generate(const ls::Ctx& ctx, size_t idx,
Generate(const Ctx& ctx, size_t idx,
const std::pair<vk::Image, vk::Image>& sourceImages,
const vk::Image& inputImage1,
const vk::Image& inputImage2,
@ -37,7 +37,7 @@ namespace chains {
/// @param idx frame index
void render(const vk::Vulkan& vk, const vk::CommandBuffer& cmd, size_t idx) const;
private:
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -12,25 +12,25 @@
#include <vulkan/vulkan_core.h>
using namespace chains;
using namespace lsfgvk::backend;
Mipmaps::Mipmaps(const ls::Ctx& ctx,
Mipmaps::Mipmaps(const Ctx& ctx,
const std::pair<vk::Image, vk::Image>& sourceImages) {
// create output images for base and 6 mips
this->images.reserve(7);
for (uint32_t i = 0; i < 7; i++)
this->images.emplace_back(ctx.vk,
ls::shift_extent(ctx.flowExtent, i), VK_FORMAT_R8_UNORM);
backend::shift_extent(ctx.flowExtent, i), VK_FORMAT_R8_UNORM);
// create descriptor sets for both input images
this->sets.reserve(2);
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampled(sourceImages.first)
.storages(this->images)
.sampler(ctx.bnbSampler)
.buffer(ctx.constantBuffer)
.build(ctx.vk, ctx.pool, ctx.shaders.get().mipmaps));
this->sets.emplace_back(ls::ManagedShaderBuilder()
this->sets.emplace_back(ManagedShaderBuilder()
.sampled(sourceImages.second)
.storages(this->images)
.sampler(ctx.bnbSampler)
@ -38,7 +38,7 @@ Mipmaps::Mipmaps(const ls::Ctx& ctx,
.build(ctx.vk, ctx.pool, ctx.shaders.get().mipmaps));
// store dispatch extent
this->dispatchExtent = ls::add_shift_extent(ctx.flowExtent, 63, 6);
this->dispatchExtent = backend::add_shift_extent(ctx.flowExtent, 63, 6);
}
void Mipmaps::prepare(std::vector<VkImage>& images) const {

View file

@ -13,14 +13,14 @@
namespace ctx { struct Ctx; }
namespace chains {
namespace lsfgvk::backend {
/// mipmaps shaderchain
class Mipmaps {
public:
/// create a mipmaps shaderchain
/// @param ctx context
/// @param sourceImages pair of source images
Mipmaps(const ls::Ctx& ctx,
Mipmaps(const Ctx& ctx,
const std::pair<vk::Image, vk::Image>& sourceImages);
/// prepare the shaderchain initially
@ -39,7 +39,7 @@ namespace chains {
private:
std::vector<vk::Image> images;
std::vector<ls::ManagedShader> sets;
std::vector<ManagedShader> sets;
VkExtent2D dispatchExtent{};
};
}

View file

@ -1,5 +1,6 @@
#pragma once
#include <exception>
#include <stdexcept>
#include <string>
@ -23,8 +24,27 @@ namespace ls {
/// get the Vulkan result code associated with this error
[[nodiscard]] virtual VkResult error() const;
private:
VkResult result;
};
/// simple error type
class [[gnu::visibility("default")]] error : public std::runtime_error {
public:
/// construct an error around an inner exception
/// @param msg error message
/// @param inner inner exception
explicit error(const std::string& msg, const std::exception& inner)
: std::runtime_error(msg + "\n- " + inner.what()), ex(inner) {}
/// construct an error
/// @param msg error message
explicit error(const std::string& msg)
: std::runtime_error(msg) {}
/// get the inner exception
[[nodiscard]] virtual const std::exception& inner() const;
private:
std::exception ex;
};
}

View file

@ -1,5 +1,7 @@
#include "lsfg-vk-common/helpers/errors.hpp"
#include <exception>
#include <vulkan/vulkan_core.h>
using namespace ls;
@ -7,3 +9,7 @@ using namespace ls;
VkResult vulkan_error::error() const {
return this->result;
}
const std::exception& error::inner() const {
return this->ex;
}

View file

@ -116,7 +116,7 @@ int main() {
<< (init_done_us - time_us) << "us\n";
// initialize lsfg-vk
lsfgvk::Instance lsfgvk{
lsfgvk::backend::Instance lsfgvk{
[](
const std::string&,
std::pair<const std::string&, const std::string&>,
@ -127,7 +127,7 @@ int main() {
"/home/pancake/.steam/steam/steamapps/common/Lossless Scaling/Lossless.dll",
true
};
lsfgvk::Context& lsfgvk_ctx = lsfgvk.openContext(
lsfgvk::backend::Context& lsfgvk_ctx = lsfgvk.openContext(
srcfds, destfds,
syncfd, EXTENT.width, EXTENT.height,
false, 1.0F / 0.5F, true

View file

@ -1,5 +1,5 @@
#include "config.hpp"
#include "lsfg-vk-backend/lsfgvk.hpp"
#include "lsfg-vk-common/helpers/errors.hpp"
#include <cstdlib>
#include <filesystem>
@ -61,7 +61,7 @@ multiplier = 2
Pacing parcingFromString(const std::string& str) {
if (str == "none")
return Pacing::None;
throw lsfgvk::error("unknown pacing method: " + str);
throw ls::error("unknown pacing method: " + str);
}
/// try to find the config
std::filesystem::path findPath() {
@ -93,7 +93,7 @@ multiplier = 2
};
if (conf.dll && !std::filesystem::exists(*conf.dll))
throw lsfgvk::error("path to dll is invalid");
throw ls::error("path to dll is invalid");
return conf;
}
@ -110,9 +110,9 @@ multiplier = 2
};
if (conf.multiplier <= 1)
throw lsfgvk::error("multiplier must be greater than 1");
throw ls::error("multiplier must be greater than 1");
if (conf.flow_scale < 0.25F || conf.flow_scale > 1.0F)
throw lsfgvk::error("flow_scale must be between 0.25 and 1.0");
throw ls::error("flow_scale must be between 0.25 and 1.0");
return conf;
}
@ -131,7 +131,7 @@ multiplier = 2
conf.allow_fp16 = std::string(no_fp16) != "1";
if (conf.dll && !std::filesystem::exists(*conf.dll))
throw lsfgvk::error("path to dll is invalid");
throw ls::error("path to dll is invalid");
return conf;
}
@ -160,9 +160,9 @@ multiplier = 2
if (pacing) conf.pacing = parcingFromString(std::string(pacing));
if (conf.multiplier <= 1)
throw lsfgvk::error("multiplier must be greater than 1");
throw ls::error("multiplier must be greater than 1");
if (conf.flow_scale < 0.25F || conf.flow_scale > 1.0F)
throw lsfgvk::error("flow_scale must be between 0.25 and 1.0");
throw ls::error("flow_scale must be between 0.25 and 1.0");
return conf;
}
@ -183,16 +183,16 @@ Configuration::Configuration() :
try {
std::filesystem::create_directories(this->path.parent_path());
if (!std::filesystem::exists(this->path.parent_path()))
throw lsfgvk::error("unable to create configuration directory");
throw ls::error("unable to create configuration directory");
std::ofstream ofs(this->path);
if (!ofs.is_open())
throw lsfgvk::error("unable to create default configuration file");
throw ls::error("unable to create default configuration file");
ofs << DEFAULT_CONFIG;
ofs.close();
} catch (const std::filesystem::filesystem_error& e) {
throw lsfgvk::error("unable to create default configuration file", e);
throw ls::error("unable to create default configuration file", e);
}
}
@ -203,7 +203,7 @@ bool Configuration::isUpToDate() {
try {
return std::filesystem::last_write_time(this->path) == this->timestamp;
} catch (const std::filesystem::filesystem_error& e) {
throw lsfgvk::error("unable to access configuration file", e);
throw ls::error("unable to access configuration file", e);
}
}
@ -211,7 +211,7 @@ void Configuration::reload() {
try {
this->timestamp = std::filesystem::last_write_time(this->path);
} catch (const std::filesystem::filesystem_error& e) {
throw lsfgvk::error("unable to access configuration file", e);
throw ls::error("unable to access configuration file", e);
}
GlobalConf global{};
@ -221,12 +221,12 @@ void Configuration::reload() {
try {
tbl = toml::parse_file(this->path.string());
} catch (const toml::parse_error& e) {
throw lsfgvk::error("unable to parse configuration", e);
throw ls::error("unable to parse configuration", e);
}
auto vrs = tbl["version"];
if (!vrs || !vrs.is_integer() || *vrs.as_integer() != 2)
throw lsfgvk::error("unsupported configuration version");
throw ls::error("unsupported configuration version");
auto gbl = tbl["global"];
if (gbl && gbl.is_table()) {

View file

@ -44,16 +44,16 @@ namespace lsfgvk::layer {
class Configuration {
public:
/// create a new configuration
/// @throws lsfgvk::error on failure
/// @throws ls::error on failure
Configuration();
/// check if the configuration is out of date
/// @throws lsfgvk::error on failure
/// @throws ls::error on failure
/// @return true if the configuration is out of date
bool isUpToDate();
/// reload the configuration from disk
/// @throws lsfgvk::error on failure
/// @throws ls::error on failure
void reload();
/// get the global configuration

View file

@ -2,13 +2,13 @@
#include "../configuration/config.hpp"
#include "../configuration/detection.hpp"
#include "swapchain.hpp"
#include "lsfg-vk-backend/lsfgvk.hpp"
#include "lsfg-vk-common/helpers/errors.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <filesystem>
#include <functional>
#include <iostream>
@ -79,7 +79,7 @@ namespace {
if (std::filesystem::exists(local))
return local;
throw lsfgvk::error("unable to locate Lossless.dll, please set the path in the configuration");
throw ls::error("unable to locate Lossless.dll, please set the path in the configuration");
}
}
@ -199,7 +199,7 @@ void Root::modifySwapchainCreateInfo(const vk::Vulkan& vk, VkSwapchainCreateInfo
void Root::createSwapchainContext(const vk::Vulkan& vk,
VkSwapchainKHR swapchain, const SwapchainInfo& info) {
if (!this->active_profile.has_value())
throw lsfgvk::error("attempted to create swapchain context while layer is inactive");
throw ls::error("attempted to create swapchain context while layer is inactive");
const auto& profile = *this->active_profile;
if (!this->backend.has_value()) { // emplace backend late, due to loader bug
@ -207,22 +207,27 @@ void Root::createSwapchainContext(const vk::Vulkan& vk,
setenv("DISABLE_LSFGVK", "1", 1); // NOLINT (c++-include)
this->backend.emplace(
[gpu = profile.gpu](
const std::string& deviceName,
std::pair<const std::string&, const std::string&> ids,
const std::optional<std::string>& pci
) {
if (!gpu)
return true;
try {
this->backend.emplace(
[gpu = profile.gpu](
const std::string& deviceName,
std::pair<const std::string&, const std::string&> ids,
const std::optional<std::string>& pci
) {
if (!gpu)
return true;
return (deviceName == *gpu)
|| (ids.first + ":" + ids.second == *gpu)
|| (pci && *pci == *gpu);
},
global.dll.value_or(findShaderDll()),
global.allow_fp16
);
return (deviceName == *gpu)
|| (ids.first + ":" + ids.second == *gpu)
|| (pci && *pci == *gpu);
},
global.dll.value_or(findShaderDll()),
global.allow_fp16
);
} catch (const std::exception& e) {
unsetenv("DISABLE_LSFGVK"); // NOLINT (c++-include)
throw ls::error("failed to create backend instance", e);
}
unsetenv("DISABLE_LSFGVK"); // NOLINT (c++-include)
}

View file

@ -2,6 +2,7 @@
#include "../configuration/config.hpp"
#include "lsfg-vk-backend/lsfgvk.hpp"
#include "lsfg-vk-common/helpers/errors.hpp"
#include "lsfg-vk-common/helpers/pointers.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include "swapchain.hpp"
@ -17,7 +18,7 @@ namespace lsfgvk::layer {
class Root {
public:
/// create the lsfg-vk root context
/// @throws lsfgvk::error on failure
/// @throws ls::error on failure
Root();
/// check if the layer is active
@ -48,16 +49,17 @@ namespace lsfgvk::layer {
/// @param vk vulkan instance
/// @param swapchain swapchain handle
/// @param info swapchain info
/// @throws ls::error on failure
void createSwapchainContext(const vk::Vulkan& vk, VkSwapchainKHR swapchain,
const SwapchainInfo& info);
/// get swapchain context
/// @param swapchain swapchain handle
/// @return swapchain context
/// @throws lsfgvk::error if not found
/// @throws ls::error if not found
[[nodiscard]] Swapchain& getSwapchainContext(VkSwapchainKHR swapchain) {
const auto& it = this->swapchains.find(swapchain);
if (it == this->swapchains.end())
throw lsfgvk::error("swapchain context not found");
throw ls::error("swapchain context not found");
return it->second;
}
@ -68,7 +70,7 @@ namespace lsfgvk::layer {
Configuration config;
std::optional<GameConf> active_profile;
ls::lazy<lsfgvk::Instance> backend;
ls::lazy<lsfgvk::backend::Instance> backend;
std::unordered_map<VkSwapchainKHR, Swapchain> swapchains;
};

View file

@ -11,6 +11,7 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <functional>
#include <optional>
#include <utility>
@ -53,7 +54,7 @@ void layer::context_ModifySwapchainCreateInfo(const GameConf& profile, uint32_t
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
switch (profile.pacing) {
case lsfgvk::layer::Pacing::None:
case Pacing::None:
createInfo.minImageCount += profile.multiplier;
if (maxImages && createInfo.minImageCount > maxImages)
createInfo.minImageCount = maxImages;
@ -63,7 +64,7 @@ void layer::context_ModifySwapchainCreateInfo(const GameConf& profile, uint32_t
}
}
Swapchain::Swapchain(const vk::Vulkan& vk, lsfgvk::Instance& backend,
Swapchain::Swapchain(const vk::Vulkan& vk, lsfgvk::backend::Instance& backend,
GameConf profile, SwapchainInfo info) :
instance(backend),
profile(std::move(profile)), info(std::move(info)) {
@ -90,16 +91,20 @@ Swapchain::Swapchain(const vk::Vulkan& vk, lsfgvk::Instance& backend,
int syncFd{};
this->syncSemaphore.emplace(vk, 0, std::nullopt, &syncFd);
this->ctx = ls::owned_ptr<ls::R<lsfgvk::Context>>(
new ls::R(backend.openContext(
{ sourceFds.at(0), sourceFds.at(1) }, destinationFds, syncFd,
extent.width, extent.height,
hdr, this->profile.flow_scale, this->profile.performance_mode
)),
[backend = &backend](ls::R<lsfgvk::Context>& ctx) {
backend->closeContext(ctx);
}
);
try {
this->ctx = ls::owned_ptr<ls::R<lsfgvk::backend::Context>>(
new ls::R(backend.openContext(
{ sourceFds.at(0), sourceFds.at(1) }, destinationFds, syncFd,
extent.width, extent.height,
hdr, this->profile.flow_scale, this->profile.performance_mode
)),
[backend = &backend](ls::R<lsfgvk::backend::Context>& ctx) {
backend->closeContext(ctx);
}
);
} catch (const std::exception& e) {
throw ls::error("failed to create swapchain context", e);
}
this->renderCommandBuffer.emplace(vk);
this->renderFence.emplace(vk);
@ -127,7 +132,11 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
const auto& sourceImage = this->sourceImages.at(this->fidx % 2);
// schedule frame generation
this->instance.get().scheduleFrames(this->ctx.get());
try {
this->instance.get().scheduleFrames(this->ctx.get());
} catch (const std::exception& e) {
throw ls::error("failed to schedule frames", e);
}
// update present mode when not using pacing
if (this->profile.pacing == Pacing::None) {
@ -189,7 +198,7 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
);
for (size_t i = 0; i < this->destinationImages.size(); i++) {
auto& postCopySemaphores = this->postCopySemaphores.at(this->idx % this->postCopySemaphores.size());
auto& pcs = this->postCopySemaphores.at(this->idx % this->postCopySemaphores.size());
auto& destinationImage = this->destinationImages.at(i);
auto& pass = this->passes.at(i);
@ -243,8 +252,8 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
}
const std::vector<VkSemaphore> signalSemaphores{
postCopySemaphores.first.handle(),
postCopySemaphores.second.handle()
pcs.first.handle(),
pcs.second.handle()
};
cmdbuf.end(vk);
@ -259,7 +268,7 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pNext = i ? nullptr : next_chain,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &postCopySemaphores.first.handle(),
.pWaitSemaphores = &pcs.first.handle(),
.swapchainCount = 1,
.pSwapchains = &swapchain,
.pImageIndices = &aqImageIdx,

View file

@ -42,7 +42,7 @@ namespace lsfgvk::layer {
/// @param backend lsfg-vk backend instance
/// @param profile active game profile
/// @param info swapchain info
Swapchain(const vk::Vulkan& vk, lsfgvk::Instance& backend,
Swapchain(const vk::Vulkan& vk, lsfgvk::backend::Instance& backend,
GameConf profile, SwapchainInfo info);
/// present a frame
@ -70,8 +70,8 @@ namespace lsfgvk::layer {
std::vector<RenderPass> passes;
std::vector<std::pair<vk::Semaphore, vk::Semaphore>> postCopySemaphores;
ls::R<lsfgvk::Instance> instance;
ls::owned_ptr<ls::R<lsfgvk::Context>> ctx;
ls::R<lsfgvk::backend::Instance> instance;
ls::owned_ptr<ls::R<lsfgvk::backend::Context>> ctx;
size_t idx{1};
size_t fidx{0}; // real frame index

View file

@ -86,19 +86,20 @@ namespace {
throw ls::vulkan_error(res, "vkCreateInstance() failed");
}
);
instance_info = new InstanceInfo{
.handle = *instance,
.funcs = vk::initVulkanInstanceFuncs(*instance, layer_info->GetInstanceProcAddr, true),
.devices = {}
};
return VK_SUCCESS;
} catch (const ls::vulkan_error& e) {
if (e.error() == VK_ERROR_EXTENSION_NOT_PRESENT)
std::cerr << "lsfg-vk: required Vulkan instance extensions are not present. "
"Your GPU driver is not supported.\n";
return e.error();
}
instance_info = new InstanceInfo{
.handle = *instance,
.funcs = vk::initVulkanInstanceFuncs(*instance, layer_info->GetInstanceProcAddr, true),
.devices = {}
};
return VK_SUCCESS;
}
// create device

View file

@ -23,7 +23,7 @@ set_target_properties(lsfg-vk-ui PROPERTIES
AUTOMOC ON
AUTOUIC ON)
add_compile_options(
target_compile_options(lsfg-vk-ui PRIVATE
-Wno-ctad-maybe-unsupported
-Wno-unsafe-buffer-usage-in-libc-call
-Wno-global-constructors)