diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e23d9c21..9a997fae8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,12 +78,12 @@ if(WIN32 AND USE_SDL2)
set(SDL2_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib64/SDL2.lib")
set(SDL2MAIN_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib64/SDL2main.lib")
set(SDL2_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/bin64/SDL2.dll")
- set(Qt6_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/6.1.0/msvc2019_64/lib/cmake/Qt6")
+ set(Qt6_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/6.5.0/msvc2022_64/lib/cmake/Qt6")
else()
set(SDL2_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib32/SDL2.lib")
set(SDL2MAIN_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib32/SDL2main.lib")
set(SDL2_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/bin32/SDL2.dll")
- set(Qt6_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/6.1.0/msvc2019_32/lib/cmake/Qt6")
+ set(Qt6_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/6.5.0/msvc2022_32/lib/cmake/Qt6")
endif()
endif()
@@ -144,19 +144,6 @@ if(MSVC)
# COMDAT folding/remove unused functions.
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /OPT:ICF")
-
- # Enable LTO/LTCG on Release builds.
- if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
- cmake_policy(SET CMP0069 NEW)
- include(CheckIPOSupported)
- check_ipo_supported(RESULT IPO_IS_SUPPORTED)
- if(IPO_IS_SUPPORTED)
- message(STATUS "Enabling LTCG/IPO.")
- set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
- else()
- message(WARNING "LTCG/IPO is not supported, this will make the build slightly slower.")
- endif()
- endif()
endif()
@@ -223,8 +210,14 @@ endif()
# We don't need exceptions, disable them to save a bit of code size.
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
+if(MSVC)
+ string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_HAS_EXCEPTIONS=0 /permissive-")
+else()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
+endif()
# Write binaries to a seperate directory.
if(WIN32)
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index 4c39663c7..717ecc6a3 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -43,6 +43,11 @@ if(${CPU_ARCH} STREQUAL "riscv64")
add_subdirectory(riscv-disas)
endif()
+if(WIN32)
+ add_subdirectory(d3d12ma)
+ add_subdirectory(winpixeventruntime)
+endif()
+
if(APPLE)
add_subdirectory(spirv-cross)
endif()
diff --git a/dep/d3d12ma/CMakeLists.txt b/dep/d3d12ma/CMakeLists.txt
new file mode 100644
index 000000000..6c63553ce
--- /dev/null
+++ b/dep/d3d12ma/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_library(d3d12ma
+ include/D3D12MemAlloc.h
+ src/D3D12MemAlloc.cpp
+)
+
+target_include_directories(d3d12ma PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index defac0066..aa591f7e3 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -68,15 +68,16 @@ if(WIN32)
http_downloader_winhttp.h
thirdparty/StackWalker.cpp
thirdparty/StackWalker.h
- win32_progress_callback.cpp
- win32_progress_callback.h
windows_headers.h
)
- target_link_libraries(common PRIVATE d3dcompiler.lib)
+ target_link_libraries(common PRIVATE winhttp.lib)
+endif()
+if(MSVC)
if(${CPU_ARCH} STREQUAL "x64")
enable_language(ASM_MASM)
target_sources(common PRIVATE fastjmp_x86.asm)
+ set_source_files_properties(fastjmp_x86.asm PROPERTIES COMPILE_FLAGS "/D_M_X86_64")
elseif(${CPU_ARCH} STREQUAL "aarch32" OR ${CPU_ARCH} STREQUAL "aarch64")
enable_language(ASM_MARMASM)
target_sources(common PRIVATE fastjmp_arm.asm)
diff --git a/src/common/common.props b/src/common/common.props
index df0058a9c..b8ee70e4b 100644
--- a/src/common/common.props
+++ b/src/common/common.props
@@ -8,7 +8,7 @@
- %(AdditionalDependencies);Comctl32.lib;winhttp.lib
+ %(AdditionalDependencies);winhttp.lib
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index b9b63fba3..891589087 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -41,7 +41,6 @@
-
@@ -66,7 +65,6 @@
-
@@ -120,4 +118,4 @@
-
+
\ No newline at end of file
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index 76ed42311..adccb7b98 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -21,7 +21,6 @@
-
thirdparty
@@ -57,7 +56,6 @@
-
thirdparty
@@ -85,4 +83,4 @@
-
+
\ No newline at end of file
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 04279e7a5..a10a2c423 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -119,6 +119,7 @@ set(RECOMPILER_SRCS
cpu_recompiler_types.h
)
+target_precompile_headers(core PRIVATE "pch.h")
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_link_libraries(core PUBLIC Threads::Threads common util zlib)
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index de388dc99..1b9275f2f 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -61,6 +61,9 @@
+
+ Create
+
@@ -129,6 +132,7 @@
+
@@ -189,6 +193,9 @@
ZYDIS_DISABLE_ENCODER;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD;%(PreprocessorDefinitions)
$(SolutionDir)dep\zydis\include;$(SolutionDir)dep\zydis\dependencies\zycore\include;%(AdditionalIncludeDirectories)
$(IntDir)/%(RelativeDir)/
+ Use
+ pch.h
+ pch.h
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 95ce97505..fb7699b44 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -59,6 +59,7 @@
+
@@ -122,5 +123,6 @@
+
\ No newline at end of file
diff --git a/src/core/pch.cpp b/src/core/pch.cpp
new file mode 100644
index 000000000..ef4256aee
--- /dev/null
+++ b/src/core/pch.cpp
@@ -0,0 +1,4 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#include "pch.h"
diff --git a/src/core/pch.h b/src/core/pch.h
new file mode 100644
index 000000000..325ed4db1
--- /dev/null
+++ b/src/core/pch.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#pragma once
+
+#include "util/pch.h"
diff --git a/src/duckstation-nogui/CMakeLists.txt b/src/duckstation-nogui/CMakeLists.txt
index 02b93ab18..1da03cf04 100644
--- a/src/duckstation-nogui/CMakeLists.txt
+++ b/src/duckstation-nogui/CMakeLists.txt
@@ -4,6 +4,7 @@ add_executable(duckstation-nogui
nogui_platform.h
)
+target_precompile_headers(duckstation-nogui PRIVATE "pch.h")
target_link_libraries(duckstation-nogui PRIVATE core util common imgui scmversion)
if(WIN32)
diff --git a/src/duckstation-nogui/duckstation-nogui.vcxproj b/src/duckstation-nogui/duckstation-nogui.vcxproj
index 71085741d..cc5525a36 100644
--- a/src/duckstation-nogui/duckstation-nogui.vcxproj
+++ b/src/duckstation-nogui/duckstation-nogui.vcxproj
@@ -3,6 +3,9 @@
+
+ Create
+
true
@@ -14,6 +17,7 @@
+
true
@@ -48,5 +52,12 @@
+
+
+ Use
+ pch.h
+ pch.h
+
+
\ No newline at end of file
diff --git a/src/duckstation-nogui/duckstation-nogui.vcxproj.filters b/src/duckstation-nogui/duckstation-nogui.vcxproj.filters
index db825fb69..d08b60d6b 100644
--- a/src/duckstation-nogui/duckstation-nogui.vcxproj.filters
+++ b/src/duckstation-nogui/duckstation-nogui.vcxproj.filters
@@ -5,6 +5,7 @@
+
@@ -13,6 +14,7 @@
+
diff --git a/src/duckstation-nogui/nogui_host.cpp b/src/duckstation-nogui/nogui_host.cpp
index 1a905b459..701c3e1f6 100644
--- a/src/duckstation-nogui/nogui_host.cpp
+++ b/src/duckstation-nogui/nogui_host.cpp
@@ -426,9 +426,6 @@ void NoGUIHost::ProcessPlatformWindowResize(s32 width, s32 height, float scale)
void NoGUIHost::ProcessPlatformMouseMoveEvent(float x, float y)
{
- if (g_gpu_device)
- g_gpu_device->SetMousePosition(static_cast(x), static_cast(y));
-
InputManager::UpdatePointerAbsolutePosition(0, x, y);
ImGuiManager::UpdateMousePosition(x, y);
}
@@ -650,7 +647,7 @@ void NoGUIHost::CPUThreadMainLoop()
Host::PumpMessagesOnCPUThread();
System::Internal::IdlePollUpdate();
- Host::RenderDisplay(false);
+ System::PresentDisplay(false);
if (!g_gpu_device->IsVsyncEnabled())
g_gpu_device->ThrottlePresentation();
}
diff --git a/src/duckstation-nogui/pch.cpp b/src/duckstation-nogui/pch.cpp
new file mode 100644
index 000000000..ef4256aee
--- /dev/null
+++ b/src/duckstation-nogui/pch.cpp
@@ -0,0 +1,4 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#include "pch.h"
diff --git a/src/duckstation-nogui/pch.h b/src/duckstation-nogui/pch.h
new file mode 100644
index 000000000..3267189f4
--- /dev/null
+++ b/src/duckstation-nogui/pch.h
@@ -0,0 +1,6 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#pragma once
+
+#include "core/pch.h"
diff --git a/src/duckstation-qt/CMakeLists.txt b/src/duckstation-qt/CMakeLists.txt
index 7d9ff95ee..efb488ca8 100644
--- a/src/duckstation-qt/CMakeLists.txt
+++ b/src/duckstation-qt/CMakeLists.txt
@@ -165,10 +165,13 @@ set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_RUNT
qt6_add_translation(QM_FILES ${TS_FILES})
add_executable(duckstation-qt ${SRCS} ${QM_FILES})
+target_precompile_headers(duckstation-qt PRIVATE "pch.h")
target_include_directories(duckstation-qt PRIVATE "${Qt6Gui_PRIVATE_INCLUDE_DIRS}" "${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(duckstation-qt PRIVATE core common imgui minizip scmversion Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Network)
if(WIN32)
+ target_sources(duckstation-qt PRIVATE duckstation-qt.rc)
+
# We want a Windows subsystem application not console.
set_target_properties(duckstation-qt PROPERTIES
WIN32_EXECUTABLE TRUE
@@ -185,7 +188,6 @@ if(WIN32)
$,--debug,--release>
--no-translations
--no-compiler-runtime
- --no-angle
"$"
)
add_custom_command(TARGET duckstation-qt POST_BUILD
diff --git a/src/duckstation-qt/duckstation-qt.vcxproj b/src/duckstation-qt/duckstation-qt.vcxproj
index 45c9e6249..513545eb4 100644
--- a/src/duckstation-qt/duckstation-qt.vcxproj
+++ b/src/duckstation-qt/duckstation-qt.vcxproj
@@ -41,6 +41,9 @@
+
+ Create
+
@@ -81,6 +84,7 @@
+
@@ -354,6 +358,13 @@
+
+
+ Use
+ pch.h
+ pch.h
+
+
$(QtEntryPointLib);%(AdditionalDependencies)
@@ -371,4 +382,4 @@
-
+
\ No newline at end of file
diff --git a/src/duckstation-qt/duckstation-qt.vcxproj.filters b/src/duckstation-qt/duckstation-qt.vcxproj.filters
index eff8c903c..3678df76d 100644
--- a/src/duckstation-qt/duckstation-qt.vcxproj.filters
+++ b/src/duckstation-qt/duckstation-qt.vcxproj.filters
@@ -91,12 +91,14 @@
+
+
@@ -257,4 +259,4 @@
translations
-
+
\ No newline at end of file
diff --git a/src/duckstation-qt/pch.cpp b/src/duckstation-qt/pch.cpp
new file mode 100644
index 000000000..ef4256aee
--- /dev/null
+++ b/src/duckstation-qt/pch.cpp
@@ -0,0 +1,4 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#include "pch.h"
diff --git a/src/duckstation-qt/pch.h b/src/duckstation-qt/pch.h
new file mode 100644
index 000000000..9a5294ade
--- /dev/null
+++ b/src/duckstation-qt/pch.h
@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#pragma once
+
+#include "core/pch.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
diff --git a/src/duckstation-qt/qthost.h b/src/duckstation-qt/qthost.h
index 32f7747ff..fd4efac66 100644
--- a/src/duckstation-qt/qthost.h
+++ b/src/duckstation-qt/qthost.h
@@ -18,7 +18,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/src/updater/CMakeLists.txt b/src/updater/CMakeLists.txt
index 50e6b5744..80af88967 100644
--- a/src/updater/CMakeLists.txt
+++ b/src/updater/CMakeLists.txt
@@ -8,5 +8,9 @@ target_link_libraries(updater PRIVATE common minizip zlib)
if(WIN32)
target_sources(updater PRIVATE
win32_main.cpp
+ win32_progress_callback.cpp
+ win32_progress_callback.h
)
+ target_link_libraries(updater PRIVATE "Comctl32.lib")
+ set_target_properties(updater PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
diff --git a/src/updater/updater.cpp b/src/updater/updater.cpp
index 5a1a02ef3..930f42858 100644
--- a/src/updater/updater.cpp
+++ b/src/updater/updater.cpp
@@ -2,11 +2,13 @@
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "updater.h"
+#include "win32_progress_callback.h"
+
#include "common/file_system.h"
#include "common/log.h"
#include "common/minizip_helpers.h"
#include "common/string_util.h"
-#include "common/win32_progress_callback.h"
+
#include
#include
#include
diff --git a/src/updater/updater.vcxproj b/src/updater/updater.vcxproj
index 13b6fbfe6..8cbed4b2b 100644
--- a/src/updater/updater.vcxproj
+++ b/src/updater/updater.vcxproj
@@ -1,18 +1,18 @@
-
+
+
-
{8bda439c-6358-45fb-9994-2ff083babe06}
@@ -24,19 +24,18 @@
{ee054e08-3799-4a59-a422-18259c105ffd}
-
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}
-
-
$(SolutionDir)dep\minizip\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+ %(AdditionalDependencies);Comctl32.lib
+
-
\ No newline at end of file
diff --git a/src/updater/updater.vcxproj.filters b/src/updater/updater.vcxproj.filters
index 3f55d5df3..a3dd32415 100644
--- a/src/updater/updater.vcxproj.filters
+++ b/src/updater/updater.vcxproj.filters
@@ -3,11 +3,13 @@
+
+
\ No newline at end of file
diff --git a/src/updater/win32_main.cpp b/src/updater/win32_main.cpp
index 72c663d48..c2a3ecbff 100644
--- a/src/updater/win32_main.cpp
+++ b/src/updater/win32_main.cpp
@@ -1,12 +1,14 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+#include "updater.h"
+#include "win32_progress_callback.h"
+
#include "common/file_system.h"
#include "common/log.h"
#include "common/string_util.h"
-#include "common/win32_progress_callback.h"
#include "common/windows_headers.h"
-#include "updater.h"
+
#include
static void WaitForProcessToExit(int process_id)
diff --git a/src/common/win32_progress_callback.cpp b/src/updater/win32_progress_callback.cpp
similarity index 100%
rename from src/common/win32_progress_callback.cpp
rename to src/updater/win32_progress_callback.cpp
diff --git a/src/common/win32_progress_callback.h b/src/updater/win32_progress_callback.h
similarity index 97%
rename from src/common/win32_progress_callback.h
rename to src/updater/win32_progress_callback.h
index 6cf6bd0b4..12ecd2333 100644
--- a/src/common/win32_progress_callback.h
+++ b/src/updater/win32_progress_callback.h
@@ -3,7 +3,7 @@
#pragma once
#include "common/progress_callback.h"
-#include "windows_headers.h"
+#include "common/windows_headers.h"
class Win32ProgressCallback final : public BaseProgressCallback
{
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
index f9606422e..6126a519b 100644
--- a/src/util/CMakeLists.txt
+++ b/src/util/CMakeLists.txt
@@ -68,6 +68,7 @@ add_library(util
window_info.h
)
+target_precompile_headers(util PRIVATE "pch.h")
target_include_directories(util PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_link_libraries(util PUBLIC common simpleini imgui)
@@ -116,6 +117,7 @@ if(ENABLE_OPENGL)
gl/context_wgl.cpp
gl/context_wgl.h
)
+ target_link_libraries(util PRIVATE "opengl32.lib")
endif()
if(LINUX OR FREEBSD OR ANDROID)
@@ -222,6 +224,28 @@ endif()
if(WIN32)
target_sources(util PRIVATE
+ d3d_common.cpp
+ d3d_common.h
+ d3d11_device.cpp
+ d3d11_device.h
+ d3d11_pipeline.cpp
+ d3d11_pipeline.h
+ d3d11_stream_buffer.cpp
+ d3d11_stream_buffer.h
+ d3d11_texture.cpp
+ d3d11_texture.h
+ d3d12_builders.cpp
+ d3d12_builders.h
+ d3d12_descriptor_heap_manager.cpp
+ d3d12_descriptor_heap_manager.h
+ d3d12_device.cpp
+ d3d12_device.h
+ d3d12_pipeline.cpp
+ d3d12_pipeline.h
+ d3d12_stream_buffer.cpp
+ d3d12_stream_buffer.h
+ d3d12_texture.cpp
+ d3d12_texture.h
dinput_source.cpp
dinput_source.h
platform_misc_win32.cpp
@@ -232,9 +256,14 @@ if(WIN32)
xinput_source.cpp
xinput_source.h
)
- target_link_libraries(util PRIVATE d3d11.lib d3d12.lib d3dcompiler.lib dxgi.lib winmm.lib)
+ target_link_libraries(util PRIVATE d3d12ma)
+ target_link_libraries(util PRIVATE d3d11.lib d3d12.lib d3dcompiler.lib dxgi.lib winmm.lib Dwmapi.lib)
+
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
+ target_link_libraries(util PRIVATE WinPixEventRuntime::WinPixEventRuntime)
+ endif()
elseif(APPLE)
- target_sources(util PRIVATE
+ set(MAC_SOURCES
cocoa_tools.h
metal_device.h
metal_device.mm
@@ -242,10 +271,12 @@ elseif(APPLE)
metal_stream_buffer.mm
platform_misc_mac.mm
)
+ target_sources(util PRIVATE ${MAC_SOURCES})
find_library(IOK_LIBRARY IOKit REQUIRED)
find_library(METAL_LIBRARY Metal)
find_library(QUARTZCORE_LIBRARY QuartzCore)
target_link_libraries(util PRIVATE ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY} ${IOK_LIBRARY})
+ set_source_files_properties(${MAC_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS TRUE)
elseif(NOT ANDROID)
target_sources(util PRIVATE
platform_misc_unix.cpp
diff --git a/src/util/pch.cpp b/src/util/pch.cpp
new file mode 100644
index 000000000..ef4256aee
--- /dev/null
+++ b/src/util/pch.cpp
@@ -0,0 +1,4 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#include "pch.h"
diff --git a/src/util/pch.h b/src/util/pch.h
new file mode 100644
index 000000000..43c2fc050
--- /dev/null
+++ b/src/util/pch.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin
+// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
+
+#pragma once
+
+#include "common/types.h"
+
+#include "fmt/format.h"
+#include "gsl/span"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
diff --git a/src/util/util.vcxproj b/src/util/util.vcxproj
index a6c0bf5ec..b9ff6b5ab 100644
--- a/src/util/util.vcxproj
+++ b/src/util/util.vcxproj
@@ -61,6 +61,7 @@
+
@@ -162,6 +163,9 @@
true
+
+ Create
+
@@ -245,6 +249,9 @@
%(AdditionalIncludeDirectories);$(SolutionDir)dep\reshadefx\include
$(IntDir)/%(RelativeDir)/
+ Use
+ pch.h
+ pch.h
diff --git a/src/util/util.vcxproj.filters b/src/util/util.vcxproj.filters
index 9e02354e7..6fbaaf54e 100644
--- a/src/util/util.vcxproj.filters
+++ b/src/util/util.vcxproj.filters
@@ -70,6 +70,7 @@
+
@@ -146,6 +147,7 @@
+