Files
ARMSX2/pcsx2-gsrunner/CMakeLists.txt
Brian Degenhardt 5da1d59568 gsrunner: capture GS dump frames with RenderDoc
Add -renderdoc <path> and -renderdoc-frame N[,C], writing one .rdc per selected
dump frame.

RenderDoc's own triggers cannot reach gsrunner on a Wayland session. It polls
only X11/xcb for the capture key, so PlatformHasKeyInput() is false and F12 is
never seen. Target control cannot drive it either: RenderDoc hooks only the core
EGL entry points, while GLContextEGL prefers eglGetPlatformDisplayEXT and
eglCreatePlatformWindowSurfaceEXT, so no native window is ever registered for the
surface and there is nothing to attach a capture to. The in-application API
sidesteps both -- StartFrameCapture(nullptr, nullptr) captures the active device
whatever the windowing system, and needs no keypress, so a headless dump replay
can capture unattended.

Captures open and close at present boundaries in Host::BeginPresentFrame(), which
runs on the GS thread with the frame's work submitted but not yet presented.

RenderDoc must already be in the process, since it installs its hooks from its
library constructor. A late dlopen hands back a working API whose hooks were
never installed and then captures nothing, so that case is refused with the
LD_PRELOAD command to use instead.

Verified on aarch64/Asahi against a God of War II dump. Vulkan surfaceless
produces a valid capture: 351 actions, 218 draws, 99 textures, render target
carrying real image data. Windowed Vulkan cannot work under RenderDoc's layer at
all, which does not advertise VK_KHR_wayland_surface. GL captures record correct
events and texture contents but replay with black render targets on Honeykrisp.

3rdparty/include/renderdoc_app.h is RenderDoc's MIT-licensed in-application API
header, vendored verbatim.
2026-07-25 09:43:57 -07:00

64 lines
2.1 KiB
CMake

add_executable(pcsx2-gsrunner)
if (PACKAGE_MODE)
install(TARGETS pcsx2-gsrunner DESTINATION ${CMAKE_INSTALL_BINDIR})
else()
install(TARGETS pcsx2-gsrunner DESTINATION ${CMAKE_SOURCE_DIR}/bin)
endif()
target_sources(pcsx2-gsrunner PRIVATE
Main.cpp
RenderDocCapture.cpp
RenderDocCapture.h
)
if(UNIX)
target_link_libraries(pcsx2-gsrunner PRIVATE ${CMAKE_DL_LIBS})
endif()
target_include_directories(pcsx2-gsrunner PRIVATE
"${CMAKE_BINARY_DIR}/common/include"
"${CMAKE_SOURCE_DIR}/pcsx2"
)
target_link_libraries(pcsx2-gsrunner PRIVATE
PCSX2_FLAGS
PCSX2
)
if(WAYLAND_API AND UNIX AND NOT APPLE)
find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner REQUIRED)
# pkg_get_variable() needs CMake 3.18; the project minimum is 3.16
# (Ubuntu 20.04 LTS ships 3.16.3), so query pkg-config directly.
execute_process(
COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT WAYLAND_PROTOCOLS_DIR)
message(FATAL_ERROR
"wayland-protocols not found via pkg-config. "
"Install wayland-protocols-devel (Fedora) / libwayland-dev (Debian).")
endif()
set(_xdg_xml "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml")
set(_xdg_h "${CMAKE_CURRENT_BINARY_DIR}/xdg-shell-client-protocol.h")
set(_xdg_c "${CMAKE_CURRENT_BINARY_DIR}/xdg-shell-protocol.c")
add_custom_command(OUTPUT ${_xdg_h}
COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header ${_xdg_xml} ${_xdg_h}
DEPENDS ${_xdg_xml} VERBATIM)
add_custom_command(OUTPUT ${_xdg_c}
COMMAND ${WAYLAND_SCANNER_EXECUTABLE} private-code ${_xdg_xml} ${_xdg_c}
DEPENDS ${_xdg_xml} VERBATIM)
target_sources(pcsx2-gsrunner PRIVATE ${_xdg_h} ${_xdg_c})
target_include_directories(pcsx2-gsrunner PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
# Generated C file; skip the C++ PCH which #includes <cstdint>.
set_source_files_properties(${_xdg_c} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
target_link_libraries(pcsx2-gsrunner PRIVATE ${WAYLAND_CLIENT_LIBRARIES})
target_include_directories(pcsx2-gsrunner PRIVATE ${WAYLAND_CLIENT_INCLUDE_DIRS})
endif()