-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Reshade FX shaders #41
Comments
I can agree that being able to use fx shaders would be great. But it would be a lot of work to get it done, since I am currently shipping spir-v binaries. What would have to be done is:
For that I could take a look how ReShade does that since you guys support vulkan, too. Other problem:
|
In case you are interested in more details: The ReShade FX compiler takes a FX shader as input and produces a SPIR-V binary that can be loaded straight into Vulkan. It also supports transforming uniform variables into specialization constants automatically. The compiler is standalone from the rest of ReShade, so can be implemented pretty easily (has been done before, e.g. for FreeStyle): Basically all that is necessary is to add the ReShade repository as a submodule and then add all Usage then looks something like this: #include "effect_parser.hpp"
#include "effect_codegen.hpp"
#include "effect_preprocessor.hpp"
reshadefx::preprocessor pp;
// pp.add_include_path(...);
// pp.add_macro_definition(...);
if (!pp.append_file(path))
return false;
reshadefx::parser parser;
std::unique_ptr<reshadefx::codegen> codegen(
reshadefx::create_codegen_spirv(true /* vulkan semantics */, false /* debug info */, true /* uniforms to spec constants */));
if (!parser.parse(std::move(pp.output()), codegen.get()))
return false;
reshadefx::module module;
codegen->write_result(module);
// module.spirv <= SPIR-V binary
// module.entry_points <= List of entry point names in the SPIR-V binary (used to select entry point in pipeline create info)
// module.spec_constants <= List of spec constants (name, offset, default value, ...)
// module.techniques <= List of "techniques" aka effects in the file, which in turn has a list of passes which contain state info (to set up pipelines) |
@crosire https://github.com/crosire/reshade/blob/master/tools/fxc.cpp is one simple example how to use it, isn't it? That actually seems to be more straight forward than I hoped for. |
Yes. The full runtime code that shows how all the data in the module is used to render with Vulkan is at https://github.com/crosire/reshade/blob/6c5c510067d9b546be61669c4a6159841a382cef/source/vulkan/runtime_vk.cpp#L612 (that contains other stuff too though, so a bit more complicated to read). The descriptor layout looks like this: |
Well i tried writing a simple program that compiles Fx shaders to spir-v. It was a pain in the ass to even compile and it still needs Also the code used some windows only C functions.
|
The code requires C++17. I compiled it before with Clang and don't remember issues, so am surprised it was such a chore. Took your changes with some fixes in crosire/reshade@ff2e73a, thanks a lot for that. You can skip |
Yeah thanks, I am stupid, now it works. |
@crosire |
On Windows yes, or else file loading for include paths will get messed up for unicode paths. Don't know about Linux. |
@DadSchoorse Thanks! I've addressed this in crosire/reshade@17bc9ca now with a slightly different approach: Using explicit names should fix this as well (tried in Godbolt to make sure). |
@crosire I got a new problem: either the driver or steam's caching system does not like all shaders being in one shader file with multiple entry points. That causes a hang during pipeline creation. I manually translated one effect to 2 glsl files with spirv-cross and then compiled these using glslangValidator and these spirv files do not cause a hang. I am currently searching for a solution, using spirv-cross at runtime would be a little bit silly. |
Mmh. It works under Windows though + is allowed by the spec. I know there was a bug in NVIDIA's OpenGL driver where this caused issues when SPIR-V with multiple entry points was loaded into OpenGL via It would also be possible to extend the compiler to support splitting entry points into multiple modules: The entry points are written to the output SPIR-V module in struct module
{
std::unordered_map<std::string, std::vector<uint32_t>> spirv_modules; // Map from entry point name to SPIR-V module
...
};
...
void write_result(module &module) override
{
...
for (size_t entry_point_index = 0; entry_point_index < module.entry_points.size(); ++entry_point_index)
{
const std::string &entry_point_name = module.entry_points[entry_point_index].name;
std::vector<uint32_t> &spirv = module.spirv_modules[entry_point_name];
// Write SPIRV header info
spirv.push_back(spv::MagicNumber);
spirv.push_back(spv::Version);
spirv.push_back(0u); // Generator magic number, see https://www.khronos.org/registry/spir-v/api/spir-v.xml
spirv.push_back(_next_id); // Maximum ID
spirv.push_back(0u); // Reserved for instruction schema
...
// Current entry point declaration
_entries.instructions[entry_point_index].write(spirv);
// All execution mode declarations
for (const auto &node : _execution_modes.instructions)
node.write(spirv);
...
}
} |
@crosire I don't know what exactly hangs, only that it hangs when calling |
@crosire I have now implemented support for simple fx files (like the cartoon one). I ended up using spirv-cross at runtime because I could not find the cause for the hangs . |
SPIR-V only supports scalar external spec constants (see |
Out of date comment
Test build ReShade FX static library on linuxreshade-linux.patchclick to expand
diff --git a/source/effect_codegen_hlsl.cpp b/source/effect_codegen_hlsl.cpp
index 1398c4c..45ddff4 100644
--- a/source/effect_codegen_hlsl.cpp
+++ b/source/effect_codegen_hlsl.cpp
@@ -271,12 +271,21 @@ private:
return semantic;
}
+ static inline bool _stringcmp(const std::string& a, const std::string& b) {
+ return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });
+ }
+
static std::string escape_name(std::string name)
{
+#ifdef _WIN32
// HLSL compiler complains about "technique" and "pass" names in strict mode (no matter the casing)
if (_stricmp(name.c_str(), "pass") == 0 ||
_stricmp(name.c_str(), "technique") == 0)
name += "_RESERVED";
+#else
+ if (_stringcmp(name, "pass") || _stringcmp(name, "technique"))
+ name += "_RESERVED";
+#endif
return name;
}
diff --git a/source/effect_expression.cpp b/source/effect_expression.cpp
index 48e1747..07b2302 100644
--- a/source/effect_expression.cpp
+++ b/source/effect_expression.cpp
@@ -304,7 +304,7 @@ bool reshadefx::expression::evaluate_constant_expression(reshadefx::tokenid op,
if (rhs.as_float[i] == 0)
constant.as_float[i] = std::numeric_limits<float>::quiet_NaN();
else
- constant.as_float[i] = std::fmodf(constant.as_float[i], rhs.as_float[i]);
+ constant.as_float[i] = std::fmod(constant.as_float[i], rhs.as_float[i]);
}
else if (type.is_signed()) {
for (unsigned int i = 0; i < type.components(); ++i)
diff --git a/source/effect_preprocessor.cpp b/source/effect_preprocessor.cpp
index ee9a7a3..83d6139 100644
--- a/source/effect_preprocessor.cpp
+++ b/source/effect_preprocessor.cpp
@@ -126,7 +126,11 @@ bool reshadefx::preprocessor::append_file(const std::filesystem::path &path)
_success = true; // Clear success flag before parsing a new file
+#ifdef _WIN32
push(std::move(data), path.u8string());
+#else
+ push(std::move(data), path.string());
+#endif
parse();
return _success;
@@ -619,7 +623,11 @@ void reshadefx::preprocessor::parse_include()
if (std::filesystem::exists(filepath = include_path / filename, ec))
break;
+#ifdef _WIN32
const std::string filepath_string = filepath.u8string();
+#else
+ const std::string filepath_string = filepath.string();
+#endif
// Detect recursive include and abort to avoid infinite loop
if (std::find_if(_input_stack.begin(), _input_stack.end(), meson.buildclick to expand
project('ReShade FX', ['cpp'], default_options : ['cpp_std=c++2a'], version : '4.5.2', meson_version : '>= 0.43')
sources = [
'source/effect_codegen_glsl.cpp',
'source/effect_codegen_hlsl.cpp',
'source/effect_codegen_spirv.cpp',
'source/effect_expression.cpp',
'source/effect_lexer.cpp',
'source/effect_parser.cpp',
'source/effect_preprocessor.cpp',
'source/effect_symbol_table.cpp',
]
headers = [
'source/effect_codegen.hpp',
'source/effect_expression.hpp',
'source/effect_lexer.hpp',
'source/effect_module.hpp',
'source/effect_parser.hpp',
'source/effect_preprocessor.hpp',
'source/effect_symbol_table.hpp',
'source/effect_token.hpp',
]
# Static lib
static_library('reshadefx', sources, include_directories: [ '/usr/include/spirv/unified1' ], install: true)
# Headers
install_headers(headers, subdir : 'reshadefx') Buildgit clone https://github.com/crosire/reshade
cd reshade
cp /path/to/meson.build .
patch -p1 < /path/to/reshade-linux.patch
meson build --prefix /tmp/reshade-fx --buildtype=release
cd build
ninja install Use (e.g. on ReshadeFxCompiler)TL;DR: click to expand
diff --git a/src/main.cpp b/src/main.cpp
index 6c09811..7919048 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,3 @@
-#include "../reshade/source/effect_parser.hpp"
-#include "../reshade/source/effect_codegen.hpp"
-#include "../reshade/source/effect_preprocessor.hpp"
#include <climits>
#include <cstdlib>
#include <cassert>
@@ -8,6 +5,11 @@
#include <vector>
#include <fstream>
#include <string>
+
+#include <reshadefx/effect_parser.hpp>
+#include <reshadefx/effect_codegen.hpp>
+#include <reshadefx/effect_preprocessor.hpp>
+
/*
Usage:
ReshadeFxCompiler <shader> -o <outputfile> -I <includepath> -w <widht> -h <height>
diff --git a/src/makefile b/src/makefile
index 973f782..41f6b90 100644
--- a/src/makefile
+++ b/src/makefile
@@ -1,20 +1,18 @@
CXX ?= g++
-CXXFLAGS ?= -O3 -Wall -Wextra -Wno-switch -Wno-missing-field-initializers -Wno-unknown-pragmas -Wno-char-subscripts
+CXXFLAGS ?= -O3 -Wall -Wextra -Wno-missing-field-initializers
CXXFLAGS += -std=c++2a
+CXXFLAGS += -I/tmp/reshade-fx/include -L/tmp/reshade-fx/lib64
LDFLAGS += -lstdc++fs
+LDFLAGS += -lreshadefx
BUILD_DIR := ../build
SRC_FILES := $(wildcard *.cpp)
OBJ_FILES := $(foreach file,$(patsubst %.cpp,%.o,$(SRC_FILES)),$(BUILD_DIR)/$(file))
-RESHADE_SRC := $(wildcard ../reshade/source/effect*.cpp)
-RESHADE_SRC := $(filter-out ../reshade/source/effect_codegen_hlsl.cpp,$(RESHADE_SRC))
-RESHADE_SRC := $(filter-out ../reshade/source/effect_codegen_glsl.cpp,$(RESHADE_SRC))
-RESHADE_OBJ := $(foreach file,$(patsubst %.cpp,%.o,$(notdir $(RESHADE_SRC))),$(BUILD_DIR)/reshade/$(file))
all: $(BUILD_DIR)/ReshadeFxCompiler
-$(BUILD_DIR)/ReshadeFxCompiler: $(OBJ_FILES) $(RESHADE_OBJ)
+$(BUILD_DIR)/ReshadeFxCompiler: $(OBJ_FILES)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)
Note
EDIT: for fxcpatchdiff --git a/tools/fxc.cpp b/tools/fxc.cpp
index c5665ac..86591dc 100644
--- a/tools/fxc.cpp
+++ b/tools/fxc.cpp
@@ -10,6 +10,7 @@
#include <vector>
#include <fstream>
#include <iostream>
+#include <cstring>
static void print_usage(const char *path)
{ version.h (placeholder, should be generated)
Using
|
@crosire equery f dev-util/reshade-fx
* Searching for reshade-fx in dev-util ...
* Contents of dev-util/reshade-fx-4.5.2:
/usr
/usr/include
/usr/include/reshade
/usr/include/reshade/effect_codegen.hpp
/usr/include/reshade/effect_expression.hpp
/usr/include/reshade/effect_lexer.hpp
/usr/include/reshade/effect_module.hpp
/usr/include/reshade/effect_parser.hpp
/usr/include/reshade/effect_preprocessor.hpp
/usr/include/reshade/effect_symbol_table.hpp
/usr/include/reshade/effect_token.hpp
/usr/lib
/usr/lib/libreshade-fx.a
/usr/lib64
/usr/lib64/libreshade-fx.a
/usr/share
/usr/share/doc
/usr/share/doc/reshade-fx-4.5.2
/usr/share/doc/reshade-fx-4.5.2/README.md.bz2 equery f dev-util/reshade-fxc
* Searching for reshade-fxc in dev-util ...
* Contents of dev-util/reshade-fxc-4.5.2:
/usr
/usr/bin
/usr/bin/reshade-fxc
/usr/share
/usr/share/doc
/usr/share/doc/reshade-fxc-4.5.2
/usr/share/doc/reshade-fxc-4.5.2/README.md.bz2 equery f media-libs/vkbasalt
* Searching for vkbasalt in media-libs ...
* Contents of media-libs/vkbasalt-0.2.2:
/usr
/usr/lib
/usr/lib/libVkLayer_vkBasalt.so
/usr/lib64
/usr/lib64/libVkLayer_vkBasalt.so
/usr/share
/usr/share/doc
/usr/share/doc/vkbasalt-0.2.2
/usr/share/doc/vkbasalt-0.2.2/README.md.bz2
/usr/share/vkBasalt
/usr/share/vkBasalt/shader
/usr/share/vkBasalt/shader/cas.frag.spv
/usr/share/vkBasalt/shader/deband.frag.spv
/usr/share/vkBasalt/shader/full_screen_triangle.vert.spv
/usr/share/vkBasalt/shader/fxaa.frag.spv
/usr/share/vkBasalt/shader/lut.frag.spv
/usr/share/vkBasalt/shader/smaa_blend.frag.spv
/usr/share/vkBasalt/shader/smaa_blend.vert.spv
/usr/share/vkBasalt/shader/smaa_edge.vert.spv
/usr/share/vkBasalt/shader/smaa_edge_color.frag.spv
/usr/share/vkBasalt/shader/smaa_edge_luma.frag.spv
/usr/share/vkBasalt/shader/smaa_neighbor.frag.spv
/usr/share/vkBasalt/shader/smaa_neighbor.vert.spv
/usr/share/vkBasalt/vkBasalt.conf
/usr/share/vulkan
/usr/share/vulkan/explicit_layer.d
/usr/share/vulkan/explicit_layer.d/VkLayer_vkBasalt.json
If you really need this, you could use it's API (main.cpp is the best example). Same for glslang: API (main). |
Merged #52 |
You could add support for Reshade FX shaders (like nvidia did for Freestyle).
Reshade is open-source too and can be found at https://github.com/crosire/reshade/
With support for Reshade FX shaders you would gain access to running all of the shader effects we make, and would not have to take time to port them to glsl.
And vice-versa if you add any interesting effects we could also run them on Reshade.
Don't hesitate to reach out in our forums or on our discord if you want to discuss this or other ideas.
The text was updated successfully, but these errors were encountered: