diff --git a/cmake/ShaderToCpp.cmake b/cmake/ShaderToCpp.cmake
new file mode 100644
index 0000000000..41009cc0ae
--- /dev/null
+++ b/cmake/ShaderToCpp.cmake
@@ -0,0 +1,31 @@
+function(shader_to_cpp SHADER_FILES_OUT SHADER_FILES_CPP_OUT CPP_OUTPUT_DIR_OUT)
+ set(SHADER_FILES "")
+ set(SHADER_FILES_CPP "")
+ set(CPP_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders_cpp")
+ file(MAKE_DIRECTORY ${CPP_OUTPUT_DIR})
+ file(GLOB_RECURSE DIR_FILES "${CMAKE_CURRENT_SOURCE_DIR}/../bin/resources/shaders/*")
+ foreach(path IN LISTS DIR_FILES)
+ if(NOT ("${path}" MATCHES ".*\.glsl$" OR "${path}" MATCHES ".*\.fx$"))
+ continue()
+ endif()
+ if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unneccessary stuff
+ continue()
+ endif()
+ get_filename_component(DIR ${path} DIRECTORY)
+ get_filename_component(API ${DIR} NAME)
+ get_filename_component(BASE ${path} NAME_WE)
+ set(cpp_path "${CPP_OUTPUT_DIR}/${API}_${BASE}.cpp")
+ add_custom_command(
+ OUTPUT ${cpp_path}
+ COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/../tools/shader_to_cpp.py ${path} ${cpp_path} "${API}_${BASE}"
+ DEPENDS ${path} ${CMAKE_CURRENT_SOURCE_DIR}/../tools/shader_to_cpp.py
+ COMMENT "Shader to CPP: ${path} -> ${cpp_path}"
+ VERBATIM
+ )
+ list(APPEND SHADER_FILES ${path})
+ list(APPEND SHADER_FILES_CPP ${cpp_path})
+ endforeach()
+ set(${SHADER_FILES_OUT} ${SHADER_FILES} PARENT_SCOPE)
+ set(${SHADER_FILES_CPP_OUT} ${SHADER_FILES_CPP} PARENT_SCOPE)
+ set(${CPP_OUTPUT_DIR_OUT} ${CPP_OUTPUT_DIR} PARENT_SCOPE)
+endfunction()
\ No newline at end of file
diff --git a/common/vsprops/ShaderToCpp.props b/common/vsprops/ShaderToCpp.props
new file mode 100644
index 0000000000..58417fb830
--- /dev/null
+++ b/common/vsprops/ShaderToCpp.props
@@ -0,0 +1,41 @@
+
+
+
+ true
+ $(OutDir)shaders_cpp\
+
+
+
+ $(BakeShadersInCpp)
+
+
+
+
+ BAKE_SHADERS_IN_CPP;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories);$(ShaderCppDir)
+
+
+
+
+
+
+
+
+
+ "python" "$(SolutionDir)\tools\shader_to_cpp.py" "%(Identity)" "$(ShaderCppDir)%(VarName).cpp" "%(VarName)"
+
+ $(ShaderCppDir)%(VarName).cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common/vsprops/ShaderToCpp.targets b/common/vsprops/ShaderToCpp.targets
new file mode 100644
index 0000000000..d37aa4e7de
--- /dev/null
+++ b/common/vsprops/ShaderToCpp.targets
@@ -0,0 +1,6 @@
+
+
+
+ ShaderToCppClean;$(CleanDependsOn)
+
+
\ No newline at end of file
diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt
index cacbebacb3..db181ea377 100644
--- a/pcsx2/CMakeLists.txt
+++ b/pcsx2/CMakeLists.txt
@@ -51,6 +51,16 @@ if(WIN32)
)
endif(WIN32)
+option(BAKE_SHADERS_IN_CPP "Bake shaders into C++ source files" OFF)
+if(BAKE_SHADERS_IN_CPP)
+ include(ShaderToCpp)
+ shader_to_cpp(SHADER_FILES SHADER_FILES_CPP CPP_OUTPUT_DIR)
+ add_custom_target(GeneratedShaders DEPENDS ${SHADER_FILES} ${SHADER_FILES_CPP})
+ add_dependencies(PCSX2 GeneratedShaders)
+ target_compile_definitions(PCSX2_FLAGS INTERFACE BAKE_SHADERS_IN_CPP=1)
+ target_include_directories(PCSX2_FLAGS INTERFACE ${CPP_OUTPUT_DIR})
+endif()
+
# Main pcsx2 source
set(pcsx2Sources
Achievements.cpp
diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp
index b3908ac3e3..21f85fdae3 100644
--- a/pcsx2/GS/Renderers/Common/GSDevice.cpp
+++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp
@@ -312,8 +312,69 @@ void GSDevice::GenerateExpansionIndexBuffer(void* buffer)
}
}
+#ifdef BAKE_SHADERS_IN_CPP
+#include "common_fxaa.cpp"
+#include "vulkan_convert.cpp"
+#include "vulkan_imgui.cpp"
+#include "vulkan_interlace.cpp"
+#include "vulkan_merge.cpp"
+#include "vulkan_present.cpp"
+#include "vulkan_shadeboost.cpp"
+#include "vulkan_tfx.cpp"
+#include "opengl_convert.cpp"
+#include "opengl_imgui.cpp"
+#include "opengl_interlace.cpp"
+#include "opengl_merge.cpp"
+#include "opengl_present.cpp"
+#include "opengl_shadeboost.cpp"
+#include "opengl_tfx_fs.cpp"
+#include "opengl_tfx_vgs.cpp"
+#ifdef _WIN32
+#include "dx11_convert.cpp"
+#include "dx11_imgui.cpp"
+#include "dx11_interlace.cpp"
+#include "dx11_merge.cpp"
+#include "dx11_present.cpp"
+#include "dx11_shadeboost.cpp"
+#include "dx11_tfx.cpp"
+#endif
+
+static const std::map baked_shaders = {
+ { "shaders/common/fxaa.fx" , common_fxaa},
+ { "shaders/vulkan/convert.glsl" , vulkan_convert},
+ { "shaders/vulkan/imgui.glsl" , vulkan_imgui},
+ { "shaders/vulkan/interlace.glsl" , vulkan_interlace},
+ { "shaders/vulkan/merge.glsl" , vulkan_merge },
+ { "shaders/vulkan/present.glsl" , vulkan_present },
+ { "shaders/vulkan/shadeboost.glsl" , vulkan_shadeboost },
+ { "shaders/vulkan/tfx.glsl" , vulkan_tfx },
+ { "shaders/opengl/convert.glsl" , opengl_convert },
+ { "shaders/opengl/imgui.glsl" , opengl_imgui },
+ { "shaders/opengl/interlace.glsl" , opengl_interlace },
+ { "shaders/opengl/merge.glsl" , opengl_merge },
+ { "shaders/opengl/present.glsl" , opengl_present },
+ { "shaders/opengl/shadeboost.glsl" , opengl_shadeboost },
+ { "shaders/opengl/tfx_fs.glsl" , opengl_tfx_fs },
+ { "shaders/opengl/tfx_vgs.glsl" , opengl_tfx_vgs },
+#ifdef _WIN32
+ { "shaders/direct3d/convert.fx" , dx11_convert },
+ { "shaders/direct3d/imgui.fx" , dx11_imgui },
+ { "shaders/direct3d/interlace.fx" , dx11_interlace },
+ { "shaders/direct3d/merge.fx" , dx11_merge },
+ { "shaders/direct3d/present.fx" , dx11_present },
+ { "shaders/direct3d/shadeboost.fx" , dx11_shadeboost },
+ { "shaders/direct3d/tfx.fx" , dx11_tfx },
+#endif
+};
+#endif
+
std::optional GSDevice::ReadShaderSource(const char* filename)
{
+#ifdef BAKE_SHADERS_IN_CPP
+ const auto it = baked_shaders.find(filename);
+ if (it != baked_shaders.end())
+ return reinterpret_cast(it->second);
+#endif
return FileSystem::ReadFileToString(Path::Combine(EmuFolders::Resources, filename).c_str());
}
diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj
index 1875a886df..400c935d38 100644
--- a/pcsx2/pcsx2.vcxproj
+++ b/pcsx2/pcsx2.vcxproj
@@ -24,6 +24,7 @@
+
@@ -70,8 +71,86 @@
+
+ vulkan_convert
+
+
+ vulkan_imgui
+
+
+ vulkan_interlace
+
+
+ vulkan_merge
+
+
+ vulkan_present
+
+
+ vulkan_shadeboost
+
+
+ vulkan_tfx
+
+
+ opengl_convert
+
+
+ opengl_imgui
+
+
+ opengl_interlace
+
+
+ opengl_merge
+
+
+ opengl_shadeboost
+
+
+ opengl_tfx_fs
+
+
+ opengl_tfx_vgs
+
+
+ opengl_present
+
+
+ dx11_convert
+
+
+ dx11_interlace
+
+
+ dx11_merge
+
+
+ dx11_shadeboost
+
+
+ dx11_tfx
+
+
+ dx11_imgui
+
+
+ dx11_present
+
+
+ common_fxaa
+
+
+
+
+
+
+
+
+
+
@@ -79,20 +158,14 @@
-
-
-
-
-
-
-
+
+
-
-
+
true
@@ -1031,5 +1104,6 @@
+
\ No newline at end of file
diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters
index 8ede454a21..e9898a59c3 100644
--- a/pcsx2/pcsx2.vcxproj.filters
+++ b/pcsx2/pcsx2.vcxproj.filters
@@ -336,65 +336,62 @@
System\Ps2\EmotionEngine\VU\Dynarec\microVU
+
+ System\Ps2\GS\Renderers\Vulkan
+
System\Ps2\GS\Shaders\Common
+
+ System\Ps2\GS\Shaders\OpenGL
+
System\Ps2\GS\Shaders\OpenGL
+
+ System\Ps2\GS\Shaders\OpenGL
+
System\Ps2\GS\Shaders\OpenGL
System\Ps2\GS\Shaders\OpenGL
-
- System\Ps2\GS\Shaders\OpenGL
-
-
+
System\Ps2\GS\Shaders\OpenGL
System\Ps2\GS\Shaders\OpenGL
-
+
System\Ps2\GS\Shaders\OpenGL
-
+
System\Ps2\GS\Shaders\OpenGL
-
+
System\Ps2\GS\Shaders\Vulkan
System\Ps2\GS\Shaders\Vulkan
-
+
System\Ps2\GS\Shaders\Vulkan
-
+
+ System\Ps2\GS\Shaders\Vulkan
+
+
System\Ps2\GS\Shaders\Vulkan
System\Ps2\GS\Shaders\Vulkan
-
- System\Ps2\GS\Shaders\Vulkan
-
System\Ps2\GS\Shaders\Vulkan
-
- System\Ps2\GS\Shaders\Direct3D
-
-
- System\Ps2\GS\Shaders\Direct3D
-
-
- System\Ps2\GS\Shaders\Direct3D
-
-
- System\Ps2\GS\Shaders\Direct3D
+
+ System\Ps2\GS\Shaders\Vulkan
System\Ps2\GS\Shaders\Direct3D
@@ -402,11 +399,23 @@
System\Ps2\GS\Shaders\Direct3D
+
+ System\Ps2\GS\Shaders\Direct3D
+
+
+ System\Ps2\GS\Shaders\Direct3D
+
System\Ps2\GS\Shaders\Direct3D
-
- System\Ps2\GS\Renderers\Vulkan
+
+ System\Ps2\GS\Shaders\Direct3D
+
+
+ System\Ps2\GS\Shaders\Direct3D
+
+
+ System\Ps2\GS\Shaders\Direct3D
diff --git a/tools/shader_to_cpp.py b/tools/shader_to_cpp.py
new file mode 100644
index 0000000000..e4f32c6080
--- /dev/null
+++ b/tools/shader_to_cpp.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+import os
+import sys
+
+def generate_cpp(input_file, output_file, var_name):
+ with open(input_file, "rb") as f:
+ data = f.read()
+
+ ascii_codes = ", ".join(str(b) for b in data)
+
+ cpp = f"""// Auto-generated with {__file__}
+
+static constexpr unsigned char {var_name}[{len(data) + 1}] = {{
+ {ascii_codes}, 0
+}};
+"""
+
+ with open(output_file, "w", newline="\n") as f:
+ f.write(cpp)
+
+ return output_file
+
+def main():
+ if len(sys.argv) != 4:
+ print("Usage: text_to_cpp.py ")
+ sys.exit(1)
+
+ input_file = sys.argv[1]
+ output_file = sys.argv[2]
+ var_name = sys.argv[3]
+ if not os.path.isfile(input_file):
+ print(f"Error: '{input_file}' does not exist or is not a file.")
+ sys.exit(1)
+
+ output_file = generate_cpp(input_file, output_file, var_name)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file