mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-07 04:36:00 -10:00
The 4.0 flip from the phase 5 plan: emuThreadDefaultFor() is true for release, nightly and dev (an unknown channel string stays Off), and VJ_EMU_THREAD_DEFAULT_VALUE is 1 for every channel. The channel still names the build in About and the log. Unchanged: a stored ui.emu_thread wins, --emu-thread off runs one start inline, a failed thread start falls back inline, headless runs stay inline unless --emu-thread on. Called by the maintainer with G1-G3 met and G4/G5 still open; the phase 5 plan and the design doc's section 8 record that. The default smoke tests now expect "default on" in every channel; the unit test pins all three channels On and unknown ones Off. Refs #1039, #967. Co-authored-by: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
dfc09f083d
commit
7637eeda23
8 files changed
+42
-32
No files matched your search
+7
-8
@@ -69,18 +69,17 @@ set(VJ_TV_DEFAULT "auto" CACHE STRING "TV mode setting for a fresh config: auto
|
||||
if(NOT VJ_TV_DEFAULT MATCHES "^(auto|manual|off)$")
|
||||
message(FATAL_ERROR "VJ_TV_DEFAULT must be auto, manual or off (got '${VJ_TV_DEFAULT}')")
|
||||
endif()
|
||||
# The build channel (#967 phase 3d, design section 8): release | nightly | dev. Nightlies default Settings > Interface >
|
||||
# Emulation thread to On for users who never chose; releases and dev builds (PR artifacts, local builds) default Off.
|
||||
# app-package.yml passes it per lane like VJ_TV_DEFAULT above; a plain configure is dev.
|
||||
set(VJ_BUILD_CHANNEL "dev" CACHE STRING "release | nightly | dev: the build channel (nightlies default the emulation thread on, #967)")
|
||||
# The build channel (#967 phase 3d, design section 8): release | nightly | dev. Since the 4.0 flip (#1039 phase 5c) every
|
||||
# channel defaults Settings > Interface > Emulation thread to On for users who never chose; a stored choice always wins.
|
||||
# The channel still names the build in About and the log. app-package.yml passes it per lane like VJ_TV_DEFAULT above;
|
||||
# a plain configure is dev. VJ_EMU_THREAD_DEFAULT_VALUE stays a variable so a channel can be defaulted Off again in one
|
||||
# place (build_channel.h's static_assert checks it against emuThreadDefaultFor).
|
||||
set(VJ_BUILD_CHANNEL "dev" CACHE STRING "release | nightly | dev: the build channel shown in About and the log (#967)")
|
||||
set_property(CACHE VJ_BUILD_CHANNEL PROPERTY STRINGS release nightly dev)
|
||||
if(NOT VJ_BUILD_CHANNEL MATCHES "^(release|nightly|dev)$")
|
||||
message(FATAL_ERROR "VJ_BUILD_CHANNEL must be release, nightly or dev (got '${VJ_BUILD_CHANNEL}')")
|
||||
endif()
|
||||
set(VJ_EMU_THREAD_DEFAULT_VALUE 0)
|
||||
if(VJ_BUILD_CHANNEL STREQUAL "nightly")
|
||||
set(VJ_EMU_THREAD_DEFAULT_VALUE 1)
|
||||
endif()
|
||||
set(VJ_EMU_THREAD_DEFAULT_VALUE 1)
|
||||
add_library(vj_build_channel INTERFACE)
|
||||
target_compile_definitions(vj_build_channel INTERFACE VJ_BUILD_CHANNEL="${VJ_BUILD_CHANNEL}" VJ_EMU_THREAD_DEFAULT=${VJ_EMU_THREAD_DEFAULT_VALUE})
|
||||
option(VJ_MAC_APP_STORE "Build the sandboxed Mac App Store edition" OFF)
|
||||
|
||||
+8
-7
@@ -566,11 +566,12 @@ busy UI no longer stalls the picture. The game runs at the true Jaguar rate (60.
|
||||
sound card's clock, and the display shows the newest frame (on a 60 Hz panel the true-rate drift alone skips one frame about every 18 s; in this phase frames that finish
|
||||
close to the take point also repeat or skip more often than in the single-thread loop, roughly 1 to 2.5 a second as
|
||||
measured on a 60 Hz panel; **Frame pacing: Match display**, below, removes both).
|
||||
The setting takes effect at the next start. It is **on** by default in nightly builds and **off** in releases (the build
|
||||
channel; About shows it, and the log prints `[emu] channel=...`). A stored choice always wins in both directions; **Reset
|
||||
group** in Settings > Interface returns to the channel's default. `dev` builds (pull-request artifacts, local builds)
|
||||
default to off; `-DVJ_BUILD_CHANNEL=nightly` builds the nightly default from source. `--emu-thread on|off` decides for one run; headless runs stay single-threaded unless it
|
||||
says `on`.
|
||||
The setting takes effect at the next start. It is **on** by default in every build since 4.0 (releases, nightlies and
|
||||
`dev` builds alike; About shows the build channel, and the log prints `[emu] channel=..., emulation thread default on`).
|
||||
A stored choice always wins in both directions; **Reset group** in Settings > Interface returns to the default. To run
|
||||
without it, turn it off in Settings (persistent) or start with `--emu-thread off` (one run); if the thread cannot start,
|
||||
the app falls back to the single-thread loop and says so in the log. Headless runs stay single-threaded unless
|
||||
`--emu-thread on` says otherwise.
|
||||
|
||||
With vsync, the window waits until just before each vblank, passing input to the emulation as it arrives, and then
|
||||
shows the newest frame (the late latch, `src/late_latch.h`). It stays off until it has found where the vblanks are,
|
||||
@@ -617,8 +618,8 @@ takes longer than a quarter of a second shows a spinner instead of freezing the
|
||||
|
||||
### Reporting a threading problem
|
||||
|
||||
The emulation thread is being qualified to become the default in releases (#1039). If something goes wrong only with it on
|
||||
(stutter, a hang, a crash, lagging input, skipping sound), please comment on #1039 or open an issue that links it, with:
|
||||
The emulation thread is the default since 4.0 (#1039). If something goes wrong only with it on (stutter, a hang, a crash,
|
||||
lagging input, skipping sound), compare with `--emu-thread off`, then comment on #1039 or open an issue that links it, with:
|
||||
|
||||
- The first line of **Help > About**: the version and build channel, such as `Virtual Jaguar 4.0.0 (nightly build)`.
|
||||
- The **Now: ...** line under **Settings > Video > Frame pacing**: which clock the thread follows, and why.
|
||||
|
||||
@@ -426,10 +426,8 @@ set_tests_properties(emu_thread_default_unit PROPERTIES TIMEOUT 60 LABELS emu_th
|
||||
# The default rule through the real app (Review Focus 4): the data dir's ui.emu_thread decides "wanted"; only an unset key
|
||||
# follows the configured channel. Headless stays inline unless --emu-thread says otherwise, so "this run" is off; the
|
||||
# stored-choice line is what pins the rule. One data dir per test (ctest -j runs them in parallel).
|
||||
set(_vj_chan_def off)
|
||||
if(VJ_BUILD_CHANNEL STREQUAL "nightly")
|
||||
set(_vj_chan_def on)
|
||||
endif()
|
||||
# Every channel defaults On since the 4.0 flip (#1039 5c); CMakeLists.txt validated the channel name already.
|
||||
set(_vj_chan_def on)
|
||||
foreach(_p unset false true)
|
||||
set(_d "${CMAKE_CURRENT_BINARY_DIR}/emu-default-${_p}")
|
||||
file(MAKE_DIRECTORY "${_d}")
|
||||
|
||||
+10
-6
@@ -1,5 +1,6 @@
|
||||
// The build channel and the emulation-thread default (#967 phase 3d, design section 8). Set by app/CMakeLists.txt
|
||||
// (VJ_BUILD_CHANNEL: release | nightly | dev; VJ_EMU_THREAD_DEFAULT: 1 for nightly) through the vj_build_channel target.
|
||||
// The build channel and the emulation-thread default (#967 phase 3d, design section 8; #1039 phase 5c). Set by
|
||||
// app/CMakeLists.txt (VJ_BUILD_CHANNEL: release | nightly | dev; VJ_EMU_THREAD_DEFAULT: 1 for every channel since the
|
||||
// 4.0 flip) through the vj_build_channel target.
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
|
||||
@@ -7,14 +8,17 @@
|
||||
#define VJ_BUILD_CHANNEL "dev"
|
||||
#endif
|
||||
#ifndef VJ_EMU_THREAD_DEFAULT
|
||||
#define VJ_EMU_THREAD_DEFAULT 0
|
||||
#define VJ_EMU_THREAD_DEFAULT 1
|
||||
#endif
|
||||
|
||||
namespace vj {
|
||||
constexpr const char* kBuildChannel = VJ_BUILD_CHANNEL; // "release" | "nightly" | "dev"
|
||||
constexpr bool kEmuThreadDefault = VJ_EMU_THREAD_DEFAULT != 0; // nightly: true
|
||||
// What a channel defaults Settings > Interface > Emulation thread to for a user who never chose.
|
||||
constexpr bool emuThreadDefaultFor(std::string_view channel) { return channel == "nightly"; }
|
||||
constexpr bool kEmuThreadDefault = VJ_EMU_THREAD_DEFAULT != 0; // every channel: true (phase 5c)
|
||||
// What a channel defaults Settings > Interface > Emulation thread to for a user who never chose. Since the 4.0 flip
|
||||
// (#1039 5c) every channel defaults On; a channel this build does not know stays Off, the conservative answer.
|
||||
constexpr bool emuThreadDefaultFor(std::string_view channel) {
|
||||
return channel == "release" || channel == "nightly" || channel == "dev";
|
||||
}
|
||||
// The setting as run: a stored choice (0 off, 1 on) always wins; only "never chosen" (any negative) follows the channel.
|
||||
constexpr bool emuThreadEffective(int pref, bool channelDefault) { return pref < 0 ? channelDefault : pref == 1; }
|
||||
static_assert(kEmuThreadDefault == emuThreadDefaultFor(kBuildChannel),
|
||||
|
||||
+2
-2
@@ -304,8 +304,8 @@ void drawInterfaceTab(App& app) {
|
||||
ui::hint("Runs the emulation on its own thread, so a slow frame or a busy window does not stall the picture, and "
|
||||
"the game keeps its true speed (60.05 Hz, 50.08 Hz in PAL) on any display. Takes effect the next time the "
|
||||
"app starts. Break, Step, breakpoints and the GDB stub work with it on. %s",
|
||||
kEmuThreadDefault ? "This is a nightly build, where it is on unless you turn it off here. Release builds default to off."
|
||||
: "Off by default here; nightly builds default to on.");
|
||||
kEmuThreadDefault ? "On unless you turn it off here; --emu-thread off runs one start without it."
|
||||
: "Off by default in this build; turn it on here.");
|
||||
if (app.emuThreadWanted() != app.emuThreadThisRun()) ImGui::TextDisabled("Restart the app to apply.");
|
||||
ImGui::SeparatorText("Save states");
|
||||
ImGui::TextUnformatted("Resume where I left off");
|
||||
|
||||
@@ -29,13 +29,14 @@ int main() {
|
||||
CHECK(emuThreadEffective(1, def) == true);
|
||||
CHECK(emuThreadEffective(-1, def) == def);
|
||||
}
|
||||
CHECK(emuThreadDefaultFor("nightly") && !emuThreadDefaultFor("release") && !emuThreadDefaultFor("dev"));
|
||||
// Since the 4.0 flip (#1039 5c) every channel defaults On; an unknown channel stays Off.
|
||||
CHECK(emuThreadDefaultFor("nightly") && emuThreadDefaultFor("release") && emuThreadDefaultFor("dev"));
|
||||
CHECK(!emuThreadDefaultFor("") && !emuThreadDefaultFor("Nightly") && !emuThreadDefaultFor("nightlies"));
|
||||
CHECK(emuThreadEffective(-5, true) && !emuThreadEffective(-5, false)); // any negative is "never chosen"
|
||||
CHECK(!emuThreadEffective(2, true)); // only 1 is On
|
||||
const std::string_view c = kBuildChannel; // what THIS build was configured with
|
||||
CHECK(c == "release" || c == "nightly" || c == "dev");
|
||||
CHECK(kEmuThreadDefault == (c == "nightly"));
|
||||
CHECK(kEmuThreadDefault); // the configured channel is one of the three above, and all three default On
|
||||
std::printf("emu_thread_default: channel %s, default %s\n", kBuildChannel, kEmuThreadDefault ? "on" : "off");
|
||||
if (g_fail) {
|
||||
std::printf("emu_thread_default: %d failure(s)\n", g_fail);
|
||||
|
||||
@@ -301,6 +301,11 @@ reach the core as commands. The restart bounce that a mode change needs is count
|
||||
is a workflow env beside the TV default; the flatpak job rewrites the manifest's committed `-DVJ_BUILD_CHANNEL=release` because
|
||||
its `config-opts` are committed. The bar that lets it ship is `no_threaded_limits` (static, in CI) plus the Studio gate
|
||||
`app/tests/emu_thread_gate_check.sh`.
|
||||
*Shipped (phase 5c, 2026-11-01):* **every channel defaults On** (`emuThreadDefaultFor` is true for `release`, `nightly`
|
||||
and `dev`; `VJ_EMU_THREAD_DEFAULT_VALUE` is 1 for all three). The maintainer called the flip before gates G4 and G5 of
|
||||
the phase 5 plan were met (the windowed evidence is the Studio's 60 Hz panel; see the plan's evidence table). Unchanged:
|
||||
a stored `ui.emu_thread` wins, `--emu-thread off` runs one start inline, a failed thread start falls back inline, and
|
||||
headless runs stay inline unless `--emu-thread on`. An unknown channel string still defaults Off.
|
||||
- The old loop stays selectable until a release ships with the setting defaulting On and no regressions; then it is
|
||||
removed.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ Issue: #1039 (part of #967 / #254). Design of record: [app-emulation-thread-desi
|
||||
|
||||
**Goal:** the 4.0 release turns Settings > Interface > Emulation thread **On by default**, on evidence, with the inline loop still selectable. This phase is mostly qualification. The only behaviour change is the last PR, which flips the release default.
|
||||
|
||||
**Status (2026-11-01):** 5c shipped. Every channel (`release`, `nightly`, `dev`) defaults On. The maintainer called the flip with G1–G3 met and G4/G5 still open (see the evidence table); any G4/G5 report now lands against the default-on build.
|
||||
|
||||
**Not in this phase:**
|
||||
- **Retiring the inline loop** (`stepEmulation`, `Pacer`, the inline branch of `runInteractive`). #1039's rule replaces the phase 4 plan's "Retiring the inline loop (phase 5)": remove it only after a stable release has shipped default-on without regressions. That follow-up issue is filed when the evidence exists, not before.
|
||||
- **Changing Frame pacing's default.** It stays Jaguar rate unless decision 1 below says otherwise.
|
||||
@@ -78,7 +80,7 @@ The `*_e2e` tests (`input_e2e`, `devices_e2e`, `bios_e2e`, `debug_scan_e2e`, `de
|
||||
- A short "Reporting a threading problem" note in the README's "Emulation thread" section: how to report (the About window's version and channel line, the perf note, `--emu-thread off` to compare).
|
||||
- One pinned comment on #1039 asking nightly users for G4 reports.
|
||||
- Refs #1039.
|
||||
- **5c `feat(app)`: releases default the emulation thread On (the flip, last).**
|
||||
- **5c `feat(app)`: releases default the emulation thread On (the flip, last).** *Shipped 2026-11-01, with `dev` On too (decision 2).*
|
||||
- `emuThreadDefaultFor("release")` returns true. `VJ_EMU_THREAD_DEFAULT_VALUE` follows in `app/CMakeLists.txt`, and the `static_assert` in `build_channel.h` and the `emu_thread_default_unit` / `emu_thread_default_smoke_*` expectations change with it.
|
||||
- Unchanged:
|
||||
- a stored `ui.emu_thread` choice still wins;
|
||||
@@ -93,7 +95,7 @@ The `*_e2e` tests (`input_e2e`, `devices_e2e`, `bios_e2e`, `debug_scan_e2e`, `de
|
||||
| | Question | Recommendation |
|
||||
|---|---|---|
|
||||
| 1 | **Frame pacing default:** keep Jaguar rate for 4.0, or default nightlies to Match display now so feedback accrues? | Default **nightlies** to Match display after G3 passes; keep Jaguar rate for the 4.0 release. Mode B's only windowed evidence is one 60 Hz macOS panel. |
|
||||
| 2 | **`dev` channel after the flip:** Off (today) or On? | **On**, with 5c. Phase 3 kept `dev` Off so PR artifacts behave like releases; after the flip that same reason means On. |
|
||||
| 2 | **`dev` channel after the flip:** Off (today) or On? | **On**, with 5c. Phase 3 kept `dev` Off so PR artifacts behave like releases; after the flip that same reason means On. *Taken: 5c sets all three channels On.* |
|
||||
| 3 | **G4 without volunteers:** if no Windows, Linux or 120 Hz report arrives, does the flip wait? | Wait for **Windows** (the largest user base), or waive in writing on #1039. Linux and 120 Hz can ship on unit-test coverage plus the inline fallback. |
|
||||
| 4 | **G5 length:** two weeks of nightlies? | Two weeks, starting when 5a merges, so the twins have run on every PR in that time. |
|
||||
|
||||
@@ -112,5 +114,5 @@ Studio = the Mac Studio (M4 Max, 16 cores) on its 60 Hz panel, every windowed ru
|
||||
| 2026-10-31 | 43383a05 | Studio | **G3 halt, inline arm** | **Not measurable.** Inline, a halt runs in the core's nested `haltedFrame` loop; `--perf-halt`'s Continue is in the outer loop, so it never comes. That nested loop still runs the UI, so the debugger's Continue button works. Run stopped after 1 h 40 min |
|
||||
| 2026-10-31 | 43383a05 | Studio | **G3 halt,** A vs B (`mbt-p5-{A,B}-halt`) | **Met.** A 5 s halt with all eight Tools windows open, then Continue: 0 underruns at Jaguar rate and at Match display. Match display ends B (locked), ticks dropped 0. The m3 run's single underrun did not come back |
|
||||
| 2026-10-31 → 11-01 | 43383a05 | Studio | **G3 phase 3 gate** (`emu_thread_gate_check.sh`, yarc; `p5-gate*`) | **Met on a quiet host,** to be run again on the 4.0 candidate. Two quiet runs pass: halted iteration p99 18.32 and 18.15 ms in part A, 18.35 and 17.57 ms in part B (limit 25 ms; phase 3 measured 18.0–20.7). Neuro ok. One run under load failed part A at p99 33.08 ms (10 of 281 halted iterations missed a vsync): the host's 1-minute load rose from 3.6 to 7.0 during it. One run never got a quiet host (load 89, Spotlight) and was skipped |
|
||||
| | | Windows, Linux, 120 Hz | **G4** | Pending: request on #1039 |
|
||||
| | | Windows, Linux, 120 Hz | **G4** | Pending: request on #1039. Not waited for: the maintainer called the flip on 2026-11-01 (5c) |
|
||||
| 2026-10-31 → 2026-11-14 | nightlies | | **G5** | Window open from the 5a merge |
|
||||
Reference in new issue
Block a user