diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 42bb1c10..691fbf61 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -1,6 +1,10 @@ project("UnleashedRecomp") set(TARGET_NAME "SWA") +if (WIN32) + option(SWA_D3D12 "Add D3D12 support for rendering" ON) +endif() + option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF) function(BIN2C) @@ -95,7 +99,7 @@ set(SWA_GPU_CXX_SOURCES "gpu/rhi/plume_vulkan.cpp" ) -if (WIN32) +if (SWA_D3D12) list(APPEND SWA_GPU_CXX_SOURCES "gpu/rhi/plume_d3d12.cpp" ) @@ -211,10 +215,11 @@ endif() set_target_properties(UnleashedRecomp PROPERTIES OUTPUT_NAME ${TARGET_NAME}) -if (WIN32) +if (SWA_D3D12) find_package(directx-headers CONFIG REQUIRED) find_package(directx12-agility CONFIG REQUIRED) find_package(d3d12-memory-allocator CONFIG REQUIRED) + target_compile_definitions(UnleashedRecomp PRIVATE SWA_D3D12) endif() find_package(SDL2 CONFIG REQUIRED) @@ -236,7 +241,7 @@ find_package(nfd CONFIG REQUIRED) find_package(Vorbis CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED) -if (WIN32) +if (SWA_D3D12) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/D3D12) add_custom_command(TARGET UnleashedRecomp POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/D3D12 @@ -252,8 +257,13 @@ if (WIN32) Microsoft::DirectX12-Agility Microsoft::DirectXShaderCompiler unofficial::D3D12MemoryAllocator - comctl32 dxgi + ) +endif() + +if (WIN32) + target_link_libraries(UnleashedRecomp PRIVATE + comctl32 ntdll winmm Synchronization @@ -300,7 +310,7 @@ target_precompile_headers(UnleashedRecomp PUBLIC ${SWA_PRECOMPILED_HEADERS}) function(compile_shader FILE_PATH TARGET_NAME) set(FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/${FILE_PATH}.hlsl) cmake_path(GET FILE_PATH STEM VARIABLE_NAME) - if (WIN32) + if (SWA_D3D12) add_custom_command( OUTPUT ${FILE_PATH}.dxil.h COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -Fh ${FILE_PATH}.dxil.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_dxil diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 171436b4..9f9a27e8 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -35,35 +35,39 @@ #endif #include "../../tools/ShaderRecomp/ShaderRecomp/shader_common.h" + +#ifdef SWA_D3D12 #include "shader/copy_vs.hlsl.dxil.h" -#include "shader/copy_vs.hlsl.spirv.h" #include "shader/csd_filter_ps.hlsl.dxil.h" -#include "shader/csd_filter_ps.hlsl.spirv.h" #include "shader/enhanced_motion_blur_ps.hlsl.dxil.h" -#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h" #include "shader/gamma_correction_ps.hlsl.dxil.h" -#include "shader/gamma_correction_ps.hlsl.spirv.h" #include "shader/gaussian_blur_3x3.hlsl.dxil.h" -#include "shader/gaussian_blur_3x3.hlsl.spirv.h" #include "shader/gaussian_blur_5x5.hlsl.dxil.h" -#include "shader/gaussian_blur_5x5.hlsl.spirv.h" #include "shader/gaussian_blur_7x7.hlsl.dxil.h" -#include "shader/gaussian_blur_7x7.hlsl.spirv.h" #include "shader/gaussian_blur_9x9.hlsl.dxil.h" -#include "shader/gaussian_blur_9x9.hlsl.spirv.h" #include "shader/imgui_ps.hlsl.dxil.h" -#include "shader/imgui_ps.hlsl.spirv.h" #include "shader/imgui_vs.hlsl.dxil.h" -#include "shader/imgui_vs.hlsl.spirv.h" #include "shader/movie_ps.hlsl.dxil.h" -#include "shader/movie_ps.hlsl.spirv.h" #include "shader/movie_vs.hlsl.dxil.h" -#include "shader/movie_vs.hlsl.spirv.h" #include "shader/resolve_msaa_depth_2x.hlsl.dxil.h" -#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h" #include "shader/resolve_msaa_depth_4x.hlsl.dxil.h" -#include "shader/resolve_msaa_depth_4x.hlsl.spirv.h" #include "shader/resolve_msaa_depth_8x.hlsl.dxil.h" +#endif + +#include "shader/copy_vs.hlsl.spirv.h" +#include "shader/csd_filter_ps.hlsl.spirv.h" +#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h" +#include "shader/gamma_correction_ps.hlsl.spirv.h" +#include "shader/gaussian_blur_3x3.hlsl.spirv.h" +#include "shader/gaussian_blur_5x5.hlsl.spirv.h" +#include "shader/gaussian_blur_7x7.hlsl.spirv.h" +#include "shader/gaussian_blur_9x9.hlsl.spirv.h" +#include "shader/imgui_ps.hlsl.spirv.h" +#include "shader/imgui_vs.hlsl.spirv.h" +#include "shader/movie_ps.hlsl.spirv.h" +#include "shader/movie_vs.hlsl.spirv.h" +#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h" +#include "shader/resolve_msaa_depth_4x.hlsl.spirv.h" #include "shader/resolve_msaa_depth_8x.hlsl.spirv.h" extern "C" @@ -74,7 +78,9 @@ extern "C" namespace plume { +#ifdef SWA_D3D12 extern std::unique_ptr CreateD3D12Interface(); +#endif extern std::unique_ptr CreateVulkanInterface(); } @@ -174,7 +180,12 @@ static FORCEINLINE void SetDirtyValue(bool& dirtyState, T& dest, const T& src) } } -static bool g_vulkan; +#ifdef SWA_D3D12 +static bool g_vulkan = false; +#else +static constexpr bool g_vulkan = true; +#endif + static std::unique_ptr g_interface; static std::unique_ptr g_device; @@ -579,13 +590,18 @@ static std::unique_ptr g_buttonBcDiff; static void LoadEmbeddedResources() { - const size_t decompressedSize = g_vulkan ? g_spirvCacheDecompressedSize : g_dxilCacheDecompressedSize; - g_shaderCache = std::make_unique(decompressedSize); - - ZSTD_decompress(g_shaderCache.get(), - decompressedSize, - g_vulkan ? g_compressedSpirvCache : g_compressedDxilCache, - g_vulkan ? g_spirvCacheCompressedSize : g_dxilCacheCompressedSize); + if (g_vulkan) + { + g_shaderCache = std::make_unique(g_spirvCacheDecompressedSize); + ZSTD_decompress(g_shaderCache.get(), g_spirvCacheDecompressedSize, g_compressedSpirvCache, g_spirvCacheCompressedSize); + } +#ifdef SWA_D3D12 + else + { + g_shaderCache = std::make_unique(g_dxilCacheDecompressedSize); + ZSTD_decompress(g_shaderCache.get(), g_dxilCacheDecompressedSize, g_compressedDxilCache, g_dxilCacheCompressedSize); + } +#endif g_buttonBcDiff = decompressZstd(g_button_bc_diff, g_button_bc_diff_uncompressed_size); } @@ -1062,6 +1078,8 @@ static GuestShader* g_csdShader; static std::unique_ptr g_enhancedMotionBlurShader; +#ifdef SWA_D3D12 + #define CREATE_SHADER(NAME) \ g_device->createShader( \ g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \ @@ -1069,6 +1087,13 @@ static std::unique_ptr g_enhancedMotionBlurShader; "main", \ g_vulkan ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL) +#else + +#define CREATE_SHADER(NAME) \ + g_device->createShader(g_##NAME##_spirv, sizeof(g_##NAME##_spirv), "main", RenderShaderFormat::SPIRV); + +#endif + static bool DetectWine() { HMODULE dllHandle = GetModuleHandle("ntdll.dll"); @@ -1288,11 +1313,18 @@ void Video::CreateHostDevice() Window::Init(); +#ifdef SWA_D3D12 g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan; +#endif LoadEmbeddedResources(); +#ifdef SWA_D3D12 g_interface = g_vulkan ? CreateVulkanInterface() : CreateD3D12Interface(); +#else + g_interface = CreateVulkanInterface(); +#endif + g_device = g_interface->createDevice(); g_triangleFanSupported = g_device->getCapabilities().triangleFan; @@ -2765,9 +2797,6 @@ static void ProcSetScissorRect(const RenderCommand& cmd) SetDirtyValue(g_dirtyStates.scissorRect, g_scissorRect.right, args.right); } -static Mutex g_compiledSpecConstantLibraryBlobMutex; -static ankerl::unordered_dense::map> g_compiledSpecConstantLibraryBlobs; - static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specConstants) { if (g_vulkan || @@ -2808,8 +2837,12 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons shader = guestShader->linkedShaders[specConstants].get(); } +#ifdef SWA_D3D12 if (shader == nullptr) { + static Mutex g_compiledSpecConstantLibraryBlobMutex; + static ankerl::unordered_dense::map> g_compiledSpecConstantLibraryBlobs; + thread_local ComPtr s_dxcCompiler; thread_local ComPtr s_dxcLinker; thread_local ComPtr s_dxcUtils; @@ -2916,6 +2949,7 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons shader = linkedShader.get(); } } +#endif return shader; } diff --git a/UnleashedRecomp/gpu/video.h b/UnleashedRecomp/gpu/video.h index 135a7dfa..34ddf886 100644 --- a/UnleashedRecomp/gpu/video.h +++ b/UnleashedRecomp/gpu/video.h @@ -274,8 +274,10 @@ struct GuestShader : GuestResource std::unique_ptr shader; struct ShaderCacheEntry* shaderCacheEntry = nullptr; ankerl::unordered_dense::map> linkedShaders; +#ifdef SWA_D3D12 std::vector> shaderBlobs; ComPtr libraryBlob; +#endif #ifdef ASYNC_PSO_DEBUG const char* name = ""; #endif diff --git a/UnleashedRecomp/stdafx.h b/UnleashedRecomp/stdafx.h index 16e8508a..f673f185 100644 --- a/UnleashedRecomp/stdafx.h +++ b/UnleashedRecomp/stdafx.h @@ -2,8 +2,14 @@ #define NOMINMAX +#if defined(_WIN32) #include +#endif + +#ifdef SWA_D3D12 #include +#endif + #include #include #include diff --git a/UnleashedRecomp/user/config.h b/UnleashedRecomp/user/config.h index 502d8546..f1b3ce57 100644 --- a/UnleashedRecomp/user/config.h +++ b/UnleashedRecomp/user/config.h @@ -28,7 +28,12 @@ public: CONFIG_DEFINE_LOCALISED("Audio", bool, MusicAttenuation, false); CONFIG_DEFINE_LOCALISED("Audio", bool, BattleTheme, true); +#ifdef SWA_D3D12 CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::D3D12); +#else + CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::Vulkan); +#endif + CONFIG_DEFINE("Video", int32_t, WindowX, WINDOWPOS_CENTRED); CONFIG_DEFINE("Video", int32_t, WindowY, WINDOWPOS_CENTRED); CONFIG_DEFINE("Video", int32_t, WindowWidth, 1280); diff --git a/UnleashedRecomp/user/config_detail.h b/UnleashedRecomp/user/config_detail.h index 5133ccad..7ca8a902 100644 --- a/UnleashedRecomp/user/config_detail.h +++ b/UnleashedRecomp/user/config_detail.h @@ -95,13 +95,17 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EVoiceLanguage) enum class EGraphicsAPI : uint32_t { +#ifdef SWA_D3D12 D3D12, +#endif Vulkan }; CONFIG_DEFINE_ENUM_TEMPLATE(EGraphicsAPI) { +#ifdef SWA_D3D12 { "D3D12", EGraphicsAPI::D3D12 }, +#endif { "Vulkan", EGraphicsAPI::Vulkan } }; diff --git a/tools/ShaderRecomp b/tools/ShaderRecomp index 12b38144..4b69741e 160000 --- a/tools/ShaderRecomp +++ b/tools/ShaderRecomp @@ -1 +1 @@ -Subproject commit 12b38144b9ff5d131e0d30af22bd38607d07d9fd +Subproject commit 4b69741e196e0a8aed9d51bbe0cf24019afab08e