mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
tests: build and run the render thread tests on Windows (MinGW)
render_thread_test is registered on MinGW (winpthreads provides the fixture's pthreads and nanosleep; the core takes its Win32 path). gl_render_thread_test gains the MinGW link path run_gl_scale_invariance.py uses on test/gl-scale-invariance-windows (static SDL3, opengl32 and its Win32 libraries, LTO, probe.exe), and a host with no window or GL 3.3 core context (headless, Windows over SSH) exits 77 from a preflight run, reported by CTest as a skip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -214,7 +214,9 @@ if(BUILD_TESTING)
|
||||
# Render thread ([video] render_thread) on vs off: the values the
|
||||
# guest reads back, native VRAM, the frame at S and the native-wide
|
||||
# surface are identical for a scripted stream with readbacks, mask
|
||||
# bits, uploads, ring wraps and per-primitive widescreen tags.
|
||||
# bits, uploads, ring wraps and per-primitive widescreen tags. A host
|
||||
# with no window/GL 3.3 context (headless, Windows over SSH) exits 77:
|
||||
# reported as skipped.
|
||||
add_test(NAME gl_render_thread_test
|
||||
COMMAND "${Python3_EXECUTABLE}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/run_gl_render_thread.py"
|
||||
@@ -223,7 +225,8 @@ if(BUILD_TESTING)
|
||||
--sdl-include "${_gl_scale_sdl_inc}"
|
||||
--sdl-library "$<TARGET_FILE:SDL3::SDL3>"
|
||||
--output "${CMAKE_CURRENT_BINARY_DIR}/gl-render-thread-results")
|
||||
set_tests_properties(gl_render_thread_test PROPERTIES LABELS "gpu;opengl;hardware" TIMEOUT 300)
|
||||
set_tests_properties(gl_render_thread_test PROPERTIES
|
||||
LABELS "gpu;opengl;hardware" TIMEOUT 300 SKIP_RETURN_CODE 77)
|
||||
unset(_gl_scale_sdl_inc)
|
||||
else()
|
||||
message(STATUS "gl_scale_invariance_test: not registered (needs macOS, Linux or MinGW, Python 3 and SDL3)")
|
||||
@@ -1127,8 +1130,9 @@ if(BUILD_TESTING)
|
||||
# Render thread core ([video] render_thread, docs/RENDER_THREAD.md):
|
||||
# ordering across ring wraps, the frame bound, stale-frame detection and
|
||||
# the drain + context hand-off sync point, against a fake executor.
|
||||
# The fixture itself uses POSIX threads and nanosleep.
|
||||
if(NOT WIN32)
|
||||
# The fixture itself uses POSIX threads and nanosleep (MinGW has both;
|
||||
# the core takes its Win32 path there).
|
||||
if(NOT MSVC)
|
||||
add_executable(render_thread_test tests/test_render_thread.c src/render_thread.c)
|
||||
target_include_directories(render_thread_test PRIVATE include)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
@@ -8,12 +8,16 @@ the stream (its own checks). A third run per scale with one frame in flight
|
||||
(PSX_TEST_RT_FRAMES is not needed: the fixture takes the bound as argv) is not
|
||||
required; the in-flight bound itself is covered by render_thread_test.
|
||||
|
||||
macOS/Linux: pass the SDL3 include directory and static library and a C
|
||||
compiler, as for run_gl_scale_invariance.py. Evidence (commands, output) is
|
||||
written to receipt.json under --output.
|
||||
macOS/Linux/Windows (MinGW): pass the SDL3 include directory and static
|
||||
library and a C compiler, as for run_gl_scale_invariance.py. Evidence
|
||||
(commands, output) is written to receipt.json under --output. When the host
|
||||
cannot create a hidden window with a GL 3.3 core context (headless, or Windows
|
||||
over SSH) the fixture exits SKIP_EXIT and so does this script: CTest reports a
|
||||
skip, not a pass.
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import re
|
||||
@@ -25,6 +29,11 @@ MAC_FRAMEWORKS = ["Cocoa", "OpenGL", "IOKit", "CoreVideo", "CoreAudio", "AudioTo
|
||||
"Carbon", "ForceFeedback", "GameController", "Metal", "QuartzCore",
|
||||
"CoreMedia", "AVFoundation", "Foundation", "CoreHaptics",
|
||||
"UniformTypeIdentifiers"]
|
||||
# The static SDL3's Win32 dependencies (as run_gl_texture_filter.py links them).
|
||||
WIN_LIBS = ["opengl32", "kernel32", "user32", "gdi32", "winmm", "imm32", "ole32",
|
||||
"oleaut32", "version", "uuid", "advapi32", "setupapi", "shell32", "dinput8"]
|
||||
SKIP_EXIT = 77
|
||||
WINDOWS = os.name == "nt" or platform.system().startswith(("MINGW", "MSYS", "CYGWIN"))
|
||||
KEYS = ("rb", "digest", "hires", "wide")
|
||||
|
||||
|
||||
@@ -78,6 +87,10 @@ def main():
|
||||
("xr", src / "psx_openxr.c"), ("rth", src / "render_thread.c"),
|
||||
("facade", src / "gpu_render.c")]
|
||||
sections = [] if platform.system() == "Darwin" else ["-ffunction-sections", "-fdata-sections"]
|
||||
# MinGW's PE linker reports undefined references from sections it later
|
||||
# collects, so there LTO drops them first (as run_gl_scale_invariance.py).
|
||||
if WINDOWS:
|
||||
sections.append("-flto")
|
||||
objs = []
|
||||
for name, path in sources:
|
||||
o = dest / (name + ".o")
|
||||
@@ -87,11 +100,15 @@ def main():
|
||||
print(r.stderr[-3000:])
|
||||
return 2
|
||||
objs.append(o)
|
||||
link = [args.cc, *objs, args.sdl_library, "-o", dest / "probe"]
|
||||
probe = dest / ("probe.exe" if WINDOWS else "probe")
|
||||
link = [args.cc, *objs, args.sdl_library, "-o", probe]
|
||||
if platform.system() == "Darwin":
|
||||
for f in MAC_FRAMEWORKS:
|
||||
link += ["-framework", f]
|
||||
link += ["-liconv", "-lm", "-lpthread", "-Wl,-dead_strip"]
|
||||
elif WINDOWS:
|
||||
# -static: no libwinpthread/libgcc DLLs needed next to probe.exe.
|
||||
link += ["-flto", "-static", *["-l" + x for x in WIN_LIBS], "-lm", "-Wl,--gc-sections"]
|
||||
else:
|
||||
link += ["-lGL", "-lm", "-ldl", "-lpthread", "-Wl,--gc-sections"]
|
||||
r = run(link)
|
||||
@@ -100,10 +117,17 @@ def main():
|
||||
return 2
|
||||
|
||||
ok = True
|
||||
first = True
|
||||
for s in [int(v) for v in args.scales.split(",") if v]:
|
||||
runs = {}
|
||||
for threaded in (0, 1):
|
||||
r = run([dest / "probe", s, threaded, args.frames])
|
||||
r = run([probe, s, threaded, args.frames])
|
||||
if first and r.returncode == SKIP_EXIT:
|
||||
# No window/GL context on this host: skip. Only the first
|
||||
# run may skip; after it, 77 is a failure like any other.
|
||||
print("SKIP:", r.stderr.strip()[-600:])
|
||||
return SKIP_EXIT
|
||||
first = False
|
||||
p = parse(r.stdout)
|
||||
tail = r.stdout.strip().splitlines()[-6:]
|
||||
print(f"scale {s} render_thread={threaded}: exit={r.returncode}", tail,
|
||||
|
||||
@@ -210,7 +210,12 @@ int main(int argc, char **argv) {
|
||||
int scale = argc > 1 ? atoi(argv[1]) : 1;
|
||||
int threaded = argc > 2 && argv[2][0] == '1';
|
||||
int frames = argc > 3 ? atoi(argv[3]) : 80;
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) return 2;
|
||||
/* No video device, window or GL context (headless, Windows over SSH):
|
||||
* exit 77, which the harness reports as a CTest skip. */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
fprintf(stderr, "SKIP no video (%s)\n", SDL_GetError());
|
||||
return 77;
|
||||
}
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
@@ -219,7 +224,19 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
SDL_Window *win = SDL_CreateWindow("Render thread hidden test", 0, 0, 320, 240,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
|
||||
if (!win) return 2;
|
||||
if (!win) { fprintf(stderr, "SKIP no window (%s)\n", SDL_GetError()); return 77; }
|
||||
{ /* Probe with the renderer's attributes: only a probe tells "no
|
||||
* context on this host" from "the renderer's init broke". */
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL_GLContext probe = SDL_GL_CreateContext(win);
|
||||
if (!probe) {
|
||||
fprintf(stderr, "SKIP no GL 3.3 core context (%s)\n", SDL_GetError());
|
||||
return 77;
|
||||
}
|
||||
SDL_GL_MakeCurrent(win, NULL);
|
||||
SDL_GL_DeleteContext(probe);
|
||||
}
|
||||
gr_set_backend(GR_BACKEND_OPENGL);
|
||||
gr_init(vram);
|
||||
gr_set_scale(scale);
|
||||
|
||||
Reference in New Issue
Block a user