From ec3f1b2aa4648d21ebf6494834db6bf33c3c217c Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 6 Apr 2024 17:06:10 +1000 Subject: [PATCH] GS/Vulkan: Swap out glslang for shaderc --- PCSX2_qt.sln | 27 ----- cmake/FindShaderc.cmake | 32 +++++ cmake/SearchForStuff.cmake | 5 +- common/vsprops/LinkPCSX2Deps.props | 3 +- pcsx2/CMakeLists.txt | 4 +- pcsx2/GS/Renderers/Vulkan/VKShaderCache.cpp | 127 +++++--------------- pcsx2/ShaderCacheVersion.h | 4 +- pcsx2/pcsx2.vcxproj | 4 - 8 files changed, 75 insertions(+), 131 deletions(-) create mode 100644 cmake/FindShaderc.cmake diff --git a/PCSX2_qt.sln b/PCSX2_qt.sln index e3064125c4..4e283b61a7 100644 --- a/PCSX2_qt.sln +++ b/PCSX2_qt.sln @@ -27,8 +27,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cubeb", "3rdparty\cubeb\cub EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ryml", "3rdparty\rapidyaml\ryml.vcxproj", "{DE9653B6-17DD-356A-9EE0-28A731772587}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glslang", "3rdparty\glslang\glslang.vcxproj", "{EF6834A9-11F3-4331-BC34-21B325ABB180}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzip", "3rdparty\libzip\libzip.vcxproj", "{20B2E9FE-F020-42A0-B324-956F5B06EA68}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d12memalloc", "3rdparty\d3d12memalloc\d3d12memalloc.vcxproj", "{D45CEC7A-3171-40DD-975D-E1544CF16139}" @@ -331,30 +329,6 @@ Global {DE9653B6-17DD-356A-9EE0-28A731772587}.Release Clang|x64.Build.0 = Release Clang|x64 {DE9653B6-17DD-356A-9EE0-28A731772587}.Release|x64.ActiveCfg = Release|x64 {DE9653B6-17DD-356A-9EE0-28A731772587}.Release|x64.Build.0 = Release|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug AVX2|x64.ActiveCfg = Debug|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug AVX2|x64.Build.0 = Debug|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug Clang AVX2|x64.ActiveCfg = Debug Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug Clang AVX2|x64.Build.0 = Debug Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug Clang|x64.ActiveCfg = Debug Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug Clang|x64.Build.0 = Debug Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug|x64.ActiveCfg = Debug|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Debug|x64.Build.0 = Debug|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel AVX2|x64.ActiveCfg = Devel|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel AVX2|x64.Build.0 = Devel|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel Clang AVX2|x64.ActiveCfg = Devel Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel Clang AVX2|x64.Build.0 = Devel Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel Clang|x64.ActiveCfg = Devel Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel Clang|x64.Build.0 = Devel Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel|x64.ActiveCfg = Devel|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Devel|x64.Build.0 = Devel|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release AVX2|x64.ActiveCfg = Release|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release AVX2|x64.Build.0 = Release|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release Clang AVX2|x64.ActiveCfg = Release Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release Clang AVX2|x64.Build.0 = Release Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release Clang|x64.ActiveCfg = Release Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release Clang|x64.Build.0 = Release Clang|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release|x64.ActiveCfg = Release|x64 - {EF6834A9-11F3-4331-BC34-21B325ABB180}.Release|x64.Build.0 = Release|x64 {20B2E9FE-F020-42A0-B324-956F5B06EA68}.Debug AVX2|x64.ActiveCfg = Debug|x64 {20B2E9FE-F020-42A0-B324-956F5B06EA68}.Debug AVX2|x64.Build.0 = Debug|x64 {20B2E9FE-F020-42A0-B324-956F5B06EA68}.Debug Clang AVX2|x64.ActiveCfg = Debug Clang|x64 @@ -620,7 +594,6 @@ Global {1EC8B3C0-8FB3-46DE-A2E0-A9121203F266} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {BF74C473-DC04-44B3-92E8-4145F4E77342} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {DE9653B6-17DD-356A-9EE0-28A731772587} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} - {EF6834A9-11F3-4331-BC34-21B325ABB180} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {20B2E9FE-F020-42A0-B324-956F5B06EA68} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {D45CEC7A-3171-40DD-975D-E1544CF16139} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} {A4323327-3F2B-4271-83D9-7F9A3C66B6B2} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38} diff --git a/cmake/FindShaderc.cmake b/cmake/FindShaderc.cmake new file mode 100644 index 0000000000..17d229646f --- /dev/null +++ b/cmake/FindShaderc.cmake @@ -0,0 +1,32 @@ +# - Try to find SHADERC +# Once done this will define +# SHADERC_FOUND - System has SHADERC +# SHADERC_INCLUDE_DIRS - The SHADERC include directories +# SHADERC_LIBRARIES - The libraries needed to use SHADERC + +FIND_PATH( + SHADERC_INCLUDE_DIR shaderc/shaderc.h + HINTS /usr/include /usr/local/include + ${SHADERC_PATH_INCLUDES} +) + +FIND_LIBRARY( + SHADERC_LIBRARY + NAMES shaderc_shared + PATHS ${ADDITIONAL_LIBRARY_PATHS} ${SHADERC_PATH_LIB} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Shaderc DEFAULT_MSG + SHADERC_LIBRARY SHADERC_INCLUDE_DIR) + +if(SHADERC_FOUND) + add_library(Shaderc::shaderc_shared UNKNOWN IMPORTED) + set_target_properties(Shaderc::shaderc_shared PROPERTIES + IMPORTED_LOCATION ${SHADERC_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${SHADERC_INCLUDE_DIR} + INTERFACE_COMPILE_DEFINITIONS "SHADERC_SHAREDLIB" + ) +endif() + +mark_as_advanced(SHADERC_INCLUDE_DIR SHADERC_LIBRARY) diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index f51bc65c4a..37ae51823a 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -19,6 +19,10 @@ find_package(LZ4 REQUIRED) find_package(WebP REQUIRED) # v1.3.2, spews an error on Linux because no pkg-config. find_package(SDL2 2.30.2 REQUIRED) +if(USE_VULKAN) + find_package(Shaderc REQUIRED) +endif() + # Platform-specific dependencies. if (WIN32) add_subdirectory(3rdparty/D3D12MemAlloc EXCLUDE_FROM_ALL) @@ -110,7 +114,6 @@ if(USE_OPENGL) endif() if(USE_VULKAN) - add_subdirectory(3rdparty/glslang EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/vulkan-headers EXCLUDE_FROM_ALL) endif() diff --git a/common/vsprops/LinkPCSX2Deps.props b/common/vsprops/LinkPCSX2Deps.props index 3b1d8d780b..05c9c44680 100644 --- a/common/vsprops/LinkPCSX2Deps.props +++ b/common/vsprops/LinkPCSX2Deps.props @@ -4,7 +4,7 @@ $(DepsLibDir);%(AdditionalLibraryDirectories) - %(AdditionalDependencies);libjpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL2.lib;zlib.lib;zstd.lib + %(AdditionalDependencies);libjpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL2.lib;shaderc_shared.lib;zlib.lib;zstd.lib @@ -16,6 +16,7 @@ + diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 543fb9d5d9..8094db3344 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -626,7 +626,7 @@ if(USE_VULKAN) GS/Renderers/Vulkan/VKStreamBuffer.h GS/Renderers/Vulkan/VKSwapChain.h ) - target_link_libraries(PCSX2_FLAGS INTERFACE Vulkan-Headers glslang) + target_link_libraries(PCSX2_FLAGS INTERFACE Vulkan-Headers Shaderc::shaderc_shared) endif() set(pcsx2GSMetalShaders @@ -1243,7 +1243,7 @@ function(setup_main_executable target) # Copy dependency libraries. set(DEPS_BINDIR "${CMAKE_SOURCE_DIR}/deps/bin") - set(DEPS_TO_COPY freetype.dll harfbuzz.dll libjpeg.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL2.dll zlib1.dll zstd.dll) + set(DEPS_TO_COPY freetype.dll harfbuzz.dll libjpeg.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL2.dll shaderc_shared.dll zlib1.dll zstd.dll) foreach(DEP_TO_COPY ${DEPS_TO_COPY}) install(FILES "${DEPS_BINDIR}/${DEP_TO_COPY}" DESTINATION "${CMAKE_SOURCE_DIR}/bin") endforeach() diff --git a/pcsx2/GS/Renderers/Vulkan/VKShaderCache.cpp b/pcsx2/GS/Renderers/Vulkan/VKShaderCache.cpp index 62e96cd787..ce88744ac1 100644 --- a/pcsx2/GS/Renderers/Vulkan/VKShaderCache.cpp +++ b/pcsx2/GS/Renderers/Vulkan/VKShaderCache.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team +// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team // SPDX-License-Identifier: LGPL-3.0+ #include "GS/GS.h" @@ -15,12 +15,8 @@ #include "common/MD5Digest.h" #include "common/Path.h" -// glslang includes -#include "SPIRV/GlslangToSpv.h" -#include "StandAlone/ResourceLimits.h" -#include "glslang/Public/ShaderLang.h" - #include "fmt/format.h" +#include "shaderc/shaderc.hpp" #include #include @@ -30,6 +26,9 @@ std::unique_ptr g_vulkan_shader_cache; +static std::unique_ptr s_shaderc_compiler; +static u32 s_next_bad_shader_id = 0; + namespace { #pragma pack(push, 4) @@ -100,49 +99,34 @@ static void FillPipelineCacheHeader(VK_PIPELINE_CACHE_HEADER* header) std::memcpy(header->uuid, GSDeviceVK::GetInstance()->GetDeviceProperties().pipelineCacheUUID, VK_UUID_SIZE); } -static unsigned s_next_bad_shader_id = 1; -static bool s_glslang_initialized = false; - -// Registers itself for cleanup via atexit -static bool InitializeGlslang() +std::optional VKShaderCache::CompileShaderToSPV(u32 stage, std::string_view source, bool debug) { - if (s_glslang_initialized) - return true; + // TODO: NOT thread safe, yet. + if (!s_shaderc_compiler) + s_shaderc_compiler = std::make_unique(); - if (!glslang::InitializeProcess()) + shaderc::CompileOptions options; + options.SetSourceLanguage(shaderc_source_language_glsl); + options.SetTargetEnvironment(shaderc_target_env_vulkan, 0); + + if (debug) { - pxFailRel("Failed to initialize glslang shader compiler"); - return false; + options.SetOptimizationLevel(shaderc_optimization_level_zero); + options.SetGenerateDebugInfo(); + } + else + { + options.SetOptimizationLevel(shaderc_optimization_level_performance); } - std::atexit(&glslang::FinalizeProcess); - s_glslang_initialized = true; - return true; -} - -std::optional VKShaderCache::CompileShaderToSPV( - u32 stage, std::string_view source, bool debug) -{ - if (!InitializeGlslang()) - return std::nullopt; - - std::unique_ptr shader = std::make_unique(static_cast(stage)); - std::unique_ptr program; - glslang::TShader::ForbidIncluder includer; - const EProfile profile = ECoreProfile; - const EShMessages messages = - static_cast(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules | (debug ? EShMsgDebugInfo : 0)); - const int default_version = 450; - - std::string full_source_code; - const char* pass_source_code = source.data(); - int pass_source_code_length = static_cast(source.size()); - shader->setStringsWithLengths(&pass_source_code, &pass_source_code_length, 1); - - auto DumpBadShader = [&shader, &source, &program](const char* msg) { + const shaderc::SpvCompilationResult result = s_shaderc_compiler->CompileGlslToSpv( + source.data(), source.length(), static_cast(stage), "source", "main", options); + if (result.GetCompilationStatus() != shaderc_compilation_status_success) + { + const std::string msg = result.GetErrorMessage(); const std::string filename = - Path::Combine(EmuFolders::Logs, fmt::format("pcsx2_bad_shader_{}.txt", s_next_bad_shader_id++)); - Console.Error("CompileShaderToSPV: %s, writing to %s", msg, filename.c_str()); + Path::Combine(EmuFolders::Logs, fmt::format("pcsx2_bad_shader_{}.txt", ++s_next_bad_shader_id)); + Console.ErrorFmt("CompileShaderToSPV(): {}, writing to {}", msg, filename.c_str()); std::ofstream ofs(filename, std::ofstream::out | std::ofstream::binary); if (ofs.is_open()) @@ -151,62 +135,17 @@ std::optional VKShaderCache::CompileShaderToSPV( ofs << "\n"; ofs << msg << std::endl; - ofs << "Shader Info Log:" << std::endl; - ofs << shader->getInfoLog() << std::endl; - ofs << shader->getInfoDebugLog() << std::endl; - if (program) - { - ofs << "Program Info Log:" << std::endl; - ofs << program->getInfoLog() << std::endl; - ofs << program->getInfoDebugLog() << std::endl; - } - ofs.close(); } - }; - if (!shader->parse(&glslang::DefaultTBuiltInResource, default_version, profile, false, true, messages, includer)) - { - DumpBadShader("Failed to parse shader"); return std::nullopt; } - - // Even though there's only a single shader, we still need to link it to generate SPV - program = std::make_unique(); - program->addShader(shader.get()); - if (!program->link(messages)) + else if (result.GetNumWarnings() > 0) { - DumpBadShader("Failed to link program"); - return std::nullopt; + Console.WarningFmt("CompileShaderToSPV(): Shader compiled with warnings:\n{}", result.GetErrorMessage()); } - glslang::TIntermediate* intermediate = program->getIntermediate(static_cast(stage)); - if (!intermediate) - { - DumpBadShader("Failed to generate SPIR-V"); - return std::nullopt; - } - - SPIRVCodeVector out_code; - spv::SpvBuildLogger logger; - glslang::SpvOptions options; - options.generateDebugInfo = debug; - glslang::GlslangToSpv(*intermediate, out_code, &logger, &options); - - // Write out messages - if (std::strlen(shader->getInfoLog()) > 0) - Console.Warning("Shader info log: %s", shader->getInfoLog()); - if (std::strlen(shader->getInfoDebugLog()) > 0) - Console.Warning("Shader debug info log: %s", shader->getInfoDebugLog()); - if (std::strlen(program->getInfoLog()) > 0) - Console.Warning("Program info log: %s", program->getInfoLog()); - if (std::strlen(program->getInfoDebugLog()) > 0) - Console.Warning("Program debug info log: %s", program->getInfoDebugLog()); - std::string spv_messages = logger.getAllMessages(); - if (!spv_messages.empty()) - Console.Warning("SPIR-V conversion messages: %s", spv_messages.c_str()); - - return out_code; + return SPIRVCodeVector(result.cbegin(), result.cend()); } VKShaderCache::VKShaderCache() = default; @@ -595,17 +534,17 @@ VkShaderModule VKShaderCache::GetShaderModule(u32 type, std::string_view shader_ VkShaderModule VKShaderCache::GetVertexShader(std::string_view shader_code) { - return GetShaderModule(EShLangVertex, std::move(shader_code)); + return GetShaderModule(shaderc_glsl_vertex_shader, std::move(shader_code)); } VkShaderModule VKShaderCache::GetFragmentShader(std::string_view shader_code) { - return GetShaderModule(EShLangFragment, std::move(shader_code)); + return GetShaderModule(shaderc_glsl_fragment_shader, std::move(shader_code)); } VkShaderModule VKShaderCache::GetComputeShader(std::string_view shader_code) { - return GetShaderModule(EShLangCompute, std::move(shader_code)); + return GetShaderModule(shaderc_glsl_compute_shader, std::move(shader_code)); } std::optional VKShaderCache::CompileAndAddShaderSPV( diff --git a/pcsx2/ShaderCacheVersion.h b/pcsx2/ShaderCacheVersion.h index f73a803376..b5c115fdf4 100644 --- a/pcsx2/ShaderCacheVersion.h +++ b/pcsx2/ShaderCacheVersion.h @@ -1,6 +1,6 @@ -// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team +// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team // SPDX-License-Identifier: LGPL-3.0+ /// Version number for GS and other shaders. Increment whenever any of the contents of the /// shaders change, to invalidate the cache. -static constexpr u32 SHADER_CACHE_VERSION = 44; +static constexpr u32 SHADER_CACHE_VERSION = 45; diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index 35b6408fae..568819ee2a 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -51,7 +51,6 @@ %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\jpgd %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\ffmpeg\include %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\glad\include - %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\glslang\glslang %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\vulkan-headers\include %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\d3d12memalloc\include %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\lzma\include @@ -822,9 +821,6 @@ {e960dfdf-1bd3-4c29-b251-d1a0919c9b09} - - {ef6834a9-11f3-4331-bc34-21b325abb180} - {20b2e9fe-f020-42a0-b324-956f5b06ea68}