diff --git a/Dalamud.Boot/DalamudStartInfo.cpp b/Dalamud.Boot/DalamudStartInfo.cpp index 985332966..f342973b0 100644 --- a/Dalamud.Boot/DalamudStartInfo.cpp +++ b/Dalamud.Boot/DalamudStartInfo.cpp @@ -116,6 +116,7 @@ void from_json(const nlohmann::json& json, DalamudStartInfo& config) { config.NoLoadThirdPartyPlugins = json.value("NoLoadThirdPartyPlugins", config.NoLoadThirdPartyPlugins); config.BootLogPath = json.value("BootLogPath", config.BootLogPath); + config.BootDebugDirectX = json.value("BootDebugDirectX", config.BootDebugDirectX); config.BootShowConsole = json.value("BootShowConsole", config.BootShowConsole); config.BootDisableFallbackConsole = json.value("BootDisableFallbackConsole", config.BootDisableFallbackConsole); config.BootWaitMessageBox = json.value("BootWaitMessageBox", config.BootWaitMessageBox); diff --git a/Dalamud.Boot/DalamudStartInfo.h b/Dalamud.Boot/DalamudStartInfo.h index cc31ba2c5..d6524968e 100644 --- a/Dalamud.Boot/DalamudStartInfo.h +++ b/Dalamud.Boot/DalamudStartInfo.h @@ -54,6 +54,7 @@ struct DalamudStartInfo { bool NoLoadThirdPartyPlugins; std::string BootLogPath; + bool BootDebugDirectX = false; bool BootShowConsole = false; bool BootDisableFallbackConsole = false; WaitMessageboxFlags BootWaitMessageBox = WaitMessageboxFlags::None; diff --git a/Dalamud.Boot/dllmain.cpp b/Dalamud.Boot/dllmain.cpp index 5c7c00b68..d191c9e97 100644 --- a/Dalamud.Boot/dllmain.cpp +++ b/Dalamud.Boot/dllmain.cpp @@ -1,6 +1,10 @@ #include "pch.h" +#include +#include + #include "DalamudStartInfo.h" +#include "hooks.h" #include "logging.h" #include "utils.h" #include "veh.h" @@ -90,6 +94,69 @@ HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) { if ((g_startInfo.BootWaitMessageBox & DalamudStartInfo::WaitMessageboxFlags::BeforeInitialize) != DalamudStartInfo::WaitMessageboxFlags::None) MessageBoxW(nullptr, L"Press OK to continue (BeforeInitialize)", L"Dalamud Boot", MB_OK); + if (g_startInfo.BootDebugDirectX) { + logging::I("Enabling DirectX Debugging."); + + const auto hD3D11 = GetModuleHandleW(L"d3d11.dll"); + const auto hDXGI = GetModuleHandleW(L"dxgi.dll"); + const auto pfnD3D11CreateDevice = static_cast( + hD3D11 ? static_cast(GetProcAddress(hD3D11, "D3D11CreateDevice")) : nullptr); + if (pfnD3D11CreateDevice) { + static hooks::direct_hook s_hookD3D11CreateDevice( + "d3d11.dll!D3D11CreateDevice", + pfnD3D11CreateDevice); + s_hookD3D11CreateDevice.set_detour([]( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext + ) -> HRESULT { + return s_hookD3D11CreateDevice.call_original( + pAdapter, + DriverType, + Software, + (Flags & ~D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY) | D3D11_CREATE_DEVICE_DEBUG, + pFeatureLevels, + FeatureLevels, + SDKVersion, + ppDevice, + pFeatureLevel, + ppImmediateContext); + }); + } else { + logging::W("Could not find d3d11!D3D11CreateDevice."); + } + + const auto pfnCreateDXGIFactory = static_cast( + hDXGI ? static_cast(GetProcAddress(hDXGI, "CreateDXGIFactory")) : nullptr); + const auto pfnCreateDXGIFactory1 = static_cast( + hDXGI ? static_cast(GetProcAddress(hDXGI, "CreateDXGIFactory1")) : nullptr); + static const auto pfnCreateDXGIFactory2 = static_cast( + hDXGI ? static_cast(GetProcAddress(hDXGI, "CreateDXGIFactory2")) : nullptr); + if (pfnCreateDXGIFactory2) { + static hooks::direct_hook s_hookCreateDXGIFactory( + "dxgi.dll!CreateDXGIFactory", + pfnCreateDXGIFactory); + static hooks::direct_hook s_hookCreateDXGIFactory1( + "dxgi.dll!CreateDXGIFactory1", + pfnCreateDXGIFactory1); + s_hookCreateDXGIFactory.set_detour([](REFIID riid, _COM_Outptr_ void **ppFactory) -> HRESULT { + return pfnCreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, ppFactory); + }); + s_hookCreateDXGIFactory1.set_detour([](REFIID riid, _COM_Outptr_ void **ppFactory) -> HRESULT { + return pfnCreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, riid, ppFactory); + }); + } else { + logging::W("Could not find dxgi!CreateDXGIFactory2."); + } + } + if (minHookLoaded) { logging::I("Applying fixes..."); xivfixes::apply_all(true); diff --git a/Dalamud.Common/DalamudStartInfo.cs b/Dalamud.Common/DalamudStartInfo.cs index c3cc33a12..b27d4b00d 100644 --- a/Dalamud.Common/DalamudStartInfo.cs +++ b/Dalamud.Common/DalamudStartInfo.cs @@ -94,6 +94,11 @@ public record DalamudStartInfo /// public bool BootShowConsole { get; set; } + /// + /// Gets or sets a value indicating whether to enable D3D11 and DXGI debugging if possible. + /// + public bool BootDebugDirectX { get; set; } + /// /// Gets or sets a value indicating whether the fallback console should be shown, if needed. /// diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs index f22c2923e..cce40da76 100644 --- a/Dalamud.Injector/EntryPoint.cs +++ b/Dalamud.Injector/EntryPoint.cs @@ -89,6 +89,7 @@ namespace Dalamud.Injector startInfo = ExtractAndInitializeStartInfoFromArguments(startInfo, args); // Remove already handled arguments + args.Remove("--debug-directx"); args.Remove("--console"); args.Remove("--msgbox1"); args.Remove("--msgbox2"); @@ -396,6 +397,7 @@ namespace Dalamud.Injector startInfo.LogName ??= string.Empty; // Set boot defaults + startInfo.BootDebugDirectX = args.Contains("--debug-directx"); startInfo.BootShowConsole = args.Contains("--console"); startInfo.BootEnableEtw = args.Contains("--etw"); startInfo.BootLogPath = GetLogPath(startInfo.LogPath, "dalamud.boot", startInfo.LogName);