Giter Club home page Giter Club logo

Comments (19)

crosire avatar crosire commented on May 12, 2024 1

@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).

from vkbasalt.

crosire avatar crosire commented on May 12, 2024 1

SPIR-V only supports scalar external spec constants (see SpecId at https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html#Decoration). But I've added support for automatic conversion of vectors/matrices into multiple scalar spec constants now: crosire/reshade@6f3694a.

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

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:

  • convert them to glsl (or hlsl) at runtime
  • convert these then to spir-v

For that I could take a look how ReShade does that since you guys support vulkan, too.

Other problem:

  • the settings need to be converted to specialization constants or uniforms buffers
  • the UI part hast to be converted to variables in the config file since I am not going to add a UI anytime soon
  • vkBasalt does not support depth buffer access yet
  • https://github.com/crosire/reshade-shaders does not mention a license in many shader files

from vkbasalt.

crosire avatar crosire commented on May 12, 2024

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 source\effect_*.* files to the makefile (in constrast to the rest of ReShade the compiler is platform independent).

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)

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

@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.
A question I still have is, what descriptor sets do these spir-v binaries use?

from vkbasalt.

crosire avatar crosire commented on May 12, 2024

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:
Set 0: Global UBO (with the uniform to spec constants option on this will be empty though, so not necessary)
Set 1: Samplers (with module.num_sampler_bindings bindings of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, the corresponding sampler info is in module.samplers)

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

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 -fpermissive and spams hundreds of warnings. The main issues are stuff like https://github.com/DadSchoorse/reshade/blob/4ad5836914a4207c48ace13f8274701fc736b822/source/effect_expression.hpp#L149

Also the code used some windows only C functions.
And now it only produces these shaders:

; SPIR-V
; Version: 1.2
; Generator: Khronos; 0
; Bound: 2
; Schema: 0
               OpCapability Shader
               OpCapability Matrix
               OpExtension "SPV_GOOGLE_hlsl_functionality1"
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450

from vkbasalt.

crosire avatar crosire commented on May 12, 2024

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 effect_codegen_hlsl.cpp and effect_codegen_glsl.cpp, since for Vulkan you only need effect_codegen_spirv.cpp.
DadSchoorse/reshade@a39841a introduced a bug: This should say FILE *file = fopen(path.c_str(), "rb");. Because right now it won't read the file and just abort immediately. With that fixed I get correct SPIR-V files after building and running ReshadeFxCompiler.

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

Yeah thanks, I am stupid, now it works.

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

@crosire source/effect_expression.hpp still uses FLT_MAX.
Also, are the .u8string() in source/effect_preprocessor.cpp necessary?

from vkbasalt.

crosire avatar crosire commented on May 12, 2024

On Windows yes, or else file loading for include paths will get messed up for unicode paths. Don't know about Linux. u8string in they way it is used only exists in C++17.

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

@crosire what is your opinion on these changes? They aren't the cleanest thing to do, but they make the code compile without -fpermissive.

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

@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.

from vkbasalt.

crosire avatar crosire commented on May 12, 2024

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 glShaderBinary. But this has been fixed since and it was never an issue under Vulkan.
So sounds like you ran into a driver bug on Linux (I don't think Steams cache comes into effect unless you use the fossilize layer explicitly)? Does it hang in the driver or somewhere else (as per the stack frame)?

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 effect_codegen_spirv.cpp line 270. So it should work to just duplicate everything else, but only write one of those entry points per module. E.g.:

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);

        ...
    }
}

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

@crosire I don't know what exactly hangs, only that it hangs when calling vkCreateGraphicsPipelines. Another weird things is, that vkcube and my own little triangle application run fine with the shaders in one module, but every game I try hangs. That's why I think it could be related to steam.
So I will look into effect_codegen_spirv.cpp

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

@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 .
However, it seems like vector settings are not converted to spec constants. Is there a reason for that?

from vkbasalt.

pchome avatar pchome commented on May 12, 2024
Out of date comment

Test build ReShade FX static library on linux

reshade-linux.patch
click 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.build
click 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')

Build

git 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: LDFLAGS += -lreshadefx

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

  • Only compilation tested, not correctness
  • Just in case it can be reused by multiple projects

EDIT: for fxc

patch

diff --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)

#define VERSION_MAJOR 4
#define VERSION_MINOR 5
#define VERSION_REVISION 2
#define VERSION_STRING_PRODUCT "ReShade FX Compiler"

Using

$ g++ -std=c++17 -I/tmp/reshade-fx/include/reshadefx -L/tmp/reshade-fx/lib64 fxc.cpp -lreshadefx -o fxc

from vkbasalt.

pchome avatar pchome commented on May 12, 2024

@crosire
FYI: So I created a packages (Gentoo) like this:

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

dev-util/reshade-fx will be common dependence for dev-util/reshade-fxc, media-libs/vkbasalt and any custom utils. The meson.build file was for testing purposes, but consider to add an build system for linux builds (Make/CMake/..., I guess Meson build could be okay too, since you require Python for ReShade itself).

@DadSchoorse

I ended up using spirv-cross at runtime because I could not find the cause for the hangs .

If you really need this, you could use it's API (main.cpp is the best example). Same for glslang: API (main).

from vkbasalt.

DadSchoorse avatar DadSchoorse commented on May 12, 2024

Merged #52

from vkbasalt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.