Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
99cf6be
docs(007): add v1.5 spec + requirements checklist + clarifications
relmer Jun 5, 2026
dac5493
docs(007): plan, research, data-model, contracts, quickstart for v1.5
relmer Jun 5, 2026
2291a40
docs(007): generate v1.5 tasks (75 tasks across 8 phases)
relmer Jun 5, 2026
99a2e38
docs(007): resolve all 13 analyze findings
relmer Jun 5, 2026
aa8648e
docs(007): drop CBN_SELENDOK secondary trigger; subclass watcher is s…
relmer Jun 5, 2026
f0d61fc
docs(007): correct ColorScheme enum + combo control id to match v1.4 …
relmer Jun 5, 2026
93b46f6
feat(007): reserve v1.5 resource IDs, pch headers, shaders folder
relmer Jun 5, 2026
5276755
feat(core): add ScanlineStyleMapping with logarithmic style->line-count
relmer Jun 5, 2026
e994da4
refactor(core): remove fade-timer overlay feature (US4)
relmer Jun 5, 2026
d06759c
test(007): add MonitorRenderContext FPS publisher tests (US1 T021)
relmer Jun 5, 2026
f7cd62b
feat(core): publish render-thread FPS to dialog timer (US1 T023)
relmer Jun 5, 2026
ba1d1e2
test(007): add v1.5 snapshot/rollback coverage to controller tests (U…
relmer Jun 5, 2026
67e01c2
feat(core): add v1.5 rollback fields and live SharedState mirrors (US…
relmer Jun 5, 2026
45b9546
test(007): add CommitLiveMode_WritesAllV15Fields (US1 T033b)
relmer Jun 5, 2026
496dc68
feat(core): add CommitLiveMode wrapper for PSN_APPLY path (US1 T033a)
relmer Jun 5, 2026
a8b712c
feat(ui): convert config dialog to two-tab property sheet (US1 T028-T…
relmer Jun 5, 2026
a85406f
test(007): glow-enabled defaults, round-trip, and bloom-bypass (US2 T…
relmer Jun 5, 2026
bb736b7
feat(core): persist GlowEnabled and gate bloom on it (US2 T037-T039)
relmer Jun 5, 2026
c80ccf7
feat(ui): wire Glow Enabled checkbox + bypass UI (US2 T040-T044)
relmer Jun 5, 2026
0bc671c
test(007): scanlines defaults, round-trip, clamping, preset-orthogona…
relmer Jun 5, 2026
b6f76e2
feat(core): persist scanline settings to registry (US3 T048-T049)
relmer Jun 5, 2026
54b9cd9
feat(ui): scanlines controls + ported shader (US3 T050+T053+T054)
relmer Jun 5, 2026
ef12cfc
refactor(ui): performance-page layout rework + label renames (mini-2.5)
relmer Jun 6, 2026
7c8f0cd
feat(ui): cross-page reset-to-defaults frame button (mini-2.5)
relmer Jun 6, 2026
ac6e77d
feat(rendering): scanline post-bloom pass (US3 T051+T052)
relmer Jun 6, 2026
c5e9466
feat(ui): tooltips on disabled glow controls (US2 T043)
relmer Jun 6, 2026
f6a8ebe
feat(core): append ColorScheme::Custom=5 (US5 T056+T059)
relmer Jun 6, 2026
52a17d5
feat(core): CustomColor + palette persistence (US5 T057+T061)
relmer Jun 6, 2026
b454df8
test(core): custom-color rollback semantics (US5 T058)
relmer Jun 6, 2026
f7c9a65
feat(rendering): custom-color render path + v1.5 live-atomics wiring …
relmer Jun 6, 2026
cdff879
feat(ui): custom color picker wiring (US5 T063-T066)
relmer Jun 6, 2026
1122b64
docs(changelog): v1.5 release notes + upgrade migration note (US6 T067)
relmer Jun 6, 2026
a3500b9
test(core): v1.4 settings regression guard + Phase 8 closure (T072a, …
relmer Jun 6, 2026
735615d
fix(ui): reposition Reset button after sheet final layout (WM_SHOWWIN…
relmer Jun 6, 2026
85eadb4
fix(ui): Cancel/Esc now closes dialog + Reset button repositions reli…
relmer Jun 6, 2026
9723ae4
fix(ui): close modeless property sheet
relmer Jun 6, 2026
4dcbe1c
fix(ui): align reset button from ok layout
relmer Jun 6, 2026
92daaba
fix(ui): remove property sheet help caption
relmer Jun 6, 2026
1511bf2
fix(ui): skip unchanged performance tab titles
relmer Jun 6, 2026
0e8b3c5
fix(ui): space scanline controls consistently
relmer Jun 6, 2026
815569f
fix(ui): route property sheet keyboard navigation
relmer Jun 6, 2026
31fa533
fix(ui): keep fullscreen toggle state synced
relmer Jun 6, 2026
dab91b9
fix(ui): reset button left-aligned to tab + z-order on rebuild + scan…
relmer Jun 6, 2026
84e33d6
fix(ui): defer modeless property sheet destroy to avoid comctl32 re-e…
relmer Jun 6, 2026
5818829
fix(ui): use canonical modeless property sheet teardown via GetCurren…
relmer Jun 6, 2026
44c3bf9
fix(ui): move only scanlines checkbox to Performance page, keep slide…
relmer Jun 6, 2026
b90223b
feat(ui): per-page FPS/GPU readout + correct centering
relmer Jun 6, 2026
7b4d960
fix(ui): remove buggy color combo subclass + add live color swatch
relmer Jun 6, 2026
9d10060
fix(ui): color swatch as owner-draw button, clickable, aligned with c…
relmer Jun 6, 2026
2714115
fix(render): overlay text picks up custom colour scheme
relmer Jun 6, 2026
dc9685b
fix(render): scanlines run independently of glow toggle
relmer Jun 6, 2026
40a9444
fix(ui): swatch cycle uses rain's clock so colour matches
relmer Jun 6, 2026
348c4eb
Merge remote-tracking branch 'origin/master' into 007-dialog-tabs-sca…
relmer Jun 6, 2026
2fd144c
test(007): T055 — automate v1.4-hive migration sanity check
relmer Jun 6, 2026
0150bad
fix(007): address PR review findings
relmer Jun 7, 2026
9c5bc8c
docs(007): add v1.5 row to README What's New table
relmer Jun 7, 2026
be6d808
docs(007): split [Unreleased] into proper [1.4] and [1.5] sections
relmer Jun 7, 2026
9a47879
docs(007): reword v1.5 README row
relmer Jun 7, 2026
452ec95
fix(config): apply live GPU and multi-monitor changes to running app
relmer Jun 7, 2026
300bd1a
chore(version): bump minor to 1.5
relmer Jun 7, 2026
76f1730
Potential fix for pull request finding
relmer Jun 7, 2026
c6015b4
docs(007): correct scanline-location, custom-color, and perf-readout …
relmer Jun 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,8 @@ git diff # Bad - will paginate
<!-- SPECKIT START -->
For additional context about technologies to be used, project structure,
shell commands, and other important information, read the current plan at
`specs/006-multimon-gpu-efficiency/plan.md` and its supporting research,
data model, contracts (`specs/006-multimon-gpu-efficiency/contracts/`),
and quickstart documents.
`specs/007-dialog-tabs-scanlines-glowtoggle/plan.md` and its supporting
research, data model, contracts
(`specs/007-dialog-tabs-scanlines-glowtoggle/contracts/`), and quickstart
documents.
<!-- SPECKIT END -->
2 changes: 1 addition & 1 deletion .specify/feature.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"feature_directory":"specs/006-multimon-gpu-efficiency"}
{"feature_directory":"specs/007-dialog-tabs-scanlines-glowtoggle"}
116 changes: 105 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,123 @@

All notable changes to MatrixRain are documented in this file.

## [Unreleased]
## [1.5.2161] - 2026-06-06

### Added

- **User Story 1 (P1) — Runtime topology and device-loss recovery.** MatrixRain now responds to monitors being added or removed while running (WM_DISPLAYCHANGE, coalesced across windows) and to the active GPU becoming unavailable (driver reset, sleep/resume, eGPU unplugged - detected via Present HRESULT). The render context is rebuilt automatically; this fixes the previously-reported "GPU stuck at ~90% after undocking a Surface Book 3" defect where the ghost monitor's render thread continued processing forever.
- **User Story 2 (P1) — Optional multi-monitor spanning.** New "Render on all monitors" checkbox in the configuration dialog (default on). Toggling it live applies within 1 second; Cancel reverts.
- **User Story 3 (P2) — GPU adapter selection.** New "GPU" dropdown in the configuration dialog listing each real adapter name (with "(default)" appended to the system default). Software/WARP adapters are excluded. Selection persists by description string; if the saved adapter is missing at startup, the application silently falls back to the system default. Live device-switch takes effect within 1 second.
- **User Story 4 (P2) — Frame cap on high-refresh monitors.** Per-monitor `FrameLimiter` engages only when the monitor's native refresh exceeds 60 Hz, capping that monitor's rendering to 60 FPS. At ≤60 Hz the existing vsync path is preserved with no measurable per-frame overhead. Substantially reduces GPU work on 144Hz / 165Hz laptop displays.
- **User Story 5 (P3) — Graphics quality preset spectrum.** New "Quality" slider (Low / Medium / High / Custom) in a "Graphics quality" group box. Three discrete tuning sliders are always visible — Glow passes (1-4), Glow resolution (Eighth / Quarter / Half / Full), Glow smoothness (Low / Medium / High). Each quality-related control has an "ⓘ" infotip; hovering or tabbing-then-pressing-Space/Enter reveals a tooltip with a description and standardized GPU-performance-impact phrase. Glow Intensity at 0% now disables the entire bloom pipeline (true off, not just darker). First-run heuristic picks a starting preset based on detected GPU class and total monitor pixel count (discrete → High; integrated + modest load → Medium; integrated + heavy load → Low). Custom-drift behaviour: any direct edit of an advanced control auto-flips the preset to Custom and saves the resulting values for restoration when the user later re-selects Custom.
- **Two-tab configuration property sheet.** The single-page settings dialog
is now split into **Visuals** and **Performance** tabs hosted by the Win32
`PropertySheetW` host control. Visuals owns Density, Speed, Glow Intensity /
Size, Color scheme, the Scanline Intensity / Style sliders, and
Start-in-fullscreen. Performance owns Multi-monitor, Enable glow, Enable
scanlines, GPU adapter, Quality preset + advanced sliders, and Show
performance metrics. Each page shows the primary monitor's FPS
and the process's GPU load in a bottom-right readout, updated once per
second (`NN fps, NN% GPU`).
- **Cross-page "Reset to defaults" button.** Lives in the property-sheet
footer (left of OK/Cancel) and resets every control on both tabs in one
click; the live preview snaps back instantly. The persisted 16-swatch
custom-colour palette is preserved across Reset (FR-035 carve-out).
- **Enable glow checkbox** on the Performance tab. Toggling it OFF
bypasses the entire bloom pipeline (no extract / blur / composite passes)
and greys every glow-dependent control on both tabs with an explanatory
tooltip pointing at the toggle's location. Bloom GPU resources stay
allocated so re-enabling is instant. Replaces the v1.4 "Glow Intensity =
0" workaround; the slider minimum is back to 1.
- **CRT scanlines post-process** (Enable toggle on Performance; Intensity /
Style sliders on Visuals). Enabled by default
on fresh installs and after upgrade (see migration note below). Intensity
slider (1-100, default 30) controls darkening strength; Style slider
(1-100, default 50) controls line density (Style 1 ≈ 981 lines / Style
100 ≈ 150 lines, geometric falloff). Runs independently of glow — the
no-glow render path routes through `m_postBloomTarget` so the scanline
PS always has a populated SRV.
- **Custom color picker** as a sixth Color combo entry (`Custom…`).
Selecting it opens the standard Win32 `ChooseColor` dialog pre-populated
with the prior custom RGB (default `RGB(0, 255, 0)`). The 16-swatch
palette persists across launches (and across Reset). A clickable
owner-draw colour swatch next to the combo previews the selected scheme;
in Cycle mode the swatch animates at 30 Hz in sync with the rain.
Clicking the swatch opens the chooser regardless of which scheme is
currently active.
- **Per-page live FPS / GPU% readout** in each page's bottom-right corner.
Stable tab title text ("Performance") avoids the per-second tab-control
flicker that an earlier prototype had.

### Changed

- Bloom pipeline is now runtime-parametric: blur passes (1-4), bloom buffer resolution (full/half/quarter/eighth), and blur kernel taps (5 / 9 / 13) are all selectable per-frame from the quality preset / advanced sliders. Three blur shader variants are compiled at startup so the tap-count switch is free at draw time.
- Default settings on a fresh install now pick a quality preset matched to detected hardware rather than always using the maximum.
- Reset button in the configuration dialog now restores every v1.4 setting (multi-monitor, GPU, quality preset, glow passes / resolution / smoothness) in addition to the v1.3 controls it previously covered.
- **Glow Intensity slider minimum** reverted from 0 to 1 (the dedicated
Enable glow toggle now owns "off").
- **Label renames** in the Performance tab: "Render on all monitors" →
"Use all monitors"; "Show debug statistics" → "Show performance
metrics". Registry value names unchanged; existing installs round-trip
without migration.
- **Modeless property-sheet teardown** now uses the canonical
`PropSheet_GetCurrentPageHwnd` polling pattern in the main message
loop instead of `DestroyWindow`-from-PSN_APPLY (which re-entered the
frame subclass and overflowed the stack).
- **Config dialog Z-order** is re-asserted after
`Application::RebuildContextsForCurrentMode` so toggling Start In
Fullscreen no longer hides the dialog behind the freshly-created
rain window.
- **Overlay text colour** (Settings/Help/Exit hint, `?` hotkey list,
`/?` usage dialog) now resolves `ColorScheme::Custom` from
`snapshot.customColor` instead of falling through `GetColorRGB`'s
green fallback.

### Removed

- The backtick (`) debug hotkey that toggled the per-character fade-timer overlay. (The "Show fade timers" dialog checkbox is unchanged.)
- The orphan fade-timer debug overlay (`ShowFadeTimers` registry value,
`m_showFadeTimers` field, dialog checkbox, and the backtick (`)
debug hotkey). Legacy `ShowFadeTimers` registry values are silently
ignored on Load.

### Fixed

- **Reset-to-defaults wiped the saved custom-colour palette.** The 16
saved swatches now survive Reset and Reset→OK per FR-035.
- **Glow-off path could sample stale bloom.** The no-glow composite
branch now binds a null SRV at slot 1 so the composite PS doesn't
resample whatever bloom texture was left bound by a prior frame.
- **Window-message ID collision.** Two `WM_APP` messages (Reset-button
reposition and custom-colour-chooser open) had been defined with the
same numeric value; separated to distinct IDs.
- **Modeless `PropertySheetW` failure path.** A `-1` return is now
recognised as failure instead of being cast to `(HWND)-1` and treated
as a valid sheet handle.

### Upgrade migration note

**Visible change on first launch after upgrading from v1.4:** existing
installs will see scanlines render immediately on the first v1.5 launch,
because `ScanlinesEnabled` defaults to ON. If you'd prefer the v1.4
look, open **Visuals → Scanlines** and uncheck **Scanlines Enabled**.
The setting persists across runs. All other v1.4 settings (density,
color scheme, glow intensity, multi-monitor, GPU adapter, quality
preset, advanced sliders) round-trip unchanged on upgrade.

### Known Issues

- None known for v1.4 functionality.
- ARM64 builds require serial (`/m:1`) MSBuild invocation under the
current Visual Studio 18 ARM64 cross-compile toolchain due to a
per-process virtual-memory limit on PCH state when the test project
is built in parallel with the EXE. This is a build-host concern, not
a runtime issue; the resulting binaries are identical.

## [1.4.2098] - 2026-06-06

### Added

- **User Story 1 (P1) — Runtime topology and device-loss recovery.** MatrixRain now responds to monitors being added or removed while running (WM_DISPLAYCHANGE, coalesced across windows) and to the active GPU becoming unavailable (driver reset, sleep/resume, eGPU unplugged - detected via Present HRESULT). The render context is rebuilt automatically; this fixes the previously-reported "GPU stuck at ~90% after undocking a Surface Book 3" defect where the ghost monitor's render thread continued processing forever.
- **User Story 2 (P1) — Optional multi-monitor spanning.** New "Use all monitors" checkbox in the configuration dialog (default on). Toggling it live applies within 1 second; Cancel reverts.
- **User Story 3 (P2) — GPU adapter selection.** New "GPU" dropdown in the configuration dialog listing each real adapter name (with "(default)" appended to the system default). Software/WARP adapters are excluded. Selection persists by description string; if the saved adapter is missing at startup, the application silently falls back to the system default. Live device-switch takes effect within 1 second.
- **User Story 4 (P2) — Frame cap on high-refresh monitors.** Per-monitor `FrameLimiter` engages only when the monitor's native refresh exceeds 60 Hz, capping that monitor's rendering to 60 FPS. At ≤60 Hz the existing vsync path is preserved with no measurable per-frame overhead. Substantially reduces GPU work on 144Hz / 165Hz laptop displays.
- **User Story 5 (P3) — Graphics quality preset spectrum.** New "Quality" slider (Low / Medium / High / Custom) in a "Graphics quality" group box. Three discrete tuning sliders are always visible — Glow passes (1-4), Glow resolution (Eighth / Quarter / Half / Full), Glow smoothness (Low / Medium / High). Each quality-related control has an "ⓘ" infotip; hovering or tabbing-then-pressing-Space/Enter reveals a tooltip with a description and standardized GPU-performance-impact phrase. First-run heuristic picks a starting preset based on detected GPU class and total monitor pixel count (discrete → High; integrated + modest load → Medium; integrated + heavy load → Low). Custom-drift behaviour: any direct edit of an advanced control auto-flips the preset to Custom and saves the resulting values for restoration when the user later re-selects Custom.

### Changed

- Bloom pipeline is now runtime-parametric: blur passes (1-4), bloom buffer resolution (full/half/quarter/eighth), and blur kernel taps (5 / 9 / 13) are all selectable per-frame from the quality preset / advanced sliders. Three blur shader variants are compiled at startup so the tap-count switch is free at draw time.
- Default settings on a fresh install now pick a quality preset matched to detected hardware rather than always using the maximum.

## [1.3.1984] - 2026-06-03

Expand Down
Loading
Loading