extract shaders from Lossless.dll

This commit is contained in:
PancakeTAS 2025-07-04 13:32:41 +02:00
parent 11778e507f
commit b34f66e38d
No known key found for this signature in database
34 changed files with 544 additions and 97 deletions

1
.gitattributes vendored
View file

@ -1,4 +1,3 @@
*.cpp diff=cpp eol=lf
*.hpp diff=cpp eol=lf
*.md diff=markdown eol=lf
*.cs binary

3
.gitignore vendored
View file

@ -6,6 +6,3 @@
/.clangd
/.cache
/.ccls
# private resources
/rsc

View file

@ -5,7 +5,6 @@ cmake_minimum_required(VERSION 3.29)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_CLANG_TIDY clang-tidy)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -30,6 +29,8 @@ target_include_directories(lsfg-vk
PRIVATE include)
target_link_libraries(lsfg-vk
PRIVATE lsfg-vk-gen vulkan)
set_target_properties(lsfg-vk
PROPERTIES CXX_CLANG_TIDY clang-tidy)
target_compile_options(lsfg-vk PRIVATE
-Weverything
# disable compat c++ flags
@ -47,4 +48,6 @@ target_compile_options(lsfg-vk PRIVATE
-Wno-global-constructors # allow globals
# required for vulkan
-Wno-cast-function-type-strict
# required for dxvk (yeah don't worry about it)
-Qunused-arguments -Wl,--unresolved-symbols=ignore-all
)

View file

@ -1,3 +1,68 @@
# dxvk subproject
include(ExternalProject)
ExternalProject_Add(dxvk_git
PREFIX ${CMAKE_BINARY_DIR}/dxvk
GIT_REPOSITORY "https://github.com/doitsujin/dxvk"
GIT_TAG "v2.6.2"
UPDATE_DISCONNECTED true
USES_TERMINAL_CONFIGURE true
USES_TERMINAL_BUILD true
CONFIGURE_COMMAND
cd ${CMAKE_BINARY_DIR}/dxvk/src/dxvk_git &&
sed -i s/private://
src/dxvk/dxvk_device.h &&
CFLAGS=-w CXXFLAGS=-w CC=clang CXX=clang++ meson setup
--buildtype "release"
--prefix "${CMAKE_BINARY_DIR}/dxvk/native/usr"
--strip
-Dbuild_id=false
--force-fallback-for=libdisplay-info
--wipe
${CMAKE_BINARY_DIR}/dxvk/build
BUILD_COMMAND
cd ${CMAKE_BINARY_DIR}/dxvk &&
ninja -C build install && # sorry cursed lol
echo "clang -shared -o libdxvkinternals.so $(find build/src/{dxbc,wsi,vulkan,dxvk,dxgi,spirv,util}/*.p -type f -name \\*.o)" > archive.sh &&
bash archive.sh
INSTALL_COMMAND ""
)
add_library(dxvk INTERFACE)
add_dependencies(dxvk dxvk_git)
target_link_directories(dxvk
INTERFACE ${CMAKE_BINARY_DIR}/dxvk/native/usr/lib
INTERFACE ${CMAKE_BINARY_DIR}/dxvk)
target_include_directories(dxvk SYSTEM
INTERFACE ${CMAKE_BINARY_DIR}/dxvk/native/usr/include/dxvk
INTERFACE ${CMAKE_BINARY_DIR}/dxvk/src/dxvk_git/src
INTERFACE ${CMAKE_BINARY_DIR}/dxvk/src/dxvk_git/include/spirv/include)
target_link_libraries(dxvk INTERFACE
dxvk_d3d11 dxvk_dxgi display-info dxvkinternals)
# pe-parse subproject
include(FetchContent)
FetchContent_Declare(peparse_git
GIT_REPOSITORY "https://github.com/trailofbits/pe-parse"
GIT_TAG "v2.1.1"
)
FetchContent_MakeAvailable(peparse_git)
add_library(peparse INTERFACE)
add_dependencies(peparse peparse_git)
target_link_directories(peparse
INTERFACE ${peparse_SOURCE_DIR}/pe-parser-library/include)
target_include_directories(peparse SYSTEM
INTERFACE ${peparse_BUILD_DIR})
target_link_libraries(peparse
INTERFACE pe-parse)
# main project
project(lsfg-vk-gen
VERSION 0.0.1
DESCRIPTION "lsfg-vk-gen: LSFG on Linux through Vulkan (backend)"
@ -5,6 +70,7 @@ project(lsfg-vk-gen
file(GLOB BACKEND_SOURCES
"src/core/*.cpp"
"src/pool/*.cpp"
"src/shaderchains/*.cpp"
"src/*.cpp"
)
@ -15,7 +81,9 @@ target_include_directories(lsfg-vk-gen
PRIVATE include
PUBLIC public)
target_link_libraries(lsfg-vk-gen
PUBLIC vulkan)
PUBLIC vulkan peparse crypto dxvk)
set_target_properties(lsfg-vk-gen
PROPERTIES CXX_CLANG_TIDY clang-tidy)
target_compile_options(lsfg-vk-gen PRIVATE
-Weverything
# disable compat c++ flags
@ -33,4 +101,8 @@ target_compile_options(lsfg-vk-gen PRIVATE
-Wno-global-constructors
# required for vulkan
-Wno-cast-function-type-strict
# required for peparse
-Wno-unused-template
# required for dxvk (yeah don't worry about it)
-Qunused-arguments -Wl,--unresolved-symbols=ignore-all
)

View file

@ -1,6 +1,7 @@
#ifndef CONTEXT_HPP
#define CONTEXT_HPP
#include "pool/shaderpool.hpp"
#include "core/commandbuffer.hpp"
#include "core/commandpool.hpp"
#include "core/descriptorpool.hpp"
@ -29,6 +30,7 @@ namespace LSFG {
/// Create a generator instance.
///
/// @param device The Vulkan device to use.
/// @param shaderpool The shader pool 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.
@ -37,7 +39,8 @@ namespace LSFG {
///
/// @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,
Context(const Core::Device& device, Pool::ShaderPool& shaderpool,
uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN);
///

View file

@ -6,7 +6,6 @@
#include <vulkan/vulkan_core.h>
#include <utility>
#include <string>
#include <vector>
#include <memory>
@ -25,13 +24,12 @@ namespace LSFG::Core {
/// Create the shader module.
///
/// @param device Vulkan device
/// @param path Path to the shader file.
/// @param code SPIR-V bytecode for the shader.
/// @param descriptorTypes Descriptor types used in the shader.
///
/// @throws std::system_error if the shader file cannot be opened or read.
/// @throws LSFG::vulkan_error if object creation fails.
///
ShaderModule(const Core::Device& device, const std::string& path,
ShaderModule(const Core::Device& device, const std::vector<uint8_t>& code,
const std::vector<std::pair<size_t, VkDescriptorType>>& descriptorTypes);
/// Get the Vulkan handle.

View file

@ -0,0 +1,86 @@
#ifndef RESOURCES_HPP
#define RESOURCES_HPP
#include <dxbc/dxbc_options.h>
#include <d3d11.h>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
namespace LSFG::Pool {
///
/// DLL resource extractor class.
///
class Extractor {
public:
Extractor() noexcept = default;
///
/// Create a new extractor.
///
/// @param path Path to the DLL file.
///
/// @throws std::runtime_error if the file cannot be parsed.
///
Extractor(const std::string& path);
///
/// Get a resource by its hash.
///
/// @param hash Hash of the resource.
/// @return Resource data
///
/// @throws std::runtime_error if the resource is not found.
///
[[nodiscard]] std::vector<uint8_t> getResource(const std::string& hash) const;
// Trivially copyable, moveable and destructible
Extractor(const Extractor&) = delete;
Extractor& operator=(const Extractor&) = delete;
Extractor(Extractor&&) = default;
Extractor& operator=(Extractor&&) = default;
~Extractor() = default;
private:
std::unordered_map<std::string, std::vector<uint8_t>> resources;
};
///
/// DirectX bytecode translator class.
///
class Translator {
public:
///
/// Create a new translator.
///
/// @throws std::runtime_error if the initialization fails.
///
Translator();
///
/// Translate DXBC into SPIR-V.
///
/// @param dxbc Bytecode to translate.
/// @return Translated SPIR-V bytecode.
///
/// @throws std::runtime_error if the translation fails.
///
[[nodiscard]] std::vector<uint8_t> translate(const std::vector<uint8_t>& dxbc) const;
// Trivially copyable, moveable and destructible
Translator(const Translator&) = delete;
Translator& operator=(const Translator&) = delete;
Translator(Translator&&) = default;
Translator& operator=(Translator&&) = default;
~Translator() = default;
private:
std::shared_ptr<ID3D11Device*> device;
std::shared_ptr<ID3D11DeviceContext*> context;
};
}
#endif // RESOURCES_HPP

View file

@ -0,0 +1,48 @@
#ifndef SHADERPOOL_HPP
#define SHADERPOOL_HPP
#include "core/device.hpp"
#include "core/shadermodule.hpp"
#include <string>
#include <unordered_map>
namespace LSFG::Pool {
///
/// Shader pool for each Vulkan device.
///
class ShaderPool {
public:
ShaderPool() noexcept = default;
///
/// Create the shader pool.
///
/// @param path Path to the shader dll
///
/// @throws std::runtime_error if the shader pool cannot be created.
///
ShaderPool(const std::string& path);
///
/// Retrieve a shader module by name or create it.
///
/// @param device Vulkan device
/// @param name Name of the shader module
/// @param types Descriptor types for the shader module
/// @return Shader module or empty
///
/// @throws LSFG::vulkan_error if the shader module cannot be created.
///
Core::ShaderModule getShader(
const Core::Device& device, const std::string& name,
const std::vector<std::pair<size_t, VkDescriptorType>>& types);
private:
std::unordered_map<std::string, std::vector<uint8_t>> shaderBytecodes;
std::unordered_map<std::string, Core::ShaderModule> shaders;
};
}
#endif // SHADERPOOL_HPP

View file

@ -1,6 +1,7 @@
#ifndef ALPHA_HPP
#define ALPHA_HPP
#include "pool/shaderpool.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
#include "core/descriptorset.hpp"
@ -26,12 +27,14 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to allocate in.
/// @param inImg The input image to process
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Alpha(const Core::Device& device, const Core::DescriptorPool& pool,
Alpha(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg);
///

View file

@ -1,6 +1,7 @@
#ifndef BETA_HPP
#define BETA_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -28,6 +29,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to allocate in.
/// @param inImgs_0 The next input images to process (when fc % 3 == 0)
/// @param inImgs_1 The prev input images to process (when fc % 3 == 0)
@ -36,7 +38,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Beta(const Core::Device& device, const Core::DescriptorPool& pool,
Beta(const Core::Device& device, Pool::ShaderPool& shaderpool,
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,

View file

@ -1,6 +1,7 @@
#ifndef DELTA_HPP
#define DELTA_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -28,6 +29,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to allocate in.
/// @param inImgs The input images to process.
/// @param optImg An optional additional input from the previous pass.
@ -35,7 +37,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Delta(const Core::Device& device, const Core::DescriptorPool& pool,
Delta(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
std::array<Core::Image, 2> inImgs,
std::optional<Core::Image> optImg,
size_t genc);

View file

@ -1,6 +1,7 @@
#ifndef DOWNSAMPLE_HPP
#define DOWNSAMPLE_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -27,6 +28,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to allocate in.
/// @param inImg_0 The next full image to downsample (when fc % 2 == 0)
/// @param inImg_1 The next full image to downsample (when fc % 2 == 1)
@ -34,7 +36,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Downsample(const Core::Device& device, const Core::DescriptorPool& pool,
Downsample(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg_0, Core::Image inImg_1,
size_t genc);

View file

@ -1,6 +1,7 @@
#ifndef EPSILON_HPP
#define EPSILON_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -28,6 +29,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to use for descriptor sets.
/// @param inImgs1 The first set of input images to process.
/// @param inImg2 The second type image to process.
@ -36,7 +38,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
Epsilon(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
std::optional<Core::Image> optImg,

View file

@ -1,6 +1,7 @@
#ifndef EXTRACT_HPP
#define EXTRACT_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -26,6 +27,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to use for descriptor sets.
/// @param inImg1 The first set of input images to process.
/// @param inImg2 The second type image to process.
@ -34,7 +36,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Extract(const Core::Device& device, const Core::DescriptorPool& pool,
Extract(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg1,
Core::Image inImg2,
VkExtent2D outExtent,

View file

@ -1,6 +1,7 @@
#ifndef GAMMA_HPP
#define GAMMA_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -30,6 +31,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to allocate in.
/// @param inImgs1_0 The next input images to process (when fc % 3 == 0).
/// @param inImgs1_1 The prev input images to process (when fc % 3 == 0).
@ -42,7 +44,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
Gamma(const Core::Device& device, Pool::ShaderPool& shaderpool,
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,

View file

@ -1,6 +1,7 @@
#ifndef MAGIC_HPP
#define MAGIC_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -28,6 +29,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to use for descriptor sets.
/// @param inImgs1_0 The next input images to process (when fc % 3 == 0).
/// @param inImgs1_1 The prev input images to process (when fc % 3 == 0).
@ -39,7 +41,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Magic(const Core::Device& device, const Core::DescriptorPool& pool,
Magic(const Core::Device& device, Pool::ShaderPool& shaderpool,
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,

View file

@ -1,6 +1,7 @@
#ifndef MERGE_HPP
#define MERGE_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -28,6 +29,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to use for descriptor sets.
/// @param inImg1 The prev full image when fc % 2 == 0
/// @param inImg2 The next full image when fc % 2 == 0
@ -39,7 +41,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Merge(const Core::Device& device, const Core::DescriptorPool& pool,
Merge(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg1,
Core::Image inImg2,
Core::Image inImg3,

View file

@ -1,6 +1,7 @@
#ifndef ZETA_HPP
#define ZETA_HPP
#include "pool/shaderpool.hpp"
#include "core/buffer.hpp"
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
@ -28,6 +29,7 @@ namespace LSFG::Shaderchains {
/// Initialize the shaderchain.
///
/// @param device The Vulkan device to create the resources on.
/// @param shaderpool The shader pool to use for shader modules.
/// @param pool The descriptor pool to use for descriptor sets.
/// @param inImgs1 The first set of input images to process.
/// @param inImg2 The second type image to process.
@ -36,7 +38,8 @@ namespace LSFG::Shaderchains {
///
/// @throws LSFG::vulkan_error if resource creation fails.
///
Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
Zeta(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
Core::Image inImg3,

View file

@ -1,6 +1,7 @@
#include "context.hpp"
#include "core/fence.hpp"
#include "core/semaphore.hpp"
#include "pool/shaderpool.hpp"
#include "lsfg.hpp"
#include <vulkan/vulkan_core.h>
@ -10,7 +11,8 @@
using namespace LSFG;
Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1,
Context::Context(const Core::Device& device, Pool::ShaderPool& shaderpool,
uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN) {
// import images
this->inImg_0 = Core::Image(device, { width, height },
@ -35,18 +37,18 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
}
// create shader chains
this->downsampleChain = Shaderchains::Downsample(device, this->descPool,
this->downsampleChain = Shaderchains::Downsample(device, shaderpool, this->descPool,
this->inImg_0, this->inImg_1, outN.size());
for (size_t i = 0; i < 7; i++)
this->alphaChains.at(i) = Shaderchains::Alpha(device, this->descPool,
this->alphaChains.at(i) = Shaderchains::Alpha(device, shaderpool, this->descPool,
this->downsampleChain.getOutImages().at(i));
this->betaChain = Shaderchains::Beta(device, this->descPool,
this->betaChain = Shaderchains::Beta(device, shaderpool, this->descPool,
this->alphaChains.at(0).getOutImages0(),
this->alphaChains.at(0).getOutImages1(),
this->alphaChains.at(0).getOutImages2(), outN.size());
for (size_t i = 0; i < 7; i++) {
if (i < 4) {
this->gammaChains.at(i) = Shaderchains::Gamma(device, this->descPool,
this->gammaChains.at(i) = Shaderchains::Gamma(device, shaderpool, this->descPool,
this->alphaChains.at(6 - i).getOutImages0(),
this->alphaChains.at(6 - i).getOutImages1(),
this->alphaChains.at(6 - i).getOutImages2(),
@ -59,7 +61,7 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
outN.size()
);
} else {
this->magicChains.at(i - 4) = Shaderchains::Magic(device, this->descPool,
this->magicChains.at(i - 4) = Shaderchains::Magic(device, shaderpool, this->descPool,
this->alphaChains.at(6 - i).getOutImages0(),
this->alphaChains.at(6 - i).getOutImages1(),
this->alphaChains.at(6 - i).getOutImages2(),
@ -70,20 +72,20 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
i == 4 ? std::nullopt : std::optional{this->epsilonChains.at(i - 5).getOutImage()},
outN.size()
);
this->deltaChains.at(i - 4) = Shaderchains::Delta(device, this->descPool,
this->deltaChains.at(i - 4) = Shaderchains::Delta(device, shaderpool, this->descPool,
this->magicChains.at(i - 4).getOutImages1(),
i == 4 ? std::nullopt
: std::optional{this->deltaChains.at(i - 5).getOutImage()},
outN.size()
);
this->epsilonChains.at(i - 4) = Shaderchains::Epsilon(device, this->descPool,
this->epsilonChains.at(i - 4) = Shaderchains::Epsilon(device, shaderpool, 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()},
outN.size()
);
this->zetaChains.at(i - 4) = Shaderchains::Zeta(device, this->descPool,
this->zetaChains.at(i - 4) = Shaderchains::Zeta(device, shaderpool, this->descPool,
this->magicChains.at(i - 4).getOutImages3(),
i == 4 ? this->gammaChains.at(i - 1).getOutImage1()
: this->zetaChains.at(i - 5).getOutImage(),
@ -92,7 +94,7 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
);
if (i >= 6)
continue; // no extract for i >= 6
this->extractChains.at(i - 4) = Shaderchains::Extract(device, this->descPool,
this->extractChains.at(i - 4) = Shaderchains::Extract(device, shaderpool, this->descPool,
this->zetaChains.at(i - 4).getOutImage(),
this->epsilonChains.at(i - 4).getOutImage(),
this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent(),
@ -100,7 +102,7 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
);
}
}
this->mergeChain = Shaderchains::Merge(device, this->descPool,
this->mergeChain = Shaderchains::Merge(device, shaderpool, this->descPool,
this->inImg_1,
this->inImg_0,
this->zetaChains.at(2).getOutImage(),

View file

@ -1,26 +1,10 @@
#include "core/shadermodule.hpp"
#include "lsfg.hpp"
#include <fstream>
using namespace LSFG::Core;
ShaderModule::ShaderModule(const Core::Device& device, const std::string& path,
ShaderModule::ShaderModule(const Core::Device& device, const std::vector<uint8_t>& code,
const std::vector<std::pair<size_t, VkDescriptorType>>& descriptorTypes) {
// read shader bytecode
std::ifstream file(path, std::ios::ate | std::ios::binary);
if (!file)
throw std::system_error(errno, std::generic_category(), "Failed to open shader file: " + path);
const std::streamsize size = file.tellg();
std::vector<uint8_t> code(static_cast<size_t>(size));
file.seekg(0, std::ios::beg);
if (!file.read(reinterpret_cast<char*>(code.data()), size))
throw std::system_error(errno, std::generic_category(), "Failed to read shader file: " + path);
file.close();
// create shader module
const uint8_t* data_ptr = code.data();
const VkShaderModuleCreateInfo createInfo{

View file

@ -2,10 +2,13 @@
#include "core/device.hpp"
#include "core/instance.hpp"
#include "context.hpp"
#include "pool/shaderpool.hpp"
#include "utils.hpp"
#include <cstdlib>
#include <ctime>
#include <optional>
#include <string>
#include <unordered_map>
using namespace LSFG;
@ -13,6 +16,7 @@ using namespace LSFG;
namespace {
std::optional<Core::Instance> instance;
std::optional<Core::Device> device;
std::optional<Pool::ShaderPool> pool;
std::unordered_map<int32_t, Context> contexts;
}
@ -20,8 +24,12 @@ void LSFG::initialize() {
if (instance.has_value() || device.has_value())
return;
char* dllPath = getenv("LSFG_DLL_PATH");
const std::string dllPathStr = dllPath ? std::string(dllPath) : "Lossless.dll";
instance.emplace();
device.emplace(*instance);
pool.emplace(dllPathStr);
Globals::initializeGlobals(*device);
@ -30,16 +38,16 @@ void LSFG::initialize() {
int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1,
const std::vector<int>& outN) {
if (!instance.has_value() || !device.has_value())
if (!instance.has_value() || !device.has_value() || !pool.has_value())
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
auto id = std::rand();
contexts.emplace(id, Context(*device, width, height, in0, in1, outN));
contexts.emplace(id, Context(*device, *pool, width, height, in0, in1, outN));
return id;
}
void LSFG::presentContext(int32_t id, int inSem, const std::vector<int>& outSem) {
if (!instance.has_value() || !device.has_value())
if (!instance.has_value() || !device.has_value() || !pool.has_value())
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
auto it = contexts.find(id);
@ -51,7 +59,7 @@ void LSFG::presentContext(int32_t id, int inSem, const std::vector<int>& outSem)
}
void LSFG::deleteContext(int32_t id) {
if (!instance.has_value() || !device.has_value())
if (!instance.has_value() || !device.has_value() || !pool.has_value())
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
auto it = contexts.find(id);
@ -63,12 +71,13 @@ void LSFG::deleteContext(int32_t id) {
}
void LSFG::finalize() {
if (!instance.has_value() || !device.has_value())
if (!instance.has_value() || !device.has_value() || !pool.has_value())
return;
Globals::uninitializeGlobals();
vkDeviceWaitIdle(device->handle());
pool.reset();
device.reset();
instance.reset();
}

View file

@ -0,0 +1,127 @@
#include "pool/extract.hpp"
#include <d3d11/d3d11_device.h>
#include <d3d11.h>
#include <dxbc/dxbc_reader.h>
#include <dxvk/dxvk_compute.h>
#include <dxvk/dxvk_context.h>
#include <dxvk/dxvk_pipelayout.h>
#include <dxvk/dxvk_shader.h>
#include <pe-parse/parse.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <array>
#include <algorithm>
#include <stdexcept>
#include <vector>
using namespace LSFG::Pool;
namespace {
using ResourceMap = std::unordered_map<std::string, std::vector<uint8_t>>;
/// Callback function for each resource.
int on_resource(void* data, const peparse::resource& res) {
if (res.type != peparse::RT_RCDATA || res.buf == nullptr || res.buf->bufLen <= 0)
return 0;
// hash the resource data
std::array<uint8_t, SHA256_DIGEST_LENGTH> hash{};
SHA256(res.buf->buf, res.buf->bufLen, hash.data());
std::array<uint8_t, SHA256_DIGEST_LENGTH * 2 + 1> base64{};
const int base64_len = EVP_EncodeBlock(base64.data(), hash.data(), hash.size());
const std::string hash_str(reinterpret_cast<const char*>(base64.data()),
static_cast<size_t>(base64_len));
// store the resource
std::vector<uint8_t> resource_data(res.buf->bufLen);
std::copy_n(res.buf->buf, res.buf->bufLen, resource_data.data());
auto* map = reinterpret_cast<ResourceMap*>(data);
(*map)[hash_str] = resource_data;
return 0;
}
}
Extractor::Extractor(const std::string& path) {
peparse::parsed_pe* pe = peparse::ParsePEFromFile(path.c_str());
if (!pe)
throw std::runtime_error("Unable to parse PE file: " + path);
peparse::IterRsrc(pe, on_resource, &this->resources);
peparse::DestructParsedPE(pe);
}
std::vector<uint8_t> Extractor::getResource(const std::string& hash) const {
auto it = this->resources.find(hash);
if (it != this->resources.end())
return it->second;
throw std::runtime_error("Resource not found: " + hash);
}
Translator::Translator() {
setenv("DXVK_WSI_DRIVER", "SDL3", 0);
setenv("DXVK_LOG_LEVEL", "error", 0);
setenv("DXVK_LOG_PATH", "none", 0);
// create d3d11 device
ID3D11Device* device{};
ID3D11DeviceContext* context{};
const D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_1;
D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE::D3D_DRIVER_TYPE_HARDWARE,
nullptr,
0,
&featureLevel, 1,
D3D11_SDK_VERSION,
&device, nullptr, &context
);
if (!device || !context)
throw std::runtime_error("Failed to create D3D11 device");
// store device in shared ptr
this->device = std::shared_ptr<ID3D11Device*>(
new ID3D11Device*(device),
[](ID3D11Device** dev) {
(*dev)->Release();
}
);
this->context = std::shared_ptr<ID3D11DeviceContext*>(
new ID3D11DeviceContext*(context),
[](ID3D11DeviceContext** ctx) {
(*ctx)->Release();
}
);
}
std::vector<uint8_t> Translator::translate(const std::vector<uint8_t>& dxbc) const {
// create compute shader and pipeline
ID3D11ComputeShader* shader = nullptr;
(*this->device)->CreateComputeShader(dxbc.data(), dxbc.size(), nullptr, &shader);
if (!shader)
throw std::runtime_error("Failed to create compute shader from DXBC");
auto* dxvk_shader = reinterpret_cast<dxvk::D3D11ComputeShader*>(shader);
auto* dxvk_device = reinterpret_cast<dxvk::D3D11Device*>(*this->device);
auto* pipeline = dxvk_device->GetDXVKDevice()->m_objects.pipelineManager().createComputePipeline({
.cs = dxvk_shader->GetCommonShader()->GetShader()
});
// extract spir-v from d3d11 shader
auto code = dxvk_shader->GetCommonShader()->GetShader()->getCode(
pipeline->getBindings(), dxvk::DxvkShaderModuleCreateInfo());
std::vector<uint8_t> spirv(code.size());
std::copy_n(reinterpret_cast<uint8_t*>(code.data()),
code.size(), spirv.data());
// cleanup-ish (i think the pipeline will linger)
shader->Release();
return spirv;
}

View file

@ -0,0 +1,76 @@
#include "pool/shaderpool.hpp"
#include "pool/extract.hpp"
using namespace LSFG;
using namespace LSFG::Pool;
const std::unordered_map<std::string, std::string> SHADERS = {
{ "alpha/0.spv", "lilEUr7nBgA8P6VSqCms09t9b+DZH6dVlcefVuFHlc8=" },
{ "alpha/1.spv", "2TRNidol3BNs/aeLl2/Om7z8bAlpehkOPVtmMao1q84=" },
{ "alpha/2.spv", "tP6qIJZhd4pGr1pop1e9ztW1gwp97ufQa2GaBZBYZJE=" },
{ "alpha/3.spv", "gA4ZejNp+RwtqjtTzGdGf5D/CjSGlwFB2nOgDAIv91k=" },
{ "beta/0.spv", "uQ/xsBMKRuJhbxstBukWMhXYuppPAYygxkb/3kNu4vI=" },
{ "beta/1.spv", "BUbrL9fZREXLlg1lmlTYD6n8DwpzHkho5bI3RLbfNJg=" },
{ "beta/2.spv", "bz0lxQjMYp6HLqw12X3jfV7H0SOZKrqUhgtw17WgTx4=" },
{ "beta/3.spv", "JA5/8p7yiiiCxmuiTsOR9Fb/z1qp8KlyU2wo9Wfpbcc=" },
{ "beta/4.spv", "/I+iYEwzOFylXZJWWNQ/oUT6SeLVnpotNXGV8y/FUVk=" },
{ "delta/0.spv", "gtBWy1WtP8NO+Z1sSPMgOJ75NaPEKvthc7imNGzJkGI=" },
{ "delta/1.spv", "JiqZZIoHay/uS1ptzlz3EWKUPct/jQHoFtN0qlEtVUU=" },
{ "delta/2.spv", "zkBa37GvAG8izeIv4o/3OowpxiobfOdNmPyVWl2BSWY=" },
{ "delta/3.spv", "neIMl/PCPonXqjtZykMb9tR4yW7JkZfMTqZPGOmJQUg=" },
{ "downsample.spv", "F9BppS+ytDjO3aoMEY7deMzLaSUhX8EuI+eH8654Fpw=" },
{ "epsilon/0.spv", "YHECg9LrgTCM8lABFOXkC5qTKoHsIMWnZ6ST3dexD08=" },
{ "epsilon/1.spv", "Uv7CfTi6x69c9Exuc16UqA7fvLTUGicHZVi5jhHKo0w=" },
{ "epsilon/2.spv", "0vmxxGRa6gbl5dqmKTBO9x/ZM2oEUJ5JtGfqcHhvouQ=" },
{ "epsilon/3.spv", "Sa/gkbCCDyCyUh8BSOa882t4qDc51oeP6+Kj3O3EaxM=" },
{ "extract.spv", "xKUdoEwFJDsc/kX/aY1FyzlMlOaJX4iHQLlthe2MvBs=" },
{ "gamma/0.spv", "AJuuF/X9NnypgBd89GbXMKcXC2meysYayiZQZwu3WhU=" },
{ "gamma/1.spv", "LLr/3D+whLd6XuKkBS7rlaNN+r8qB/Khr4ii+M7KSxY=" },
{ "gamma/2.spv", "KjHXdawBR8AMK7Kud/vXJmJTddXFKppREEpsykjwZDc=" },
{ "gamma/3.spv", "zAnAC73i76AJjv0o1To3bBu2jnIWXzX3NlSMvU3Lgxw=" },
{ "gamma/4.spv", "ivQ7ltprazBOXb46yxul9HJ5ByJk2LbG034cC6NkEpk=" },
{ "gamma/5.spv", "lHYgyCpWnMIB74HL22BKQyoqUGvUjgR79W4vXFXzXe4=" },
{ "magic.spv", "ZdoTjEhrlbAxq0MtaJyk6jQ5+hrySEsnvn+jseukAuI=" },
{ "merge.spv", "dnluf4IHKNaqz6WvH7qodn+fZ56ORx+w3MUOwH7huok=" },
{ "zeta/0.spv", "LLr/3D+whLd6XuKkBS7rlaNN+r8qB/Khr4ii+M7KSxY=" },
{ "zeta/1.spv", "KjHXdawBR8AMK7Kud/vXJmJTddXFKppREEpsykjwZDc=" },
{ "zeta/2.spv", "zAnAC73i76AJjv0o1To3bBu2jnIWXzX3NlSMvU3Lgxw=" },
{ "zeta/3.spv", "ivQ7ltprazBOXb46yxul9HJ5ByJk2LbG034cC6NkEpk=" },
{ "zeta/4.spv", "lHYgyCpWnMIB74HL22BKQyoqUGvUjgR79W4vXFXzXe4=" }
};
ShaderPool::ShaderPool(const std::string& path) {
const Extractor extractor(path);
const Translator translator;
for (const auto& [name, hash] : SHADERS) {
auto data = extractor.getResource(hash);
if (data.empty())
throw std::runtime_error("Shader code is empty: " + name);
auto code = translator.translate(data);
if (code.empty())
throw std::runtime_error("Shader code translation failed: " + name);
shaderBytecodes[name] = std::move(code);
}
}
Core::ShaderModule ShaderPool::getShader(
const Core::Device& device, const std::string& name,
const std::vector<std::pair<size_t, VkDescriptorType>>& types) {
auto it = shaders.find(name);
if (it != shaders.end())
return it->second;
// create the shader module
auto cit = shaderBytecodes.find(name);
if (cit == shaderBytecodes.end())
throw std::runtime_error("Shader code translation failed: " + name);
auto code = cit->second;
Core::ShaderModule shader(device, code, types);
shaders[name] = shader;
return shader;
}

View file

@ -3,23 +3,24 @@
using namespace LSFG::Shaderchains;
Alpha::Alpha(const Core::Device& device, const Core::DescriptorPool& pool,
Alpha::Alpha(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg)
: inImg(std::move(inImg)) {
this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/alpha/0.spv",
shaderpool.getShader(device, "alpha/0.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/alpha/1.spv",
shaderpool.getShader(device, "alpha/1.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/alpha/2.spv",
shaderpool.getShader(device, "alpha/2.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/alpha/3.spv",
shaderpool.getShader(device, "alpha/3.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } })

View file

@ -3,7 +3,8 @@
using namespace LSFG::Shaderchains;
Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool,
Beta::Beta(const Core::Device& device, Pool::ShaderPool& shaderpool,
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,
@ -12,23 +13,23 @@ Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool,
inImgs_1(std::move(inImgs_1)),
inImgs_2(std::move(inImgs_2)) {
this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/beta/0.spv",
shaderpool.getShader(device, "beta/0.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 8+4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/beta/1.spv",
shaderpool.getShader(device, "beta/1.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/beta/2.spv",
shaderpool.getShader(device, "beta/2.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/beta/3.spv",
shaderpool.getShader(device, "beta/3.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/beta/4.spv",
shaderpool.getShader(device, "beta/4.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 6, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,26 +3,27 @@
using namespace LSFG::Shaderchains;
Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool,
Delta::Delta(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
std::array<Core::Image, 2> inImgs,
std::optional<Core::Image> optImg,
size_t genc)
: inImgs(std::move(inImgs)),
optImg(std::move(optImg)) {
this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/delta/0.spv",
shaderpool.getShader(device, "delta/0.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/delta/1.spv",
shaderpool.getShader(device, "delta/1.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/delta/2.spv",
shaderpool.getShader(device, "delta/2.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/delta/3.spv",
shaderpool.getShader(device, "delta/3.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,12 +3,13 @@
using namespace LSFG::Shaderchains;
Downsample::Downsample(const Core::Device& device, const Core::DescriptorPool& pool,
Downsample::Downsample(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg_0, Core::Image inImg_1,
size_t genc)
: inImg_0(std::move(inImg_0)),
inImg_1(std::move(inImg_1)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/downsample.spv",
this->shaderModule = shaderpool.getShader(device, "downsample.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,7 +3,8 @@
using namespace LSFG::Shaderchains;
Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
Epsilon::Epsilon(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
std::optional<Core::Image> optImg,
@ -12,19 +13,19 @@ Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool,
inImg2(std::move(inImg2)),
optImg(std::move(optImg)) {
this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/epsilon/0.spv",
shaderpool.getShader(device, "epsilon/0.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/epsilon/1.spv",
shaderpool.getShader(device, "epsilon/1.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/epsilon/2.spv",
shaderpool.getShader(device, "epsilon/2.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/epsilon/3.spv",
shaderpool.getShader(device, "epsilon/3.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,14 +3,15 @@
using namespace LSFG::Shaderchains;
Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool,
Extract::Extract(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg1,
Core::Image inImg2,
VkExtent2D outExtent,
size_t genc)
: inImg1(std::move(inImg1)),
inImg2(std::move(inImg2)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/extract.spv",
this->shaderModule = shaderpool.getShader(device, "extract.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,7 +3,8 @@
using namespace LSFG::Shaderchains;
Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
Gamma::Gamma(const Core::Device& device, Pool::ShaderPool& shaderpool,
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,
@ -18,29 +19,29 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool,
inImg2(std::move(inImg2)),
optImg2(std::move(optImg2)) {
this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/gamma/0.spv",
shaderpool.getShader(device, "gamma/0.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 10, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 3, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }),
Core::ShaderModule(device, "rsc/shaders/gamma/1.spv",
shaderpool.getShader(device, "gamma/1.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/gamma/2.spv",
shaderpool.getShader(device, "gamma/2.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/gamma/3.spv",
shaderpool.getShader(device, "gamma/3.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/gamma/4.spv",
shaderpool.getShader(device, "gamma/4.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }),
Core::ShaderModule(device, "rsc/shaders/gamma/5.spv",
shaderpool.getShader(device, "gamma/5.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 2, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,7 +3,8 @@
using namespace LSFG::Shaderchains;
Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool,
Magic::Magic(const Core::Device& device, Pool::ShaderPool& shaderpool,
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,
@ -16,7 +17,7 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool,
inImgs1_2(std::move(inImgs1_2)),
inImg2(std::move(inImg2)), inImg3(std::move(inImg3)),
optImg(std::move(optImg)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/magic.spv",
this->shaderModule = shaderpool.getShader(device, "magic.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4+4+2+1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 3+3+2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,7 +3,8 @@
using namespace LSFG::Shaderchains;
Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
Merge::Merge(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
Core::Image inImg1,
Core::Image inImg2,
Core::Image inImg3,
@ -16,7 +17,7 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
inImg3(std::move(inImg3)),
inImg4(std::move(inImg4)),
inImg5(std::move(inImg5)) {
this->shaderModule = Core::ShaderModule(device, "rsc/shaders/merge.spv",
this->shaderModule = shaderpool.getShader(device, "merge.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 5, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -3,7 +3,8 @@
using namespace LSFG::Shaderchains;
Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
Zeta::Zeta(const Core::Device& device, Pool::ShaderPool& shaderpool,
const Core::DescriptorPool& pool,
std::array<Core::Image, 3> inImgs1,
Core::Image inImg2,
Core::Image inImg3,
@ -12,19 +13,19 @@ Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool,
inImg2(std::move(inImg2)),
inImg3(std::move(inImg3)) {
this->shaderModules = {{
Core::ShaderModule(device, "rsc/shaders/zeta/0.spv",
shaderpool.getShader(device, "zeta/0.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/zeta/1.spv",
shaderpool.getShader(device, "zeta/1.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/zeta/2.spv",
shaderpool.getShader(device, "zeta/2.spv",
{ { 1, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 4, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE } }),
Core::ShaderModule(device, "rsc/shaders/zeta/3.spv",
shaderpool.getShader(device, "zeta/3.spv",
{ { 2, VK_DESCRIPTOR_TYPE_SAMPLER },
{ 6, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },

View file

@ -21,7 +21,9 @@ namespace {
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
// create lsfg
Loader::DL::disableHooks();
LSFG::initialize();
Loader::DL::enableHooks();
// add extensions
auto extensions = Utils::addExtensions(pCreateInfo->ppEnabledExtensionNames,
@ -70,13 +72,13 @@ namespace {
// store device info
try {
const char* frameGen = std::getenv("LSFG_MULTIPLIER");
if (!frameGen) frameGen = "1";
if (!frameGen) frameGen = "2";
devices.emplace(*pDevice, DeviceInfo {
.device = *pDevice,
.physicalDevice = physicalDevice,
.queue = Utils::findQueue(*pDevice, physicalDevice, &createInfo,
VK_QUEUE_GRAPHICS_BIT),
.frameGen = std::stoul(frameGen)
.frameGen = std::max<size_t>(1, std::stoul(frameGen) - 1)
});
} catch (const std::exception& e) {
Log::error("Failed to create device info: {}", e.what());
@ -133,6 +135,7 @@ namespace {
));
swapchainToDeviceTable.emplace(*pSwapchain, device);
Log::debug("Created swapchain with {} images", imageCount);
} catch (const LSFG::vulkan_error& e) {
Log::error("Encountered Vulkan error {:x} while creating swapchain: {}",
static_cast<uint32_t>(e.error()), e.what());