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