From b1dc6fbf3de287e4b324e51c3d58b8289491e0d8 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:20:25 +0200 Subject: [PATCH 01/80] Document stacking implementation plan --- VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md | 500 +++++++++++++++++ VNM_PLOT_IMPLEMENTATION_PLAN.md | 543 +++++++++++++++++++ 2 files changed, 1043 insertions(+) create mode 100644 VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md create mode 100644 VNM_PLOT_IMPLEMENTATION_PLAN.md diff --git a/VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md b/VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md new file mode 100644 index 00000000..e624ede5 --- /dev/null +++ b/VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md @@ -0,0 +1,500 @@ +# vnm_plot architecture and performance-first stacking review + +Review target: `vnm_plot` at `2d94f0184cdfb099d8d8aafae5a0d955f03566ee` + +Review date: 2026-07-10 +Scope: existing architecture, correctness, duplication, performance, and a first-class stacked-series design for independently sampled and independently levelled data sources. + +## Executive conclusion + +**Failure headline: 19 failed or terminated executions were observed—nine CI jobs/workflows, one style gate, five local/environment diagnostics, and four report-validation commands; their provenance, recovery, and ownership are grouped below.** + +`vnm_plot` has a sound foundation and does not need a rewrite. The data/layout/RHI/Qt target split, immutable render-boundary descriptors, held snapshot lifetimes, per-source LOD planning, nanosecond timestamps, and D3D11-compatible prepare/record split should be preserved. The highest-value work is to make the current frame plan the single producer for range, rendering, interaction, and the proposed stack composition; remove avoidable steady-state snapshots, CPU staging, and GPU uploads; and tighten source lifetime and status contracts. + +The requested stack should be a core frame-planning capability, not a custom rendering layer and not an application-side precomputed `h` source. Each component selects its LOD independently. The planner then evaluates those source-local curves under a strict screen-space composition/output budget and emits cumulative bottom/top bands. Two bounded strategies remain viable: an event union exact for the selected curves, or a shared bounded screen grid with better per-input density but another approximation. Native-backend and visual A/B evidence must choose one before implementation. Both support unrelated timestamps/LOD ladders and bound composition/GPU output; current snapshot/window APIs may still copy, lock, or align against more history, so those costs must be measured and, if necessary, given a bounded source hook before stacks are enabled by default. + +The recommended implementation order is: + +1. Completed during review: publish the `vnm_msdf_text` contract to `master`, rerun the live integration, and preserve both the initial red and subsequent green evidence. +2. Establish truthful production counters and remove unchanged-frame uploads and test-only render-loop work. +3. Consolidate frame snapshots, range planning, point evaluation, source statuses, and ownership. +4. Add the bounded stack planner and its mathematical tests. +5. Add the stacked-band RHI path, Qt interaction/preview integration, and end-to-end performance gates. + +No proposed feature should land on the strength of a microbenchmark alone. The acceptance gate must include full-frame p50/p95/p99, total GPU upload bytes, allocation count, snapshot/query work, producer wait time, and native-backend identity. + +## Review method and governance + +This review followed `varinomics-standards`, including claim classification, concrete remediation for every finding, observable verification, explicit reporting of failed gates, test-oracle-first sequencing, and performance evidence that spans the real end-to-end path. + +Four initial model reviews were used, followed by a separate Codex claim audit and local verification: + +- three high-reasoning Codex reviews covering architecture, data/render mechanics, and falsification; +- one different-model Claude Fable review launched with model `claude-fable-5`, read-only repository tools, and no MCP tools; +- a final Codex claim audit over the combined findings and competing stack designs; +- a local source trace, builds, tests, style gate, CI observation, and benchmark inspection. + +External review artifacts remain outside this repository. The Fable output is at `C:\plms\invoking_claude_from_codex\runs\vnm_plot_fable_review_20260710_20260710_105351\outputs\01_vnm_plot_full_review.md`. This document is the governed synthesis: it incorporates supported findings and explicitly rejects suggestions that conflict with repository evidence, performance requirements, or the simpler canonical design. + +Claims are labelled as follows: + +- **Source-confirmed**: directly established by the cited code, build, test, CI, or benchmark output. +- **Inferred**: a consequence supported by the source but not yet measured in a representative production workload. +- **Proposed**: a design or acceptance contract that requires owner approval before implementation. +- **Unresolved**: evidence is insufficient for a production conclusion; the next measurement is stated. + +### Final claim-audit corrections + +The final Codex claim audit confirmed the principal findings and made four useful scope corrections that this synthesis adopts: + +1. The duplicate auto-range scanner is real redundancy, but a normal valid policy does **not** execute both scanners in one request. The remedy is consolidation and drift prevention, not a claim of a measured double scan. +2. Policy-pointer invalidation and per-frame Qt map copying are source-confirmed mechanisms; their production severity remains unmeasured. Their batches therefore require replacement-heavy and 1/100/1000-series measurements before priority is raised. +3. Upload evidence must distinguish sample geometry from complete QRhi traffic. The renderer should report primary, LINE-window, stack, uniform, and known custom-layer bytes separately plus a total; if a custom layer cannot expose bytes, the total must be labelled incomplete rather than guessed. +4. A budgeted exact union is internally consistent only when “exact” is explicitly limited to the independently selected LOD functions and LOD selection enforces the input budget before union. A full-width grid per member would emit `K*W`, but a bounded grid with `N=floor(M/(D*K))` (and `D=1` for all-LINEAR input) also respects the same total output budget and can retain far more input density for large K. The default is therefore **unresolved** pending native-backend compose/bytes/p95 and visual spike/step A/B evidence. + +The audit also confirmed that commit `e605b5f` deliberately removed LOD hysteresis. This report therefore does not reintroduce it. + +## Existing architecture to preserve + +These are positive findings, but each has a concrete preservation rule so subsequent work does not accidentally erase the benefit. + +| Evidence | Assessment | Concrete preservation rule and verification | +|---|---|---| +| `CMakeLists.txt:286-366,415-478,553-580` | **Source-confirmed:** data, layout, RHI, and Qt Quick are separate link targets. | Put stack mathematics and evaluation in layout/core, QRhi resources in RHI, and UI storage/interaction in Qt. Add a dependency-direction CMake smoke that builds each narrow target; do not introduce Qt types below the Qt target. | +| `include/vnm_plot/core/types.h:294-352` | **Source-confirmed:** snapshots explicitly retain storage lifetime. | The frame-level cache and stack planner must retain the complete snapshot result until composition and render finish. Add a source whose storage dies immediately after snapshot return and verify ASan-safe rendering. | +| `src/qt/plot_widget.cpp:167-196` | **Source-confirmed:** series descriptors are cloned before crossing to the render side. | Keep each published descriptor/map snapshot immutable. Put membership on that descriptor and document `apply_series_updates` as the required atomic topology path; individual add/remove calls commit and may render an intermediate topology, so callers requiring atomic group changes must use the batch API. | +| `include/vnm_plot/rhi/series_renderer.h:63-78`, `src/qt/plot_renderer.cpp:467-523` | **Source-confirmed:** resource upload/prepare occurs before the pass and record occurs inside it, including D3D11 constraints. | Stack buffers must be created and uploaded during prepare and only bound/drawn during record. Exercise the shader/resource smoke on every supported backend. | +| `src/core/series_window_planner.cpp:229-246,860-923` | **Source-confirmed:** LOD is chosen per source from that source's scale ladder. | Stack planning must request one independent plan per component. Tests must use deliberately unrelated LOD counts and scales and assert no equality of LOD indices is assumed. | +| `include/vnm_plot/core/types.h`, `include/vnm_plot/rhi/series_renderer.h:81-105`, `src/core/series_renderer.cpp:1723-1734` | **Source-confirmed:** CPU timestamps remain signed 64-bit nanoseconds and are rebased for fp32 GPU use. | Keep timestamp merge/comparison in `int64_t`; rebase only the final visible group buffer. Test values near both signed limits without subtracting in a way that overflows. | + +A broad dependency-injection system, plugin framework, source-tree rewrite, or container replacement has no demonstrated payoff and should not be undertaken. If profiling later identifies a specific registry or allocation bottleneck, change only that producer and repeat the end-to-end gate. + +## Observed failures and current gate status + +There were **19 failed or terminated executions** during this review. They are grouped here so a later successful command cannot hide them. + +### Resolved live-`master` integration failure: eight initial CI jobs + +All eight first-attempt jobs from the four workflows failed during configure/build: + +- Linux: +- Windows: +- macOS: +- FreeBSD: + +Both text-OFF and text-ON first attempts failed because `vnm_plot` required an LCD contract that was not yet present on fetched `vnm_msdf_text` `master`: text-OFF could not find `vnm_msdf_text/include/vnm_msdf_text/lcd_contract.h`, and text-ON could not find target `vnm_msdf_text::lcd_contract`. The required sibling commit `c03a350` (`Commonize LCD contract and package smokes`) was subsequently pushed to that repository's `master` during the review. + +Concrete recovery and result: + +1. `vnm_msdf_text@c03a350` was pushed to `master`. +2. All four workflows were rerun as attempt 2; all eight configurations passed on 2026-07-10. +3. Keep both `GIT_TAG master` declarations at `CMakeLists.txt:203-218`; this repository intentionally uses the owner's dependency `master` as a live integration oracle. +4. Configure from a checkout with no sibling dependency present, then run install/package-consumer smoke tests so local directory leakage cannot mask the fetched `master` state. +5. Record the resolved dependency commit in CI artifacts for diagnosis and benchmark comparison, without pinning it. + +The dependency repository's own `c03a350` push workflows passed on [Linux](https://github.com/imakris/vnm_msdf_text/actions/runs/29083205733), [macOS](https://github.com/imakris/vnm_msdf_text/actions/runs/29083205779), and [FreeBSD](https://github.com/imakris/vnm_msdf_text/actions/runs/29083205767). Its [Windows workflow](https://github.com/imakris/vnm_msdf_text/actions/runs/29083204930) failed at workflow level with zero jobs and no logs. Cause is **unresolved**: run a GitHub Actions-aware validator such as `actionlint` on `.github/workflows/ci-windows.yml`, inspect expression-context availability—particularly job-level `runner.temp`—and land/rerun a focused workflow-only correction. Do not guess at a product-code fix. This dependency workflow failure keeps Batch 0 open even though all eight dependent `vnm_plot` attempt-2 jobs are green. + +### Repository style gate: one failed execution + +The governed style pipeline stopped on 14 violations. Five in `test_msdf_lcd_shader_reference.cpp` were introduced by `2d94f01`; the other nine in `series_renderer.cpp`/`types.cpp` predate that commit but remain perpetuated and exposed by the current tree: + +- `src/core/series_renderer.cpp:95`; +- `src/core/types.cpp:47,49,51,53,389,391,393,394`; +- `tests/test_msdf_lcd_shader_reference.cpp:217,219,221,223,225`. + +Concrete recovery: change only the reported switch/case layout and indentation, rerun the complete style pipeline from its first stage, and keep the formatting-only patch separate from semantic work. Do not mix this cleanup into stack implementation. + +### Local/environment diagnostics: five failed or terminated executions + +1. A first direct MSVC build invocation failed in standard-library headers because the compiler environment was not initialized. The governed `vcvarsall.bat x64` invocation then built successfully and CTest passed 21/21. Concrete recovery is to use the standards-provided initialized command in local documentation/automation rather than interpreting the first failure as product source breakage. +2. One `QT_QPA_PLATFORM=offscreen` run passed 20/21; `PlotInteractionItem` failed because the local Qt deployment contained only the Windows platform plugin. The same test passed with `QT_QPA_PLATFORM=windows`. Concrete recovery is to deploy the offscreen plugin where offscreen is required or select an actually installed platform in the local Windows gate; CI should keep exercising its intended headless platform. +3. One cold dynamic benchmark exceeded 30 seconds and was terminated; warmed repetitions completed. Cause is **unresolved**. Instrument backend creation, first shader/pipeline creation, first submitted frame, frame count, producer lock wait, and generator shutdown before changing production code. Add a bounded startup timeout with a phase-labelled failure to the harness. +4. `gh run view --log-failed` for the dependency Windows workflow returned failure because the workflow created no jobs/log archive. Query run/job metadata first; treat an empty job list as workflow validation failure instead of requesting nonexistent logs. +5. An unauthenticated web fetch of the same private/uncached run returned a cache-miss error. Use the authenticated GitHub CLI/API and local workflow validation for this repository; do not infer a cause from the failed page fetch. + +### Report-validation diagnostics: four failed executions + +Two independently written mechanical source-reference checks hit the same PowerShell interpolation parse error in the check command itself (`$path:$line` and `$p:$end`). A later stale-wording grep also had a malformed PowerShell double-quoted pattern because a Markdown backtick escaped its closing quote. The first staged `git diff --check` then rejected two Markdown hard-break trailing spaces at the report header. Their corrected forms parsed 53 references in the final primary check with none invalid; the differently tokenized proof check parsed 41 citation groups with every endpoint valid; the corrected single-quoted grep found no stale wording; and the final cached diff check passed. Concrete prevention: retain explicit braced interpolation such as `${path}:${line}`, single-quote literal grep patterns containing Markdown backticks, and use blank lines rather than trailing-space hard breaks. + +The corrected local command built successfully and CTest passed **21/21 tests in 1.60 seconds**. The build also emitted C4459 shadow warnings for `k_ns_per_ms` and `k_ns_per_second` in `include/vnm_plot/core/algo.h:717-718` and `src/qt/plot_widget.cpp:1277`, shadowing canonical constants in `time_units.h`. The concrete fix is to remove the local duplicates and use the canonical constants, then enable this warning as an error for project code after the existing warnings are cleared. + +Failure ownership is explicit: dependency publication and the four `vnm_plot` workflow reruns are complete; dependency Batch 0 still owns its jobless Windows workflow; Batch 0A owns the 14 style violations; Batch 2 owns the shadow warnings; local gate automation owns initialized MSVC/platform selection; and the benchmark-integrity batch owns cold-start instrumentation. The concrete recommendation is to delegate the remaining remediation groups to those responsible agents/batches and require each to return its named gate evidence before closure. The green `vnm_plot` attempt 2 does not erase the eight initial failures or their provenance. + +## Prioritized architecture and performance findings + +### P0 — The intentional cross-repository `master` oracle exposed delivery order; dependent CI recovered, dependency Windows CI remains open + +**Classification: Source-confirmed delivery failure and partial recovery under an owner-approved policy.** Both fallback declarations deliberately use the owner's moving `master`; the first attempts correctly exposed that the consumer reached `master` before the required dependency contract did. After `c03a350` reached dependency `master`, all eight dependent `vnm_plot` attempt-2 jobs passed. The dependency's own Windows workflow still fails before creating jobs. + +**Remediation:** completed for the consumer break: publish the sibling change to its `master`, keep `vnm_plot` tracking `master`, and rerun all dependent workflows. Keep Batch 0 open until the dependency Windows workflow passes, add resolved dependency commit metadata, and retain no-sibling/install/package consumption coverage. For future coupled changes, push the dependency contract first and confirm its CI before pushing the consumer; if live integration breaks, leave it red until the repositories are compatible rather than masking it with a revision pin. + +**Performance relevance:** no direct runtime effect. Because the dependency intentionally moves, every benchmark artifact must record its resolved commit so before/after binaries remain attributable without changing the `master` policy. + +### P1 — VISIBLE auto-range does not use the displayed LOD plan + +**Classification: Source-confirmed correctness and performance issue.** `Auto_v_range_mode::VISIBLE` says it uses LOD selection (`include/vnm_plot/core/plot_config.h:40-47`), but `src/core/auto_range_resolver.cpp:432-439` selects LOD 0 for every mode except `GLOBAL_LOD`. The renderer chooses the actual visible LOD later in `src/core/series_window_planner.cpp:860-923`. This can scan full-resolution visible data and compute a range that differs from the curve actually displayed. + +**Remediation:** introduce one internal `Frame_series_planner` before range/layout. It produces one immutable per-series/per-view plan containing source, selected LOD, snapshot/status, source window, drawable spans, semantics, and cache identity. Use full framebuffer width—not post-label `usable_width`—as the deterministic LOD-budget width for both range and renderer; final layout may still use `usable_width` for transforms, but it must not reselect LOD. `Frame_range_planner` consumes those plans for VISIBLE range, and `Series_renderer` consumes the same plans for upload/draw. Do not call the two planners independently or introduce an unbounded layout/replan cycle. + +**Verification:** use a source with million-, ten-thousand-, and thousand-sample levels at width 1000. Assert range and renderer consume the same selected LOD and source sequence, and that each `(source, LOD)` is snapshotted once per frame. + +### P2 — Unchanged frames restage and upload primary and line-window data + +**Classification: Source-confirmed performance issue.** A valid snapshot leads to primary staging/upload in `src/core/series_renderer.cpp:1640-1805`. A custom layer requests a frame snapshot even when sequence and view are unchanged (`src/core/series_renderer.cpp:879-893`; `src/core/series_window_planner.cpp:382-391`), so unchanged data is uploaded. LINE rebuilds and uploads its padded window at `src/core/series_renderer.cpp:1921-2063`. The public profiler counts the primary upload at `src/core/series_renderer.cpp:1368-1435` but omits the line-window upload at `2058-2062`. + +**Remediation:** add two explicit keys to each view state: + +- `sample_upload_key`: source identity, stable nonzero sequence, selected LOD, origin, access/semantics key, source window, drawable-span hash, nonfinite behavior, hold behavior, and view kind. A zero/unstable sequence or conservative semantics disables cross-frame reuse and increments a reason counter; treating zero as a reusable version risks stale geometry; +- `line_window_key`: primary-content revision incremented on every content upload, interpolation, and segment spans. Allocation generation alone is insufficient because an in-place primary upload changes content without reallocating the VBO. + +When the relevant key matches, retain the buffer even if a current CPU snapshot was required for a custom layer. Continue calling custom-layer prepare as its ABI requires. Publish primary, line-window, and total sample upload counts and bytes. + +**Verification:** after warm-up, static LINE and LINE+custom-layer frames with stable nonzero sequence/non-conservative semantics must report zero library-owned primary/LINE CPU restaging and uploads, with identical library pixels. An arbitrary custom layer may legitimately upload in each `prepare()`; report that separately and never claim it is zero when unobservable. A data-affecting mutation for LINE must cause one primary upload and one derived line-window upload, each exactly once; styles without LINE perform only their required primary upload. Zero/unstable/conservative inputs must recompute rather than reuse. Change `tests/test_qrhi_layer_lifecycle.cpp:1033-1049`, which currently expects an unchanged second-frame upload, only after the new oracle is owner-approved. + +### P3 — Snapshot caching is per series instead of per frame/source/LOD + +**Classification: Source-confirmed mechanism; cost is inferred until measured.** Each series state owns its own cache (`include/vnm_plot/rhi/series_renderer.h:147-152`; `src/core/series_window_planner.cpp:248-269`). Multiple series using the same source and LOD can therefore obtain multiple copies and potentially observe different sequences. + +**Remediation:** make the `Frame_series_planner` own a cache keyed by `(Data_source*, LOD)`, storing the complete `snapshot_result_t` including status and hold. Every descriptor and snapshot hold remains alive for the frame, so the object address cannot be recycled during that cache lifetime. Do not use shared-pointer control-block ownership as this object key: aliasing pointers can share a control block while naming different source subobjects. Clear the cache only after every range, custom-layer, composition, and render consumer finishes. A stack shares this cache with ordinary series. + +**Verification:** ten series sharing one source/LOD produce exactly one snapshot request; two selected LODs produce exactly two; all plans report the same sequence for a shared key. A copy-on-snapshot source should show the removed bytes and time in full-frame counters. + +### P4 — UI range and indicator paths duplicate and diverge from renderer semantics + +**Classification: Source-confirmed correctness and performance issue.** `auto_adjust_view()` snapshots/scans LOD 0 at `src/qt/plot_widget.cpp:1106-1147`. Indicators snapshot LOD 0 at `1312-1371` and use `bracket_timestamp()`, which infers order from endpoints and binary-searches (`include/vnm_plot/core/algo.h:615-675`) despite `Data_source` supporting `UNORDERED`. These paths also bypass the renderer's complete nonfinite policy. + +**Remediation:** add one core `resolve_sample_at` evaluator and one public `Data_source::query_sample(timestamp, mode, context)` status-returning hook. The default hook may snapshot and evaluate; indexed sources override it. Required behavior: + +- ascending/descending: O(log n); +- unknown: cache monotonic classification by identity/sequence/access semantics; +- unordered nearest: O(n) correct global nearest; +- unordered interpolation: explicit unsupported unless the source supplies a direct semantic query; +- all paths: use the same interpolation, duplicate-timestamp, hold, and nonfinite producer used for rendering. + +Route `auto_adjust_view()` through the same range producer used by frame auto-range. The stack planner and stacked indicator must call the same evaluator rather than implement another interpolation loop. For pixel-parity indicators, the UI publishes the cursor timestamp to the renderer; the renderer evaluates it from the same held frame plan/snapshot and publishes immutable indicator values back, accepting one-frame latency. Do not independently query after render, because the source may have advanced. A direct source query remains valid for non-pixel-parity operations only when selected LOD and expected sequence are supplied and mismatch is discarded/retried. + +**Verification:** unordered timestamps `[0,90,10,100]` queried at 11 must resolve to 10 in nearest mode. Cover descending data, duplicate timestamps, every nonfinite policy, all-empty/nonfinite windows, and a million-sample indexed source that proves bounded direct-query work. Tooltip values must match the displayed selected LOD. + +### P5 — `Data_source::snapshot()` erases EMPTY, BUSY, and FAILED distinctions + +**Classification: Source-confirmed design issue.** `include/vnm_plot/core/types.h:729-733` converts non-ready outcomes into an empty snapshot. The production users are limited to `src/core/auto_range_resolver.cpp:60` and the Qt paths at `src/qt/plot_widget.cpp:1111,1320`. + +**Remediation:** remove the wrapper atomically and migrate each user to `try_snapshot()`: + +- EMPTY: valid absence of data; +- BUSY: keep the last complete operation/view without mutation and increment a busy observation; +- FAILED: suppress that operation and report once through the configured diagnostic path; +- READY: consume while retaining its hold. + +Do not leave a deprecated alias, because it would retain the ambiguity. + +**Verification:** a four-state source must prove no view mutation on BUSY, an observable diagnostic on FAILED, no draw on EMPTY, and normal consumption on READY. + +### P6 — Non-owning `Data_source_ref` can outlive its source across the render boundary + +**Classification: Source-confirmed lifetime risk.** The raw reference path is stored by `include/vnm_plot/core/types.h:787-829`, used by both preview and ordinary series at `include/vnm_plot/core/types.h:955,1001-1032`, exposed by `include/vnm_plot/core/basic_series_builder.h:67-71`, and cloned for asynchronous rendering without extending source lifetime. Production examples use it, as does the benchmark. + +**Remediation:** replace `Data_source_ref` in both `series_data_t` and `preview_config_t` with `std::shared_ptr`, then remove `set_data_source_ref`, `data_source_ref`, and the builder overload in one public API change. Migrate `hello_plot`, `function_plotter`, tests, and benchmark; do not add a no-op deleter compatibility bridge. In the benchmark, make `Benchmark_data_source` own a `shared_ptr>` and let generator/window share it. Merely changing the source from `unique_ptr` to `shared_ptr` while it retains `Ring_buffer&` would allow the plot-held source to outlive its buffer during QObject teardown. Shared-pointer copying occurs when immutable descriptors are published, not per sample or draw. + +**Verification:** ASan test releases every caller handle after adding ordinary and preview series and renders safely until removal; a benchmark teardown test destroys the window/generator while the render descriptor briefly remains held; TSan stress replaces/removes series during render synchronization. `rg "Data_source_ref|set_data_source_ref|data_source_ref\\("` must return no production, example, benchmark, or public-header use. + +### P7 — Floating timestamp-member conversion can invoke undefined behavior + +**Classification: Source-confirmed correctness issue.** `include/vnm_plot/core/access_policy.h:63-77` multiplies a floating member by `1e9` and casts directly to `int64_t`. NaN, infinity, or out-of-range finite values make the conversion invalid/undefined. README and typed API tests make floating seconds an adopted behavior, so it cannot simply be ignored. + +**Remediation:** performance-first preference is to require integral nanoseconds in the member-pointer hot path with `static_assert`, and provide a checked ingestion conversion so floating timestamps normalize once. If the convenience API must remain, return value-plus-validity, check finite/range before conversion, and propagate an invalid window; do not clamp or use `INT64_MIN` as a sentinel because it is a valid timestamp. + +**Verification:** typed and erased tests for NaN, infinities, boundary values, and one-step outside boundaries under UBSan. Benchmark accessor dispatch and full-frame planning to confirm the chosen contract adds no hot-loop regression. + +### P8 — Test-only vectors execute in the production draw loop + +**Classification: Source-confirmed easy performance win.** Four vectors labelled test instrumentation in `include/vnm_plot/rhi/series_renderer.h:181-186` are cleared per frame (`src/core/series_renderer.cpp:660-667`) and receive four `push_back` calls per draw (`1552-1561`). + +**Remediation:** guard members and all writes with the existing `VNM_PLOT_ENABLE_TEST_HOOKS`; build the lifecycle test against a hook-enabled library/object and normal releases without it. Provide a test accessor instead of `private`/`public` preprocessor rewriting. + +**Verification:** normal Release objects contain no hook vectors/writes, hook-enabled tests retain their ordering assertions, and production draw/upload output is unchanged. + +### P9 — Policy identity and series identity can invalidate too much or reuse the wrong state + +**Classification: Source-confirmed invalidation mechanism; allocator-ABA consequence is inferred.** Access cache identity includes policy object address (`include/vnm_plot/core/types.h:102-129,569-581`), while descriptors are cloned on update (`src/qt/plot_widget.cpp:178-193`). Color-only updates can therefore invalidate data caches. Pointer-address identity also risks accidental reuse after destruction/allocation at the same address. + +**Remediation:** key geometry state by stable series ID plus a monotonic `geometry_revision` that changes when source, access/layout semantics, interpolation, nonfinite/hold behavior, or other data-affecting fields change. Preserve that revision for color/label-only clones only when access semantics are non-conservative or the caller supplied a stable semantics key/revision. A conservative callable clone with no comparable semantic identity must invalidate even on an otherwise visual-only full-descriptor update. For member/offset semantics, key by byte layout and semantic value/revision rather than the cloned policy object's address. Source `shared_ptr` ownership provides lifetime only, not cache identity. + +**Verification:** a color/label-only update with stable explicit semantics preserves `geometry_revision` and causes no snapshot, range rescan, VBO upload, or custom-layer recreation; a conservative callable without a semantics key invalidates; callable replacement or semantic revision invalidates once; remove/re-add creates a new registry incarnation and never reuses prior GPU/cache state under allocator churn. + +### P10 — Qt synchronization copies configuration and the full series map on unchanged frames + +**Classification: Source-confirmed operation; cost is inferred.** `src/qt/plot_renderer.cpp:205-216` copies `Plot_config` and the complete map before consulting revision state. + +**Remediation:** compare `m_config_revision` before copying configuration. Add a series revision incremented under the existing series mutex by add/remove/clear/apply; copy the map only when it changes. Keep the current locking model rather than adding an event bus or model hierarchy. + +**Verification:** with 1, 32, 256, and 1000 static series, record exactly one initial map/config copy and none until mutation. Measure allocations and synchronize p95; rendered and upload counters must be unchanged. + +### P11 — Range/interpolation logic has reached the consolidation threshold + +**Classification: Source-confirmed redundancy with a preserved exception.** Range logic exists in `Data_source::query_v_range()` (`src/core/types.cpp:851-954`), a private auto-range scanner (`src/core/auto_range_resolver.cpp:47-150`), and the Qt auto-adjust aggregator (`include/vnm_plot/core/algo.h:530-613`). However, `Data_access_policy::is_valid()` requires timestamps, while `tests/test_cache_invalidation.cpp:576-650` confirms that GLOBAL value-only access without timestamps falls back to a full snapshot range scan. Deleting the private scanner before the canonical producer learns that all-time case would remove adopted behavior. + +**Remediation:** first make canonical `Data_source::query_v_range()` accept value-only or range-only access for an all-time GLOBAL query, scanning the whole selected snapshot without timestamp filtering. Time-bounded VISIBLE queries still require timestamps. Route auto-adjust through that producer and reuse `resolve_sample_at` for point semantics. Only after parity tests pass should `scan_series_range()` and its final unsupported branch be deleted. This preserves one producer without deleting the value-only oracle. + +**Verification:** keep `test_global_value_only_access_falls_back_to_snapshot_scan` green and add range-only/all-time parity. Cover time order, interpolation, hold, gaps, nonfinite policies, and every source status. Only then may `rg "scan_series_range"` return no matches. + +### P12 — The benchmark can report success without proving the real native path + +**Classification: Source-confirmed measurement defect.** `benchmark/src/benchmark_window.cpp:538-605` can silently fall back to QRhi Null. Reports do not record the actual QRhi implementation/device, and `--finish` is optional/default false. CI builds the benchmark but does not run it, and benchmark helper tests are disabled by default. Current sample upload metrics omit line-window bytes. + +The static Bars artifact at `C:\Users\imak\AppData\Local\Temp\vnm_plot_review_bench\inspector_benchmark_20260710_090221_SIM_Bars.txt` reports 2605 frames, two primary sample uploads per frame, 160 reported bytes per frame, and two monotonic scans. The live Trades artifact at `C:\Users\imak\AppData\Local\Temp\vnm_plot_review_bench\inspector_benchmark_20260710_090223_SIM_Trades.txt` reports 2665 frames, 5328 primary uploads, 39,239,776 reported primary bytes, and 130 monotonic scans. Treat these as artifact-backed diagnostic observations, not valid GPU-performance evidence: the reports omit actual QRhi implementation, the exact invocation was not retained, and line-window traffic is absent. + +**Remediation:** hard-fail native-backend creation unless `--rhi-backend null` is explicitly requested. Record actual QRhi implementation, adapter/device, build type, text mode, dimensions, sample/LOD scenario, and finish state. Name submission-only and GPU-finished timings distinctly. Run fixed untimed warm-up frames, reset the profiler, and start the measurement clock only after static fill/thread startup; report cold startup separately. Add deterministic scenarios for 1/8/64 ordinary series and 2/4/8 stacked members with unrelated LODs and phase-shifted timestamps. Export scanned samples, snapshot count/time/bytes, primary/line/stack/uniform/known-custom upload bytes and total, composition time, allocations, producer wait, memory high-water, and output count. If custom-layer traffic cannot be observed, label the total incomplete. + +**Verification:** a short fixed-seed native smoke in CI gates deterministic counters, shader creation, and non-null pixels. Raw timing gates run on pinned hardware with identical backend/finish/build parameters and retained artifacts. Diagnose the cold timeout with phase timing before setting a threshold. + +### P13 — Documentation currently advertises behavior that the source does not provide + +**Classification: Source-confirmed.** README lists `COLORMAP_AREA` at `README.md:150`, but the public enum has no colormap and API tests assert its absence. The VISIBLE LOD claim conflicts with the range implementation. The configuration example mutates `config.line_width_px` at `README.md:204` before `set_config`, while `set_config` intentionally preserves several widget-owned visual fields (`include/vnm_plot/qt/plot_widget.h:118-120`; `src/qt/plot_widget.cpp:219-231`). `benchmark/ARCHITECTURE.md:27-28` says the benchmark source copies on snapshot and computes ranges, while `benchmark/include/benchmark_data_source.h:21-64` exposes a held zero-copy view and relies on the base range scan. + +**Remediation:** remove the nonexistent colormap bullet; implement the shared VISIBLE plan proposed in P1 rather than weakening its performance promise; update the example to call `set_line_width_px`; and regenerate benchmark architecture notes from the actual source contract. Longer term, leave each setting on one canonical public surface rather than duplicating it in config and widget setters. + +**Verification:** compile README API snippets in a small smoke target, grep documented display styles against the enum, and review documentation in the same commit as any public contract change. + +### P14 — Small cleanups should remain small + +**Classification: Source-confirmed.** These are safe, bounded changes: + +- replace the duplicate `floor_div` in `include/vnm_plot/core/algo.h:734` with the canonical, better edge-case-aware implementation in `time_units.h:433`; +- remove `cached_snapshot_hold` if it merely duplicates the hold already carried by the snapshot result; +- reject/erase null descriptors in `apply_series_updates` rather than retaining a map key whose renderer resources survive because cleanup only sees key absence; +- make `Series_view_plan` own or directly expose the canonical `sample_window_t` instead of manually copying equivalent fields at `src/core/series_renderer.cpp:977-1004`; +- cache LOD scale topology only after declaring it immutable or adding `lod_layout_revision()`; otherwise the cache would be incorrect. + +**Verification:** focused unit tests for floor division signed extremes, null replacement resource cleanup, and plan/window field parity. Add a topology revision invalidation test only if topology caching/revision is actually introduced. Do not create a shared helper for the two existing `checked_size_add/product` copies; two uses are below the governance N=3 consolidation threshold. + +## First-class stacked-series contract + +### Public API: extend ordinary series registration + +**Proposed.** Keep one canonical series registry and add one optional immutable group identifier: + +```cpp +std::optional stack_group_id; +``` + +Add `Basic_series_builder::stack(group_id)` and `clear_stack()`. An enabled series with no membership behaves exactly as today. Enabled members with the same group form one stack in ascending existing series-ID order. Existing source, access policy, interpolation, nonfinite behavior, color, label, preview source, and style remain per series. Reuse the existing ID as order instead of adding a second ordering concept; add a distinct order property only if an actual caller later needs to reorder layers without changing IDs. + +This is preferred over a separate `Stack_data`/`add_stack()` object because it reuses the canonical registration/update/lifetime path and avoids a second descriptor hierarchy. `apply_series_updates` is the documented atomic way to change multiple members. Individual `add_series`/`remove_series` calls are not group-atomic: they commit each intermediate topology, and a still-valid two-of-three-member group can render that intermediate partial sum. Callers requiring atomic topology must batch. If the owner requires atomicity regardless of caller behavior, re-evaluate a group-owned immutable descriptor before implementing this API. A member must provide both timestamp and scalar `get_value` access; `Data_access_policy::is_valid()` alone is insufficient because range-only access cannot define `cj(t)`. `cj` always comes from `get_value`, even when a draw-range accessor also exists. Missing either required accessor returns `STACK_REQUIRES_SCALAR_VALUE`; any missing source invalidates the current group. Within one immutable topology, silently dropping a failed member is forbidden because it would display a different sum. + +An enabled member with `Display_style::NONE` still contributes mathematically but emits no band, boundary, or dots of its own; later cumulative members and the final total still include it. `enabled=false` is the canonical way to exclude a component from the sum. This keeps visibility and mathematical membership explicit rather than making style selection mutate data semantics. A group requires at least two enabled members (`STACK_REQUIRES_TWO_MEMBERS`) and at least one supported visible built-in style across the group (`STACK_GROUP_HAS_NO_VISIBLE_STYLE` otherwise). DOTS, LINE, and AREA combinations are the supported first-version styles. + +For the first version, a stack member with `Qrhi_series_layer` is explicitly unsupported and invalidates the group with `CUSTOM_LAYER_IN_STACK`. The custom-layer ABI describes one ordinary planned window and has no cumulative bottom/top contract; silently drawing it at raw component coordinates would make it disagree with the stack. A future stacked custom-layer ABI requires a separate owner-approved use case and benchmark. + +### Mathematical definition + +**Proposed; owner approval required before tests are treated as oracle.** For ordered component functions `c1...cK`: + +```text +S0(t) = 0 +Sj(t) = Sj-1(t) + cj(t) +``` + +Layer `j` fills the band between `Sj-1` and `Sj`. Its boundary line is `Sj`; the last boundary is the requested `h`. Values are accumulated in `double`, checked, and narrowed to float only for GPU storage. + +- Negative values use algebraic stacking: a negative component descends from the preceding cumulative value. Do not silently use a separate positive/negative baseline because then the final top is not `f+g`. +- AREA draws the bottom/top band. LINE draws cumulative boundaries. DOTS draw cumulative knots. Zero is only the `S0` baseline. +- Auto-range includes every bottom and top, not only `h`. For `f=100, g=-100`, the visible range must still include the intermediate 100 band. +- The feature means “sum of the selected displayed LOD approximations.” The source API does not state whether a coarse LOD sample is a mean, extrema envelope, or exact raw sample, so claiming raw LOD-0 analytic truth would be false. + +### Timestamp, interpolation, domain, and status semantics + +**Proposed; owner approval required for the intersection-domain rule.** Each member is evaluated as its own selected piecewise function: + +- Candidate A builds the ordered union of selected member timestamps. Candidate B builds a view-derived shared grid. Neither may match array indices, require equal timestamps, or choose one operand's grid. +- LINEAR evaluates piecewise linearly at every emitted position. STEP_AFTER is right-continuous: a value becomes active at its timestamp and holds until the next. Candidate A emits a left-limit event and then a right-value event at a changing step timestamp; without both, geometry would bridge the discontinuity. Candidate B evaluates right-continuously at grid positions and accepts the measured/signed-off screen-space displacement described by its approximation contract. Mixed modes are allowed. +- Equal timestamps collapse to the sample with the highest physical source index, regardless of traversal direction, making the winner identical for ascending and descending planning and simultaneous changes deterministic. +- ASCENDING and DESCENDING use direction-aware cursors. UNKNOWN performs one cached classification per identity/sequence/access key only when sequence is stable and nonzero; otherwise it scans once for the frame-held snapshot and does not reuse that classification across frames. Truly UNORDERED data returns explicit `UNORDERED_STACK_INPUT`; sorting every frame is both expensive and semantically ambiguous for a function. +- The group domain is the intersection where every component has a value. There is no left extrapolation. Right extension is allowed only when each otherwise-ended component explicitly uses hold-last-forward. +- BREAK_SEGMENT intersects valid spans across components. SKIP removes the invalid knot and connects its valid neighbours. REPLACE_WITH_ZERO contributes zero. REJECT_WINDOW rejects the whole group window. +- EMPTY yields an empty group. FAILED suppresses the group and reports once. Define a structural key containing registry incarnations, membership/order, source objects, access semantics, view, and configuration but excluding live sequences. On BUSY, ignore every newly acquired operand and reuse the previous complete group wholesale only if that structural key matches; otherwise suppress. Never combine fresh and stale generations. +- Snapshots from different sources are individually stable, not transactionally simultaneous. Different LOD snapshots of the same source have no stronger atomicity guarantee. The contract must say this. Applications needing atomic cross-signal or cross-LOD publication must publish through one coordinated snapshot/revision contract. + +### Bounded independent LOD planning and unresolved sampling strategy + +**Proposed common constraint; strategy unresolved.** Neither “merge all LOD 0 samples” nor “give every member a full one-sample-per-pixel input before an unbounded union” is acceptable. The first grows with history; the second can emit approximately `K^2*width` cumulative band samples. + +Let: + +- `W` be full framebuffer plot width before label layout; +- `K` be enabled group members; +- `C` be an internal calibrated total band-samples-per-pixel budget, initially 2; +- `D` be 1 for all-LINEAR groups and 2 when STEP_AFTER output can require paired left/right events; +- `M = floor(C * W)` be the hard emitted band-ordinate-pair budget; +- `A = align_up(64, QRhi uniform-buffer alignment)` be the actual per-member uniform allocation/update allowance for the active backend; +- `H = 32*M + A*K + 64` be a conservative first-version hard total stack-upload byte cap derived below from base and LINE-boundary record formats, not a separately tuned performance knob. + +Extend the planner request with separate `render_width_px` and `max_visible_samples`; do not overload the shader/view width. Every strategy selects each source independently from its own ladder and includes interpolation brackets/synthetic hold knots in its input count. If even a coarsest complete window exceeds the chosen per-input cap, return `LOD_BUDGET_EXCEEDED` rather than dropping brackets or falling back to raw history. + +**Candidate A—budgeted event union.** Let `B=floor(M/(D*K^2))`. Require `B>=2`. With each input at most `B`, union `U<=K*B`, events `E<=D*U`, and output pairs `K*E<=M`. It is exact relative to selected piecewise curves, including step discontinuities, but input density falls quadratically with K; for `W=800,K=32,C=2`, it cannot represent a segment and returns `STACK_BUDGET_TOO_SMALL`. + +**Candidate B—bounded shared grid.** Use the same D factor and let `N=floor(M/(D*K))` shared grid timestamps; require `N>=2` so interpolation brackets and a drawable segment have an unambiguous budget, otherwise return `STACK_BUDGET_TOO_SMALL`. Cap each selected source window at N. Evaluate every component with monotonic cursors. For STEP_AFTER, when the sampled value changes, emit left/right events at the grid transition where the change is observed, so `E<=D*N`, output `K*E<=M`, and CPU work is `O(sum(ni)+K*E)`. At `W=800,K=32,C=2`, an all-LINEAR group retains 50 grid values per band; a step-capable group retains 25 grid positions and up to 50 events. It adds a screen-space approximation: narrow spikes can alias and a true step between grid points is displaced to the sampled transition. + +Do not choose a default from asymptotic argument alone. Prototype both outside the public API with identical independent LOD selection and hard `M/H` counters. Compare native-backend compose time, total bytes, allocations, producer wait, and full-frame p50/p95/p99 for K={2,8,32} and W={800,3840}; visually inspect phase-shifted narrow spikes, mixed LINEAR/STEP_AFTER discontinuities, gaps, and cancellation. The owner selects one strategy before its tests become product oracle; do not ship two speculative modes. + +For either candidate, final buffer construction counts every update/padding byte against `H`; if actual record formats change, recompute the `sizeof`-based bound and tests in the same commit. Return `STACK_OUTPUT_BUDGET_EXCEEDED` rather than exceeding `M` or `H`. Composition/output is screen-bounded; snapshot copying, locking, and full-snapshot window alignment are not yet proven bounded. + +`C` should remain internal until native-backend quality/performance results show that callers need control. Verify the hard output/byte bounds and explicit budget failures for both prototypes. + +Do not add LOD hysteresis as part of this feature. Commit `e605b5f` deliberately reverted hysteresis; absent a new owner decision and evidence, selection must remain deterministic under the current policy. + +### Shared frame plan and cache + +**Proposed.** Add internal `Frame_series_planner` and `Stack_planner` producers in the layout/core target. The frame dependency flow is: + +```text +immutable series registry + | +frame snapshot cache: (Data_source*, LOD) -> complete result/hold + | +independent per-series plans -----> ordinary VISIBLE range and renderer + | +stack composition plans ----------> stacked range and stacked renderer + | +final layout, upload, draw, preview, and interaction observations +``` + +Give each registry entry an incarnation that survives ordinary descriptor clones and changes only on remove/re-add. Use the map's series revision only to detect/publish a new immutable registry snapshot; do not include it in geometry equality. The stack geometry key includes ordered registry incarnations and geometry revisions; source object addresses and sequences; selected LODs; source windows/spans; access semantic identities/revisions; interpolation, nonfinite, and hold behavior; main/preview kind; visible time range; time origin; and pre-layout framebuffer width. Exclude color, label, and built-in draw-style state from composition/base-upload identity; those change draw commands/uniforms or a separately keyed boundary buffer only. An identical geometry key means no merge, allocation, or base geometry upload. + +Composite reuse is allowed only when every source supplies a stable nonzero sequence and every access policy supplies non-conservative semantic identity/revision. Otherwise correctness wins: recompute the bounded group and record the reason reuse was disabled. BUSY follows the separate structural-key rule above and never consumes a partially fresh operand set. + +Reuse vectors and preserve capacity so steady-state composition allocates zero heap blocks. Do not implement suffix-only incremental recomposition from `current_sequence()`: the current contract does not promise append-only immutable prefixes or report the first changed index. If profiling later proves this necessary, first add an explicit source change-range contract, then key and test it. + +### GPU representation and draw order + +**Proposed.** Use one changed-group base upload rather than duplicate bottom/top timestamps in K ordinary-series VBOs: + +- one contiguous `float t_rel[E]` block, where E is the final event-union or grid-point count, plus an event-side stream when Candidate A has equal-timestamp left/right ordering; +- K contiguous `{float bottom, float top}[E]` blocks; +- small span/offset metadata for broken domains. + +The base time/ordinate payload is `4E+8KE`; for `K>=2` and `K*E<=M`, it is at most `10M`. Event-side data costs at most `M/2`, and two-`uint32_t` span records cost at most `4M`, so base geometry/metadata is below `14.5M`. A stacked-band vertex shader uses D3D11/SM5-compatible vertex attributes and emits quads between bottom and top without clamping their order. Candidate-A equal-timestamp left/right events emit a vertical edge instead of a diagonal bridge. + +Boundary lines need an explicit derived buffer; the ordinary renderer's D3D11 path requires `prev,p0,p1,next` and cannot read the proposed blocks without edge padding. For each visible LINE member and group span of length at least two, stage compact `{t_rel, cumulative_top}` pairs as `[first, samples..., last]`. Bind the same buffer four times with 8-byte stride and offsets 0/8/16/24 to a stack-boundary shader. The unpadded values cost at most `8M`; because drawable LINE spans contain at least two events, all duplicate edge padding costs at most another `8M`. Key this buffer separately by base-composite content revision, LINE-member mask/style revision, and spans. A style change may rebuild the boundary buffer but must not recompose/reupload base bands. + +The worst-case base `14.5M` plus boundary `16M` fits the rounded `32M` geometry allowance in `H`; backend-aligned uniforms/header use the remaining explicit `A*K+64`. Record A and every actual aligned update, and hard-fail if they exceed `H`. Draw filled bands in component order, then cumulative boundaries so the final line visibly represents `h`. Prepare/upload outside the render pass; bind/draw inside. + +Before committing this layout, benchmark it against the simpler 16-byte interleaved per-layer representation on the supported backends. Accept the group layout only if it reduces total bytes/CPU staging without increasing draw or binding cost enough to regress full-frame p95. Regardless of layout, counters must separately report stack time/value bytes, metadata bytes, upload count, and vertices. + +Stacking must not use `Qrhi_series_layer`: that API receives one already-planned series window and would have to duplicate multi-source snapshots, LOD selection, range, caching, and failures. Keep the custom-layer ABI unchanged. + +### Auto-range, preview, and indicators + +**Proposed.** The shared stack plan computes min/max for every emitted bottom/top during its one composition pass. VISIBLE range consumes exactly those extrema. + +GLOBAL and GLOBAL_LOD should not construct full-history composite geometry. Extend `data_query_context_t` with an explicit value projection: existing ordinary rendering may request draw extent, while stacks request `SCALAR_VALUE`, which reads `get_value` even when `get_range` exists; an override that cannot honor the projection returns UNSUPPORTED and uses the canonical scalar fallback. GLOBAL uses each source's LOD 0; GLOBAL_LOD uses each source's own coarsest level, without relating ladder indices. First compute every selected level's effective time domain, including explicit right hold, and intersect them; a disjoint intersection returns EMPTY. Restrict each scalar range query to that common domain, then compute conservative prefix bounds by summing minima/maxima for every prefix plus zero. This cannot clip a defined band, though it may remain wider because extrema and internal valid spans need not overlap simultaneously; exact internal-gap composition is intentionally avoided for global modes. Cache domain and scalar results by source/range semantic keys. + +Preview invokes the same planner independently with effective preview sources, LODs, width, and range; it must not fall back to unrelated zero-based areas. + +At the cursor, evaluate the published rendered representation and return, per member, `component_y`, `stack_base_y`, and cumulative `y`, plus `stack_total_y`. Candidate A uses its emitted event-union plan; Candidate B interpolates/evaluates its emitted grid/event output, not a fresher or more exact underlying curve. Place markers on cumulative tops. Never query raw LOD 0 or bypass the selected representation when producing a pixel-parity tooltip. + +## Designs reviewed: rejected and unresolved + +| Design | Decision and concrete replacement | +|---|---| +| Require equal timestamps or match array indices | Rejected: loses or mispairs samples. Use either the explicit event union or the explicit shared grid selected by the A/B gate. | +| Use one component's timestamps as master | Rejected: operand-order-dependent and can miss another component's breakpoint. A shared grid, if selected, is view-derived rather than borrowed from an operand. | +| Require equal LOD indices | Rejected: indices and scales are source-local. Apply an independent visible-sample budget to each source. | +| Always compose LOD 0 | Rejected: work grows with history and ignores the library's LOD contract. Bound selected input/output by framebuffer width. | +| Give every component the full pixel budget | Rejected: cumulative output can grow as `K^2*W`. Partition the single M budget according to the chosen candidate. | +| Unbounded exact union | Rejected: mathematically attractive but violates the performance requirement. Candidate A is exact only for its budgeted selected curves. | +| Bounded shared-grid resampling | **Unresolved candidate B:** it respects M and retains more per-input density for large K, but adds spike/step approximation. Choose against Candidate A only through the named native-backend/visual A/B gate. | +| Precomputed full-history `Summed_series_source` | Rejected as the first-class visual feature: `try_snapshot(lod)` has no view budget, unrelated LOD Cartesian combinations are undefined, and updates can rebuild/copy history. It remains an application option when analytic derived data is independently required. | +| Custom QRhi series layer | Rejected: wrong ownership/planning boundary. Implement one shared core stack plan consumed by range and RHI. | +| GPU compute merge first | Rejected: current inputs are CPU snapshots and backend portability matters. Start with bounded linear CPU composition; revisit only after profiling identifies composition as dominant. | +| Separate positive/negative baselines | Rejected for this request because the top would no longer necessarily be `h=f+g`. Add only as a separately named future contract. | +| Suffix incremental cache inferred from sequence | Rejected: sequence does not prove append-only immutable history. Add an explicit change-range contract first if measurements require it. | +| Separate `add_stack()` descriptor hierarchy | Rejected for the simpler caller-disciplined contract because it duplicates registration, preview, style, and lifetime APIs. Reconsider a group-owned immutable descriptor only if the owner requires group-topology atomicity even when callers use individual add/remove operations. | +| Reintroduce LOD hysteresis | Rejected under current repository policy; a prior commit explicitly removed it. Requires a new owner decision and evidence. | + +## Governed implementation batches + +Each batch must be independently useful, reviewed, and measured. Do not land unused scaffolding or compatibility paths. + +### Batch 0 — Restore dependency and CI integrity (consumer recovered; dependency Windows still open) + +Files/tools: `vnm_plot/CMakeLists.txt` and package smoke configuration; separately authorized sibling `vnm_msdf_text/.github/workflows/ci-windows.yml`; `actionlint` (or equivalent GitHub Actions-aware validation) plus an actual GitHub workflow rerun. + +Deliverable: required dependency contract is present on `master` and all eight dependent `vnm_plot` jobs are green. Remaining deliverables are a valid green dependency Windows workflow, resolved dependency commit recording, and retained no-sibling install/consumer smoke. + +Gate: `actionlint`/workflow validation passes and dependency Windows creates real jobs; exact fetched revision is recorded; dependency Linux/Windows/macOS/FreeBSD workflows pass; dependent `vnm_plot` Linux/Windows/macOS/FreeBSD text-OFF/text-ON pass. + +### Batch 0A — Close existing style debt without semantic mixing + +Files: `src/core/series_renderer.cpp:95`, `src/core/types.cpp:47-53,389-394`, and `tests/test_msdf_lcd_shader_reference.cpp:217-225`. + +Deliverable: only the 14 reported case-layout/indentation corrections, with the five current-commit and nine older/perpetuated violations preserved in the commit message provenance. Do not mix stack or hot-path changes into this batch. + +Gate: rerun the governed style pipeline from its first stage and require it to pass; run the initialized Release build and 21-test CTest gate to prove formatting changed no behavior. The shadowed time constants are handled in Batch 2 because their removal changes source tokens beyond formatting. + +### Batch 1 — Truthful hot-path observations and unchanged-frame reuse + +Files: `include/vnm_plot/rhi/series_renderer.h`, `src/core/series_renderer.cpp`, QRhi lifecycle tests, benchmark profiler/reporting, `benchmark/ARCHITECTURE.md`, benchmark CMake/workflows. + +Deliverable: test hooks absent from production, complete primary/line upload counters, keyed unchanged-frame buffer reuse, actual backend metadata, deterministic CI smoke. + +Gate: static second frame has zero library restage/upload; a LINE mutation uploads primary content once and derived line-window content once; native backend and total bytes recorded; non-stack pixels/draws unchanged. Under identical Release build, backend, finish mode, dimensions, sources, seed, and instrumentation, compare before/after full-frame p50/p95/p99, GPU-finished time, allocations, producer wait, and memory for static and live workloads. Accept only with the deterministic counter win and no statistically meaningful end-to-end regression. + +### Batch 2 — Canonical ownership, status, evaluator, and frame plan + +Files: `include/vnm_plot/core/types.h`, `basic_series_builder.h`, `access_policy.h`, `algo.h`, `time_units.h`, `src/core/types.cpp`, `series_window_planner.*`, new `frame_series_planner.*`, auto/frame range, `include/vnm_plot/rhi/series_renderer.h`, `src/core/series_renderer.cpp`, `plot_renderer.cpp`, `plot_widget.cpp`, `examples/hello_plot`, `examples/function_plotter`, `benchmark/include/benchmark_data_source.h`, `benchmark/include/benchmark_window.h`, `benchmark/src/benchmark_window.cpp`, `README.md`, and focused tests. + +Deliverable: shared ownership only, explicit snapshot statuses, canonical point/range semantics, frame `(source,LOD)` cache, and VISIBLE/render plan identity. It also owns the bounded P14 cleanups: canonical `floor_div`, duplicate snapshot-hold removal, null-update erase, plan/window consolidation, canonical time constants, and conditional LOD-topology cache only if measured. README removes nonexistent colormap/config drift and documents the resulting source/query contract. No stack-only public metadata or unused stack planner lands in this batch. + +Gate: ASan/TSan lifetime tests, UBSan timestamp cases, unordered/nonfinite evaluator table, one snapshot per shared key, no unchanged Qt map copy, VISIBLE range/render parity, warning-clean initialized build, and all focused cleanup tests. Compare identical-workload before/after full-frame p50/p95/p99, allocations, producer wait, snapshot bytes/time, alignment scans, and memory for held zero-copy and copy-on-snapshot sources; require no statistically meaningful non-stack regression. If history growth increases acquisition work beyond the owner-accepted bound, stop and add/approve a bounded window-snapshot hook before Batch 3; do not add it speculatively. + +### Batch 3 — Atomic end-to-end stack feature + +Files: public series metadata/builder, new `src/core/stack_planner.{h,cpp}` (with internal placement consistent with the layout target), scalar range projection, frame-range integration, Qt registry/API/preview/indicator publication, series renderer state/commands, one stack-band shader and boundary path, CMake/QSB assets, focused math/RHI/interaction tests, example/QML, benchmark scenarios, and architecture documentation. + +Deliverable: one usable public capability in the same governed batch—A/B-selected bounded composition strategy, independent LOD requests, cumulative bands, status/domain handling, VISIBLE/global scalar range, cached RHI rendering, preview parity, frame-pinned indicators, example, and representative benchmark. Internal commits may aid review, but no stack-only public metadata, unconsumed planner, or unused shader is pushed independently. + +Gate: complete owner-approved acceptance matrix; hard band-ordinate and total-byte bounds; linear visit counters; zero steady allocation after warm-up; stable/non-conservative unchanged second frame zero composition/upload; unstable/conservative inputs perform bounded recomposition and expose the disable reason; shader bake and prepare/record lifecycle on every backend; non-stack counters bit-for-bit unchanged. Human approval is required for representative positive, negative, mixed-step, gap, and unrelated-LOD scenes before any golden image becomes an oracle. Compare full-frame native-backend p50/p95/p99, CPU plan/compose, GPU-finished time, total bytes, draws, allocations, snapshot bytes/time, alignment scans, producer wait, memory, and LOD changes. Require no statistically meaningful non-stack regression under identical builds; agree any numeric timing threshold from baseline evidence rather than inventing one. + +## Stack acceptance matrix + +The matrix becomes an authoritative product oracle only after the owner accepts the complete proposed contract, including scalar-only contribution/range semantics, duplicate winner, BUSY wholesale reuse, singleton/style/custom-layer limits, and explicit budget failures. Algebraic negatives and intersection-of-defined-domains are the two most visible mathematical decisions. Provisional mechanics/falsification tests may be written earlier, but they must not silently settle these policies. + +| Case | Required observable result | +|---|---| +| Offset LINEAR timestamp grids | Candidate A includes both breakpoint sets; Candidate B evaluates both curves at every shared grid point. In either prototype, the final boundary is the double-precision sum at every emitted position. | +| Sampling strategy A/B | Candidate A and bounded-grid Candidate B use identical M/H and workloads but their defined B/N input caps; native compose/bytes/p95 plus spike/step visual evidence selects exactly one product strategy before oracle approval. | +| Mixed LINEAR and STEP_AFTER | Candidate A emits left/right at the true selected-curve timestamp; Candidate B emits left/right at its sampled grid transition. Both avoid a diagonal bridge, and indicators match the chosen representation; Candidate B's displacement is part of visual A/B approval. | +| Unrelated LOD counts/scales | Each source records an independently selected level satisfying its budget; no same-index assumption appears. | +| Coarsest LOD exceeds budget | Group reports `LOD_BUDGET_EXCEEDED`; there is no LOD-0 fallback or partial render. | +| Strategy budget too small | Candidate A B<2 or Candidate B N<2 reports `STACK_BUDGET_TOO_SMALL`; neither constructs ambiguous zero/one-point geometry. | +| Descending and UNKNOWN-monotonic | Direction-aware result matches ascending reference; stable nonzero sequence caches classification, while zero/unstable sequence scans once per frame-held snapshot only. | +| Truly unordered | Explicit group failure; no sort allocation and no misleading partial sum. | +| Duplicate timestamps | Highest physical source index wins consistently in ascending/descending planner and indicator. | +| Negative/cancellation `100 + -100` | Second band descends to zero; range still includes the first cumulative 100. | +| Disjoint/partially overlapping domains | Only intersection renders, except explicit right hold; no left extrapolation. GLOBAL/GLOBAL_LOD intersect selected-level domains first and return EMPTY when disjoint. | +| Nonfinite policies | BREAK/SKIP/ZERO/REJECT outcomes match the canonical evaluator and affect the whole sum where undefined. | +| BUSY/FAILED/EMPTY | BUSY reuses a previous complete group wholesale only on structural-key match and ignores all fresh operands; FAILED diagnoses/suppresses; EMPTY is empty; generations never mix. | +| Group topology update | One `apply_series_updates` publishes the complete new group in one map revision. Individual add/remove commits intermediate topology and may render a valid partial membership; documentation/tests require batching when atomic topology matters. | +| One sequence/policy/view mutation | Cache invalidates once; composition runs once, base geometry uploads once, and—when LINE is present—the separately keyed padded boundary buffer uploads once. A style-only LINE change performs no recomposition/base upload and updates only boundary/draw state. | +| Unchanged second frame | With stable nonzero sequences and non-conservative semantics: zero composition, zero allocation, zero group upload, identical pixels/commands. Otherwise bounded recomposition occurs and records its disable reason. | +| Preview | Uses independent preview sources/LODs and same cumulative contract. | +| Indicator | Reports component, base, cumulative top, and total from the published rendered event/grid representation, matching pixels even when Candidate B approximates the selected LOD curve. | +| Custom QRhi layer on a member | Explicit `CUSTOM_LAYER_IN_STACK`; no raw-coordinate custom draw is silently mixed with cumulative geometry. | +| Scalar/range-only member | `get_value` defines the contribution even when range exists; missing scalar value returns `STACK_REQUIRES_SCALAR_VALUE`; GLOBAL scalar projection never sums draw envelopes. | +| Singleton/all-NONE group | Fewer than two enabled members returns `STACK_REQUIRES_TWO_MEMBERS`; all members visually NONE returns `STACK_GROUP_HAS_NO_VISIBLE_STYLE`; an individual NONE member still contributes. | +| Boundary LINE storage | Four-binding prev/p0/p1/next shader consumes the separately keyed padded cumulative-top buffer; base plus boundary updates remain within H. | +| Zero/unstable sequence or conservative access identity | Correct bounded recomposition occurs and a counter identifies why cache reuse was disabled. | +| Signed timestamp extremes | Merge/window logic is overflow-safe and preserves ordering. | +| K={2,8,32}, W={800,3840} | Band ordinates remain within `M`, all uploaded bytes/metadata/padding remain within derived cap `H`, or an explicit budget status is returned. Separately report any snapshot/alignment cost that still grows with history. | + +## Final recommendation + +The dependent `vnm_plot` CI repair is complete; close the dependency's jobless Windows workflow as the remaining Batch 0 item. Then start `vnm_plot` implementation with Batch 0A and the unchanged-frame/counter batch; they are the clearest remaining easy wins and create trustworthy evidence for the larger change. Consolidate source/frame semantics before adding stacking; otherwise the stack would multiply existing snapshot, range, and interaction inconsistencies. + +The stack architecture itself is viable without relating source timestamps or LOD ladders: independently select bounded source-local LOD windows, use the A/B-selected bounded event-union or shared-grid evaluator, accumulate double-precision cumulative bands, and upload one cached group representation. Before acceptance tests become product oracle, the owner must approve the complete proposed contract summarized in the matrix, including the sampling-strategy result. Its two most visible mathematical choices are: + +1. accept algebraic negative stacking so the final boundary is always the actual sum; +2. accept intersection-of-defined-domains, with right extension only through explicit hold-forward. + +The other scalar/range, duplicate, BUSY, singleton/style/custom-layer, cache, and budget policies are also explicit owner decisions, not silently settled implementation details. Every proposed choice has a concrete source boundary, failure behavior, cache identity, qualified performance bound, and executable gate. diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md new file mode 100644 index 00000000..85e3a480 --- /dev/null +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -0,0 +1,543 @@ +# vnm_plot implementation plan + +Plan date: 2026-07-10 + +Execution record updated: 2026-07-10 + +Source review: `VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md` at `vnm_plot@2d94f01` + +## Outcome + +Proceed in five gated stages: + +1. close the remaining CI/style baseline; +2. instrument, capture a native baseline, then remove known unchanged-frame work in the same renderer/benchmark batch; +3. consolidate ownership, status, query, range, frame-planning, and Qt publication contracts; +4. settle the stack contract and sampling strategy with a private benchmark A/B experiment; +5. land one complete end-to-end stack feature and run final gates. + +The product stack implementation does not begin until Stages 2–4 pass and the owner accepts the complete stack contract. The separately authorized dependency Windows repair may run in parallel with local `vnm_plot` work once dependent consumer CI and local product gates are green, but it remains a final-merge gate. + +Claude was unavailable for the stated 85-minute review window. Three Codex workers provided cross-worker review; under governance this is not different-model independence. Local commits and review branches may be pushed and PRs may be opened to run CI and gather review. No batch is merged to `master` until the repository owner/human or a different model such as Fable independently reviews it. Each batch receives two review rounds plus its executable gate; require a third round when round two finds a material issue or the remediation materially changes the reviewed behavior. + +## Failure ledger + +The architecture review records **19 failed or terminated executions** in [Observed failures and current gate status](VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md#observed-failures-and-current-gate-status). Plan authoring added one failed `apply_patch` verification: a combined patch expected text that no longer exactly matched the staged draft. Codex `/root` owned the authoring error and recovered by rereading the file and applying smaller exact hunks, bringing the running total to **20**. Preserve both ledgers rather than replacing them with later green results. + +| Current state | Owning batch | +|---|---| +| Dependency Windows workflow failed before creating jobs | Startup failure recovered by `vnm_msdf_text@b9c216a`; real Windows jobs were created. At the 2026-07-10 execution-record update, Linux/macOS/FreeBSD and the normal Windows job were green while Windows full export was still running in [run 29090524058](https://github.com/imakris/vnm_msdf_text/actions/runs/29090524058). Retain the original failure and close Batch 1A only after the terminal four-platform result is recorded. | +| Fourteen style violations | Batch 1B — open | +| Benchmark cold dynamic timeout unresolved | Codex `/root` performance-harness owner; Batch 2 instruments it and the ledger stays open after Batch 2 if cause remains unresolved | +| `vnm_plot` eight first-attempt CI failures | Recovered on attempt 2; retain as closed evidence | +| MSVC initialization, local Qt platform, report-validation, and plan-authoring command failures | Recovered/documented; keep in final handoff | + +## Fixed rules + +- Owner repositories track `master`. Do not pin `vnm_msdf_text` to a tag or commit. Record its resolved commit in build/benchmark artifacts only. +- Preserve the current data/layout/RHI/Qt target boundaries and D3D11 prepare-before-pass/record-in-pass rule. +- Reuse existing series registration, profiler, snapshot, and planner patterns before adding new public types. +- No compatibility aliases for APIs removed because their semantics are unsafe or ambiguous. +- No stack-only metadata, planner, shader, public API, counter, or report field lands unused. +- Performance decisions require full-frame evidence on a real recorded QRhi backend; microbenchmarks and Null QRhi are diagnostic only. +- Every failed or terminated gate remains visible with cause, recovery, and owner even if a later rerun passes. +- Every batch is reviewed in two rounds, with a third round after a material round-two finding/remediation, independently approved by the owner/human or a different model, and passes its named gate before merge. +- The implementation agent is authorized to create local commits, push in-scope review branches, and open PRs. Prefer PR review over direct `master` pushes; do not force-push shared branches or rewrite published history. +- The approved removals of `Data_source_ref`, its raw-reference builders/setters, and ambiguous `Data_source::snapshot()` are intentional breaking API changes. Do not add compatibility aliases or no-op-deleter bridges; provide migration notes and consumer-smoke evidence in the owning batch. + +## Responsibilities + +These assignments apply unless the owner changes them before a batch starts. + +| Batches | Implementation executor | Decision approver / independent reviewer | Gate recorder | Failure-remediation owner | +|---|---|---|---|---| +| 1A | Codex `/root`, only after sibling-repository authorization | Repository owner; Fable or human review before merge | Codex `/root` | Batch 1A executor | +| 1B, 2 | Codex `/root` | Repository owner; Fable or human review before merge | Codex `/root` | Active batch executor | +| 3A–3D | Codex `/root` | Repository owner for API/oracle decisions; Fable or human review before each merge | Codex `/root` | Active batch executor | +| 4A–4B | Codex `/root` for decision record/prototype | Repository owner chooses contract and A/B winner; independent review verifies evidence | Codex `/root` | Batch 4 executor | +| 5 | Codex `/root` | Repository owner plus independent Fable/human review | Codex `/root` | Batch 5 executor | + +### Recorded owner authorization + +On 2026-07-10 the repository owner authorized the implementation agent to create local commits, push review branches, and open PRs for the in-scope work. This authorization does not waive batch gates, independent review, branch protection, or the prohibition on destructive history rewriting. + +The owner also approved: + +- D1–D3 and D5–D10 using the recommended positions below; +- the intentional removal of `Data_source_ref`, the raw-reference API, and ambiguous `Data_source::snapshot()` without compatibility aliases; +- automatic generation of the fixed benchmark scenarios and numeric noise-margin proposal after baseline calibration, followed by owner review of the generated manifest before Checkpoint 2.2. + +## Decisions required + +The owner-approved decisions below are product oracle subject to their executable evidence gates. D4 alone remains unresolved until the Stage 4 A/B experiment and visual review. + +| ID | Decision | Approved contract | Status and remaining evidence | +|---|---|---|---| +| D1 | Negative values | Algebraic cumulative stacking; a negative component descends from the previous cumulative value, preserving `h=f+g`. | **Approved 2026-07-10.** Retain visible cancellation/negative verification. | +| D2 | Defined domain | Intersection of all enabled component domains; no left extrapolation; right extension only through explicit hold-forward. | **Approved 2026-07-10.** Retain overlap, disjoint, and hold verification. | +| D3 | Group topology | Optional `stack_group_id` on ordinary series; ascending series ID is order; callers use `apply_series_updates` when topology must change atomically. Individual add/remove may render intermediate membership. | **Approved 2026-07-10.** Caller-disciplined atomicity is the product contract. | +| D4 | Sampling strategy | Unresolved between bounded exact event union and bounded shared grid. Ship exactly one, not both. | **Open.** Stage 4 A/B native-backend and visual evidence; owner selects the winner. | +| D5 | Scalar/style contract | Contribution always uses scalar `get_value`; at least two enabled members; individual `NONE` members contribute invisibly; all-NONE and custom-layer groups fail explicitly. | **Approved 2026-07-10.** Retain the status-table tests. | +| D6 | Busy/failure contract | BUSY reuses only a prior complete structurally matching group wholesale; FAILED suppresses/diagnoses; EMPTY is empty; generations never mix. | **Approved 2026-07-10.** Retain streaming/counter verification. | +| D7 | Floating timestamp API | Require integral nanoseconds in the member-pointer hot path and provide checked floating-to-ns conversion at ingestion. | **Approved 2026-07-10.** Typed/erased UBSan and performance verification remain required before Batch 3B closes. | +| D8 | Duplicate timestamps | Highest physical source index wins regardless of traversal direction. | **Approved 2026-07-10.** Retain ascending/descending duplicate tests. | +| D9 | Pixel-parity indicators | Renderer evaluates cursor time from the held published frame and returns immutable values with one-frame latency. | **Approved 2026-07-10.** Retain published-frame identity tests. | +| D10 | Unchanged-frame reuse | Stable nonzero `current_sequence()` plus stable/non-conservative access semantics authorizes reuse; zero/unstable/conservative inputs rebuild and report why. | **Approved 2026-07-10.** The existing second-frame upload oracle may change after Checkpoint 2.1 retains its baseline. | + +## Execution automation contract + +The implementation should make each batch reproducible through one gate runner and machine-readable manifests rather than a collection of undocumented shell commands. The exact script layout may follow repository conventions established in Batch 2, but it must implement these contracts when the corresponding capability first becomes necessary: + +1. **Preflight:** record source commit/diff identity, compiler, CMake, Qt, Python, external standards revision/hash, graphics backend/device/driver, dependency commit, relevant environment, and complete invocation. Missing tools such as `actionlint` are explicit environment-bootstrap failures, not missing product specifications. Bootstrap tools with a recorded version/hash rather than relying on an unversioned global installation. +2. **Gate result:** emit a versioned manifest containing batch/checkpoint, start/end time, command, exit status, phase, inputs, artifact hashes, CI run/job URLs, and recovery relationship. Failed or terminated attempts are append-only; a green rerun never overwrites them. +3. **Artifacts:** write raw local evidence below the active build tree's `gate-artifacts////` directory and upload the same bundle from CI/PR runs. Do not commit raw timing output to the source tree. +4. **Delivery:** local commits and review-branch pushes are allowed before gates close so CI and reviewers can inspect them. Merge to `master` is the protected event and requires the named batch gate and independent approval. +5. **Review rounds:** run two review/remediation rounds. Run a third when the second round identifies a material correctness, API, cache, performance, or evidence defect, or when its remediation materially changes reviewed behavior. +6. **Backend matrix:** deterministic native smoke uses D3D11 on Windows, Metal on macOS, Vulkan and desktop OpenGL on Linux where available, and desktop OpenGL on FreeBSD. A backend unavailable on its intended runner is reported explicitly rather than silently replaced. Null QRhi remains diagnostic only. Raw timing comparisons use one accepted machine/backend/build fingerprint; a fingerprint mismatch invalidates comparison. +7. **Calibration generation:** generate scenario manifests from the fixed plan matrices, dimensions, seeds, warm-up counts, and seven-run protocol. Preserve every raw run. Do not remove outliers automatically; an interrupted or failed run is retained and a replacement run is a separately identified attempt. +8. **Calibration arithmetic:** deterministic counters whose accepted baseline is zero use exact-zero regression rules. For positive metrics, calculate relative median drift from the two calibration sets as specified below. If a median is zero/nonpositive or below declared measurement resolution, report relative margin as unavailable and propose a resolution-based absolute rule instead. The runner must not silently turn unstable calibration into a permissive threshold; it emits `CALIBRATION_REVIEW_REQUIRED` with the observed drift/resolution and proposed rule for owner approval. +9. **A/B evidence:** mechanically reject a D4 candidate that violates correctness or M/V/H bounds. For surviving candidates, generate a numerical comparison, deterministic screenshots, pixel differences, and a side-by-side visual bundle. The runner may recommend but never silently select the D4 winner. +10. **Conditional stops:** the Stage 3C source-eligibility failure and any proposed Batch 3E remain owner decisions because they change supported-source scope or public API. Automation must present the failing evidence and the two plan-authorized choices without choosing one. + +## Stage 1 — Close the baseline + +### Batch 1A — Repair dependency Windows workflow + +Execution status recorded 2026-07-10: + +- the smallest workflow-only fix landed on dependency `master` as `vnm_msdf_text@b9c216a`; +- the invalid job-level `runner.temp` use was replaced by step-level `RUNNER_TEMP` initialization exported through `GITHUB_ENV`; +- dependency Linux, macOS, and FreeBSD passed at `b9c216a`; Windows created both real jobs and its normal job passed, while its full-export job remained in progress in run `29090524058` at the time of this record; +- all eight dependent `vnm_plot@2d94f01` text-OFF/text-ON jobs passed on attempt 2; +- `actionlint` is not installed locally; retain its versioned bootstrap/validation as environment evidence rather than treating it as a missing project definition. + +Scope: + +- separately authorized sibling file `C:\plms\bsd_licensed\vnm_msdf_text\.github\workflows\ci-windows.yml`; +- no `vnm_plot` production-source change; +- retain `master` tracking. + +Actions: + +1. Run `actionlint C:\plms\bsd_licensed\vnm_msdf_text\.github\workflows\ci-windows.yml`, recording the actionlint version/hash outside the repository. +2. Inspect expression-context availability, especially job-level `runner.temp`. +3. Make the smallest workflow-only correction. +4. Push the sibling workflow correction to `master`. +5. Require dependency Linux, Windows, macOS, and FreeBSD workflows to pass and Windows to create real jobs. +6. Rerun dependent `vnm_plot` workflows if the dependency contents—not only workflow syntax—change. + +Gate: + +- dependency four-platform CI green; +- `vnm_plot` text-OFF/text-ON CI green on Linux, Windows, macOS, and FreeBSD; +- resolved dependency commit recorded, never pinned. + +### Batch 1B — Formatting-only debt + +Files: + +- `src/core/series_renderer.cpp:95`; +- `src/core/types.cpp:47-53,389-394`; +- `tests/test_msdf_lcd_shader_reference.cpp:217-225`. + +Actions: + +- change only the 14 reported case-layout/indentation violations; +- keep provenance: five arrived in `2d94f01`, nine predate it. +- use the canonical Varinomics pipeline: + + ```powershell + python C:\plms\varinomics\varinomics-standards\tools\style_pipeline.py ` + --root C:\plms\bsd_licensed\vnm_plot + ``` + +- add `--write` only to apply the confirmed formatting fixes, then rerun without `--write` from the first stage; +- record standards repository base `f5edc8b` and `style_pipeline.py` SHA-256 `8715313C94D8DCC4257EB3792459BA8D7C759C9CEB6958958B64560FD65CB2F4` with the gate because the standards repository is external and moving. + +Gate: + +- governed style pipeline passes from its first stage; +- initialized Release build passes; +- CTest passes 21/21. + +Parallel rule: Batch 1A remains a final-merge gate, but it does not block local Batch 1B/2 work while dependent `vnm_plot` CI and local product gates are green. Batch 1B must pass before semantic `vnm_plot` changes are pushed for review. + +## Stage 2 — Establish evidence, then remove unchanged-frame work + +### Batch 2 — One governed hot-path batch with two local checkpoints + +Both checkpoints touch the same renderer, benchmark, counters, and tests. They remain one delivery batch/PR; the native baseline checkpoint must pass before the optimization checkpoint starts. + +Primary files: + +- `include/vnm_plot/rhi/series_renderer.h`; +- `include/vnm_plot/core/types.h` and access-policy contract documentation; +- `src/core/series_renderer.cpp`; +- benchmark ring buffer/source, CLI, reporting, profiler, CMake, and `benchmark/ARCHITECTURE.md`; +- QRhi lifecycle and benchmark helper tests; +- relevant workflows. + +Hypothesis and full-path boundary: + +- hypothesis: compiling out test tracing and reusing stable primary/LINE buffers removes library CPU staging and GPU upload without reducing live producer throughput or worsening full-frame latency outside calibrated machine noise; +- boundary: static frame entry through QRhi GPU finish, and live generator publication through snapshot/plan/upload/GPU finish, including allocations, source locks, and producer wait. + +#### Checkpoint 2.1 — Instrument and retain the baseline + +1. Add an explicit graphics-backend option. Native creation hard-fails on Null unless Null was explicitly requested. +2. Record `QRhi::backend()`, device/driver, build type, text mode, dimensions, seed, scenario, finish state, and resolved dependency commit. +3. Record exact source-tree hash plus local diff/commit identity, compiler, Qt version, and complete invocation with every raw artifact so Checkpoint 2.1 remains reproducible after Checkpoint 2.2 changes the same delivery batch. +4. Separate cold startup, untimed warm-up, submission timing, and GPU-finished timing. +5. Repair benchmark sequence semantics: ring occupancy and monotonic revision are separate; `clear()` empties occupancy and increments rather than resets revision. Snapshot and `current_sequence()` expose the same stable revision. +6. In the same batch, document the public contract: stable nonzero `current_sequence()` is required for reuse; zero/unstable disables it; access-semantic identity must cover callable behavior; a custom layer still receives `prepare()` even when library-owned buffers are reused. +7. Report primary sample, LINE-window, uniform, known custom, and total observable upload bytes/counts. Do not add stack/composition fields before Stage 5 consumes them. +8. Report snapshots and bytes/time, order-scan samples, allocations, producer wait, published samples/second, dropped/overwritten samples, memory high-water, planning time, output count, and full-frame p50/p95/p99. +9. Enable benchmark helper tests and add a short deterministic native-backend CI smoke. Hosted CI gates counters/pixels, not raw timing. +10. Instrument the unresolved cold dynamic timeout by backend creation, shader/pipeline creation, first submission, frame count, producer lock wait, and shutdown. + +Measurement protocol: + +- use one named machine/backend/build and retain all raw artifacts; +- use fixed static Bars and live Trades scenarios plus 1/8/64 ordinary LINE series at fixed dimensions/seeds; +- run two independent baseline calibration sets, each with two untimed warm-up runs and seven measured runs; +- compare run-level medians and frame-level p50/p95/p99, GPU-finished time, allocations, producer wait, published samples/second, dropped/overwritten samples, and memory; +- derive each metric's noise margin from the maximum relative median drift between the two calibration sets and record measurement resolution; +- the gate runner generates the exact scenario manifest and proposed per-metric relative/absolute rules from retained calibration artifacts using the execution automation contract; +- before Checkpoint 2.2, the repository owner reviews and approves that generated manifest: lower-is-better positive metrics require `after <= baseline * (1 + approved_noise_margin)`, while positive producer throughput requires `after >= baseline * (1 - approved_noise_margin)`. Deterministic-zero and sub-resolution metrics use the generated exact/absolute rules. No later batch may replace these rules without a plan amendment. + +Checkpoint gate: + +- fixed-seed native smoke and sequence-reset tests pass; +- public/header contract review and stable/zero/conservative/custom-layer API tests pass; +- Null cannot masquerade as GPU evidence; +- both calibration sets and the approved numeric rule are retained; +- cold timeout has a source-confirmed cause or remains explicitly open with phase evidence; +- the recorded D10 approval authorizes the existing unchanged-second-frame oracle change after Checkpoint 2.1 retains the baseline. + +#### Checkpoint 2.2 — Remove test work and unchanged uploads + +1. Compile test-only vectors/writes only with `VNM_PLOT_ENABLE_TEST_HOOKS`. +2. Add `sample_upload_key` using source, stable nonzero sequence, selected LOD, origin, access semantics, window/spans, policies, and view kind. +3. Add a primary-content revision incremented on every primary upload. +4. Key padded LINE data by primary-content revision, interpolation, and spans—not allocation generation. +5. Stable/non-conservative unchanged frames reuse library buffers even when a custom layer requests a current CPU snapshot. +6. Before Batch 3A removes raw references, a `Data_source_ref` without an owner disables cross-frame reuse and records `nonowning_source`; an owning key retains the shared owner/control-block identity plus object pointer so allocator address reuse cannot false-hit. +7. Zero/unstable/conservative semantics rebuild and record the disable reason. +8. Preserve custom-layer `prepare()` and report its observable traffic separately. + +Deterministic gate: + +- stable second frame: zero library primary/LINE restaging/upload; +- changed LINE frame: one primary and one LINE-window upload, each once; +- style without LINE: only its required primary upload; +- zero/unstable/conservative input: rebuild plus disable-reason counter; +- non-owning source: rebuild plus `nonowning_source` reason; +- pixels and command order unchanged. + +End-to-end gate: + +- repeat the approved seven-run protocol with identical inputs; +- deterministic counter win is present; +- every regression metric satisfies the owner-approved numeric noise rule; +- all raw before/after artifacts remain attached to the batch. + +## Stage 3 — Consolidate existing contracts before stacking + +Stage 3 has four independently useful batches. None introduces stack-only public API. + +### Batch 3A — Owning sources and explicit snapshot statuses + +Primary files: + +- `include/vnm_plot/core/types.h`; +- `include/vnm_plot/core/basic_series_builder.h`; +- examples, benchmark source/window, and focused tests; +- every ordinary and preview source assignment. + +Hypothesis: ownership/status changes move lifetime checks to descriptor publication without increasing render-thread snapshot time or producer wait. The full-path boundary is descriptor publication through snapshot consumption and teardown. + +Actions: + +1. Replace `Data_source_ref` in ordinary and preview descriptors with `shared_ptr`. +2. Remove raw-reference setters/builders without a no-op-deleter bridge. +3. Make `Benchmark_data_source` own/share its `Ring_buffer`; changing only the source pointer type would leave a teardown UAF. +4. Remove ambiguous `Data_source::snapshot()` and migrate its three production callers to explicit `try_snapshot()` handling. +5. EMPTY means no data; BUSY preserves the current operation; FAILED diagnoses/suppresses; READY retains its hold. +6. Remove renderer snapshot-hold storage that becomes redundant once complete snapshot results are held canonically. + +Gate: + +- `rg "Data_source_ref|set_data_source_ref|data_source_ref\("` has no public, production, example, or benchmark hits; +- Ubuntu Clang ASan (`-fsanitize=address`) ordinary/preview lifetime and benchmark teardown pass; +- Ubuntu Clang TSan core/update-remove stress is run with `-fsanitize=thread`; if Qt/QRhi cannot link or run under TSan, record `UNSUPPORTED` with compiler/linker evidence and run the same stress test without sanitizer on all four CI platforms; +- four-status tests pass; +- repeat the approved Stage 2 full-path protocol; source wait and latency satisfy its numeric rule. + +### Batch 3B — One evaluator and one range producer + +Primary files: + +- `include/vnm_plot/core/algo.h` and access/query types; +- `src/core/types.cpp`; +- `src/core/auto_range_resolver.cpp`; +- `src/qt/plot_widget.cpp`; +- focused range/interaction tests. + +Prerequisite: the recorded owner approvals for D7, D8, and D9 satisfy the semantic decision gate. Their named UBSan, performance, duplicate, and published-frame evidence remains required. Existing duplicate/indicator tests are not changed before Batch 3B establishes that evidence. + +Hypothesis: one canonical evaluator preserves render semantics while indexed sources eliminate full LOD-0 UI copies/scans; the measurement boundary is cursor/auto-adjust request through immutable result publication. + +Actions: + +1. Add one `resolve_sample_at` producer for ordering, interpolation, duplicate winner, hold, and nonfinite semantics. +2. Preserve GLOBAL value-only/range-only access without timestamps in canonical `Data_source::query_v_range()`. +3. Time-bounded VISIBLE and point queries still require timestamp access. +4. Route auto-adjust and indicators through canonical producers. +5. Delete the private range scanner only after value-only/all-time parity is proven. +6. For pixel-parity indicators, the UI publishes cursor time and the renderer returns immutable values from the held rendered frame; accept one-frame latency. +7. Resolve the floating timestamp decision D7 in this batch so stacking does not inherit undefined conversion. +8. Replace duplicate local time constants and `floor_div` with the canonical time-unit implementation; update README query/indicator contracts with the same API change. + +Gate: + +- existing GLOBAL value-only test remains green; +- unordered `[0,90,10,100]`, query 11 resolves nearest timestamp 10; +- ascending, descending, duplicates (highest physical index wins), nonfinite policies, hold, and all statuses pass; +- indicator equals the rendered frame and never a newer source generation; +- UBSan floating timestamp boundary cases pass; +- duplicate scanner is absent only after parity; +- direct indexed million-sample cursor/auto-adjust work is bounded and satisfies the Stage 2 numeric regression rule; fallback-source cost remains reported. + +### Batch 3C — Shared frame plan and range/render identity + +Primary files: + +- `src/core/series_window_planner.*`; +- new internal `frame_series_planner.*` only if it immediately replaces current production planning; +- frame range and renderer paths; +- focused cache/layout tests. + +Hypothesis: one shared plan and attempted-LOD cache removes duplicate snapshots/scans and range/render disagreement without increasing acquisition cost as retained history grows. The full-path boundary is frame planning entry through range result and renderer-consumed plan. + +Actions: + +1. Use full pre-layout framebuffer width as the deterministic LOD-budget width; final usable width changes transforms, not selected LOD. +2. Produce one immutable per-series/per-view frame plan consumed by VISIBLE range and rendering. +3. Share only complete `snapshot_result_t` values through a frame cache keyed `(Data_source*, LOD)`; cache every attempted level, not only the winner, and retain holds for the frame. Do not cache `query_time_window()` by that key because its result also depends on time range, access semantics, interpolation, hold, and nonfinite policy; leave direct query results uncached until evidence justifies their complete key. +4. Make `Series_view_plan` own one `sample_window_t`; delete duplicated window fields and migrate renderer/tests atomically. +5. Key renderer geometry reuse with existing immutable descriptor fields, owning source identity, stable access semantics, and concrete plan/window data. Do not add registry-incarnation or geometry-revision concepts. +6. Update README VISIBLE/frame-plan behavior with the production change. + +Gate: + +- VISIBLE range and renderer use the same LOD, sequence, window, and one snapshot; +- ten series sharing one source/LOD call `try_snapshot()` once per frame; +- attempted-LOD cache counters prove each `(source,lod)` acquisition occurs once per frame; +- at fixed W/visible interval, run 1x/10x/100x retained histories for direct/zero-copy, copy-on-snapshot, and unknown-order sources after a changed sequence: exact snapshot bytes/physical visits at 100x must not exceed the 1x value, and time/producer-lock metrics must satisfy the approved Stage 2 noise rule for any source class eligible for stacking; fallback classes that fail remain measured but are not silently declared stack-safe; +- warning-clean initialized build and all focused tests pass; +- the approved Stage 2 protocol passes for full-frame latency, allocations, snapshot bytes/time, alignment scans, producer wait, and memory. + +Stop condition: if a source class required for stacking fails the fixed-history-growth gate, stop Stage 3 and let the owner choose either an explicit stack-ineligible source status or a plan amendment. Only an approved amendment may create named Batch 3E with exact bounded-window-hook files, API oracle, source migrations, and gates; no unnamed hook or scaffolding exists in the current plan. + +### Batch 3D — Qt publication and update semantics + +Primary files: + +- `src/qt/plot_widget.cpp`; +- `src/qt/plot_renderer.cpp`; +- Qt synchronization/cache tests; +- matching README configuration example. + +Hypothesis: an existing-map publication revision eliminates unchanged map/config copying without changing renderer geometry identity or frame output. The boundary is Qt synchronize entry through immutable map publication. + +Actions: + +1. Add only a series-map publication revision for Qt copying. +2. In one `apply_series_updates` lock, null entries erase their IDs and add/update/remove commit together; increment the map revision exactly once for the batch. +3. Individual add/remove remains a committed intermediate topology; callers use the batch API when stack membership must change atomically. +4. Copy map/config only when its publication revision changes. +5. Geometry equality continues to use source identity, access semantics, and plan/window fields; global map revision, color, and label do not invalidate geometry. +6. Conservative callable access without a stable semantics key still invalidates safely. +7. Update the README example to use the canonical widget setter for widget-owned fields. + +Gate: + +- one initial map/config copy, then zero until mutation; +- one mixed add/update/remove call publishes one revision and contains no null map entries; +- color/label-only stable-semantic update causes no snapshot/range scan/geometry upload; +- conservative callable clone invalidates; +- pixel/command output is unchanged; +- approved Stage 2 synchronization/full-frame metrics satisfy the numeric rule. + +## Stage 4 — Settle the stack design with evidence + +### Batch 4A — Contract decision record + +The execution record already approves D1–D3 and D5–D6. Batch 4A converts those decisions into the complete reviewed stack contract and leaves only D4 open. D3 uses `std::optional stack_group_id` with ascending existing series ID and caller-batched topology; do not add a group descriptor. The record also fixes: + +- component order; +- scalar/range projection; +- duplicate winner; +- nonfinite and hold behavior; +- BUSY wholesale reuse key; +- singleton, all-NONE, and custom-layer failures; +- GLOBAL/GLOBAL_LOD common-domain behavior; +- cross-source/cross-LOD non-atomic snapshot wording; +- preview and indicator behavior. + +Do not add product semantic tests before approval. Private benchmark prototypes may assert only mechanical bounds, checked arithmetic, and explicit failures; they do not settle product semantics. + +### Batch 4B — Sampling A/B experiment + +In this batch, extend the internal planner request with separate `render_width_px` and optional `max_visible_samples`. Ordinary series pass no cap and retain the existing closest-to-one-pixel `choose_lod_level()` behavior; focused irregular-ladder and coarsest-over-budget tests require identical ordinary LOD/window/pixels. The private stack paths pass B/N without overloading shader width. + +Build two private compositor functions in the existing benchmark using that canonical selector/evaluator, plus one benchmark-private QRhi upload/draw adapter and shader shared by both candidates with the simple interleaved layout intended for Stage 5. This makes native GPU-finished and visual A/B evidence real without adding a public interface, strategy enum, planner hierarchy, or target. Before Batch 4B closes, delete the losing function, its mechanical checks, configuration, and documentation; retain the winning benchmark path, raw artifacts, and decision record until Stage 5 promotes it. + +Common definitions: + +- `W`: full framebuffer width; +- `K`: enabled members; +- `C`: internal ordinate-pairs-per-pixel budget, initially 2 for the experiment; +- `D`: 1 for all-LINEAR, 2 when STEP_AFTER requires paired events; +- `M=floor(C*W)`: per-group/per-view hard band-ordinate-pair cap; +- `A=align_up(sizeof(actual_prototype_stack_uniform_std140), rhi->ubufAlignment())`, with a static assertion for the real record layout—not a guessed 64 bytes; +- `U`: actual uniform blocks updated for that group/view; +- `H_limit=checked_add(checked_mul(40,M), checked_mul(A,U))`: conservative per-group/per-view upload cap for the simple interleaved layout, group-shared metadata, padded boundaries, and aligned uniforms; +- `V=sum(physical_input_visits)+K*E`: composition visits, hard-capped at `2*M`. + +Actual prototype upload bytes are `12*K*E + 8*group_span_count + 8*sum_line(span_length+2) + sizeof(actual_prototype_stack_uniform_std140)*U`; upload only real uniform bytes, not alignment padding. Paired equal-timestamp events are stored in left/right vector order, so no GPU event-side stream exists. H_limit/memory reservation uses `A*U`. With `K*E<=M`, base is <=12M, group-shared spans <=4M, and padded LINE data <=16M; 40M leaves explicit alignment headroom. Span records must remain group-shared; if formats or ownership change, re-derive H_limit before use. Use checked add/multiply/divide for `D*K*K`, `D*K`, `K*E`, `A*U`, M, H, V, and every byte count. Overflow, V>2M, or actual bytes>H_limit returns an explicit budget status. Main, preview, and multiple groups each have their own M/H/V result; frame totals are reported as sums, never treated as one group's allowance. + +Both prototypes call the same benchmark-local wrapper around the production LOD/window selector with explicit `max_visible_samples`; only composition differs. “Complete input” and V count interpolation padding, duplicate-collapse visits, hold samples, and every physical sample examined across attempted and selected LODs. The frame cache retains every attempted `(Data_source*,LOD)` result, not only the winning level. + +Candidate A — budgeted event union: + +- `B=floor(M/(D*K*K))`, require B>=2; +- shared selector chooses each source-local LOD independently with physical input visits <=B; +- event union exact relative to selected curves; +- STEP pairs are emitted consecutively in left/right vector order at the same timestamp; +- `E<=D*K*B`, `K*E<=M`. + +Candidate B — bounded shared grid: + +- `N=floor(M/(D*K))`, require N>=2; +- shared selector chooses each source-local LOD independently with physical input visits <=N; +- `E<=D*N`, `K*E<=M`; +- STEP changes use consecutive left/right vector-order events at the sampled grid transition; +- grid approximation and step displacement are explicit. + +A/B matrix: + +- K={2,8,32}; W={800,3840}; +- LINEAR, STEP_AFTER, mixed interpolation; +- phase-shifted grids, narrow spikes, duplicates, gaps, negative cancellation; +- unrelated LOD counts/scales; +- static and live sources; +- native backend, identical Release build/finish/instrumentation. + +Record: + +- selected LOD/input counts; +- compose CPU time, physical visits, and V; +- output pairs/vertices; +- base/boundary/metadata/uniform/total bytes; +- allocations and memory; +- producer wait and snapshot cost; +- full-frame p50/p95/p99 and GPU-finished time; +- human visual verdict for spikes, steps, gaps, and cancellation. + +Decision gate: + +- uncapped ordinary series retain identical selected LODs, windows, and pixels on regular/irregular ladders and coarsest-over-budget cases; +- both candidates respect M, V, and H_limit or return an explicit budget status; +- both repeat the approved Stage 2 seven-run native-backend protocol with identical workloads and candidate-specific B/N caps; +- choose exactly one strategy using performance plus visual evidence; +- record why the loser was rejected; +- source search proves the losing function, flags, mechanical checks, and docs are absent before Batch 4B closes; +- do not expose C or a strategy switch unless evidence proves applications need it. + +## Stage 5 — Land one complete stack feature + +### Batch 5 — Atomic end-to-end feature delivery + +This is one governed delivery batch even if developed as reviewable local commits. Do not merge or deliver public metadata, an unused planner, or an unused shader separately. + +Hypothesis and full-path boundary: the selected bounded strategy renders the owner-approved cumulative function within per-group/view M/V/H limits, preserves non-stack behavior, and keeps main/preview producer throughput within the Stage 2 numeric rule. Measure from source publication through frame planning, composition, uploads, GPU finish, preview, and frame-published indicator results. + +Scope: + +- move/promote the winning benchmark compositor and shared QRhi adapter/shader into the canonical layout/RHI targets, switch the benchmark to the production producer, and delete all benchmark-local winner copies in the same commit; +- `std::optional stack_group_id` on ordinary descriptors, ascending existing series ID as order, and existing `apply_series_updates` for atomic caller-intended topology; +- selected bounded composition planner; +- VISIBLE range consumes every bottom/top extremum from the exact same immutable composed plan used by rendering; +- bounded scalar GLOBAL/GLOBAL_LOD range: intersect effective member domains, query scalar min/max at each source-local selected level, accumulate every prefix lower/upper in `double`, cache by domain/levels/sequences/semantics, and report fallback scan work; +- frame cache and complete structural/data cache keys; +- one group VBO containing contiguous per-member interleaved `{float t_rel,bottom,top}` blocks (`static_assert(sizeof==12)`) and one band shader; do not start with a split shared-time layout; +- AREA bottom/top bands; +- DOTS cumulative knots; +- LINE cumulative boundaries using a separately keyed padded `{t_rel,top}` buffer and four prev/p0/p1/next bindings; +- stack/composition/upload observations first consumed by this feature; +- preview membership/order from ordinary descriptors, while main and preview independently plan their effective sources/access/styles/LODs; a missing/failed preview member suppresses only the complete preview group, never main and never a partial preview; +- frame-published cumulative indicators; +- extend the existing `examples/preview_config` executable rather than add another example/QML target; +- focused math/RHI/interaction tests; +- representative benchmark scenarios and documentation. + +Cache rules: + +- base composition requires stable nonzero sequences and non-conservative/explicit access semantics for cross-frame reuse; +- unstable/conservative inputs recompute within M/H and record the disable reason; +- BUSY may reuse only a prior complete structural match wholesale; +- reuse keys use existing immutable descriptor fields, owning source identity, access semantics, and concrete plan/window fields—no new registry-incarnation/geometry-revision scheme; +- color/label changes do not recompose; +- boundary data key is base-content revision, LINE-membership mask, and spans; +- color, width, opacity, and pixel-snap changes update uniforms/draw state only and never upload boundary data; +- adding/removing LINE style changes boundary membership and may rebuild boundary data, not base geometry; +- changed LINE data composes once, uploads base once, and uploads padded boundary once. + +Correctness gate: + +- all owner-approved contract cases pass; +- negative cancellation includes intermediate cumulative range; +- VISIBLE range/render plan identity proves cancellation and every intermediate cumulative extremum cannot be clipped; +- common-domain EMPTY and hold behavior pass; +- Candidate-specific STEP behavior has no diagonal bridge; +- preview and indicator match the published rendered representation; +- main and preview LODs remain independent; +- failed/empty preview group never suppresses main and never renders partial preview; +- unordered input, failed member, custom layer, missing scalar, singleton, all-NONE, and budget failures are explicit; +- no partial member is silently dropped within one immutable topology. + +Performance gate: + +- define the actual stack std140 uniform record first, static-assert its layout, compute A from its real size/backend alignment, and use checked arithmetic for every per-group/per-view M/V/H bound; +- observed upload bytes equal `12*K*E + metadata + 8*sum_line(span_length+2) + sizeof(actual_stack_uniform_std140)*U`; aligned reservation uses A*U, and both remain within their checked H_limit/memory bounds; +- zero steady allocation after warm-up where cache reuse is permitted; +- stable unchanged second frame: zero composition/base/boundary upload; +- output, composition visits, snapshot bytes, alignment visits, and producer locks satisfy the Stage 3C bounded-history gate; +- GLOBAL and GLOBAL_LOD repeat the 1x/10x/100x fixed-domain history gate; a fallback scalar range scan that grows with history returns explicit `STACK_GLOBAL_RANGE_UNBOUNDED`/ineligible status unless a separately approved bounded direct-range contract exists; +- non-stack counters are bit-for-bit unchanged; +- repeat the approved Stage 2 raw-run protocol; full-frame p50/p95/p99, GPU-finished time, bytes, draws, allocations, snapshots, producer wait, and memory satisfy its numeric rule; +- introduce a split shared-time/ordinate layout only through a later measured plan amendment if the simple one-VBO layout fails an accepted bytes/p95 target. + +Visual gate: + +- human approval of positive, negative, cancellation, mixed STEP/LINEAR, gap, preview, and unrelated-LOD examples before any screenshot becomes a golden oracle. + +## Final release gate + +Before the feature merge/release is considered complete: + +1. governed style pipeline passes; +2. initialized Release build and full CTest pass; +3. shader bake/resource lifecycle passes on every supported backend; +4. dependency and `vnm_plot` Linux/Windows/macOS/FreeBSD workflows pass; +5. clean no-sibling configure/install/consumer smoke passes while fetching dependency `master`; +6. benchmark metadata names actual backend and resolved dependency commit; +7. deterministic and end-to-end performance gates pass; +8. two or three review rounds plus owner/human or different-model independent review recheck every contract/cache/performance claim; +9. all observed failures, including recovered ones, remain in the handoff; +10. worktree contains only the intended batch changes. + +## Recommended immediate next action + +The Batch 1A startup repair has landed; monitor its remaining Windows full-export job and record the terminal four-platform result. Locally, start with Batch 1B, then Batch 2; do not touch product stack code before the evidence and contract stages pass. Review branches may be pushed, but no batch is merged while Batch 1A remains red or incomplete. This is the shortest path that produces trustworthy evidence without idling local work. From 3fe78e6d9122cd70e5ace1f8e9c71a1749858a74 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:34:54 +0200 Subject: [PATCH 02/80] style: align switch case layout --- src/core/series_renderer.cpp | 2 +- src/core/types.cpp | 23 ++++++++--------------- tests/test_msdf_lcd_shader_reference.cpp | 15 +++++---------- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index df49778b..13952158 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -91,7 +91,7 @@ int builtin_primitive_z_order(Display_style primitive_style) int view_band_order(Series_view_kind view_kind) { switch (view_kind) { - case Series_view_kind::MAIN: return 0; + case Series_view_kind::MAIN: return 0; case Series_view_kind::PREVIEW: return 1; } return 1; diff --git a/src/core/types.cpp b/src/core/types.cpp index dfeb025a..5262815c 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -44,14 +44,10 @@ struct time_window_candidates_t Data_query_status status_from_snapshot(snapshot_result_t::Snapshot_status status) { switch (status) { - case snapshot_result_t::Snapshot_status::READY: - return Data_query_status::READY; - case snapshot_result_t::Snapshot_status::EMPTY: - return Data_query_status::EMPTY; - case snapshot_result_t::Snapshot_status::BUSY: - return Data_query_status::BUSY; - case snapshot_result_t::Snapshot_status::FAILED: - return Data_query_status::FAILED; + case snapshot_result_t::Snapshot_status::READY: return Data_query_status::READY; + case snapshot_result_t::Snapshot_status::EMPTY: return Data_query_status::EMPTY; + case snapshot_result_t::Snapshot_status::BUSY: return Data_query_status::BUSY; + case snapshot_result_t::Snapshot_status::FAILED: return Data_query_status::FAILED; } return Data_query_status::FAILED; } @@ -386,13 +382,10 @@ time_window_candidates_t time_window_candidates( const data_query_context_t& query) { switch (source.time_order(lod)) { - case Time_order::ASCENDING: - return ascending_candidates(snapshot, access, query); - case Time_order::DESCENDING: - return descending_candidates(snapshot, access, query); - case Time_order::UNKNOWN: - case Time_order::UNORDERED: - return linear_candidates(snapshot, access, query); + case Time_order::ASCENDING: return ascending_candidates(snapshot, access, query); + case Time_order::DESCENDING: return descending_candidates(snapshot, access, query); + case Time_order::UNKNOWN: + case Time_order::UNORDERED: return linear_candidates(snapshot, access, query); } return linear_candidates(snapshot, access, query); } diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 0c4a962d..82291f71 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -214,16 +214,11 @@ std::string sample_expression_for_offset(float offset) std::string lcd_order_bool_name(lcd::Resolved_lcd_subpixel_order order) { switch (order) { - case lcd::Resolved_lcd_subpixel_order::RGB: - return "lcd_rgb"; - case lcd::Resolved_lcd_subpixel_order::BGR: - return "lcd_bgr"; - case lcd::Resolved_lcd_subpixel_order::VRGB: - return "lcd_vrgb"; - case lcd::Resolved_lcd_subpixel_order::VBGR: - return "lcd_vbgr"; - case lcd::Resolved_lcd_subpixel_order::NONE: - break; + case lcd::Resolved_lcd_subpixel_order::RGB: return "lcd_rgb"; + case lcd::Resolved_lcd_subpixel_order::BGR: return "lcd_bgr"; + case lcd::Resolved_lcd_subpixel_order::VRGB: return "lcd_vrgb"; + case lcd::Resolved_lcd_subpixel_order::VBGR: return "lcd_vbgr"; + case lcd::Resolved_lcd_subpixel_order::NONE: break; } return {}; From c7e82d90a366fd7186120290c72e5e1ecf2a30d9 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:36:38 +0200 Subject: [PATCH 03/80] Record staged style baseline remediation --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 49 +++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index 85e3a480..eb0df424 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -22,12 +22,19 @@ Claude was unavailable for the stated 85-minute review window. Three Codex worke ## Failure ledger -The architecture review records **19 failed or terminated executions** in [Observed failures and current gate status](VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md#observed-failures-and-current-gate-status). Plan authoring added one failed `apply_patch` verification: a combined patch expected text that no longer exactly matched the staged draft. Codex `/root` owned the authoring error and recovered by rereading the file and applying smaller exact hunks, bringing the running total to **20**. Preserve both ledgers rather than replacing them with later green results. +The architecture review records **19 failed or terminated executions** in [Observed failures and current gate status](VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md#observed-failures-and-current-gate-status). Plan authoring added one failed `apply_patch` verification: a combined patch expected text that no longer exactly matched the staged draft. Codex `/root` owned the authoring error and recovered by rereading the file and applying smaller exact hunks, bringing the total to **20** before implementation began. + +Batch 1B then added two failed style executions, bringing the running total to **22**: + +1. The aggregate `style_pipeline.py --write` invocation against the three originally named files advanced beyond the 14 switch fixes and attempted 737 insertions/826 deletions. Review caught `fix_hanging_indent.py` deleting a ternary expression's `?`, true arm, and `:` in `sample_statement_for_offset()` before commit. Codex `/root` owned the unsafe invocation, rejected the output, and restored all generated changes through `apply_patch`; no corrupting change was retained. +2. After applying only the authorized 14 switch fixes, the canonical no-write pipeline passed its first stage and failed at stage two on four previously hidden `else if` layout violations. A read-only audit then showed 22 of 27 rule groups red; those counts are diagnostic/provisional because earlier ordered fixes can affect later checks. + +Preserve all ledgers rather than replacing them with later green results. | Current state | Owning batch | |---|---| | Dependency Windows workflow failed before creating jobs | Startup failure recovered by `vnm_msdf_text@b9c216a`; real Windows jobs were created. At the 2026-07-10 execution-record update, Linux/macOS/FreeBSD and the normal Windows job were green while Windows full export was still running in [run 29090524058](https://github.com/imakris/vnm_msdf_text/actions/runs/29090524058). Retain the original failure and close Batch 1A only after the terminal four-platform result is recorded. | -| Fourteen style violations | Batch 1B — open | +| Style baseline | The original 14 switch violations are recovered in local checkpoint `3fe78e6`. The short-circuiting pipeline exposed broader pre-existing governed debt and an unsafe `fix_hanging_indent.py` rewrite; expanded Batch 1B remains open. | | Benchmark cold dynamic timeout unresolved | Codex `/root` performance-harness owner; Batch 2 instruments it and the ledger stays open after Batch 2 if cause remains unresolved | | `vnm_plot` eight first-attempt CI failures | Recovered on attempt 2; retain as closed evidence | | MSVC initialization, local Qt platform, report-validation, and plan-authoring command failures | Recovered/documented; keep in final handoff | @@ -132,27 +139,53 @@ Gate: - `vnm_plot` text-OFF/text-ON CI green on Linux, Windows, macOS, and FreeBSD; - resolved dependency commit recorded, never pinned. -### Batch 1B — Formatting-only debt +### Batch 1B — Formatting-only baseline migration -Files: +Initial checkpoint files: - `src/core/series_renderer.cpp:95`; - `src/core/types.cpp:47-53,389-394`; - `tests/test_msdf_lcd_shader_reference.cpp:217-225`. -Actions: +The original review observed only the first failing pipeline stage because the pipeline stops at the first nonzero checker. Once those 14 violations were fixed, the next stage and a read-only all-rule audit proved the baseline is broader. The batch remains formatting-only, but its scope expands to checker-enumerated C/C++ files as each canonical rule becomes active. + +#### Checkpoint 1B.1 — Original switch debt - change only the 14 reported case-layout/indentation violations; - keep provenance: five arrived in `2d94f01`, nine predate it. -- use the canonical Varinomics pipeline: +- retained local commit: `3fe78e6`; +- gate evidence: switch checker green, `git diff --check` green, initialized Release build green, CTest 21/21 green. + +#### Checkpoint 1B.2 — Newly exposed `else if` debt + +- apply only the four token-preserving `else if` to `else` newline `if` layout fixes reported at: + - `src/core/layout_calculator.cpp:756,1024`; + - `src/qt/plot_widget.cpp:1197`; + - `include/vnm_plot/core/types.h:562`; +- rerun the switch and unbraced-control-flow checks, `git diff --check`, initialized Release build, and CTest 21/21. + +#### Checkpoint 1B.3 onward — Ordered rule migration + +Process exactly one canonical style rule at a time in pipeline order: + +1. retain the no-write checker's enumerated findings and external standards identity; +2. run only that rule's fixer against its enumerated files, never the aggregate pipeline `--write`; +3. require a lexical C/C++ token-equivalence check for every formatting rewrite before build/test; any intended token change requires an explicit plan amendment and leaves this batch; +4. inspect and retain the complete diff, then rerun all preceding rules plus the active rule; +5. run `git diff --check`, the initialized Release build, and CTest 21/21; +6. obtain the iterative three-worker and Claude Fable review required for the batch, feeding findings into the next remediation/review round; +7. continue until the complete canonical pipeline passes without `--write`. + +The canonical check command is: ```powershell python C:\plms\varinomics\varinomics-standards\tools\style_pipeline.py ` --root C:\plms\bsd_licensed\vnm_plot ``` -- add `--write` only to apply the confirmed formatting fixes, then rerun without `--write` from the first stage; -- record standards repository base `f5edc8b` and `style_pipeline.py` SHA-256 `8715313C94D8DCC4257EB3792459BA8D7C759C9CEB6958958B64560FD65CB2F4` with the gate because the standards repository is external and moving. +Record standards repository base `f5edc8b` and `style_pipeline.py` SHA-256 `8715313C94D8DCC4257EB3792459BA8D7C759C9CEB6958958B64560FD65CB2F4` with the initial gate because the standards repository is external and moving. Repin both after any standards-tool repair. + +`fix_hanging_indent.py` is quarantined: an isolated replay proved that its operator-return renderer corrupts the `std::string{}` ternary in `tests/test_msdf_lcd_shader_reference.cpp::sample_statement_for_offset()`. Do not run that fixer again until the standards repository has a focused regression test and corrected implementation, or until the affected findings are satisfied by manually reviewed token-equivalent edits. A later green result does not erase the failed aggregate-write execution. Gate: From 36947c37a4a65b9c65b082add9ddef4f0f53f2f3 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:39:40 +0200 Subject: [PATCH 04/80] style: split else-if layout --- include/vnm_plot/core/types.h | 3 ++- src/core/layout_calculator.cpp | 6 ++++-- src/qt/plot_widget.cpp | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index a3ce9a78..99ea601a 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -559,7 +559,8 @@ inline erased_access_policy_t make_erased_access_policy_view( if (view.dispatch_kind == access_dispatch_kind_t::NONE) { view.dispatch_kind = access_dispatch_kind_t::STD_FUNCTION; } - else if (view.dispatch_kind == access_dispatch_kind_t::MEMBER_POINTER) { + else + if (view.dispatch_kind == access_dispatch_kind_t::MEMBER_POINTER) { view.dispatch_kind = access_dispatch_kind_t::MIXED; } } diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 1371cd68..e28a672c 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -753,7 +753,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par if (use_monospace) { width = advance * float(text.size()); } - else if (params.measure_text_func) { + else + if (params.measure_text_func) { width = params.measure_text_func(text.c_str()); if (width <= 0.f && advance > 0.f) { width = advance * float(text.size()); @@ -1021,7 +1022,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par if (use_monospace) { w = advance * float(label.size()); } - else if (params.measure_text_func) { + else + if (params.measure_text_func) { VNM_PLOT_PROFILE_SCOPE( profiler, "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.measure_text"); diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index 324c918a..525eada7 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -1194,7 +1194,8 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anc if (adjust_t && has_time_axis) { m_time_axis->set_t_range(agg.tmin_ns, agg.tmax_ns); } - else if (adjust_t) { + else + if (adjust_t) { std::unique_lock lock(m_data_cfg_mutex); apply_time_axis_update_to_data_config( m_data_cfg, From 4b950f8a210912c93ac5f31ce87ccbffb06b9382 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:41:18 +0200 Subject: [PATCH 05/80] style: normalize guard tables --- include/vnm_plot/core/algo.h | 22 +++++-------- include/vnm_plot/core/time_units.h | 24 ++++---------- include/vnm_plot/core/types.h | 8 ++--- src/core/font_renderer.cpp | 8 ++--- src/core/layout_calculator.cpp | 40 ++++++------------------ src/core/series_renderer.cpp | 28 +++++------------ src/core/series_window_planner.cpp | 8 ++--- src/core/text_lcd_policy.h | 8 ++--- src/core/text_renderer.cpp | 16 +++------- src/qt/plot_interaction_item.cpp | 16 +++------- src/qt/plot_time_axis.cpp | 8 ++--- src/qt/plot_widget.cpp | 8 ++--- tests/test_msdf_lcd_shader_reference.cpp | 40 ++++++------------------ 13 files changed, 60 insertions(+), 174 deletions(-) diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 4570b85f..8ad684c8 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -237,12 +237,8 @@ inline double get_shift(double section_size, double minval) return 0.0; } ret /= m; - if (!std::isfinite(ret)) { - return 0.0; - } - if (ret < 0) { - ret += section_size; - } + if (!std::isfinite(ret)) { return 0.0; } + if (ret < 0) { ret += section_size; } return std::isfinite(ret) ? ret : 0.0; } @@ -493,12 +489,8 @@ visible_sample_window_t select_visible_sample_window( continue; } const std::int64_t ts = get_timestamp(sample); - if (ts < t_min_ns || ts > t_max_ns) { - continue; - } - if (match_first == snapshot.count) { - match_first = i; - } + if (ts < t_min_ns || ts > t_max_ns) { continue; } + if (match_first == snapshot.count) { match_first = i; } match_last = i + 1; } if (match_first < match_last) { @@ -720,10 +712,10 @@ inline std::int64_t choose_snap_ns(std::int64_t span_ns) constexpr std::int64_t k_ns_per_day = 86400LL * k_ns_per_second; constexpr std::int64_t k_ns_per_year = 365LL * k_ns_per_day; - if (span_ns <= k_ns_per_ms) { return 1LL; } - if (span_ns <= k_ns_per_second) { return k_ns_per_us; } + if (span_ns <= k_ns_per_ms) { return 1LL; } + if (span_ns <= k_ns_per_second) { return k_ns_per_us; } if (span_ns <= k_ns_per_day) { return k_ns_per_second; } - if (span_ns <= k_ns_per_year) { return k_ns_per_hour; } + if (span_ns <= k_ns_per_year) { return k_ns_per_hour; } return k_ns_per_day; } diff --git a/include/vnm_plot/core/time_units.h b/include/vnm_plot/core/time_units.h index bfcbb1a9..3dbb6765 100644 --- a/include/vnm_plot/core/time_units.h +++ b/include/vnm_plot/core/time_units.h @@ -236,12 +236,8 @@ inline std::uint64_t duration_at_fraction_ns( std::uint64_t duration_ns, long double fraction) noexcept { - if (!std::isfinite(fraction) || fraction <= 0.0L) { - return 0; - } - if (fraction >= 1.0L) { - return duration_ns; - } + if (!std::isfinite(fraction) || fraction <= 0.0L) { return 0; } + if (fraction >= 1.0L) { return duration_ns; } const long double rounded = std::round(static_cast(duration_ns) * fraction); @@ -364,12 +360,8 @@ inline std::optional translate_time_range_by_duration_ns( Time_translation_direction direction) noexcept { const auto span = positive_span_ns(range.min_ns, range.max_ns); - if (!span) { - return std::nullopt; - } - if (duration_ns == 0) { - return range; - } + if (!span) { return std::nullopt; } + if (duration_ns == 0) { return range; } if (direction == Time_translation_direction::FORWARD) { time_range_t shifted{ @@ -456,12 +448,8 @@ inline std::int64_t saturating_ms_to_ns(std::int64_t ms_value) noexcept constexpr std::int64_t k_min_ms = std::numeric_limits::min() / k_ns_per_ms; - if (ms_value > k_max_ms) { - return std::numeric_limits::max(); - } - if (ms_value < k_min_ms) { - return std::numeric_limits::min(); - } + if (ms_value > k_max_ms) { return std::numeric_limits::max(); } + if (ms_value < k_min_ms) { return std::numeric_limits::min(); } return ms_value * k_ns_per_ms; } diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 99ea601a..1fff4b9f 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -337,12 +337,8 @@ struct data_snapshot_t return nullptr; } const size_t count1 = count - count2; - if (index < count1) { - return static_cast(data) + index * stride; - } - if (!data2 || count2 == 0) { - return nullptr; - } + if (index < count1) { return static_cast(data) + index * stride; } + if (!data2 || count2 == 0) { return nullptr; } return static_cast(data2) + (index - count1) * stride; } diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index ddac3253..9f456aa8 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -510,12 +510,8 @@ std::shared_ptr load_cached_font_from_disk( font->font_digest = digest; std::uint32_t atlas_size = 0; - if (!read(atlas_size)) { - return nullptr; - } - if (atlas_size != static_cast(k_atlas_texture_size)) { - return nullptr; - } + if (!read(atlas_size)) { return nullptr; } + if (atlas_size != static_cast(k_atlas_texture_size)) { return nullptr; } font->atlas.atlas_size = static_cast(atlas_size); std::uint32_t baked_pixel_height = 0; diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index e28a672c..e69f1d82 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -54,12 +54,8 @@ std::int64_t saturating_round_to_int64(long double value) noexcept } const long double rounded = std::round(value); - if (rounded <= k_min) { - return std::numeric_limits::min(); - } - if (rounded >= k_max) { - return std::numeric_limits::max(); - } + if (rounded <= k_min) { return std::numeric_limits::min(); } + if (rounded >= k_max) { return std::numeric_limits::max(); } return static_cast(rounded); } @@ -80,12 +76,8 @@ std::int64_t saturating_floor_to_int64(long double value) noexcept } const long double floored = std::floor(value); - if (floored <= k_min) { - return std::numeric_limits::min(); - } - if (floored >= k_max) { - return std::numeric_limits::max(); - } + if (floored <= k_min) { return std::numeric_limits::min(); } + if (floored >= k_max) { return std::numeric_limits::max(); } return static_cast(floored); } @@ -115,18 +107,10 @@ class Timestamp_label_cache double adjusted_font_size, size_t format_signature) { - if (!std::isfinite(step)) { - step = 0.0; - } - if (!std::isfinite(range)) { - range = 0.0; - } - if (!std::isfinite(monospace_advance)) { - monospace_advance = 0.0f; - } - if (!std::isfinite(adjusted_font_size)) { - adjusted_font_size = 0.0; - } + if (!std::isfinite(step)) { step = 0.0; } + if (!std::isfinite(range)) { range = 0.0; } + if (!std::isfinite(monospace_advance)) { monospace_advance = 0.0f; } + if (!std::isfinite(adjusted_font_size)) { adjusted_font_size = 0.0; } const auto step_bits = to_ieee_bits(step); const auto range_bits = to_ieee_bits(range); @@ -1097,12 +1081,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par auto write_it = candidates.begin(); for (auto it = candidates.begin(); it != candidates.end(); ++it) { const bool anchor_taken = has_anchor_within(accepted, it->x_anchor, k_coincide); - if (anchor_taken) { - continue; - } - if (write_it != it) { - *write_it = std::move(*it); - } + if (anchor_taken) { continue; } + if (write_it != it) { *write_it = std::move(*it); } ++write_it; } candidates.erase(write_it, candidates.end()); diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index 13952158..24cc50f4 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -143,12 +143,8 @@ std::vector builtin_segment_spans( bool has_builtin_segment_span(const sample_window_t& window) { - if (window.gpu_count < 2) { - return false; - } - if (window.nonfinite_policy == Nonfinite_sample_policy::SKIP) { - return true; - } + if (window.gpu_count < 2) { return false; } + if (window.nonfinite_policy == Nonfinite_sample_policy::SKIP) { return true; } return std::any_of( window.drawable_spans.begin(), window.drawable_spans.end(), @@ -161,12 +157,8 @@ bool is_builtin_primitive_drawable( Display_style primitive_style, const sample_window_t& window) { - if (window.gpu_count == 0) { - return false; - } - if (primitive_style == Display_style::DOTS) { - return true; - } + if (window.gpu_count == 0) { return false; } + if (primitive_style == Display_style::DOTS) { return true; } return has_builtin_segment_span(window); } @@ -1414,15 +1406,9 @@ void Series_renderer::prepare( [](const auto& a, const auto& b) { const int a_view = view_band_order(a.view_kind); const int b_view = view_band_order(b.view_kind); - if (a_view != b_view) { - return a_view < b_view; - } - if (a.z_order != b.z_order) { - return a.z_order < b.z_order; - } - if (a.series_order != b.series_order) { - return a.series_order < b.series_order; - } + if (a_view != b_view) { return a_view < b_view; } + if (a.z_order != b.z_order) { return a.z_order < b.z_order; } + if (a.series_order != b.series_order) { return a.series_order < b.series_order; } return a.insertion_order < b.insertion_order; }); diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index fc04db40..92110ec6 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -78,12 +78,8 @@ drawable_window_result_t build_drawable_window( sample, nonfinite_policy, ignored); - if (status == sample_draw_status_t::FAILED) { - return false; - } - if (status == sample_draw_status_t::SKIPPED) { - return true; - } + if (status == sample_draw_status_t::FAILED) { return false; } + if (status == sample_draw_status_t::SKIPPED) { return true; } if (result.spans.empty() || result.spans.back().source_first + diff --git a/src/core/text_lcd_policy.h b/src/core/text_lcd_policy.h index e7f4ac39..bba5aa70 100644 --- a/src/core/text_lcd_policy.h +++ b/src/core/text_lcd_policy.h @@ -24,12 +24,8 @@ constexpr text_lcd_resolved_subpixel_order_t text_lcd_auto_order_from_detections text_lcd_resolved_subpixel_order_t qt_order, text_lcd_resolved_subpixel_order_t os_order) { - if (vnm::msdf_text::lcd::is_display_specific(qt_order)) { - return qt_order; - } - if (vnm::msdf_text::lcd::is_display_specific(os_order)) { - return os_order; - } + if (vnm::msdf_text::lcd::is_display_specific(qt_order)) { return qt_order; } + if (vnm::msdf_text::lcd::is_display_specific(os_order)) { return os_order; } return text_lcd_resolved_subpixel_order_t::NONE; } diff --git a/src/core/text_renderer.cpp b/src/core/text_renderer.cpp index 27f59179..49d69d5d 100644 --- a/src/core/text_renderer.cpp +++ b/src/core/text_renderer.cpp @@ -52,12 +52,8 @@ bool fit_rect_vertically_within(glm::vec4& rect, float& baseline_y, const glm::v } float dy = 0.0f; - if (rect.y < clip.y) { - dy = clip.y - rect.y; - } - if (rect.w + dy > clip.w) { - dy += clip.w - (rect.w + dy); - } + if (rect.y < clip.y) { dy = clip.y - rect.y; } + if (rect.w + dy > clip.w) { dy += clip.w - (rect.w + dy); } const glm::vec4 shifted( rect.x, @@ -192,12 +188,8 @@ bool update_and_draw_faded_labels( continue; } - if (state.alpha > 0.0f) { - draw_fn(it->first, state); - } - if (state.direction != 0) { - any_active = true; - } + if (state.alpha > 0.0f) { draw_fn(it->first, state); } + if (state.direction != 0) { any_active = true; } ++it; } diff --git a/src/qt/plot_interaction_item.cpp b/src/qt/plot_interaction_item.cpp index c1328bcf..a1f4d25f 100644 --- a/src/qt/plot_interaction_item.cpp +++ b/src/qt/plot_interaction_item.cpp @@ -401,18 +401,10 @@ bool Plot_interaction_item::handle_wheel( } qreal dy = angle_delta_y; - if (dy == 0.0) { - dy = pixel_delta_y; - } - if (dy == 0.0) { - dy = angle_delta_x; - } - if (dy == 0.0) { - dy = pixel_delta_x; - } - if (dy == 0.0) { - return false; - } + if (dy == 0.0) { dy = pixel_delta_y; } + if (dy == 0.0) { dy = angle_delta_x; } + if (dy == 0.0) { dy = pixel_delta_x; } + if (dy == 0.0) { return false; } const auto mods = Qt::KeyboardModifiers::fromInt(modifiers); const qreal steps = dy / 120.0; diff --git a/src/qt/plot_time_axis.cpp b/src/qt/plot_time_axis.cpp index c6421a2c..0da513fb 100644 --- a/src/qt/plot_time_axis.cpp +++ b/src/qt/plot_time_axis.cpp @@ -125,12 +125,8 @@ double Plot_time_axis::shared_vbar_width_px() const void Plot_time_axis::update_shared_vbar_width(const QObject* owner, double width_px) { - if (!m_sync_vbar_width || !owner) { - return; - } - if (!std::isfinite(width_px) || width_px <= 0.0) { - return; - } + if (!m_sync_vbar_width || !owner) { return; } + if (!std::isfinite(width_px) || width_px <= 0.0) { return; } m_vbar_width_by_owner[owner] = width_px; diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index 525eada7..a2c31801 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -528,12 +528,8 @@ void Plot_widget::set_time_axis(Plot_time_axis* axis) &Plot_time_axis::shared_vbar_width_changed, this, [this](double px) { - if (!m_time_axis || !m_time_axis->sync_vbar_width()) { - return; - } - if (px <= 0.0 || !std::isfinite(px)) { - return; - } + if (!m_time_axis || !m_time_axis->sync_vbar_width()) { return; } + if (px <= 0.0 || !std::isfinite(px)) { return; } apply_vbar_width_target(px); }); m_time_axis_sync_vbar_connection = QObject::connect( diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 82291f71..58813c95 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -173,41 +173,21 @@ std::string sample_name_for_offset(float offset) std::string weight_name_for_value(float weight) { - if (weight == ref::k_lcd_filter_edge) { - return "filter_edge"; - } - if (weight == ref::k_lcd_filter_side) { - return "filter_side"; - } - if (weight == ref::k_lcd_filter_center) { - return "filter_center"; - } + if (weight == ref::k_lcd_filter_edge) { return "filter_edge"; } + if (weight == ref::k_lcd_filter_side) { return "filter_side"; } + if (weight == ref::k_lcd_filter_center) { return "filter_center"; } return {}; } std::string sample_expression_for_offset(float offset) { - if (offset == -3.0f) { - return "glyph_ratio - subpixel_step * 3.0"; - } - if (offset == -2.0f) { - return "glyph_ratio - subpixel_step * 2.0"; - } - if (offset == -1.0f) { - return "glyph_ratio - subpixel_step"; - } - if (offset == 0.0f) { - return "glyph_ratio"; - } - if (offset == 1.0f) { - return "glyph_ratio + subpixel_step"; - } - if (offset == 2.0f) { - return "glyph_ratio + subpixel_step * 2.0"; - } - if (offset == 3.0f) { - return "glyph_ratio + subpixel_step * 3.0"; - } + if (offset == -3.0f) { return "glyph_ratio - subpixel_step * 3.0"; } + if (offset == -2.0f) { return "glyph_ratio - subpixel_step * 2.0"; } + if (offset == -1.0f) { return "glyph_ratio - subpixel_step"; } + if (offset == 0.0f) { return "glyph_ratio"; } + if (offset == 1.0f) { return "glyph_ratio + subpixel_step"; } + if (offset == 2.0f) { return "glyph_ratio + subpixel_step * 2.0"; } + if (offset == 3.0f) { return "glyph_ratio + subpixel_step * 3.0"; } return {}; } From 1034d1b9e7f7ac115ad5a4500c31648aa787d485 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:42:19 +0200 Subject: [PATCH 06/80] style: align test macro continuations --- tests/test_macros.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/test_macros.h b/tests/test_macros.h index ab74fdc4..02aa386f 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -2,23 +2,23 @@ #include -#define TEST_ASSERT(cond, msg) \ - do { \ - if (!(cond)) { \ +#define TEST_ASSERT(cond, msg) \ + do { \ + if (!(cond)) { \ std::cerr << "FAIL: " << msg << " (line " << __LINE__ << ")" << std::endl; \ - return false; \ - } \ + return false; \ + } \ } while (0) -#define RUN_TEST(test_fn) \ - do { \ - std::cout << "Running " << #test_fn << "... "; \ - if (test_fn()) { \ - std::cout << "OK" << std::endl; \ - ++passed; \ - } \ - else { \ - std::cout << "FAIL" << std::endl; \ - ++failed; \ - } \ +#define RUN_TEST(test_fn) \ + do { \ + std::cout << "Running " << #test_fn << "... "; \ + if (test_fn()) { \ + std::cout << "OK" << std::endl; \ + ++passed; \ + } \ + else { \ + std::cout << "FAIL" << std::endl; \ + ++failed; \ + } \ } while (0) From d76a403aa7414d10e64459267fc99f6b342e2d3a Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:43:34 +0200 Subject: [PATCH 07/80] style: wrap long signatures --- include/vnm_plot/qt/plot_time_axis.h | 4 +++- include/vnm_plot/qt/plot_widget.h | 12 ++++++++++-- include/vnm_plot/rhi/chrome_renderer.h | 6 +++++- include/vnm_plot/rhi/font_renderer.h | 5 ++++- src/core/font_renderer.cpp | 11 +++++++++-- src/core/text_renderer_stub.cpp | 10 ++++++++-- src/qt/plot_interaction_item.cpp | 4 +++- src/qt/plot_time_axis.cpp | 4 +++- tests/test_qrhi_layer_lifecycle.cpp | 4 +++- 9 files changed, 48 insertions(+), 12 deletions(-) diff --git a/include/vnm_plot/qt/plot_time_axis.h b/include/vnm_plot/qt/plot_time_axis.h index 33901e88..83ea79db 100644 --- a/include/vnm_plot/qt/plot_time_axis.h +++ b/include/vnm_plot/qt/plot_time_axis.h @@ -81,7 +81,9 @@ class Plot_time_axis : public QObject // shot and skip the seed/slide branching, which is the right shape when // a caller already has both bounds in hand. Q_INVOKABLE void set_t_range_qml_ms(qint64 t_min_ms, qint64 t_max_ms); - Q_INVOKABLE void set_available_t_range_qml_ms(qint64 t_available_min_ms, qint64 t_available_max_ms); + Q_INVOKABLE void set_available_t_range_qml_ms( + qint64 t_available_min_ms, + qint64 t_available_max_ms); Q_INVOKABLE void adjust_t_from_mouse_diff(double ref_width, double diff); Q_INVOKABLE void adjust_t_from_mouse_diff_on_preview(double ref_width, double diff); diff --git a/include/vnm_plot/qt/plot_widget.h b/include/vnm_plot/qt/plot_widget.h index ad5ad920..fd3627aa 100644 --- a/include/vnm_plot/qt/plot_widget.h +++ b/include/vnm_plot/qt/plot_widget.h @@ -201,8 +201,16 @@ class Plot_widget : public QQuickRhiItem // Q_INVOKABLEs that take or return timestamps cross the QML boundary // in milliseconds-since-epoch. Result maps also report entry["x"] in ms. - Q_INVOKABLE QVariantList get_indicator_samples(double x_ms, double plot_width, double plot_height, double mouse_px = -1.0) const; - Q_INVOKABLE QVariantList get_nearest_samples(double x_ms, double plot_width, double plot_height, double mouse_px = -1.0) const; + Q_INVOKABLE QVariantList get_indicator_samples( + double x_ms, + double plot_width, + double plot_height, + double mouse_px = -1.0) const; + Q_INVOKABLE QVariantList get_nearest_samples( + double x_ms, + double plot_width, + double plot_height, + double mouse_px = -1.0) const; Q_INVOKABLE QString format_timestamp_precise(qint64 timestamp_ms) const; // --- Qt Quick RHI Interface --- diff --git a/include/vnm_plot/rhi/chrome_renderer.h b/include/vnm_plot/rhi/chrome_renderer.h index 660c8cc9..4274f06e 100644 --- a/include/vnm_plot/rhi/chrome_renderer.h +++ b/include/vnm_plot/rhi/chrome_renderer.h @@ -29,7 +29,11 @@ class Chrome_renderer private: // Helper to compute grid layer parameters for vertical axis - grid_layer_params_t calculate_grid_params(double min, double max, double pixel_span, double font_px); + grid_layer_params_t calculate_grid_params( + double min, + double max, + double pixel_span, + double font_px); }; } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/font_renderer.h b/include/vnm_plot/rhi/font_renderer.h index 447073f7..124a4cc3 100644 --- a/include/vnm_plot/rhi/font_renderer.h +++ b/include/vnm_plot/rhi/font_renderer.h @@ -92,7 +92,10 @@ class Font_renderer void initialize(Asset_loader& asset_loader, int pixel_height, bool force_rebuild = false); // Initializes CPU font metrics/cache for layout calculation before the render pass. - void initialize_metrics(Asset_loader& asset_loader, int pixel_height, bool force_rebuild = false); + void initialize_metrics( + Asset_loader& asset_loader, + int pixel_height, + bool force_rebuild = false); // Releases this instance's weak reference to the shared resources. void deinitialize(); diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 9f456aa8..680d468e 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -959,7 +959,10 @@ void Font_renderer::initialize(Asset_loader& asset_loader, int pixel_height, boo m_impl->m_resources = &resources; } -void Font_renderer::initialize_metrics(Asset_loader& asset_loader, int pixel_height, bool force_rebuild) +void Font_renderer::initialize_metrics( + Asset_loader& asset_loader, + int pixel_height, + bool force_rebuild) { if (!force_rebuild && m_impl->m_font_cache && @@ -998,7 +1001,11 @@ float Font_renderer::measure_text_px(const char* text) const *atlas, m_impl->current_draw_pixel_height(), text); } -bool Font_renderer::text_visual_bounds_px(const char* text, float x, float y, glm::vec4& bounds) const +bool Font_renderer::text_visual_bounds_px( + const char* text, + float x, + float y, + glm::vec4& bounds) const { const msdf_atlas_t* atlas = m_impl->current_atlas(); if (!text || !atlas) { diff --git a/src/core/text_renderer_stub.cpp b/src/core/text_renderer_stub.cpp index 1ff1b358..ca6e2da3 100644 --- a/src/core/text_renderer_stub.cpp +++ b/src/core/text_renderer_stub.cpp @@ -12,13 +12,19 @@ Text_renderer::Text_renderer(Font_renderer* fr) { } -bool Text_renderer::render(const frame_context_t& /*ctx*/, bool /*fade_v_labels*/, bool /*fade_h_labels*/) +bool Text_renderer::render( + const frame_context_t& /*ctx*/, + bool /*fade_v_labels*/, + bool /*fade_h_labels*/) { // No-op in stub - return false to indicate no animations in progress return false; } -bool Text_renderer::prepare(const frame_context_t& /*ctx*/, bool /*fade_v_labels*/, bool /*fade_h_labels*/) +bool Text_renderer::prepare( + const frame_context_t& /*ctx*/, + bool /*fade_v_labels*/, + bool /*fade_h_labels*/) { // No-op in stub - return false to indicate no animations in progress return false; diff --git a/src/qt/plot_interaction_item.cpp b/src/qt/plot_interaction_item.cpp index a1f4d25f..7cc66ede 100644 --- a/src/qt/plot_interaction_item.cpp +++ b/src/qt/plot_interaction_item.cpp @@ -163,7 +163,9 @@ qreal Plot_interaction_item::zoom_animation_scale_factor(qreal velocity, qreal e return std::pow(s_base_k, integrated_velocity); } -qreal Plot_interaction_item::zoom_animation_velocity_after(qreal velocity, qreal elapsed_timer_steps) +qreal Plot_interaction_item::zoom_animation_velocity_after( + qreal velocity, + qreal elapsed_timer_steps) { if (elapsed_timer_steps <= 0.0) { return velocity; diff --git a/src/qt/plot_time_axis.cpp b/src/qt/plot_time_axis.cpp index 0da513fb..bd52813b 100644 --- a/src/qt/plot_time_axis.cpp +++ b/src/qt/plot_time_axis.cpp @@ -293,7 +293,9 @@ void Plot_time_axis::set_t_range_qml_ms(qint64 t_min_ms, qint64 t_max_ms) set_t_range(ms_for_qml_to_ns(t_min_ms), ms_for_qml_to_ns(t_max_ms)); } -void Plot_time_axis::set_available_t_range_qml_ms(qint64 t_available_min_ms, qint64 t_available_max_ms) +void Plot_time_axis::set_available_t_range_qml_ms( + qint64 t_available_min_ms, + qint64 t_available_max_ms) { set_available_t_range( ms_for_qml_to_ns(t_available_min_ms), diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index f580f716..721ab517 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -470,7 +470,9 @@ plot::frame_layout_result_t make_layout() return layout; } -plot::frame_context_t make_context(const plot::frame_layout_result_t& layout, const plot::Plot_config& config) +plot::frame_context_t make_context( + const plot::frame_layout_result_t& layout, + const plot::Plot_config& config) { plot::frame_context_t ctx{layout}; ctx.t0 = 0; From 9aeec209e25deefaf4e2162abbe805e6082e3e51 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:47:34 +0200 Subject: [PATCH 08/80] style: normalize prototype blocks --- include/vnm_plot/core/access_policy.h | 80 ++++----- include/vnm_plot/core/algo.h | 74 ++++----- include/vnm_plot/core/layout_calculator.h | 6 +- include/vnm_plot/core/time_grid.h | 2 +- include/vnm_plot/core/time_units.h | 78 ++++----- include/vnm_plot/core/types.h | 75 +++++---- include/vnm_plot/qt/plot_interaction_item.h | 19 ++- include/vnm_plot/qt/plot_time_axis.h | 45 +++-- include/vnm_plot/qt/plot_widget.h | 40 +++-- include/vnm_plot/rhi/chrome_renderer.h | 8 +- include/vnm_plot/rhi/font_renderer.h | 35 ++-- include/vnm_plot/rhi/primitive_renderer.h | 31 +++- include/vnm_plot/rhi/qrhi_series_layer.h | 2 +- include/vnm_plot/rhi/series_renderer.h | 38 +++-- include/vnm_plot/rhi/text_renderer.h | 17 +- src/core/auto_range_resolver.cpp | 160 +++++++++--------- src/core/auto_range_resolver.h | 14 +- src/core/chrome_renderer.cpp | 20 +-- src/core/font_renderer.cpp | 92 +++++------ src/core/frame_range_planner.cpp | 11 +- src/core/frame_range_planner.h | 11 +- src/core/label_pane_geometry.h | 12 +- src/core/layout_calculator.cpp | 30 ++-- src/core/primitive_renderer.cpp | 30 ++-- src/core/rhi_helpers.h | 50 +++--- src/core/series_renderer.cpp | 43 ++--- src/core/series_window_planner.cpp | 24 +-- src/core/text_lcd_policy.h | 12 +- src/core/text_renderer.cpp | 30 ++-- src/core/time_grid.cpp | 12 +- src/core/types.cpp | 172 ++++++++++---------- src/qt/plot_interaction_item.cpp | 18 +- src/qt/plot_renderer.cpp | 22 +-- src/qt/plot_time_axis.cpp | 8 +- src/qt/plot_widget.cpp | 12 +- src/qt/t_axis_adjust.h | 40 +++-- src/qt/text_lcd_resolver.cpp | 12 +- src/qt/text_lcd_resolver.h | 15 +- tests/test_cache_invalidation.cpp | 4 +- tests/test_concurrent_series.cpp | 8 +- tests/test_data_source_queries.cpp | 22 +-- tests/test_font_disk_cache.cpp | 10 +- tests/test_layout_calculator.cpp | 6 +- tests/test_msdf_lcd_shader_reference.cpp | 8 +- tests/test_plot_interaction_item.cpp | 29 ++-- tests/test_qrhi_layer_lifecycle.cpp | 69 ++++---- tests/test_snapshot_caching.cpp | 36 ++-- 47 files changed, 835 insertions(+), 757 deletions(-) diff --git a/include/vnm_plot/core/access_policy.h b/include/vnm_plot/core/access_policy.h index 3ad510a1..fd90e7a3 100644 --- a/include/vnm_plot/core/access_policy.h +++ b/include/vnm_plot/core/access_policy.h @@ -79,8 +79,8 @@ constexpr std::int64_t timestamp_member_to_ns(Timestamp value) template const std::decay_t& member_at_offset( - const void* sample, - std::size_t offset) + const void* sample, + std::size_t offset) { const auto* bytes = static_cast(sample); return *reinterpret_cast*>(bytes + offset); @@ -88,8 +88,8 @@ const std::decay_t& member_at_offset( template std::int64_t member_timestamp_access( - const erased_access_policy_t& access, - const void* sample) + const erased_access_policy_t& access, + const void* sample) { using timestamp_t = std::decay_t; return timestamp_member_to_ns( @@ -98,8 +98,8 @@ std::int64_t member_timestamp_access( template float member_value_access( - const erased_access_policy_t& access, - const void* sample) + const erased_access_policy_t& access, + const void* sample) { using value_t = std::decay_t; return static_cast( @@ -108,8 +108,8 @@ float member_value_access( template std::pair member_range_access( - const erased_access_policy_t& access, - const void* sample) + const erased_access_policy_t& access, + const void* sample) { using range_min_t = std::decay_t; using range_max_t = std::decay_t; @@ -126,12 +126,12 @@ std::pair member_range_access( // distinguishes user sample types so caches stay correct across mixed-type // series. inline std::uint64_t compute_sample_layout_key( - std::size_t sample_stride, - std::size_t timestamp_offset, - std::size_t value_offset, - bool has_range, - std::size_t range_min_offset, - std::size_t range_max_offset) + std::size_t sample_stride, + std::size_t timestamp_offset, + std::size_t value_offset, + bool has_range, + std::size_t range_min_offset, + std::size_t range_max_offset) { std::uint64_t h = k_fnv_offset_basis; h = fnv1a_mix(h, sample_stride); @@ -169,16 +169,16 @@ constexpr std::uint64_t member_semantics_tag() } inline std::uint64_t compute_sample_semantics_key( - std::size_t sample_stride, - std::size_t timestamp_offset, - std::uint64_t timestamp_tag, - std::size_t value_offset, - std::uint64_t value_tag, - bool has_range, - std::size_t range_min_offset, - std::uint64_t range_min_tag, - std::size_t range_max_offset, - std::uint64_t range_max_tag) + std::size_t sample_stride, + std::size_t timestamp_offset, + std::uint64_t timestamp_tag, + std::size_t value_offset, + std::uint64_t value_tag, + bool has_range, + std::size_t range_min_offset, + std::uint64_t range_min_tag, + std::size_t range_max_offset, + std::uint64_t range_max_tag) { std::uint64_t h = k_fnv_offset_basis; h = fnv1a_mix(h, 0x53454D414E544943ULL); @@ -282,8 +282,8 @@ struct Data_access_policy_typed } Data_access_policy_typed& set_semantics_key( - std::uint64_t value, - std::uint64_t revision = 0) noexcept + std::uint64_t value, + std::uint64_t revision = 0) noexcept { semantics_key = detail::make_explicit_sample_semantics_key(value, revision); @@ -317,22 +317,22 @@ struct Data_access_policy_typed private: template friend void assign_standard_accessors( - Data_access_policy_typed& policy, - Timestamp_member S::* timestamp_member, - Value_member S::* value_member); + Data_access_policy_typed& policy, + Timestamp_member S::* timestamp_member, + Value_member S::* value_member); template friend Data_access_policy_typed make_access_policy( - Timestamp_member S::* timestamp_member, - Value_member S::* value_member); + Timestamp_member S::* timestamp_member, + Value_member S::* value_member); template friend Data_access_policy_typed make_access_policy( - Timestamp_member S::* timestamp_member, - Value_member S::* value_member, - Range_min_member S::* range_min_member, - Range_max_member S::* range_max_member); + Timestamp_member S::* timestamp_member, + Value_member S::* value_member, + Range_min_member S::* range_min_member, + Range_max_member S::* range_max_member); void set_internal_access(detail::erased_access_policy_t access) { @@ -363,9 +363,9 @@ struct Data_access_policy_typed template inline void assign_standard_accessors( - Data_access_policy_typed& policy, - Timestamp_member Sample::* timestamp_member, - Value_member Sample::* value_member) + Data_access_policy_typed& policy, + Timestamp_member Sample::* timestamp_member, + Value_member Sample::* value_member) { policy.get_timestamp = [timestamp_member](const Sample& sample) -> std::int64_t { using timestamp_t = std::decay_t; @@ -391,7 +391,7 @@ template inline Data_access_policy_typed make_access_policy( Timestamp_member Sample::* timestamp_member, - Value_member Sample::* value_member, + Value_member Sample::* value_member, Range_min_member Sample::* range_min_member, Range_max_member Sample::* range_max_member) { @@ -447,7 +447,7 @@ inline Data_access_policy_typed make_access_policy( template inline Data_access_policy_typed make_access_policy( Timestamp_member Sample::* timestamp_member, - Value_member Sample::* value_member) + Value_member Sample::* value_member) { Data_access_policy_typed policy; const std::size_t timestamp_offset = detail::member_offset(timestamp_member); diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 8ad684c8..3ba915d4 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -337,11 +337,11 @@ std::vector compute_lod_scales(const DataSourceT& data_source) // sample pointer; nullptr means malformed or torn input and fails the search. template std::optional bsearch_ts_impl( - std::size_t count, - AddrFn&& addr, - GetTimestampFn&& get_timestamp, - Cmp&& cmp, - std::int64_t t_ns) + std::size_t count, + AddrFn&& addr, + GetTimestampFn&& get_timestamp, + Cmp&& cmp, + std::int64_t t_ns) { std::size_t lo = 0; std::size_t hi = count; @@ -366,11 +366,11 @@ std::optional bsearch_ts_impl( // get_timestamp accessor must return the same unit. template std::size_t lower_bound_timestamp( - const void* data, - std::size_t count, - std::size_t stride, - GetTimestampFn&& get_timestamp, - std::int64_t t_ns) + const void* data, + std::size_t count, + std::size_t stride, + GetTimestampFn&& get_timestamp, + std::int64_t t_ns) { if (data == nullptr || count == 0 || stride == 0) { return 0; @@ -389,8 +389,8 @@ std::size_t lower_bound_timestamp( template std::size_t lower_bound_timestamp( const data_snapshot_t& snapshot, - GetTimestampFn&& get_timestamp, - std::int64_t t_ns) + GetTimestampFn&& get_timestamp, + std::int64_t t_ns) { if (!snapshot.is_valid()) { return 0; @@ -408,11 +408,11 @@ std::size_t lower_bound_timestamp( // Query value t_ns is in nanoseconds (API convention). template std::size_t upper_bound_timestamp( - const void* data, - std::size_t count, - std::size_t stride, - GetTimestampFn&& get_timestamp, - std::int64_t t_ns) + const void* data, + std::size_t count, + std::size_t stride, + GetTimestampFn&& get_timestamp, + std::int64_t t_ns) { if (data == nullptr || count == 0 || stride == 0) { return 0; @@ -431,8 +431,8 @@ std::size_t upper_bound_timestamp( template std::size_t upper_bound_timestamp( const data_snapshot_t& snapshot, - GetTimestampFn&& get_timestamp, - std::int64_t t_ns) + GetTimestampFn&& get_timestamp, + std::int64_t t_ns) { if (!snapshot.is_valid()) { return 0; @@ -467,10 +467,10 @@ struct visible_sample_window_t template visible_sample_window_t select_visible_sample_window( const data_snapshot_t& snapshot, - GetTimestampFn&& get_timestamp, - std::int64_t t_min_ns, - std::int64_t t_max_ns, - bool timestamps_monotonic) + GetTimestampFn&& get_timestamp, + std::int64_t t_min_ns, + std::int64_t t_max_ns, + bool timestamps_monotonic) { if (!snapshot.is_valid()) { return {}; @@ -533,12 +533,12 @@ struct visible_sample_aggregate_t template visible_sample_aggregate_t aggregate_visible_sample_range( const data_snapshot_t& snapshot, - GetTimestampFn&& get_timestamp, - GetRangeFn&& get_range, - std::int64_t window_tmin_ns, - std::int64_t window_tmax_ns, - Series_interpolation interpolation, - Empty_window_behavior empty_window_behavior) + GetTimestampFn&& get_timestamp, + GetRangeFn&& get_range, + std::int64_t window_tmin_ns, + std::int64_t window_tmax_ns, + Series_interpolation interpolation, + Empty_window_behavior empty_window_behavior) { visible_sample_aggregate_t aggregate; if (!snapshot.is_valid() || window_tmax_ns < window_tmin_ns) { @@ -606,10 +606,10 @@ visible_sample_aggregate_t aggregate_visible_sample_range( template timestamp_bracket_t bracket_timestamp_impl( - std::size_t count, - AddrFn&& addr, - GetTimestampFn&& get_timestamp, - double t_ns) + std::size_t count, + AddrFn&& addr, + GetTimestampFn&& get_timestamp, + double t_ns) { if (count == 0) { return {}; @@ -670,8 +670,8 @@ timestamp_bracket_t bracket_timestamp_impl( template timestamp_bracket_t bracket_timestamp( const data_snapshot_t& snapshot, - GetTimestampFn&& get_timestamp, - double t_ns) + GetTimestampFn&& get_timestamp, + double t_ns) { if (!snapshot.is_valid()) { return {}; @@ -758,8 +758,8 @@ inline std::int64_t choose_origin_ns(std::int64_t t_view_min_ns, std::int64_t sp // Chooses the LOD level whose pixels-per-sample is closest to 1.0. inline std::size_t choose_lod_level( - const std::vector& scales, - double base_pps) + const std::vector& scales, + double base_pps) { if (scales.empty() || !(base_pps > 0.0)) { return 0; diff --git a/include/vnm_plot/core/layout_calculator.h b/include/vnm_plot/core/layout_calculator.h index f5639774..c56a4380 100644 --- a/include/vnm_plot/core/layout_calculator.h +++ b/include/vnm_plot/core/layout_calculator.h @@ -96,9 +96,9 @@ class Layout_calculator private: // Check if intervals fit without overlap bool fits_with_gap( - const std::vector>& level, - const std::vector>& accepted, - float min_gap) const; + const std::vector>& level, + const std::vector>& accepted, + float min_gap) const; // Scratch buffers (reused to avoid allocations) mutable std::vector> m_scratch_vals; diff --git a/include/vnm_plot/core/time_grid.h b/include/vnm_plot/core/time_grid.h index 8e036fdd..9cc32aef 100644 --- a/include/vnm_plot/core/time_grid.h +++ b/include/vnm_plot/core/time_grid.h @@ -12,6 +12,6 @@ grid_layer_params_t build_time_grid_layers( double t_max_seconds, double width_px, double font_px, - bool* out_dropped_non_multiple_step_or_null = nullptr); + bool* out_dropped_non_multiple_step_or_null = nullptr); } // namespace vnm::plot diff --git a/include/vnm_plot/core/time_units.h b/include/vnm_plot/core/time_units.h index 3dbb6765..323db3f2 100644 --- a/include/vnm_plot/core/time_units.h +++ b/include/vnm_plot/core/time_units.h @@ -26,8 +26,8 @@ enum class Time_translation_direction }; inline std::optional checked_add_ns( - std::int64_t value_ns, - std::int64_t delta_ns) noexcept + std::int64_t value_ns, + std::int64_t delta_ns) noexcept { if (delta_ns > 0 && value_ns > std::numeric_limits::max() - delta_ns) @@ -43,8 +43,8 @@ inline std::optional checked_add_ns( } inline std::optional checked_sub_ns( - std::int64_t value_ns, - std::int64_t delta_ns) noexcept + std::int64_t value_ns, + std::int64_t delta_ns) noexcept { if (delta_ns > 0 && value_ns < std::numeric_limits::min() + delta_ns) @@ -60,8 +60,8 @@ inline std::optional checked_sub_ns( } inline std::int64_t saturating_add_ns( - std::int64_t value_ns, - std::int64_t delta_ns) noexcept + std::int64_t value_ns, + std::int64_t delta_ns) noexcept { const auto result = checked_add_ns(value_ns, delta_ns); if (result) { @@ -73,8 +73,8 @@ inline std::int64_t saturating_add_ns( } inline std::int64_t saturating_sub_ns( - std::int64_t value_ns, - std::int64_t delta_ns) noexcept + std::int64_t value_ns, + std::int64_t delta_ns) noexcept { const auto result = checked_sub_ns(value_ns, delta_ns); if (result) { @@ -86,8 +86,8 @@ inline std::int64_t saturating_sub_ns( } inline std::int64_t saturating_add_duration_ns( - std::int64_t value_ns, - std::uint64_t duration_ns) noexcept + std::int64_t value_ns, + std::uint64_t duration_ns) noexcept { std::int64_t result = value_ns; std::uint64_t remaining = duration_ns; @@ -109,8 +109,8 @@ inline std::int64_t saturating_add_duration_ns( } inline std::int64_t saturating_sub_duration_ns( - std::int64_t value_ns, - std::uint64_t duration_ns) noexcept + std::int64_t value_ns, + std::uint64_t duration_ns) noexcept { std::int64_t result = value_ns; std::uint64_t remaining = duration_ns; @@ -132,8 +132,8 @@ inline std::int64_t saturating_sub_duration_ns( } inline std::optional positive_span_ns( - std::int64_t min_ns, - std::int64_t max_ns) noexcept + std::int64_t min_ns, + std::int64_t max_ns) noexcept { if (!(max_ns > min_ns)) { return std::nullopt; @@ -146,8 +146,8 @@ inline std::optional positive_span_ns( namespace detail { inline std::int64_t positive_span_ns_for_signed_api( - std::int64_t min_ns, - std::int64_t max_ns) noexcept + std::int64_t min_ns, + std::int64_t max_ns) noexcept { const auto span = positive_span_ns(min_ns, max_ns); if (!span) { @@ -162,16 +162,16 @@ inline std::int64_t positive_span_ns_for_signed_api( } // namespace detail inline long double span_ns_as_long_double( - std::int64_t min_ns, - std::int64_t max_ns) noexcept + std::int64_t min_ns, + std::int64_t max_ns) noexcept { return static_cast(max_ns) - static_cast(min_ns); } inline std::optional positive_span_ns_as_long_double( - std::int64_t min_ns, - std::int64_t max_ns) noexcept + std::int64_t min_ns, + std::int64_t max_ns) noexcept { if (!(max_ns > min_ns)) { return std::nullopt; @@ -180,8 +180,8 @@ inline std::optional positive_span_ns_as_long_double( } inline std::int64_t midpoint_ns( - std::int64_t min_ns, - std::int64_t max_ns) noexcept + std::int64_t min_ns, + std::int64_t max_ns) noexcept { if (min_ns <= max_ns) { const std::uint64_t span = @@ -197,8 +197,8 @@ inline std::int64_t midpoint_ns( } inline time_range_t centered_time_range_ns( - std::int64_t center_ns, - std::uint64_t span_ns) noexcept + std::int64_t center_ns, + std::uint64_t span_ns) noexcept { if (span_ns == 0) { return {center_ns, center_ns}; @@ -233,8 +233,8 @@ inline time_range_t centered_time_range_ns( } inline std::uint64_t duration_at_fraction_ns( - std::uint64_t duration_ns, - long double fraction) noexcept + std::uint64_t duration_ns, + long double fraction) noexcept { if (!std::isfinite(fraction) || fraction <= 0.0L) { return 0; } if (fraction >= 1.0L) { return duration_ns; } @@ -254,8 +254,8 @@ inline std::uint64_t duration_at_fraction_ns( } inline std::optional time_at_fraction_ns( - time_range_t range, - long double fraction) noexcept + time_range_t range, + long double fraction) noexcept { const auto span = positive_span_ns(range.min_ns, range.max_ns); if (!span) { @@ -268,8 +268,8 @@ inline std::optional time_at_fraction_ns( } inline std::uint64_t scaled_duration_ns( - std::uint64_t duration_ns, - long double scale) noexcept + std::uint64_t duration_ns, + long double scale) noexcept { if (!std::isfinite(scale) || scale <= 0.0L || duration_ns == 0) { return 0; @@ -291,9 +291,9 @@ inline std::uint64_t scaled_duration_ns( } inline time_range_t time_range_around_pivot_ns( - std::int64_t pivot_ns, - std::uint64_t left_span_ns, - std::uint64_t right_span_ns) noexcept + std::int64_t pivot_ns, + std::uint64_t left_span_ns, + std::uint64_t right_span_ns) noexcept { if (left_span_ns > std::numeric_limits::max() - right_span_ns) { return { @@ -331,8 +331,8 @@ inline time_range_t time_range_around_pivot_ns( } inline std::optional translate_time_range_ns( - time_range_t range, - std::int64_t delta_ns) noexcept + time_range_t range, + std::int64_t delta_ns) noexcept { const auto span = positive_span_ns(range.min_ns, range.max_ns); if (!span) { @@ -355,8 +355,8 @@ inline std::optional translate_time_range_ns( } inline std::optional translate_time_range_by_duration_ns( - time_range_t range, - std::uint64_t duration_ns, + time_range_t range, + std::uint64_t duration_ns, Time_translation_direction direction) noexcept { const auto span = positive_span_ns(range.min_ns, range.max_ns); @@ -391,8 +391,8 @@ inline std::optional translate_time_range_by_duration_ns( } inline std::optional clamp_time_range_to_available_ns( - time_range_t target, - time_range_t available) noexcept + time_range_t target, + time_range_t available) noexcept { const auto target_span = positive_span_ns(target.min_ns, target.max_ns); if (!target_span) { diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 1fff4b9f..6d2fd7b7 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -129,12 +129,14 @@ struct access_policy_cache_key_t }; erased_access_policy_t make_erased_access_policy_view( - const Data_access_policy& policy); + const Data_access_policy& policy); + access_policy_cache_key_t make_access_policy_cache_key( - const Data_access_policy* policy, - const erased_access_policy_t& view); + const Data_access_policy* policy, + const erased_access_policy_t& view); + sample_semantics_key_t make_sample_semantics_key( - const Data_access_policy* policy); + const Data_access_policy* policy); template class access_function_slot_t; @@ -216,9 +218,9 @@ class access_function_slot_t friend struct ::vnm::plot::Data_access_policy_typed; void bind_internal_access( - erased_access_policy_t* access, - std::uint64_t* revision, - sample_semantics_key_t* semantics_key = nullptr) noexcept + erased_access_policy_t* access, + std::uint64_t* revision, + sample_semantics_key_t* semantics_key = nullptr) noexcept { m_internal_access = access; m_revision = revision; @@ -245,8 +247,8 @@ class access_function_slot_t }; inline sample_semantics_key_t make_explicit_sample_semantics_key( - std::uint64_t value, - std::uint64_t revision) noexcept + std::uint64_t value, + std::uint64_t revision) noexcept { sample_semantics_key_t key; if (value != 0) { @@ -455,8 +457,8 @@ struct Data_access_policy } Data_access_policy& set_semantics_key( - std::uint64_t value, - std::uint64_t revision = 0) noexcept + std::uint64_t value, + std::uint64_t revision = 0) noexcept { semantics_key = detail::make_explicit_sample_semantics_key(value, revision); @@ -465,12 +467,14 @@ struct Data_access_policy private: friend detail::erased_access_policy_t detail::make_erased_access_policy_view( - const Data_access_policy& policy); + const Data_access_policy& policy); + friend detail::access_policy_cache_key_t detail::make_access_policy_cache_key( - const Data_access_policy* policy, - const detail::erased_access_policy_t& view); + const Data_access_policy* policy, + const detail::erased_access_policy_t& view); + friend sample_semantics_key_t detail::make_sample_semantics_key( - const Data_access_policy* policy); + const Data_access_policy* policy); template friend struct Data_access_policy_typed; @@ -504,8 +508,8 @@ struct Data_access_policy namespace detail { inline std::int64_t std_function_access_timestamp( - const erased_access_policy_t& view, - const void* sample) + const erased_access_policy_t& view, + const void* sample) { const auto* policy = static_cast(view.ctx); return policy && policy->get_timestamp @@ -514,16 +518,16 @@ inline std::int64_t std_function_access_timestamp( } inline float std_function_access_value( - const erased_access_policy_t& view, - const void* sample) + const erased_access_policy_t& view, + const void* sample) { const auto* policy = static_cast(view.ctx); return policy && policy->get_value ? policy->get_value(sample) : 0.0f; } inline std::pair std_function_access_range( - const erased_access_policy_t& view, - const void* sample) + const erased_access_policy_t& view, + const void* sample) { const auto* policy = static_cast(view.ctx); return policy && policy->get_range @@ -564,8 +568,8 @@ inline erased_access_policy_t make_erased_access_policy_view( } inline access_policy_cache_key_t make_access_policy_cache_key( - const Data_access_policy* policy, - const erased_access_policy_t& view) + const Data_access_policy* policy, + const erased_access_policy_t& view) { access_policy_cache_key_t key; key.identity = policy; @@ -678,16 +682,16 @@ struct sample_draw_value_t }; sample_draw_status_t read_sample_draw_value( - const erased_access_policy_t& access, - const void* sample, - Nonfinite_sample_policy policy, - sample_draw_value_t& out); + const erased_access_policy_t& access, + const void* sample, + Nonfinite_sample_policy policy, + sample_draw_value_t& out); sample_draw_status_t read_sample_draw_value( - const Data_access_policy& access, - const void* sample, - Nonfinite_sample_policy policy, - sample_draw_value_t& out); + const Data_access_policy& access, + const void* sample, + Nonfinite_sample_policy policy, + sample_draw_value_t& out); } // namespace detail @@ -770,11 +774,12 @@ class Data_source /// snapshot fallback; UNSUPPORTED is ignored (local scan). Only opt in via /// `supports_direct_time_window_query()` when these hold. virtual data_query_result_t query_time_window( - std::size_t lod, - const data_query_context_t& query); + std::size_t lod, + const data_query_context_t& query); + virtual data_query_result_t query_v_range( - std::size_t lod, - const data_query_context_t& query); + std::size_t lod, + const data_query_context_t& query); }; diff --git a/include/vnm_plot/qt/plot_interaction_item.h b/include/vnm_plot/qt/plot_interaction_item.h index 8ecc3f17..bd09c12f 100644 --- a/include/vnm_plot/qt/plot_interaction_item.h +++ b/include/vnm_plot/qt/plot_interaction_item.h @@ -34,19 +34,22 @@ class Plot_interaction_item : public QQuickItem void set_pin_time_pivot_to_right(bool pinned); bool is_interaction_enabled() const; - void set_interaction_enabled(bool enabled); + + void set_interaction_enabled( + bool enabled); Q_INVOKABLE bool handle_wheel( - qreal x, - qreal y, - qreal angle_delta_x, - qreal angle_delta_y, - qreal pixel_delta_x, - qreal pixel_delta_y, - int modifiers); + qreal x, + qreal y, + qreal angle_delta_x, + qreal angle_delta_y, + qreal pixel_delta_x, + qreal pixel_delta_y, + int modifiers); signals: void plot_widget_changed(); + void time_plot_widget_changed(); void pin_time_pivot_to_right_changed(); void interaction_enabled_changed(); diff --git a/include/vnm_plot/qt/plot_time_axis.h b/include/vnm_plot/qt/plot_time_axis.h index 83ea79db..18f2a7d0 100644 --- a/include/vnm_plot/qt/plot_time_axis.h +++ b/include/vnm_plot/qt/plot_time_axis.h @@ -80,15 +80,29 @@ class Plot_time_axis : public QObject // one side at a time, but these atomic setters validate ordering in one // shot and skip the seed/slide branching, which is the right shape when // a caller already has both bounds in hand. - Q_INVOKABLE void set_t_range_qml_ms(qint64 t_min_ms, qint64 t_max_ms); + Q_INVOKABLE void set_t_range_qml_ms( + qint64 t_min_ms, + qint64 t_max_ms); + Q_INVOKABLE void set_available_t_range_qml_ms( - qint64 t_available_min_ms, - qint64 t_available_max_ms); + qint64 t_available_min_ms, + qint64 t_available_max_ms); + + Q_INVOKABLE void adjust_t_from_mouse_diff( + double ref_width, + double diff); + + Q_INVOKABLE void adjust_t_from_mouse_diff_on_preview( + double ref_width, + double diff); - Q_INVOKABLE void adjust_t_from_mouse_diff(double ref_width, double diff); - Q_INVOKABLE void adjust_t_from_mouse_diff_on_preview(double ref_width, double diff); - Q_INVOKABLE void adjust_t_from_mouse_pos_on_preview(double ref_width, double x_pos); - Q_INVOKABLE void adjust_t_from_pivot_and_scale(double pivot, double scale); + Q_INVOKABLE void adjust_t_from_mouse_pos_on_preview( + double ref_width, + double x_pos); + + Q_INVOKABLE void adjust_t_from_pivot_and_scale( + double pivot, + double scale); // QML-facing indicator API: timestamp is milliseconds-since-epoch. Q_INVOKABLE void set_indicator_state(QObject* owner, bool active, qint64 t_ms); Q_INVOKABLE void set_indicator_state(QObject* owner, bool active, qint64 t_ms, double x_norm); @@ -107,20 +121,21 @@ class Plot_time_axis : public QObject signals: void t_limits_changed(); + void sync_vbar_width_changed(); void shared_vbar_width_changed(double width_px); void indicator_state_changed(); private: bool apply_time_axis_limits_if_changed( - qint64 t_min_ns, - qint64 t_max_ns, - qint64 t_available_min_ns, - qint64 t_available_max_ns, - bool t_min_initialized, - bool t_max_initialized, - bool t_available_min_initialized, - bool t_available_max_initialized); + qint64 t_min_ns, + qint64 t_max_ns, + qint64 t_available_min_ns, + qint64 t_available_max_ns, + bool t_min_initialized, + bool t_max_initialized, + bool t_available_min_initialized, + bool t_available_max_initialized); qint64 m_t_min = 0; qint64 m_t_max = 0; diff --git a/include/vnm_plot/qt/plot_widget.h b/include/vnm_plot/qt/plot_widget.h index fd3627aa..1ed563a9 100644 --- a/include/vnm_plot/qt/plot_widget.h +++ b/include/vnm_plot/qt/plot_widget.h @@ -100,8 +100,14 @@ class Plot_widget : public QQuickRhiItem // --- Data Management --- // Add or update a data series - void add_series(int id, std::shared_ptr series); - void apply_series_updates(const std::vector>>& updates); + void add_series( + int id, + std::shared_ptr + series); + + void apply_series_updates( + const std::vector>>& + updates); // Remove a data series void remove_series(int id); @@ -187,17 +193,17 @@ class Plot_widget : public QQuickRhiItem Q_INVOKABLE virtual void adjust_t_from_pivot_and_scale(double pivot, double scale); Q_INVOKABLE virtual void adjust_v_from_mouse_diff(float ref_height, float diff); Q_INVOKABLE virtual void adjust_v_from_pivot_and_scale(float pivot, float scale); - Q_INVOKABLE void adjust_v_to_target(float target_vmin, float target_vmax); - Q_INVOKABLE void auto_adjust_view(bool adjust_t, double extra_v_scale); - Q_INVOKABLE void auto_adjust_view(bool adjust_t, double extra_v_scale, bool anchor_zero); + Q_INVOKABLE void adjust_v_to_target(float target_vmin, float target_vmax); + Q_INVOKABLE void auto_adjust_view(bool adjust_t, double extra_v_scale); + Q_INVOKABLE void auto_adjust_view(bool adjust_t, double extra_v_scale, bool anchor_zero); Q_INVOKABLE virtual bool can_zoom_in() const; - Q_INVOKABLE double update_dpi_scaling_factor(); - Q_INVOKABLE void set_visible_info(int flags); - Q_INVOKABLE void set_relative_preview_height(float relative); - Q_INVOKABLE void set_preview_height_min(double v); - Q_INVOKABLE void set_preview_height_max(double v); - Q_INVOKABLE void set_show_if_calculated_preview_height_below_min(bool v); - Q_INVOKABLE void set_preview_height_steps(int steps); + Q_INVOKABLE double update_dpi_scaling_factor(); + Q_INVOKABLE void set_visible_info(int flags); + Q_INVOKABLE void set_relative_preview_height(float relative); + Q_INVOKABLE void set_preview_height_min(double v); + Q_INVOKABLE void set_preview_height_max(double v); + Q_INVOKABLE void set_show_if_calculated_preview_height_below_min(bool v); + Q_INVOKABLE void set_preview_height_steps(int steps); // Q_INVOKABLEs that take or return timestamps cross the QML boundary // in milliseconds-since-epoch. Result maps also report entry["x"] in ms. @@ -206,12 +212,15 @@ class Plot_widget : public QQuickRhiItem double plot_width, double plot_height, double mouse_px = -1.0) const; + Q_INVOKABLE QVariantList get_nearest_samples( double x_ms, double plot_width, double plot_height, double mouse_px = -1.0) const; - Q_INVOKABLE QString format_timestamp_precise(qint64 timestamp_ms) const; + + Q_INVOKABLE QString format_timestamp_precise( + qint64 timestamp_ms) const; // --- Qt Quick RHI Interface --- @@ -219,6 +228,7 @@ class Plot_widget : public QQuickRhiItem signals: void t_limits_changed(); + void v_limits_changed(); void v_auto_changed(); void preview_height_changed(); @@ -251,7 +261,8 @@ class Plot_widget : public QQuickRhiItem double plot_width, double plot_height, double mouse_px, - Indicator_sample_mode mode) const; + Indicator_sample_mode + mode) const; // Plot_renderer reads m_config / m_data_cfg under the matching shared_mutexes // during synchronize(); friending lets it touch those members directly @@ -310,6 +321,7 @@ class Plot_widget : public QQuickRhiItem double compute_preview_height_px(double widget_height_px) const; std::pair current_v_range() const; data_config_t data_cfg_snapshot() const; + template void update_config_field(Field& field, Value new_value, Signal signal); diff --git a/include/vnm_plot/rhi/chrome_renderer.h b/include/vnm_plot/rhi/chrome_renderer.h index 4274f06e..f16e5619 100644 --- a/include/vnm_plot/rhi/chrome_renderer.h +++ b/include/vnm_plot/rhi/chrome_renderer.h @@ -30,10 +30,10 @@ class Chrome_renderer private: // Helper to compute grid layer parameters for vertical axis grid_layer_params_t calculate_grid_params( - double min, - double max, - double pixel_span, - double font_px); + double min, + double max, + double pixel_span, + double font_px); }; } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/font_renderer.h b/include/vnm_plot/rhi/font_renderer.h index 124a4cc3..a1ca38e3 100644 --- a/include/vnm_plot/rhi/font_renderer.h +++ b/include/vnm_plot/rhi/font_renderer.h @@ -62,9 +62,9 @@ namespace detail { using font_disk_cache_digest_t = std::array; [[nodiscard]] bool validate_font_disk_cache_file( - const std::filesystem::path& path, - const font_disk_cache_digest_t& expected_digest, - int pixel_height); + const std::filesystem::path& path, + const font_disk_cache_digest_t& expected_digest, + int pixel_height); } // namespace detail #endif @@ -93,16 +93,16 @@ class Font_renderer // Initializes CPU font metrics/cache for layout calculation before the render pass. void initialize_metrics( - Asset_loader& asset_loader, - int pixel_height, - bool force_rebuild = false); + Asset_loader& asset_loader, + int pixel_height, + bool force_rebuild = false); // Releases this instance's weak reference to the shared resources. void deinitialize(); void set_log_callbacks( - std::function log_error, - std::function log_debug); + std::function log_error, + std::function log_debug); // --- Text Measurement --- @@ -139,17 +139,18 @@ class Font_renderer // Uploads the current QRhi CPU batch into this frame's draw plan and clears it. void rhi_queue_draw( const frame_context_t& ctx, - const glm::mat4& pmv, - const glm::vec4& color, - const text_scissor_t& scissor = {}, - const text_shadow_t& shadow = {}); + const glm::mat4& pmv, + const glm::vec4& color, + const text_scissor_t& scissor = {}, + const text_shadow_t& shadow = {}); + void rhi_queue_draw( const frame_context_t& ctx, - const glm::mat4& pmv, - const glm::vec4& color, - const text_scissor_t& scissor, - const text_shadow_t& shadow, - const text_lcd_t& lcd); + const glm::mat4& pmv, + const glm::vec4& color, + const text_scissor_t& scissor, + const text_shadow_t& shadow, + const text_lcd_t& lcd); // Uploads the accumulated QRhi text geometry after all draw batches are queued. void rhi_finalize_frame(const frame_context_t& ctx); diff --git a/include/vnm_plot/rhi/primitive_renderer.h b/include/vnm_plot/rhi/primitive_renderer.h index bdc45af3..b9a68806 100644 --- a/include/vnm_plot/rhi/primitive_renderer.h +++ b/include/vnm_plot/rhi/primitive_renderer.h @@ -64,10 +64,10 @@ class Primitive_renderer // queued onto ctx.rhi_updates; the actual draw is recorded by // record_draws() during the open pass. void draw_grid_shader( - const frame_context_t& ctx, - const glm::vec2& origin, - const glm::vec2& size, - const glm::vec4& color, + const frame_context_t& ctx, + const glm::vec2& origin, + const glm::vec2& size, + const glm::vec4& color, const grid_layer_params_t& vertical_levels, const grid_layer_params_t& horizontal_levels); @@ -113,13 +113,26 @@ class Primitive_renderer // state. Friendship via membership lets the helpers reach private types // (rect_vertex_t, rhi_state_t) without exposing them publicly. static bool rhi_ensure_rect_pipeline( - rhi_state_t& rhi_state, QRhi* rhi, QRhiRenderTarget* rt); + rhi_state_t& rhi_state, + QRhi* rhi, + QRhiRenderTarget* rt); + static bool rhi_ensure_grid_pipeline( - rhi_state_t& rhi_state, QRhi* rhi, QRhiRenderTarget* rt); + rhi_state_t& rhi_state, + QRhi* rhi, + QRhiRenderTarget* rt); + static bool rhi_ensure_grid_quad_vbo( - rhi_state_t& rhi_state, QRhi* rhi, QRhiResourceUpdateBatch* updates); - static void rhi_on_backend_change(rhi_state_t& rhi_state, QRhi* rhi); - static void rhi_reset_frame_plan(rhi_state_t& rhi_state); + rhi_state_t& rhi_state, + QRhi* rhi, + QRhiResourceUpdateBatch* updates); + + static void rhi_on_backend_change( + rhi_state_t& rhi_state, + QRhi* rhi); + + static void rhi_reset_frame_plan( + rhi_state_t& rhi_state); static constexpr int k_rect_initial_quads = 256; }; diff --git a/include/vnm_plot/rhi/qrhi_series_layer.h b/include/vnm_plot/rhi/qrhi_series_layer.h index 6b10c4c7..e7b01736 100644 --- a/include/vnm_plot/rhi/qrhi_series_layer.h +++ b/include/vnm_plot/rhi/qrhi_series_layer.h @@ -127,7 +127,7 @@ class Qrhi_series_layer series_view_uniform_std140_t make_series_view_uniform( const frame_context_t& frame, - const series_data_t& series, + const series_data_t& series, const sample_window_t& window); } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/series_renderer.h b/include/vnm_plot/rhi/series_renderer.h index 447fd71c..9573089e 100644 --- a/include/vnm_plot/rhi/series_renderer.h +++ b/include/vnm_plot/rhi/series_renderer.h @@ -68,14 +68,18 @@ class Series_renderer // only legal outside an open pass, and beginPass consumes its 4th // argument before the renderer's own draws would otherwise have written // to it. - void prepare(const frame_context_t& ctx, - const std::map>& series); + void prepare( + const frame_context_t& ctx, + const std::map>& + series); // Render all series in the frame context. Records draws only when // ctx.rhi is non-null; uploads must already have been submitted via // prepare() + beginPass(batch). - void render(const frame_context_t& ctx, - const std::map>& series); + void render( + const frame_context_t& ctx, + const std::map>& + series); private: struct gpu_sample_t @@ -210,24 +214,28 @@ class Series_renderer // open render pass. bool rhi_prepare_series_view_samples( const frame_context_t& ctx, - vbo_view_state_t& view_state, + vbo_view_state_t& view_state, const sample_window_t& window); + bool rhi_prepare_series_primitive( const frame_context_t& ctx, - const series_data_t* series, - Display_style primitive_style, - vbo_view_state_t& view_state, + const series_data_t* series, + Display_style primitive_style, + vbo_view_state_t& view_state, const sample_window_t& window, - float line_width_px, - float point_diameter_px, - float area_fill_alpha, - std::vector* out_segment_spans = nullptr); + float line_width_px, + float point_diameter_px, + float area_fill_alpha, + std::vector* + out_segment_spans = nullptr); + void rhi_record_series_primitive( const frame_context_t& ctx, - Display_style primitive_style, - vbo_view_state_t& view_state, + Display_style primitive_style, + vbo_view_state_t& view_state, const sample_window_t& window, - const std::vector& segment_spans); + const std::vector& + segment_spans); }; } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/text_renderer.h b/include/vnm_plot/rhi/text_renderer.h index 77bb4589..78c30292 100644 --- a/include/vnm_plot/rhi/text_renderer.h +++ b/include/vnm_plot/rhi/text_renderer.h @@ -33,10 +33,10 @@ class Text_renderer // false keeps LCD disabled for that axis label surface. bool prepare( const frame_context_t& ctx, - bool fade_v_labels, - bool fade_h_labels, - bool vertical_axis_label_pane_is_opaque, - bool horizontal_axis_label_pane_is_opaque); + bool fade_v_labels, + bool fade_h_labels, + bool vertical_axis_label_pane_is_opaque, + bool horizontal_axis_label_pane_is_opaque); // QRhi path: record the prepared text draw calls inside the active pass. void record(const frame_context_t& ctx); @@ -80,12 +80,13 @@ class Text_renderer bool render_axis_labels( const frame_context_t& ctx, - bool fade_labels, - bool vertical_axis_label_pane_is_opaque = false); + bool fade_labels, + bool vertical_axis_label_pane_is_opaque = false); + bool render_info_overlay( const frame_context_t& ctx, - bool fade_labels, - bool horizontal_axis_label_pane_is_opaque = false); + bool fade_labels, + bool horizontal_axis_label_pane_is_opaque = false); }; } // namespace vnm::plot diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index 29bbe63e..6d2e958e 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -18,12 +18,12 @@ constexpr time_range_t all_time_window() } sample_draw_status_t include_sample_range( - const Data_access_policy& access, - const void* sample, - Nonfinite_sample_policy nonfinite_policy, - float& out_min, - float& out_max, - bool& have_any) + const Data_access_policy& access, + const void* sample, + Nonfinite_sample_policy nonfinite_policy, + float& out_min, + float& out_max, + bool& have_any) { sample_draw_value_t draw_value; const sample_draw_status_t status = @@ -45,17 +45,17 @@ sample_draw_status_t include_sample_range( } bool scan_series_range( - Data_source& source, - const Data_access_policy& access, - std::size_t level, - Series_interpolation interpolation, - Empty_window_behavior empty_window_behavior, - Nonfinite_sample_policy nonfinite_policy, - bool visible_only, - std::int64_t t_min, - std::int64_t t_max, - float& out_min, - float& out_max) + Data_source& source, + const Data_access_policy& access, + std::size_t level, + Series_interpolation interpolation, + Empty_window_behavior empty_window_behavior, + Nonfinite_sample_policy nonfinite_policy, + bool visible_only, + std::int64_t t_min, + std::int64_t t_max, + float& out_min, + float& out_max) { data_snapshot_t snapshot = source.snapshot(level); if (!snapshot.is_valid()) { @@ -150,10 +150,10 @@ bool scan_series_range( } void apply_auto_v_range_padding( - const Plot_config& config, - bool data_range_nonnegative, - float& v_min, - float& v_max) + const Plot_config& config, + bool data_range_nonnegative, + float& v_min, + float& v_max) { if (v_max == v_min) { const float pad = std::max(std::abs(v_min) * 0.01f, 0.5f); @@ -180,11 +180,11 @@ void apply_auto_v_range_padding( } data_query_context_t make_query( - const Data_access_policy& access, - time_range_t time_window, - Series_interpolation interpolation, - Empty_window_behavior empty_window_behavior, - Nonfinite_sample_policy nonfinite_policy) + const Data_access_policy& access, + time_range_t time_window, + Series_interpolation interpolation, + Empty_window_behavior empty_window_behavior, + Nonfinite_sample_policy nonfinite_policy) { data_query_context_t query; query.access = &access; @@ -197,12 +197,12 @@ data_query_context_t make_query( } bool same_cache_shape( - const auto_range_cache_entry_t& entry, - const Data_source& source, - const Data_access_policy& access, - std::size_t lod_level, - const data_query_context_t& query, - std::uint64_t sequence) + const auto_range_cache_entry_t& entry, + const Data_source& source, + const Data_access_policy& access, + std::size_t lod_level, + const data_query_context_t& query, + std::uint64_t sequence) { const erased_access_policy_t access_view = make_erased_access_policy_view(access); @@ -226,13 +226,13 @@ bool same_cache_shape( } auto_range_cache_entry_t make_cache_entry( - const Data_source& source, - const Data_access_policy& access, - std::size_t lod_level, - const data_query_context_t& query, - std::uint64_t sequence, - Data_query_status status, - value_range_t range) + const Data_source& source, + const Data_access_policy& access, + std::size_t lod_level, + const data_query_context_t& query, + std::uint64_t sequence, + Data_query_status status, + value_range_t range) { auto_range_cache_entry_t entry; const erased_access_policy_t access_view = @@ -258,8 +258,8 @@ auto_range_cache_entry_t make_cache_entry( } std::map* cache_entries( - auto_range_cache_t* cache, - bool preview) + auto_range_cache_t* cache, + bool preview) { if (!cache) { return nullptr; @@ -268,9 +268,10 @@ std::map* cache_entries( } void prune_cache_entries( - auto_range_cache_t* cache, - bool preview, - const std::map>& series) + auto_range_cache_t* cache, + bool preview, + const std::map>& + series) { std::map* entries = cache_entries(cache, preview); if (!entries) { @@ -295,20 +296,20 @@ bool valid_query_range(value_range_t range) } bool query_or_scan_series_range( - int series_id, - bool preview, - Data_source& source, - const Data_access_policy& access, - std::size_t level, - Series_interpolation interpolation, - Empty_window_behavior empty_window_behavior, - Nonfinite_sample_policy nonfinite_policy, - bool visible_only, - time_range_t time_window, - auto_range_cache_t* cache, - Profiler* profiler, - float& out_min, - float& out_max) + int series_id, + bool preview, + Data_source& source, + const Data_access_policy& access, + std::size_t level, + Series_interpolation interpolation, + Empty_window_behavior empty_window_behavior, + Nonfinite_sample_policy nonfinite_policy, + bool visible_only, + time_range_t time_window, + auto_range_cache_t* cache, + Profiler* profiler, + float& out_min, + float& out_max) { data_query_context_t query = make_query( access, @@ -398,13 +399,14 @@ bool query_or_scan_series_range( } bool resolve_series_collection_range( - const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - bool preview, - auto_range_cache_t* cache, - float& out_min, - float& out_max) + const std::map>& + series, + const data_config_t& data_cfg, + const Plot_config& config, + bool preview, + auto_range_cache_t* cache, + float& out_min, + float& out_max) { bool have_any = false; Profiler* profiler = config.profiler.get(); @@ -473,10 +475,10 @@ std::pair fallback_range(const data_config_t& data_cfg) } std::pair finalize_auto_range( - const data_config_t& data_cfg, - const Plot_config& config, - float v_min, - float v_max) + const data_config_t& data_cfg, + const Plot_config& config, + float v_min, + float v_max) { if (!std::isfinite(v_min) || !std::isfinite(v_max) || v_max < v_min) { return fallback_range(data_cfg); @@ -490,11 +492,12 @@ std::pair finalize_auto_range( } // namespace std::pair resolve_main_v_range( - const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - bool v_auto, - auto_range_cache_t* cache) + const std::map>& + series, + const data_config_t& data_cfg, + const Plot_config& config, + bool v_auto, + auto_range_cache_t* cache) { if (!v_auto) { return {data_cfg.v_manual_min, data_cfg.v_manual_max}; @@ -518,10 +521,11 @@ std::pair resolve_main_v_range( } std::pair resolve_preview_v_range( - const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - auto_range_cache_t* cache) + const std::map>& + series, + const data_config_t& data_cfg, + const Plot_config& config, + auto_range_cache_t* cache) { float v_min = std::numeric_limits::max(); float v_max = std::numeric_limits::lowest(); diff --git a/src/core/auto_range_resolver.h b/src/core/auto_range_resolver.h index ed7f8db2..2d0c80e2 100644 --- a/src/core/auto_range_resolver.h +++ b/src/core/auto_range_resolver.h @@ -39,15 +39,15 @@ struct auto_range_cache_t std::pair resolve_main_v_range( const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - bool v_auto, - auto_range_cache_t* cache = nullptr); + const data_config_t& data_cfg, + const Plot_config& config, + bool v_auto, + auto_range_cache_t* cache = nullptr); std::pair resolve_preview_v_range( const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - auto_range_cache_t* cache = nullptr); + const data_config_t& data_cfg, + const Plot_config& config, + auto_range_cache_t* cache = nullptr); } // namespace vnm::plot::detail diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index f51836bc..525a8d63 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -32,11 +32,11 @@ float compute_grid_alpha(float spacing_px, double cell_span_min, double fade_den } void append_grid_level( - grid_layer_params_t& levels, - float spacing_px, - float start_px, - double cell_span_min, - double fade_den) + grid_layer_params_t& levels, + float spacing_px, + float start_px, + double cell_span_min, + double fade_den) { levels.spacing_px[levels.count] = spacing_px; levels.start_px[levels.count] = start_px; @@ -57,8 +57,8 @@ grid_layer_params_t flip_grid_levels_y(const grid_layer_params_t& levels, float glm::vec2 to_gl_origin( const frame_context_t& ctx, - const glm::vec2& top_left, - const glm::vec2& size) + const glm::vec2& top_left, + const glm::vec2& size) { const float win_h = static_cast(ctx.win_h); return {top_left.x, win_h - (top_left.y + size.y)}; @@ -107,7 +107,7 @@ grid_layer_params_t Chrome_renderer::calculate_grid_params( void Chrome_renderer::render_grid_and_backgrounds( const frame_context_t& ctx, - Primitive_renderer& prims) + Primitive_renderer& prims) { vnm::plot::Profiler* profiler = ctx.config ? ctx.config->profiler.get() : nullptr; VNM_PLOT_PROFILE_SCOPE( @@ -243,7 +243,7 @@ void Chrome_renderer::render_grid_and_backgrounds( void Chrome_renderer::render_zero_line( const frame_context_t& ctx, - Primitive_renderer& prims) + Primitive_renderer& prims) { const double range_v = double(ctx.v1) - double(ctx.v0); if (!(range_v > 0.0)) { @@ -286,7 +286,7 @@ void Chrome_renderer::render_zero_line( void Chrome_renderer::render_preview_overlay( const frame_context_t& ctx, - Primitive_renderer& prims) + Primitive_renderer& prims) { vnm::plot::Profiler* profiler = ctx.config ? ctx.config->profiler.get() : nullptr; VNM_PLOT_PROFILE_SCOPE( diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 680d468e..aac9e935 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -179,8 +179,8 @@ static std::mutex s_cached_fonts_mutex; static std::unordered_map> s_cached_fonts; std::shared_ptr get_cached_font( - int pixel_height, - const std::array& font_digest) + int pixel_height, + const std::array& font_digest) { std::lock_guard lock(s_cached_fonts_mutex); auto it = s_cached_fonts.find(pixel_height); @@ -272,13 +272,13 @@ double draw_scale_for(const msdf_atlas_t& atlas, int draw_pixel_height) } void add_text_to_vectors( - const char* text, - float x, - float y, - int draw_pixel_height, - const msdf_atlas_t& atlas, - std::vector& vertex_data, - std::vector& index_data) + const char* text, + float x, + float y, + int draw_pixel_height, + const msdf_atlas_t& atlas, + std::vector& vertex_data, + std::vector& index_data) { if (!text) { return; @@ -436,8 +436,8 @@ std::string digest_to_hex(const std::array& digest) } std::filesystem::path cache_file_path( - int pixel_height, - const std::array& font_digest) + int pixel_height, + const std::array& font_digest) { static std::filesystem::path s_cache_dir; @@ -465,18 +465,18 @@ std::filesystem::path cache_file_path( // Forward declarations for disk cache helpers std::shared_ptr load_cached_font_from_disk( - const std::filesystem::path& path, - const std::array& expected_digest, - int pixel_height); + const std::filesystem::path& path, + const std::array& expected_digest, + int pixel_height); void save_cached_font_to_disk( - const std::filesystem::path& path, - const cached_font_data_t& font); + const std::filesystem::path& path, + const cached_font_data_t& font); std::shared_ptr load_cached_font_from_disk( - const std::filesystem::path& path, - const std::array& expected_digest, - int pixel_height) + const std::filesystem::path& path, + const std::array& expected_digest, + int pixel_height) { std::ifstream in(path, std::ios::binary); if (!in) { @@ -628,8 +628,8 @@ std::shared_ptr load_cached_font_from_disk( } void save_cached_font_to_disk( - const std::filesystem::path& path, - const cached_font_data_t& font) + const std::filesystem::path& path, + const cached_font_data_t& font) { std::ofstream out(path, std::ios::binary | std::ios::trunc); if (!out) { @@ -690,8 +690,8 @@ void save_cached_font_to_disk( } std::shared_ptr build_font_cache( - int pixel_height, - const std::array& font_digest, + int pixel_height, + const std::array& font_digest, const std::function& log_error, const std::function& log_debug) { @@ -720,8 +720,8 @@ std::shared_ptr build_font_cache( } std::shared_ptr load_or_build_font_cache( - Asset_loader& asset_loader, - int pixel_height, + Asset_loader& asset_loader, + int pixel_height, const std::function& log_error, const std::function& log_debug) { @@ -773,9 +773,9 @@ std::shared_ptr load_or_build_font_cache( namespace detail { bool validate_font_disk_cache_file( - const std::filesystem::path& path, - const font_disk_cache_digest_t& expected_digest, - int pixel_height) + const std::filesystem::path& path, + const font_disk_cache_digest_t& expected_digest, + int pixel_height) { return static_cast( load_cached_font_from_disk(path, expected_digest, pixel_height)); @@ -932,8 +932,8 @@ Font_renderer::Font_renderer() Font_renderer::~Font_renderer() = default; void Font_renderer::set_log_callbacks( - std::function log_error, - std::function log_debug) + std::function log_error, + std::function log_debug) { m_impl->m_log_error = log_error; m_impl->m_log_debug = log_debug; @@ -960,9 +960,9 @@ void Font_renderer::initialize(Asset_loader& asset_loader, int pixel_height, boo } void Font_renderer::initialize_metrics( - Asset_loader& asset_loader, - int pixel_height, - bool force_rebuild) + Asset_loader& asset_loader, + int pixel_height, + bool force_rebuild) { if (!force_rebuild && m_impl->m_font_cache && @@ -1002,10 +1002,10 @@ float Font_renderer::measure_text_px(const char* text) const } bool Font_renderer::text_visual_bounds_px( - const char* text, - float x, - float y, - glm::vec4& bounds) const + const char* text, + float x, + float y, + glm::vec4& bounds) const { const msdf_atlas_t* atlas = m_impl->current_atlas(); if (!text || !atlas) { @@ -1128,21 +1128,21 @@ void Font_renderer::rhi_begin_frame() void Font_renderer::rhi_queue_draw( const frame_context_t& ctx, - const glm::mat4& pmv, - const glm::vec4& color, - const text_scissor_t& scissor, - const text_shadow_t& shadow) + const glm::mat4& pmv, + const glm::vec4& color, + const text_scissor_t& scissor, + const text_shadow_t& shadow) { rhi_queue_draw(ctx, pmv, color, scissor, shadow, {}); } void Font_renderer::rhi_queue_draw( const frame_context_t& ctx, - const glm::mat4& pmv, - const glm::vec4& color, - const text_scissor_t& scissor, - const text_shadow_t& shadow, - const text_lcd_t& lcd) + const glm::mat4& pmv, + const glm::vec4& color, + const text_scissor_t& scissor, + const text_shadow_t& shadow, + const text_lcd_t& lcd) { if (!ctx.rhi || !ctx.rhi_updates || !ctx.render_target || !m_impl->m_font_cache) { m_impl->m_rhi_vertex_data.clear(); diff --git a/src/core/frame_range_planner.cpp b/src/core/frame_range_planner.cpp index 9a46c95b..9ad83567 100644 --- a/src/core/frame_range_planner.cpp +++ b/src/core/frame_range_planner.cpp @@ -19,11 +19,12 @@ value_range_plan_t make_value_range_plan(std::pair range) } // namespace Frame_range_plan Frame_range_planner::plan( - const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - bool v_auto, - bool preview_enabled) + const std::map>& + series, + const data_config_t& data_cfg, + const Plot_config& config, + bool v_auto, + bool preview_enabled) { Frame_range_plan plan; plan.main_v_range = make_value_range_plan( diff --git a/src/core/frame_range_planner.h b/src/core/frame_range_planner.h index 14b9d553..7b19d626 100644 --- a/src/core/frame_range_planner.h +++ b/src/core/frame_range_planner.h @@ -15,11 +15,12 @@ class Frame_range_planner { public: Frame_range_plan plan( - const std::map>& series, - const data_config_t& data_cfg, - const Plot_config& config, - bool v_auto, - bool preview_enabled); + const std::map>& + series, + const data_config_t& data_cfg, + const Plot_config& config, + bool v_auto, + bool preview_enabled); private: auto_range_cache_t m_cache; diff --git a/src/core/label_pane_geometry.h b/src/core/label_pane_geometry.h index 09357c30..1182f07f 100644 --- a/src/core/label_pane_geometry.h +++ b/src/core/label_pane_geometry.h @@ -12,7 +12,7 @@ namespace vnm::plot::detail { [[nodiscard]] inline bool horizontal_axis_label_pane_rect( const frame_context_t& ctx, - glm::vec4& rect) + glm::vec4& rect) { const double frame_right = static_cast(ctx.win_w); const double frame_bottom = static_cast(ctx.win_h); @@ -42,7 +42,7 @@ namespace vnm::plot::detail { [[nodiscard]] inline bool vertical_axis_label_pane_rect( const frame_context_t& ctx, - glm::vec4& rect) + glm::vec4& rect) { const double frame_right = static_cast(ctx.win_w); const double frame_bottom = static_cast(ctx.win_h); @@ -75,10 +75,10 @@ namespace vnm::plot::detail { } [[nodiscard]] inline bool framebuffer_scissor_from_top_left_rect( - const glm::vec4& rect, - int window_width, - int window_height, - text_scissor_t& scissor) + const glm::vec4& rect, + int window_width, + int window_height, + text_scissor_t& scissor) { if (window_width <= 0 || window_height <= 0 || !std::isfinite(rect.x) || diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index e69f1d82..51674d84 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -99,13 +99,13 @@ class Timestamp_label_cache { public: void set_context( - double step, - double range, - uint64_t measure_key, - float monospace_advance, - bool monospace_advance_reliable, - double adjusted_font_size, - size_t format_signature) + double step, + double range, + uint64_t measure_key, + float monospace_advance, + bool monospace_advance_reliable, + double adjusted_font_size, + size_t format_signature) { if (!std::isfinite(step)) { step = 0.0; } if (!std::isfinite(range)) { range = 0.0; } @@ -237,8 +237,8 @@ class Format_signature_cache { public: size_t get_or_compute( - double step, - double range, + double step, + double range, const Layout_calculator::parameters_t& params) { if (!params.format_timestamp_func) { @@ -398,9 +398,9 @@ Format_signature_cache& format_signature_cache() } bool has_anchor_within( - const std::vector>& intervals, - float anchor, - float tolerance) + const std::vector>& intervals, + float anchor, + float tolerance) { if (intervals.empty()) { return false; @@ -429,9 +429,9 @@ bool has_anchor_within( } // namespace bool Layout_calculator::fits_with_gap( - const std::vector>& level, - const std::vector>& accepted, - float min_gap) const + const std::vector>& level, + const std::vector>& accepted, + float min_gap) const { if (level.empty()) { return true; diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index adb0c428..902f6822 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -224,9 +224,9 @@ void Primitive_renderer::batch_rect(const glm::vec4& color, const glm::vec4& rec } bool Primitive_renderer::rhi_ensure_rect_pipeline( - rhi_state_t& rhi_state, - QRhi* rhi, - QRhiRenderTarget* rt) + rhi_state_t& rhi_state, + QRhi* rhi, + QRhiRenderTarget* rt) { QRhiRenderPassDescriptor* rpd = rt->renderPassDescriptor(); const int samples = rt->sampleCount(); @@ -271,9 +271,9 @@ bool Primitive_renderer::rhi_ensure_rect_pipeline( } bool Primitive_renderer::rhi_ensure_grid_pipeline( - rhi_state_t& rhi_state, - QRhi* rhi, - QRhiRenderTarget* rt) + rhi_state_t& rhi_state, + QRhi* rhi, + QRhiRenderTarget* rt) { QRhiRenderPassDescriptor* rpd = rt->renderPassDescriptor(); const int samples = rt->sampleCount(); @@ -315,9 +315,9 @@ bool Primitive_renderer::rhi_ensure_grid_pipeline( } bool Primitive_renderer::rhi_ensure_grid_quad_vbo( - rhi_state_t& rhi_state, - QRhi* rhi, - QRhiResourceUpdateBatch* updates) + rhi_state_t& rhi_state, + QRhi* rhi, + QRhiResourceUpdateBatch* updates) { if (rhi_state.grid_quad_vbo) { return true; @@ -497,10 +497,10 @@ void Primitive_renderer::clear_rect_batch() } void Primitive_renderer::draw_grid_shader( - const frame_context_t& ctx, - const glm::vec2& origin, - const glm::vec2& size, - const glm::vec4& color, + const frame_context_t& ctx, + const glm::vec2& origin, + const glm::vec2& size, + const glm::vec4& color, const grid_layer_params_t& vertical_levels, const grid_layer_params_t& horizontal_levels) { @@ -631,8 +631,8 @@ std::size_t Primitive_renderer::queued_op_count() const } void Primitive_renderer::record_draws( - [[maybe_unused]] const frame_context_t& ctx, - [[maybe_unused]] std::size_t end) + [[maybe_unused]] const frame_context_t& ctx, + [[maybe_unused]] std::size_t end) { if (!ctx.rhi || !ctx.cb) { return; diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index 9e5dc525..9912c040 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -105,10 +105,10 @@ inline bool checked_size_product(std::size_t lhs, std::size_t rhs, std::size_t& } inline bool qrhi_byte_size( - std::size_t element_count, - std::size_t element_bytes, - std::size_t& out_bytes, - quint32& out_qrhi_bytes) + std::size_t element_count, + std::size_t element_bytes, + std::size_t& out_bytes, + quint32& out_qrhi_bytes) { std::size_t bytes = 0; if (!checked_size_product(element_count, element_bytes, bytes) || @@ -121,26 +121,26 @@ inline bool qrhi_byte_size( } inline bool qrhi_byte_size( - std::size_t element_count, - std::size_t element_bytes, - quint32& out_qrhi_bytes) + std::size_t element_count, + std::size_t element_bytes, + quint32& out_qrhi_bytes) { std::size_t bytes = 0; return qrhi_byte_size(element_count, element_bytes, bytes, out_qrhi_bytes); } inline bool qrhi_buffer_offset( - std::size_t element_index, - std::size_t element_bytes, - quint32& out_offset) + std::size_t element_index, + std::size_t element_bytes, + quint32& out_offset) { return qrhi_byte_size(element_index, element_bytes, out_offset); } inline bool qrhi_grown_capacity_bytes( - std::size_t bytes_needed, - std::size_t& out_capacity_bytes, - quint32& out_qrhi_capacity_bytes) + std::size_t bytes_needed, + std::size_t& out_capacity_bytes, + quint32& out_qrhi_capacity_bytes) { if (!to_qrhi_byte_count(bytes_needed, out_qrhi_capacity_bytes)) { return false; @@ -167,11 +167,11 @@ inline bool qrhi_grown_capacity_bytes( // Replaces the ~6-line "newShaderResourceBindings + setBindings + create" // dance that recurred across primitive/grid/series renderers. inline bool rebuild_single_ubo_srb( - QRhi* rhi, - std::unique_ptr& srb, - QRhiBuffer* ubo, - quint32 ubo_bytes, - QRhiShaderResourceBinding::StageFlags stages) + QRhi* rhi, + std::unique_ptr& srb, + QRhiBuffer* ubo, + quint32 ubo_bytes, + QRhiShaderResourceBinding::StageFlags stages) { srb.reset(rhi->newShaderResourceBindings()); if (!srb) { @@ -187,10 +187,10 @@ inline bool rebuild_single_ubo_srb( // bytes. Returns true if the buffer is ready; on failure the unique_ptr is // reset to null so callers can early-out cleanly. inline bool ensure_dynamic_ubo( - QRhi* rhi, - std::unique_ptr& ubo, - std::size_t& capacity_bytes, - quint32 bytes_needed) + QRhi* rhi, + std::unique_ptr& ubo, + std::size_t& capacity_bytes, + quint32 bytes_needed) { if (ubo && capacity_bytes >= bytes_needed) { return true; @@ -227,9 +227,9 @@ struct alpha_blended_pipeline_desc_t // caller is free to bind a per-draw SRB with a different UBO handle // (matching layout) at draw time. inline std::unique_ptr build_alpha_blended_pipeline( - QRhi* rhi, - QRhiRenderTarget* rt, - const alpha_blended_pipeline_desc_t& desc) + QRhi* rhi, + QRhiRenderTarget* rt, + const alpha_blended_pipeline_desc_t& desc) { if (!rhi || !rt || !desc.vert.isValid() || !desc.frag.isValid()) { return nullptr; diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index 24cc50f4..b080e5c7 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -58,9 +58,9 @@ bool is_default_series_color(const glm::vec4& color) } bool line_window_sample_count( - std::size_t source_count, - Series_interpolation interpolation, - std::size_t& out_count) + std::size_t source_count, + Series_interpolation interpolation, + std::size_t& out_count) { out_count = 0; if (source_count == 0) { @@ -154,7 +154,7 @@ bool has_builtin_segment_span(const sample_window_t& window) } bool is_builtin_primitive_drawable( - Display_style primitive_style, + Display_style primitive_style, const sample_window_t& window) { if (window.gpu_count == 0) { return false; } @@ -193,7 +193,7 @@ static_assert(sizeof(series_view_uniform_std140_t) == 128, "Series_view_t std140 series_view_uniform_std140_t make_series_view_uniform( const frame_context_t& frame, - const series_data_t& series, + const series_data_t& series, const sample_window_t& window) { series_view_uniform_std140_t uniform{}; @@ -647,7 +647,8 @@ void Series_renderer::clear_frame_snapshot_caches() void Series_renderer::prepare( const frame_context_t& ctx, - const std::map>& series) + const std::map>& + series) { m_rhi_state->frame_draw_states.clear(); m_rhi_state->prepared_draws.clear(); @@ -1500,7 +1501,8 @@ void Series_renderer::prepare( void Series_renderer::render( const frame_context_t& ctx, - const std::map>& series) + const std::map>& + series) { if (!ctx.rhi) { prepare(ctx, series); @@ -1582,7 +1584,7 @@ void Series_renderer::render( bool Series_renderer::rhi_prepare_series_view_samples( const frame_context_t& ctx, - vbo_view_state_t& view_state, + vbo_view_state_t& view_state, const sample_window_t& window) { QRhi* rhi = ctx.rhi; @@ -1802,15 +1804,15 @@ bool Series_renderer::rhi_prepare_series_view_samples( } bool Series_renderer::rhi_prepare_series_primitive( - const frame_context_t& ctx, - const series_data_t* series, - Display_style primitive_style, - vbo_view_state_t& view_state, - const sample_window_t& window, - float line_width_px, - float point_diameter_px, - float area_fill_alpha, - std::vector* out_segment_spans) + const frame_context_t& ctx, + const series_data_t* series, + Display_style primitive_style, + vbo_view_state_t& view_state, + const sample_window_t& window, + float line_width_px, + float point_diameter_px, + float area_fill_alpha, + std::vector* out_segment_spans) { if (!series) { return false; @@ -2265,10 +2267,11 @@ bool Series_renderer::rhi_prepare_series_primitive( void Series_renderer::rhi_record_series_primitive( const frame_context_t& ctx, - Display_style primitive_style, - vbo_view_state_t& view_state, + Display_style primitive_style, + vbo_view_state_t& view_state, const sample_window_t& window, - const std::vector& segment_spans) + const std::vector& + segment_spans) { QRhiCommandBuffer* cb = ctx.cb; if (!cb) { diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index 92110ec6..e8e82fa7 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -53,12 +53,12 @@ struct direct_time_window_query_t }; drawable_window_result_t build_drawable_window( - const data_snapshot_t& snapshot, - const erased_access_policy_t& access, - Nonfinite_sample_policy nonfinite_policy, - std::size_t source_first, - std::size_t source_last_exclusive, - bool hold_last_forward) + const data_snapshot_t& snapshot, + const erased_access_policy_t& access, + Nonfinite_sample_policy nonfinite_policy, + std::size_t source_first, + std::size_t source_last_exclusive, + bool hold_last_forward) { drawable_window_result_t result; result.source_first = source_first; @@ -126,12 +126,12 @@ drawable_window_result_t build_drawable_window( } bool select_hold_source_index( - const data_snapshot_t& snapshot, - const erased_access_policy_t& access, - Nonfinite_sample_policy nonfinite_policy, - std::size_t candidate_index, - std::size_t& out_index, - bool& out_failed) + const data_snapshot_t& snapshot, + const erased_access_policy_t& access, + Nonfinite_sample_policy nonfinite_policy, + std::size_t candidate_index, + std::size_t& out_index, + bool& out_failed) { out_failed = false; if (candidate_index >= snapshot.count) { diff --git a/src/core/text_lcd_policy.h b/src/core/text_lcd_policy.h index bba5aa70..c69c51ef 100644 --- a/src/core/text_lcd_policy.h +++ b/src/core/text_lcd_policy.h @@ -30,7 +30,7 @@ constexpr text_lcd_resolved_subpixel_order_t text_lcd_auto_order_from_detections } constexpr text_lcd_resolved_subpixel_order_t text_lcd_effective_order( - text_lcd_request_t requested, + text_lcd_request_t requested, text_lcd_resolved_subpixel_order_t auto_resolved) { if (requested.automatic) { @@ -41,14 +41,14 @@ constexpr text_lcd_resolved_subpixel_order_t text_lcd_effective_order( } constexpr text_lcd_resolved_subpixel_order_t text_lcd_effective_order_for_frame( - text_lcd_request_t requested, + text_lcd_request_t requested, text_lcd_resolved_subpixel_order_t auto_resolved_order) { return text_lcd_effective_order(requested, auto_resolved_order); } constexpr text_lcd_resolved_subpixel_order_t text_lcd_effective_order_for_frame( - const text_lcd_request_t* requested, + const text_lcd_request_t* requested, text_lcd_resolved_subpixel_order_t auto_resolved_order) { return requested != nullptr @@ -57,10 +57,10 @@ constexpr text_lcd_resolved_subpixel_order_t text_lcd_effective_order_for_frame( } constexpr bool text_lcd_draw_is_eligible( - text_lcd_draw_surface_t surface, + text_lcd_draw_surface_t surface, text_lcd_resolved_subpixel_order_t frame_order, - float background_alpha, - bool has_opaque_backing) + float background_alpha, + bool has_opaque_backing) { if (!vnm::msdf_text::lcd::is_display_specific(frame_order) || !(background_alpha >= k_text_lcd_opaque_alpha_cutoff)) diff --git a/src/core/text_renderer.cpp b/src/core/text_renderer.cpp index 49d69d5d..5a112e2b 100644 --- a/src/core/text_renderer.cpp +++ b/src/core/text_renderer.cpp @@ -99,8 +99,8 @@ text_lcd_resolved_subpixel_order_t text_lcd_frame_order(const frame_context_t& c text_lcd_t text_lcd_for_background( const frame_context_t& ctx, - const glm::vec4& background, - bool draw_lcd_eligible) + const glm::vec4& background, + bool draw_lcd_eligible) { text_lcd_t lcd; lcd.subpixel_order = draw_lcd_eligible @@ -112,11 +112,11 @@ text_lcd_t text_lcd_for_background( template bool update_and_draw_faded_labels( - const Labels& labels, - Tracker& tracker, - float fade_duration_ms, - KeyFunc&& key_fn, - DrawFunc&& draw_fn) + const Labels& labels, + Tracker& tracker, + float fade_duration_ms, + KeyFunc&& key_fn, + DrawFunc&& draw_fn) { using key_t = typename Tracker::key_type; @@ -223,10 +223,10 @@ bool Text_renderer::prepare(const frame_context_t& ctx, bool fade_v_labels, bool bool Text_renderer::prepare( const frame_context_t& ctx, - bool fade_v_labels, - bool fade_h_labels, - bool vertical_axis_label_pane_is_opaque, - bool horizontal_axis_label_pane_is_opaque) + bool fade_v_labels, + bool fade_h_labels, + bool vertical_axis_label_pane_is_opaque, + bool horizontal_axis_label_pane_is_opaque) { if (!m_fonts) { return false; @@ -249,8 +249,8 @@ void Text_renderer::record(const frame_context_t& ctx) bool Text_renderer::render_axis_labels( const frame_context_t& ctx, - bool fade_labels, - bool vertical_axis_label_pane_is_opaque) + bool fade_labels, + bool vertical_axis_label_pane_is_opaque) { const auto& pl = ctx.layout; const bool dark_mode = ctx.dark_mode; @@ -377,8 +377,8 @@ bool Text_renderer::render_axis_labels( bool Text_renderer::render_info_overlay( const frame_context_t& ctx, - bool fade_labels, - bool horizontal_axis_label_pane_is_opaque) + bool fade_labels, + bool horizontal_axis_label_pane_is_opaque) { const auto& pl = ctx.layout; const bool dark_mode = ctx.dark_mode; diff --git a/src/core/time_grid.cpp b/src/core/time_grid.cpp index b9c341e4..6f8d84d9 100644 --- a/src/core/time_grid.cpp +++ b/src/core/time_grid.cpp @@ -31,11 +31,11 @@ float compute_grid_alpha(float spacing_px, double cell_span_min, double fade_den } void append_grid_level( - grid_layer_params_t& levels, - float spacing_px, - float start_px, - double cell_span_min, - double fade_den) + grid_layer_params_t& levels, + float spacing_px, + float start_px, + double cell_span_min, + double fade_den) { levels.spacing_px[levels.count] = spacing_px; levels.start_px[levels.count] = start_px; @@ -52,7 +52,7 @@ grid_layer_params_t build_time_grid_layers( double t_max_seconds, double width_px, double font_px, - bool* out_dropped_non_multiple_step_or_null) + bool* out_dropped_non_multiple_step_or_null) { if (out_dropped_non_multiple_step_or_null) { *out_dropped_non_multiple_step_or_null = false; diff --git a/src/core/types.cpp b/src/core/types.cpp index 5262815c..0427b5a2 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -73,10 +73,10 @@ bool wants_hold_forward(const data_query_context_t& query) } bool timestamp_at( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - std::size_t index, - std::int64_t& timestamp_ns) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + std::size_t index, + std::int64_t& timestamp_ns) { const void* sample = snapshot.at(index); if (!sample) { @@ -108,10 +108,10 @@ void include_range(value_range_t& range, bool& has_value, float low, float high) } sample_scan_status sample_value_range( - const Data_access_policy& access, - const void* sample, - Nonfinite_sample_policy policy, - value_range_t& range) + const Data_access_policy& access, + const void* sample, + Nonfinite_sample_policy policy, + value_range_t& range) { detail::sample_draw_value_t draw_value; const detail::sample_draw_status_t draw_status = @@ -127,20 +127,20 @@ sample_scan_status sample_value_range( } sample_scan_status sample_status_for_staging( - const Data_access_policy& access, - const void* sample, - Nonfinite_sample_policy policy) + const Data_access_policy& access, + const void* sample, + Nonfinite_sample_policy policy) { value_range_t ignored; return sample_value_range(access, sample, policy, ignored); } bool include_sample_range( - value_range_t& range, - bool& has_value, - const Data_access_policy& access, - const void* sample, - Nonfinite_sample_policy policy) + value_range_t& range, + bool& has_value, + const Data_access_policy& access, + const void* sample, + Nonfinite_sample_policy policy) { value_range_t sample_range; const sample_scan_status scan_status = @@ -155,10 +155,10 @@ bool include_sample_range( } std::size_t ascending_first_ge( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - std::int64_t target_ns, - bool& valid) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + std::int64_t target_ns, + bool& valid) { std::size_t first = 0; std::size_t count = snapshot.count; @@ -182,10 +182,10 @@ std::size_t ascending_first_ge( } std::size_t ascending_first_gt( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - std::int64_t target_ns, - bool& valid) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + std::int64_t target_ns, + bool& valid) { std::size_t first = 0; std::size_t count = snapshot.count; @@ -209,10 +209,10 @@ std::size_t ascending_first_gt( } std::size_t descending_first_le( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - std::int64_t target_ns, - bool& valid) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + std::int64_t target_ns, + bool& valid) { std::size_t first = 0; std::size_t count = snapshot.count; @@ -236,10 +236,10 @@ std::size_t descending_first_le( } std::size_t descending_first_lt( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - std::int64_t target_ns, - bool& valid) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + std::int64_t target_ns, + bool& valid) { std::size_t first = 0; std::size_t count = snapshot.count; @@ -263,9 +263,9 @@ std::size_t descending_first_lt( } time_window_candidates_t ascending_candidates( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query) { bool valid = true; time_window_candidates_t out; @@ -287,9 +287,9 @@ time_window_candidates_t ascending_candidates( } time_window_candidates_t descending_candidates( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query) { bool valid = true; time_window_candidates_t out; @@ -311,9 +311,9 @@ time_window_candidates_t descending_candidates( } time_window_candidates_t linear_candidates( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query) { bool found = false; bool gap_after_match = false; @@ -375,11 +375,11 @@ time_window_candidates_t linear_candidates( } time_window_candidates_t time_window_candidates( - const Data_source& source, - const data_snapshot_t& snapshot, - const Data_access_policy& access, - std::size_t lod, - const data_query_context_t& query) + const Data_source& source, + const data_snapshot_t& snapshot, + const Data_access_policy& access, + std::size_t lod, + const data_query_context_t& query) { switch (source.time_order(lod)) { case Time_order::ASCENDING: return ascending_candidates(snapshot, access, query); @@ -391,11 +391,11 @@ time_window_candidates_t time_window_candidates( } bool validate_match_range( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query, - std::size_t first, - std::size_t last_exclusive) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query, + std::size_t first, + std::size_t last_exclusive) { for (std::size_t index = first; index < last_exclusive; ++index) { const void* sample = snapshot.at(index); @@ -412,11 +412,11 @@ bool validate_match_range( } bool scan_value_range( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query, - value_range_t& range, - bool& has_value) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query, + value_range_t& range, + bool& has_value) { value_range_t held_range; bool has_held_candidate = false; @@ -495,10 +495,10 @@ bool scan_value_range( } sample_scan_status held_sample_status( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query, - std::size_t index) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query, + std::size_t index) { const void* sample = snapshot.at(index); if (!sample) { @@ -508,13 +508,13 @@ sample_scan_status held_sample_status( } bool select_held_sample_index( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query, - Time_order source_order, - std::size_t candidate_index, - std::size_t& out_index, - bool& out_failed) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query, + Time_order source_order, + std::size_t candidate_index, + std::size_t& out_index, + bool& out_failed) { out_failed = false; if (candidate_index >= snapshot.count) { @@ -610,11 +610,11 @@ bool select_held_sample_index( } validated_time_window_t validated_time_window( - const data_snapshot_t& snapshot, - const Data_access_policy& access, - const data_query_context_t& query, - Time_order source_order, - const time_window_candidates_t& candidates) + const data_snapshot_t& snapshot, + const Data_access_policy& access, + const data_query_context_t& query, + Time_order source_order, + const time_window_candidates_t& candidates) { validated_time_window_t out; if (!candidates.valid) { @@ -694,8 +694,8 @@ namespace detail { namespace { bool normalize_draw_component( - float& value, - Nonfinite_sample_policy policy) + float& value, + Nonfinite_sample_policy policy) { if (std::isfinite(value)) { return true; @@ -718,10 +718,10 @@ sample_draw_status_t status_for_nonfinite( } // namespace sample_draw_status_t read_sample_draw_value( - const erased_access_policy_t& access, - const void* sample, - Nonfinite_sample_policy policy, - sample_draw_value_t& out) + const erased_access_policy_t& access, + const void* sample, + Nonfinite_sample_policy policy, + sample_draw_value_t& out) { out = sample_draw_value_t{}; if (!sample) { @@ -754,10 +754,10 @@ sample_draw_status_t read_sample_draw_value( } sample_draw_status_t read_sample_draw_value( - const Data_access_policy& access, - const void* sample, - Nonfinite_sample_policy policy, - sample_draw_value_t& out) + const Data_access_policy& access, + const void* sample, + Nonfinite_sample_policy policy, + sample_draw_value_t& out) { return read_sample_draw_value( make_erased_access_policy_view(access), @@ -791,8 +791,8 @@ std::vector Data_source::lod_scales() const } data_query_result_t Data_source::query_time_window( - std::size_t lod, - const data_query_context_t& query) + std::size_t lod, + const data_query_context_t& query) { data_query_result_t result; if (!query.access || !query.access->get_timestamp) { @@ -842,8 +842,8 @@ data_query_result_t Data_source::query_time_window( } data_query_result_t Data_source::query_v_range( - std::size_t lod, - const data_query_context_t& query) + std::size_t lod, + const data_query_context_t& query) { data_query_result_t result; if (!query.access || !query.access->is_valid()) { diff --git a/src/qt/plot_interaction_item.cpp b/src/qt/plot_interaction_item.cpp index 7cc66ede..18a7d68b 100644 --- a/src/qt/plot_interaction_item.cpp +++ b/src/qt/plot_interaction_item.cpp @@ -164,8 +164,8 @@ qreal Plot_interaction_item::zoom_animation_scale_factor(qreal velocity, qreal e } qreal Plot_interaction_item::zoom_animation_velocity_after( - qreal velocity, - qreal elapsed_timer_steps) + qreal velocity, + qreal elapsed_timer_steps) { if (elapsed_timer_steps <= 0.0) { return velocity; @@ -384,13 +384,13 @@ void Plot_interaction_item::wheelEvent(QWheelEvent* event) } bool Plot_interaction_item::handle_wheel( - qreal x, - qreal y, - qreal angle_delta_x, - qreal angle_delta_y, - qreal pixel_delta_x, - qreal pixel_delta_y, - int modifiers) + qreal x, + qreal y, + qreal angle_delta_x, + qreal angle_delta_y, + qreal pixel_delta_x, + qreal pixel_delta_y, + int modifiers) { if (!m_interaction_enabled || !m_plot_widget) { return false; diff --git a/src/qt/plot_renderer.cpp b/src/qt/plot_renderer.cpp index bc01b668..ba4829af 100644 --- a/src/qt/plot_renderer.cpp +++ b/src/qt/plot_renderer.cpp @@ -76,17 +76,17 @@ label_pane_opacity_t label_pane_opacity_for_text(const frame_context_t& ctx) } Layout_calculator::parameters_t build_layout_params( - float v_min, - float v_max, - std::int64_t t_min_ns, - std::int64_t t_max_ns, - int win_w, - double usable_height, - double vbar_width, - double preview_height, - double font_px, - const Plot_config& config, - const Font_renderer* fonts) + float v_min, + float v_max, + std::int64_t t_min_ns, + std::int64_t t_max_ns, + int win_w, + double usable_height, + double vbar_width, + double preview_height, + double font_px, + const Plot_config& config, + const Font_renderer* fonts) { Layout_calculator::parameters_t params; params.v_min = v_min; diff --git a/src/qt/plot_time_axis.cpp b/src/qt/plot_time_axis.cpp index bd52813b..8c037f31 100644 --- a/src/qt/plot_time_axis.cpp +++ b/src/qt/plot_time_axis.cpp @@ -554,10 +554,10 @@ bool Plot_time_axis::apply_time_axis_limits_if_changed( qint64 t_max_ns, qint64 t_available_min_ns, qint64 t_available_max_ns, - bool t_min_initialized, - bool t_max_initialized, - bool t_available_min_initialized, - bool t_available_max_initialized) + bool t_min_initialized, + bool t_max_initialized, + bool t_available_min_initialized, + bool t_available_max_initialized) { const bool changed = m_t_min != t_min_ns || diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index a2c31801..f6fb134d 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -88,7 +88,7 @@ detail::Time_axis_model widget_time_axis_model(const data_config_t& cfg) void apply_time_axis_model_to_data_config( const detail::Time_axis_model& model, - data_config_t& cfg) + data_config_t& cfg) { cfg.t_min = model.t_min(); cfg.t_max = model.t_max(); @@ -1248,11 +1248,11 @@ QVariantList Plot_widget::get_nearest_samples( } QVariantList Plot_widget::get_samples_for_time( - double x_ms, - double plot_width, - double plot_height, - double mouse_px, - Indicator_sample_mode mode) const + double x_ms, + double plot_width, + double plot_height, + double mouse_px, + Indicator_sample_mode mode) const { QVariantList result; diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index 6fe3c92b..530d710f 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -32,8 +32,10 @@ struct time_axis_update_result_t // against `ref_width`. Commit receives the new (t_min, t_max). template inline void adjust_t_from_mouse_diff_impl( - const t_view_snapshot_t& view, double ref_width, double diff, - Commit&& commit) + const t_view_snapshot_t& view, + double ref_width, + double diff, + Commit&& commit) { if (ref_width <= 0.0) { return; @@ -65,8 +67,10 @@ inline void adjust_t_from_mouse_diff_impl( // moves in the same direction as the cursor. template inline void adjust_t_from_mouse_diff_on_preview_impl( - const t_view_snapshot_t& view, double ref_width, double diff, - Commit&& commit) + const t_view_snapshot_t& view, + double ref_width, + double diff, + Commit&& commit) { if (ref_width <= 0.0) { return; @@ -99,8 +103,10 @@ inline void adjust_t_from_mouse_diff_on_preview_impl( // width, keeping the current span. template inline void adjust_t_from_mouse_pos_on_preview_impl( - const t_view_snapshot_t& view, double ref_width, double x_pos, - Commit&& commit) + const t_view_snapshot_t& view, + double ref_width, + double x_pos, + Commit&& commit) { if (ref_width <= 0.0) { return; @@ -125,8 +131,10 @@ inline void adjust_t_from_mouse_pos_on_preview_impl( // <1.0 zooms in, >1.0 zooms out). template inline void adjust_t_from_pivot_and_scale_impl( - const t_view_snapshot_t& view, double pivot, double scale, - Commit&& commit) + const t_view_snapshot_t& view, + double pivot, + double scale, + Commit&& commit) { if (scale <= 0.0) { return; @@ -169,10 +177,10 @@ class Time_axis_model qint64 t_max, qint64 t_available_min, qint64 t_available_max, - bool t_min_initialized, - bool t_max_initialized, - bool t_available_min_initialized, - bool t_available_max_initialized) + bool t_min_initialized, + bool t_max_initialized, + bool t_available_min_initialized, + bool t_available_max_initialized) : m_t_min(t_min), m_t_max(t_max), @@ -546,10 +554,10 @@ class Time_axis_model qint64 t_max_ns, qint64 t_available_min_ns, qint64 t_available_max_ns, - bool t_min_initialized, - bool t_max_initialized, - bool t_available_min_initialized, - bool t_available_max_initialized) + bool t_min_initialized, + bool t_max_initialized, + bool t_available_min_initialized, + bool t_available_max_initialized) { const bool changed = m_t_min != t_min_ns || diff --git a/src/qt/text_lcd_resolver.cpp b/src/qt/text_lcd_resolver.cpp index 3da5a897..c2094d03 100644 --- a/src/qt/text_lcd_resolver.cpp +++ b/src/qt/text_lcd_resolver.cpp @@ -88,8 +88,8 @@ text_lcd_resolved_subpixel_order_t text_lcd_subpixel_order_from_windows() } // anonymous namespace text_lcd_resolved_subpixel_order_t resolve_text_lcd_subpixel_order_from_probes( - text_lcd_request_t requested, - const text_lcd_resolver_probes_t& probes) + text_lcd_request_t requested, + const text_lcd_resolver_probes_t& probes) { if (!requested.automatic) { return detail::text_lcd_effective_order( @@ -112,7 +112,7 @@ text_lcd_resolved_subpixel_order_t resolve_text_lcd_subpixel_order_from_probes( text_lcd_resolved_subpixel_order_t resolve_text_lcd_subpixel_order_for_window( text_lcd_request_t requested, - QQuickWindow* window) + QQuickWindow* window) { text_lcd_resolver_probes_t probes; probes.qt_probe = [window] { @@ -142,9 +142,9 @@ text_lcd_resolved_subpixel_order_t text_lcd_from_qt_subpixel_hint(int qt_subpixe } text_lcd_resolved_subpixel_order_t text_lcd_from_windows_font_smoothing_settings( - bool enabled, - unsigned int smoothing_type, - unsigned int smoothing_orientation) + bool enabled, + unsigned int smoothing_type, + unsigned int smoothing_orientation) { if (!enabled) { return text_lcd_resolved_subpixel_order_t::NONE; diff --git a/src/qt/text_lcd_resolver.h b/src/qt/text_lcd_resolver.h index 70cd9ec0..d6e6ed63 100644 --- a/src/qt/text_lcd_resolver.h +++ b/src/qt/text_lcd_resolver.h @@ -17,18 +17,19 @@ struct text_lcd_resolver_probes_t }; text_lcd_resolved_subpixel_order_t resolve_text_lcd_subpixel_order_from_probes( - text_lcd_request_t requested, - const text_lcd_resolver_probes_t& probes); + text_lcd_request_t requested, + const text_lcd_resolver_probes_t& probes); text_lcd_resolved_subpixel_order_t resolve_text_lcd_subpixel_order_for_window( text_lcd_request_t requested, - QQuickWindow* window); + QQuickWindow* window); -text_lcd_resolved_subpixel_order_t text_lcd_from_qt_subpixel_hint(int qt_subpixel_hint); +text_lcd_resolved_subpixel_order_t text_lcd_from_qt_subpixel_hint( + int qt_subpixel_hint); text_lcd_resolved_subpixel_order_t text_lcd_from_windows_font_smoothing_settings( - bool enabled, - unsigned int smoothing_type, - unsigned int smoothing_orientation); + bool enabled, + unsigned int smoothing_type, + unsigned int smoothing_orientation); } // namespace vnm::plot diff --git a/tests/test_cache_invalidation.cpp b/tests/test_cache_invalidation.cpp index f61c993c..777e2b88 100644 --- a/tests/test_cache_invalidation.cpp +++ b/tests/test_cache_invalidation.cpp @@ -80,8 +80,8 @@ class Query_range_source final : public Data_source { } data_query_result_t query_v_range( - std::size_t lod, - const data_query_context_t& query) override + std::size_t lod, + const data_query_context_t& query) override { ++query_calls; last_query_lod = lod; diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index 9f4d7ea3..dc1a8ccb 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -57,15 +57,15 @@ const sample_t* sample_at(const plot::data_snapshot_t& snapshot, std::size_t ind } const Blocking_sample* blocking_sample_at( - const plot::data_snapshot_t& snapshot, - std::size_t index) + const plot::data_snapshot_t& snapshot, + std::size_t index) { return reinterpret_cast(snapshot.at(index)); } std::vector make_blocking_samples( - float generation, - std::shared_ptr probe = {}) + float generation, + std::shared_ptr probe = {}) { std::vector samples; samples.reserve(16); diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 5e35c253..077c0b00 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -75,8 +75,8 @@ class Query_source final : public plot::Data_source }; plot::Data_access_policy make_value_access( - int* timestamp_calls = nullptr, - int* value_calls = nullptr) + int* timestamp_calls = nullptr, + int* value_calls = nullptr) { plot::Data_access_policy access; access.get_timestamp = [timestamp_calls](const void* sample) -> std::int64_t { @@ -108,9 +108,9 @@ plot::Data_access_policy make_timestamp_access(int* timestamp_calls = nullptr) } plot::data_query_context_t make_query( - const plot::Data_access_policy& access, - std::int64_t t_min, - std::int64_t t_max) + const plot::Data_access_policy& access, + std::int64_t t_min, + std::int64_t t_max) { plot::data_query_context_t query; query.access = &access; @@ -122,9 +122,9 @@ plot::data_query_context_t make_query( } plot::data_query_context_t make_hold_query( - const plot::Data_access_policy& access, - std::int64_t t_min, - std::int64_t t_max) + const plot::Data_access_policy& access, + std::int64_t t_min, + std::int64_t t_max) { plot::data_query_context_t query = make_query(access, t_min, t_max); query.interpolation = plot::Series_interpolation::STEP_AFTER; @@ -133,9 +133,9 @@ plot::data_query_context_t make_hold_query( } plot::data_query_context_t make_draw_query( - const plot::Data_access_policy& access, - std::int64_t t_min, - std::int64_t t_max) + const plot::Data_access_policy& access, + std::int64_t t_min, + std::int64_t t_max) { plot::data_query_context_t query = make_query(access, t_min, t_max); query.empty_window_behavior = plot::Empty_window_behavior::DRAW_NOTHING; diff --git a/tests/test_font_disk_cache.cpp b/tests/test_font_disk_cache.cpp index 727d307a..51c67790 100644 --- a/tests/test_font_disk_cache.cpp +++ b/tests/test_font_disk_cache.cpp @@ -122,8 +122,8 @@ void write_valid_glyph(std::ofstream& out) } bool write_cache_file( - const std::filesystem::path& path, - const cache_file_options_t& options) + const std::filesystem::path& path, + const cache_file_options_t& options) { std::ofstream out(path, std::ios::binary | std::ios::trunc); if (!out) { @@ -180,9 +180,9 @@ bool write_cache_file( } bool cache_file_is_valid( - const std::filesystem::path& path, - const digest_t& expected_digest, - int pixel_height = static_cast(k_pixel_height)) + const std::filesystem::path& path, + const digest_t& expected_digest, + int pixel_height = static_cast(k_pixel_height)) { return plot::detail::validate_font_disk_cache_file(path, expected_digest, pixel_height); } diff --git a/tests/test_layout_calculator.cpp b/tests/test_layout_calculator.cpp index 207344c1..899de998 100644 --- a/tests/test_layout_calculator.cpp +++ b/tests/test_layout_calculator.cpp @@ -32,9 +32,9 @@ struct Recorded_call }; plot::Layout_calculator::parameters_t make_minimal_params( - std::int64_t t_min_ns, - std::int64_t t_max_ns, - std::vector& recorded_calls) + std::int64_t t_min_ns, + std::int64_t t_max_ns, + std::vector& recorded_calls) { plot::Layout_calculator::parameters_t params; params.v_min = 0.0f; diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 58813c95..05cc7ebd 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -135,8 +135,8 @@ glsl_token_list_t tokenize_glsl(std::string_view text) } bool contains_token_sequence( - const glsl_token_list_t& tokens, - const glsl_token_list_t& expected) + const glsl_token_list_t& tokens, + const glsl_token_list_t& expected) { if (expected.empty() || tokens.size() < expected.size()) { return false; @@ -159,8 +159,8 @@ bool contains_token_sequence( } bool contains_glsl_token_sequence( - const glsl_token_list_t& shader_tokens, - std::string_view expected_statement) + const glsl_token_list_t& shader_tokens, + std::string_view expected_statement) { return contains_token_sequence(shader_tokens, tokenize_glsl(expected_statement)); } diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index 5b645101..138faa96 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -58,10 +58,9 @@ zoom_state_t advance_zoom(double initial_velocity, const std::vector& el } std::shared_ptr make_sample_series( - std::vector samples, - plot::Series_interpolation interpolation, - plot::Empty_window_behavior empty_window_behavior = - plot::Empty_window_behavior::DRAW_NOTHING) + std::vector samples, + plot::Series_interpolation interpolation, + plot::Empty_window_behavior empty_window_behavior = plot::Empty_window_behavior::DRAW_NOTHING) { auto source = std::make_shared>( std::move(samples)); @@ -85,11 +84,11 @@ std::shared_ptr make_sample_series( } void configure_view( - plot::Plot_widget& widget, - std::int64_t tmin_ns, - std::int64_t tmax_ns, - float vmin, - float vmax) + plot::Plot_widget& widget, + std::int64_t tmin_ns, + std::int64_t tmax_ns, + float vmin, + float vmax) { plot::Plot_view view; view.t_range = std::pair{tmin_ns, tmax_ns}; @@ -101,18 +100,18 @@ void configure_view( } void configure_time_window( - plot::Plot_widget& widget, - std::int64_t tmin_ns, - std::int64_t tmax_ns, - std::int64_t t_available_min_ns, - std::int64_t t_available_max_ns) + plot::Plot_widget& widget, + std::int64_t tmin_ns, + std::int64_t tmax_ns, + std::int64_t t_available_min_ns, + std::int64_t t_available_max_ns) { widget.set_t_range(tmin_ns, tmax_ns); widget.set_available_t_range(t_available_min_ns, t_available_max_ns); } void configure_indicator_widget( - plot::Plot_widget& widget, + plot::Plot_widget& widget, plot::Series_interpolation interpolation) { constexpr std::int64_t k_second_ns = 1'000'000'000LL; diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 721ab517..28d9dd68 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -341,11 +341,11 @@ class Recording_layer final : public plot::Qrhi_series_layer { public: Recording_layer( - std::string id, - std::uint64_t revision, - int z_order, - std::vector& events, - int& create_count) + std::string id, + std::uint64_t revision, + int z_order, + std::vector& events, + int& create_count) : m_id(std::move(id)), m_revision(revision), @@ -426,9 +426,11 @@ class Offscreen_rhi_fixture bool render_layer_frame( plot::Series_renderer& renderer, plot::frame_context_t& ctx, - const std::map>& series_map, - std::vector& events, - std::string& error_message) + const std::map>& + series_map, + std::vector& + events, + std::string& error_message) { QRhiCommandBuffer* command_buffer = nullptr; if (m_rhi->beginOffscreenFrame(&command_buffer) != QRhi::FrameOpSuccess || !command_buffer) { @@ -472,7 +474,7 @@ plot::frame_layout_result_t make_layout() plot::frame_context_t make_context( const plot::frame_layout_result_t& layout, - const plot::Plot_config& config) + const plot::Plot_config& config) { plot::frame_context_t ctx{layout}; ctx.t0 = 0; @@ -488,8 +490,8 @@ plot::frame_context_t make_context( } std::shared_ptr make_layer_only_series( - std::shared_ptr source, - std::vector> layers) + std::shared_ptr source, + std::vector> layers) { auto series = std::make_shared(); series->style = plot::Display_style::NONE; @@ -500,9 +502,9 @@ std::shared_ptr make_layer_only_series( } std::shared_ptr make_builtin_plus_layer_series( - std::shared_ptr source, - plot::Display_style style, - std::vector> layers) + std::shared_ptr source, + plot::Display_style style, + std::vector> layers) { auto series = std::make_shared(); series->style = style; @@ -513,8 +515,8 @@ std::shared_ptr make_builtin_plus_layer_series( } std::shared_ptr make_line_plus_layer_series( - std::shared_ptr source, - std::vector> layers) + std::shared_ptr source, + std::vector> layers) { return make_builtin_plus_layer_series( std::move(source), @@ -523,8 +525,8 @@ std::shared_ptr make_line_plus_layer_series( } const layer_event_t* find_prepare_event( - const std::vector& events, - std::string_view layer_id) + const std::vector& events, + std::string_view layer_id) { for (const auto& event : events) { if (event.layer_id == layer_id && event.action == "prepare") { @@ -535,9 +537,9 @@ const layer_event_t* find_prepare_event( } std::size_t find_event_index( - const std::vector& events, - std::string_view layer_id, - std::string_view action) + const std::vector& events, + std::string_view layer_id, + std::string_view action) { for (std::size_t i = 0; i < events.size(); ++i) { if (events[i].layer_id == layer_id && events[i].action == action) { @@ -548,11 +550,11 @@ std::size_t find_event_index( } bool assert_compact_upload_state( - const plot::Series_renderer& renderer, - int series_id, - const layer_event_t& prepare, - std::size_t expected_line_window_sample_count, - std::string_view label) + const plot::Series_renderer& renderer, + int series_id, + const layer_event_t& prepare, + std::size_t expected_line_window_sample_count, + std::string_view label) { constexpr std::size_t k_gpu_sample_bytes = sizeof(float) * 4u; @@ -606,13 +608,14 @@ bool assert_compact_upload_state( } bool assert_drawable_span( - const std::vector& spans, - std::size_t index, - std::size_t source_first, - std::size_t source_count, - std::size_t gpu_first, - std::size_t gpu_count, - std::string_view label) + const std::vector& + spans, + std::size_t index, + std::size_t source_first, + std::size_t source_count, + std::size_t gpu_first, + std::size_t gpu_count, + std::string_view label) { TEST_ASSERT(index < spans.size(), std::string(label) + " expected drawable span index"); diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 5ff9b1a6..41d2df7a 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -183,7 +183,7 @@ class Direct_window_source final : public Data_source { } plot::data_query_result_t query_time_window( std::size_t /*lod*/, - const plot::data_query_context_t& query) override + const plot::data_query_context_t& query) override { ++query_calls; last_query_time_window = query.time_window; @@ -273,13 +273,13 @@ void fill_lod_samples(Two_level_source& source) } plot::Series_view_plan plan_two_level_lod_width( - Two_level_source& source, - const Data_access_policy& access, - const std::vector& scales, - plot::detail::series_window_planner_state_t& state, - plot::detail::Series_window_snapshot_cache& cache, - std::uint64_t frame_id, - double width_px) + Two_level_source& source, + const Data_access_policy& access, + const std::vector& scales, + plot::detail::series_window_planner_state_t& state, + plot::detail::Series_window_snapshot_cache& cache, + std::uint64_t frame_id, + double width_px) { plot::detail::series_window_plan_request_t request; request.planner_state = &state; @@ -297,8 +297,8 @@ plot::Series_view_plan plan_two_level_lod_width( } std::shared_ptr make_single_level_source( - std::vector timestamps, - plot::Time_order order) + std::vector timestamps, + plot::Time_order order) { auto source = std::make_shared(); source->order = order; @@ -311,10 +311,10 @@ std::shared_ptr make_single_level_source( } const plot::detail::series_window_planner_state_t* render_source_and_get_main_state( - Series_renderer& renderer, - const frame_context_t& ctx, + Series_renderer& renderer, + const frame_context_t& ctx, std::shared_ptr series, - int series_id) + int series_id) { std::map> series_map; series_map[series_id] = std::move(series); @@ -767,11 +767,11 @@ bool test_ascending_time_order_skips_monotonicity_scan() } bool run_defensive_time_order_scan_case( - plot::Time_order order, - std::vector timestamps, - plot::detail::Timestamp_window_search expected_search, - bool expected_monotonic, - const std::string& label) + plot::Time_order order, + std::vector timestamps, + plot::detail::Timestamp_window_search expected_search, + bool expected_monotonic, + const std::string& label) { auto data_source = make_single_level_source(timestamps, order); From 7ac9a99b9158df4ee3b4e1988a8190001065b26d Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:49:02 +0200 Subject: [PATCH 09/80] style: normalize constructor initializer layout --- include/vnm_plot/core/types.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 6d2fd7b7..89d80c4a 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -902,8 +902,9 @@ class Vector_data_source : public Data_source Payload() = default; Payload(std::vector payload_data, std::uint64_t payload_sequence) - : data(std::move(payload_data)) - , sequence(payload_sequence) + : + data(std::move(payload_data)), + sequence(payload_sequence) {} std::vector data; From 690aa2c56048480b91c95d427fff226c6724c639 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:51:13 +0200 Subject: [PATCH 10/80] style: normalize aggregate brace layout --- src/core/font_renderer.cpp | 2 +- src/core/primitive_renderer.cpp | 9 +- src/core/rhi_helpers.h | 2 +- tests/test_cache_invalidation.cpp | 52 ++++---- tests/test_concurrent_series.cpp | 4 +- tests/test_core_algo.cpp | 20 +-- tests/test_data_source_queries.cpp | 88 ++++++------- tests/test_gpu_sample_origin.cpp | 8 +- tests/test_msdf_lcd_shader_reference.cpp | 10 +- tests/test_plot_interaction_item.cpp | 12 +- tests/test_qrhi_layer_lifecycle.cpp | 150 +++++++++++------------ tests/test_snapshot_caching.cpp | 32 ++--- tests/test_text_lcd_resolver.cpp | 20 +-- 13 files changed, 210 insertions(+), 199 deletions(-) diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index aac9e935..16cc8470 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -1400,7 +1400,7 @@ void Font_renderer::rhi_queue_draw( rhi_state.pipeline.reset(rhi->newGraphicsPipeline()); rhi_state.pipeline->setShaderStages({ - { QRhiShaderStage::Vertex, rhi_state.vert }, + { QRhiShaderStage::Vertex, rhi_state.vert }, { QRhiShaderStage::Fragment, rhi_state.frag } }); rhi_state.pipeline->setVertexInputLayout(vlayout); diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index 902f6822..8b8cc4f5 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -132,11 +132,14 @@ struct Primitive_renderer::rhi_state_t std::size_t resource_index; // For RECT: number of instances (== quads) in vbo. // For GRID: scissor rectangle in QRhi's bottom-left coordinates. - union { - struct { + union + { + struct + { quint32 instance_count; } rect; - struct { + struct + { int x, y, w, h; } grid; }; diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index 9912c040..5c51d127 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -255,7 +255,7 @@ inline std::unique_ptr build_alpha_blended_pipeline( return nullptr; } pipeline->setShaderStages({ - { QRhiShaderStage::Vertex, desc.vert }, + { QRhiShaderStage::Vertex, desc.vert }, { QRhiShaderStage::Fragment, desc.frag } }); pipeline->setVertexInputLayout(desc.vlayout); diff --git a/tests/test_cache_invalidation.cpp b/tests/test_cache_invalidation.cpp index 777e2b88..08ff435f 100644 --- a/tests/test_cache_invalidation.cpp +++ b/tests/test_cache_invalidation.cpp @@ -37,14 +37,16 @@ using plot::value_range_t; namespace { -struct Test_sample { +struct Test_sample +{ std::int64_t t; float v; }; constexpr std::uint64_t k_stable_policy_semantics = 0x535441424C45; -class Query_range_source final : public Data_source { +class Query_range_source final : public Data_source +{ public: std::vector samples; Data_query_status query_status = Data_query_status::UNSUPPORTED; @@ -103,7 +105,8 @@ class Query_range_source final : public Data_source { }; -class Snapshot_range_source final : public Data_source { +class Snapshot_range_source final : public Data_source +{ public: std::vector samples; std::uint64_t snapshot_sequence = 1; @@ -135,7 +138,8 @@ class Snapshot_range_source final : public Data_source { } }; -class Counting_profiler final : public plot::Profiler { +class Counting_profiler final : public plot::Profiler +{ public: void begin_scope(const char* /*name*/) override {} void end_scope() override {} @@ -350,9 +354,9 @@ bool test_unsupported_query_falls_back_to_snapshot_scan() auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; source->samples = { - {0, 6.0f}, - {5, 8.0f}, - {10, 12.0f}, + { 0, 6.0f }, + { 5, 8.0f }, + { 10, 12.0f }, }; Plot_config config; @@ -408,9 +412,9 @@ bool test_default_query_profiler_counts_snapshot_scan() auto profiler = std::make_shared(); auto source = std::make_shared(); source->samples = { - {0, 6.0f}, - {5, 8.0f}, - {10, 12.0f}, + { 0, 6.0f }, + { 5, 8.0f }, + { 10, 12.0f }, }; Plot_config config; @@ -509,9 +513,9 @@ bool test_visible_step_after_hold_forward_contributes_held_sample() auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; source->samples = { - {5, -4.0f}, - {15, 6.0f}, - {25, 100.0f}, + { 5, -4.0f }, + { 15, 6.0f }, + { 25, 100.0f }, }; auto series = make_series(source); @@ -544,9 +548,9 @@ bool test_visible_step_after_skip_fallback_keeps_earlier_drawable_held_sample() auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; source->samples = { - {5, -4.0f}, - {9, nan}, - {15, 6.0f}, + { 5, -4.0f }, + { 9, nan }, + { 15, 6.0f }, }; auto series = make_series(source); @@ -578,9 +582,9 @@ bool test_global_value_only_access_falls_back_to_snapshot_scan() auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; source->samples = { - {0, -3.0f}, - {0, 8.0f}, - {0, 2.0f}, + { 0, -3.0f }, + { 0, 8.0f }, + { 0, 2.0f }, }; auto series = make_series(source); @@ -610,8 +614,8 @@ bool test_failed_query_does_not_fall_back_to_stale_scan() auto source = std::make_shared(); source->query_status = Data_query_status::FAILED; source->samples = { - {0, 1.0f}, - {5, 2.0f}, + { 0, 1.0f }, + { 5, 2.0f }, }; const data_config_t cfg = make_data_config(); @@ -1083,9 +1087,9 @@ bool test_frame_range_planner_preserves_step_after_visible_scan() auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; source->samples = { - {5, -3.0f}, - {15, 8.0f}, - {25, 100.0f}, + { 5, -3.0f }, + { 15, 8.0f }, + { 25, 100.0f }, }; auto series = make_series(source); diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index dc1a8ccb..b323fe03 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -104,8 +104,8 @@ bool test_vector_source_set_data_bumps_sequence() bool test_vector_source_constructor_data_is_published() { std::vector samples = { - {0.0, 4.0f}, - {1.0, 5.0f}, + { 0.0, 4.0f }, + { 1.0, 5.0f }, }; plot::Vector_data_source source(std::move(samples)); diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index 0cd8ef5d..1af25432 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -157,7 +157,7 @@ bool test_decimal_precision_helpers_reject_invalid_scaled_values() TEST_ASSERT(!plot::detail::any_fractional_at_precision({nan}, 1), "NaN values should be rejected cleanly"); TEST_ASSERT(!plot::detail::any_fractional_at_precision( - {std::numeric_limits::max()}, + { std::numeric_limits::max() }, 1), "values whose scaled form exceeds the safe integer range should be rejected"); TEST_ASSERT(!plot::detail::any_fractional_at_precision({1.25}, 400), @@ -228,9 +228,9 @@ bool test_timestamp_search_rejects_null_samples() bool test_raw_timestamp_search_rejects_zero_stride() { std::vector samples = { - {0, 0.0f}, - {1, 1.0f}, - {2, 2.0f} + { 0, 0.0f}, + { 1, 1.0f}, + { 2, 2.0f} }; int get_timestamp_calls = 0; @@ -335,11 +335,11 @@ bool test_select_visible_sample_window_monotonic_extends_bounds() bool test_select_visible_sample_window_non_monotonic_scans() { std::vector samples = { - {10, 0.0f}, - {4, 0.0f}, - {20, 0.0f}, - {6, 0.0f}, - {2, 0.0f} + { 10, 0.0f}, + { 4, 0.0f}, + { 20, 0.0f}, + { 6, 0.0f}, + { 2, 0.0f} }; plot::data_snapshot_t snap; @@ -377,7 +377,7 @@ bool test_select_visible_sample_window_non_monotonic_scans() bool test_aggregate_visible_sample_range_includes_step_after_hold() { std::vector samples = { - {0, 2.0f}, + { 0, 2.0f }, {15, 8.0f} }; diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 077c0b00..54dcc052 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -158,9 +158,9 @@ bool test_query_v_range_without_access_is_unsupported() bool test_ready_value_range_scan_populates_sequence() { Query_source source({ - {0, 3.0f}, - {1, -2.0f}, - {2, 5.0f}, + { 0, 3.0f }, + { 1, -2.0f }, + { 2, 5.0f }, }); source.set_sequence(123); @@ -242,9 +242,9 @@ bool test_ascending_skip_hold_value_range_scans_bounded_prefix() bool test_unordered_value_range_aggregates_discontiguous_matches() { Query_source source({ - {0, 1.0f}, - {100, 100.0f}, - {5, 2.0f}, + { 0, 1.0f }, + { 100, 100.0f }, + { 5, 2.0f }, }); source.set_time_order(plot::Time_order::UNORDERED); @@ -317,10 +317,10 @@ bool test_nonfinite_values_are_skipped_or_zeroed_by_policy() const plot::Data_access_policy access = make_value_access(); Query_source mixed_source({ - {0, 5.0f}, - {1, nan}, - {2, -2.0f}, - {3, inf}, + { 0, 5.0f }, + { 1, nan }, + { 2, -2.0f }, + { 3, inf }, }); const auto default_query = make_query(access, 0, 3); TEST_ASSERT(default_query.nonfinite_policy == plot::Nonfinite_sample_policy::BREAK_SEGMENT, @@ -334,8 +334,8 @@ bool test_nonfinite_values_are_skipped_or_zeroed_by_policy() "nonfinite values should not contribute to the default aggregate range"); Query_source nonfinite_source({ - {0, nan}, - {1, inf}, + { 0, nan }, + { 1, inf }, }); auto replace_query = make_query(access, 0, 1); replace_query.nonfinite_policy = plot::Nonfinite_sample_policy::REPLACE_WITH_ZERO; @@ -383,11 +383,11 @@ bool test_query_time_window_returns_simple_ascending_window() bool test_query_time_window_handles_descending_inclusive_bounds() { Query_source source({ - {9, 9.0f}, - {7, 7.0f}, - {5, 5.0f}, - {3, 3.0f}, - {1, 1.0f}, + { 9, 9.0f }, + { 7, 7.0f }, + { 5, 5.0f }, + { 3, 3.0f }, + { 1, 1.0f }, }); source.set_time_order(plot::Time_order::DESCENDING); @@ -404,10 +404,10 @@ bool test_query_time_window_handles_descending_inclusive_bounds() bool test_query_time_window_hold_forward_includes_held_sample() { Query_source source({ - {0, 0.0f}, - {10, 10.0f}, - {20, 20.0f}, - {30, 30.0f}, + { 0, 0.0f }, + { 10, 10.0f }, + { 20, 20.0f }, + { 30, 30.0f }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -425,9 +425,9 @@ bool test_query_time_window_keeps_break_segment_gaps_in_window() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 1.0f}, - {1, nan}, - {2, 2.0f}, + { 0, 1.0f }, + { 1, nan }, + { 2, 2.0f }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -445,9 +445,9 @@ bool test_query_time_window_reject_window_fails_on_nonfinite_in_window_sample() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 1.0f}, - {1, nan}, - {2, 2.0f}, + { 0, 1.0f }, + { 1, nan }, + { 2, 2.0f }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -465,8 +465,8 @@ bool test_query_time_window_does_not_hold_nonfinite_break_segment_sample() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 7.0f}, - {2, nan}, + { 0, 7.0f }, + { 2, nan }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -482,8 +482,8 @@ bool test_query_time_window_skip_holds_latest_drawable_sample() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 7.0f}, - {2, nan}, + { 0, 7.0f }, + { 2, nan }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -503,8 +503,8 @@ bool test_query_time_window_reject_window_fails_on_nonfinite_held_sample() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 7.0f}, - {2, nan}, + { 0, 7.0f }, + { 2, nan }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -521,9 +521,9 @@ bool test_query_time_window_reject_window_fails_on_nonfinite_held_sample() bool test_hold_forward_value_range_includes_pre_window_sample() { Query_source source({ - {0, 10.0f}, - {5, 1.0f}, - {6, 2.0f}, + { 0, 10.0f }, + { 5, 1.0f }, + { 6, 2.0f }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -540,8 +540,8 @@ bool test_hold_forward_value_range_includes_pre_window_sample() bool test_hold_forward_value_range_ready_from_held_sample_only() { Query_source source({ - {0, 7.0f}, - {2, 9.0f}, + { 0, 7.0f }, + { 2, 9.0f }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -559,8 +559,8 @@ bool test_hold_forward_does_not_use_nonfinite_break_segment_sample() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 7.0f}, - {2, nan}, + { 0, 7.0f }, + { 2, nan }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -576,8 +576,8 @@ bool test_hold_forward_skip_uses_latest_drawable_pre_window_sample() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 7.0f}, - {2, nan}, + { 0, 7.0f }, + { 2, nan }, }); source.set_time_order(plot::Time_order::ASCENDING); @@ -597,8 +597,8 @@ bool test_hold_forward_reject_window_fails_on_nonfinite_held_candidate() { const float nan = std::numeric_limits::quiet_NaN(); Query_source source({ - {0, 7.0f}, - {2, nan}, + { 0, 7.0f }, + { 2, nan }, }); source.set_time_order(plot::Time_order::ASCENDING); diff --git a/tests/test_gpu_sample_origin.cpp b/tests/test_gpu_sample_origin.cpp index 2fc68696..00408234 100644 --- a/tests/test_gpu_sample_origin.cpp +++ b/tests/test_gpu_sample_origin.cpp @@ -169,15 +169,15 @@ bool test_fp32_snap_step_resolution_at_bucket_boundaries() std::int64_t t_view_min_ns; } cases[] = { // 1 us bucket (span <= 1 s). End-rel <= ~1 s; ulp << 1 us. - { k_ns_per_second, k_ns_per_us, 0LL }, + { k_ns_per_second, k_ns_per_us, 0LL }, // 1 s bucket (span <= 1 day). End-rel <= ~86400 s; ulp ~6 ms. - { k_ns_per_day, k_ns_per_second, 0LL }, + { k_ns_per_day, k_ns_per_second, 0LL }, // 1 hour bucket (span <= 1 year). End-rel ~3.15e7 s exceeds 2^24; // ulp at end ~2 s vs 3600 s snap, so rounding is preserved. - { k_ns_per_year, k_ns_per_hour, 0LL }, + { k_ns_per_year, k_ns_per_hour, 0LL }, // 1 day fallback (span > 1 year). End-rel ~3.15e9 s; ulp at end // ~256 s vs 86400 s snap, so rounding is still preserved. - { 100LL * k_ns_per_year, k_ns_per_day, 0LL }, + { 100LL * k_ns_per_year, k_ns_per_day, 0LL }, }; for (const auto& c : cases) { diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 05cc7ebd..a1216054 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -313,11 +313,11 @@ bool test_cpp_order_values_match_shader_reference() }; constexpr case_t cases[] = { - {lcd::Resolved_lcd_subpixel_order::NONE, ref::k_lcd_order_none_value, ref::k_lcd_order_none_uniform}, - {lcd::Resolved_lcd_subpixel_order::RGB, ref::k_lcd_order_rgb_value, ref::k_lcd_order_rgb_uniform }, - {lcd::Resolved_lcd_subpixel_order::BGR, ref::k_lcd_order_bgr_value, ref::k_lcd_order_bgr_uniform }, - {lcd::Resolved_lcd_subpixel_order::VRGB, ref::k_lcd_order_vrgb_value, ref::k_lcd_order_vrgb_uniform}, - {lcd::Resolved_lcd_subpixel_order::VBGR, ref::k_lcd_order_vbgr_value, ref::k_lcd_order_vbgr_uniform}, + { lcd::Resolved_lcd_subpixel_order::NONE, ref::k_lcd_order_none_value, ref::k_lcd_order_none_uniform }, + { lcd::Resolved_lcd_subpixel_order::RGB, ref::k_lcd_order_rgb_value, ref::k_lcd_order_rgb_uniform }, + { lcd::Resolved_lcd_subpixel_order::BGR, ref::k_lcd_order_bgr_value, ref::k_lcd_order_bgr_uniform }, + { lcd::Resolved_lcd_subpixel_order::VRGB, ref::k_lcd_order_vrgb_value, ref::k_lcd_order_vrgb_uniform }, + { lcd::Resolved_lcd_subpixel_order::VBGR, ref::k_lcd_order_vbgr_value, ref::k_lcd_order_vbgr_uniform }, }; for (const case_t& item : cases) { diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index 138faa96..b20def26 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -119,7 +119,7 @@ void configure_indicator_widget( configure_view(widget, 0, k_second_ns, 0.0f, 10.0f); widget.add_series(1, make_sample_series( { - {0, 0.0f}, + { 0, 0.0f }, {k_second_ns, 10.0f} }, interpolation)); @@ -237,10 +237,10 @@ bool test_auto_adjust_view_uses_visible_samples_for_value_and_time_range() configure_view(widget, 5, 25, -100.0f, 100.0f); widget.add_series(1, make_sample_series( { - {0, 100.0f}, - {10, 2.0f}, - {20, 8.0f}, - {30, -100.0f} + { 0, 100.0f }, + { 10, 2.0f }, + { 20, 8.0f }, + { 30, -100.0f} }, plot::Series_interpolation::LINEAR)); @@ -262,7 +262,7 @@ bool test_auto_adjust_view_includes_step_after_held_sample() configure_view(widget, 10, 20, -100.0f, 100.0f); widget.add_series(1, make_sample_series( { - {0, 2.0f}, + { 0, 2.0f }, {15, 8.0f} }, plot::Series_interpolation::STEP_AFTER)); diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 28d9dd68..43961a4c 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -83,7 +83,7 @@ class Test_source final : public plot::Data_source Test_source() { set_samples({ - {0LL, 1.0f}, + { 0LL, 1.0f }, {1'000'000'000LL, 2.0f}, {2'000'000'000LL, 3.0f}, {3'000'000'000LL, 4.0f}, @@ -1227,10 +1227,10 @@ bool test_builtin_staging_normalizes_finite_reversed_ranges() auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f, 3.0f, 1.0f}, - {1LL * k_second_ns, 2.0f, 4.0f, 2.0f}, - {2LL * k_second_ns, 3.0f, 5.0f, 3.0f}, - {3LL * k_second_ns, 4.0f, 6.0f, 4.0f} + { 0LL, 1.0f, 3.0f, 1.0f }, + { 1LL * k_second_ns, 2.0f, 4.0f, 2.0f}, + { 2LL * k_second_ns, 3.0f, 5.0f, 3.0f}, + { 3LL * k_second_ns, 4.0f, 6.0f, 4.0f} }); auto series = std::make_shared(); @@ -1301,7 +1301,7 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() }; const policy_case_t cases[] = { - {plot::Nonfinite_sample_policy::BREAK_SEGMENT, "break-gap", 100}, + { plot::Nonfinite_sample_policy::BREAK_SEGMENT, "break-gap", 100 }, {plot::Nonfinite_sample_policy::SKIP, "skip-gap", 101} }; @@ -1312,10 +1312,10 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() std::string(test_case.layer_id), 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, nan}, - {3LL * k_second_ns, 4.0f}, + { 0LL, 1.0f }, + { 1LL * k_second_ns, 2.0f }, + { 2LL * k_second_ns, nan }, + { 3LL * k_second_ns, 4.0f }, {4LL * k_second_ns, 5.0f} }); @@ -1425,10 +1425,10 @@ bool test_nonfinite_replace_with_zero_keeps_contiguous_span() "replace-zero", 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, nan}, - {3LL * k_second_ns, 4.0f}, + { 0LL, 1.0f }, + { 1LL * k_second_ns, 2.0f }, + { 2LL * k_second_ns, nan }, + { 3LL * k_second_ns, 4.0f }, {4LL * k_second_ns, 5.0f} }); @@ -1509,9 +1509,9 @@ bool test_nonfinite_reject_window_suppresses_drawable_upload() "reject-window", 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, nan}, + { 0LL, 1.0f }, + { 1LL * k_second_ns, 2.0f }, + { 2LL * k_second_ns, nan }, {3LL * k_second_ns, 4.0f} }); @@ -1568,9 +1568,9 @@ bool test_nonfinite_reject_window_invalidates_prior_upload_before_busy() auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); auto series = std::make_shared(); @@ -1612,8 +1612,8 @@ bool test_nonfinite_reject_window_invalidates_prior_upload_before_busy() "initial finite REJECT_WINDOW frame should draw"); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, nan}, + { 0LL, 1.0f }, + { 1LL * k_second_ns, nan }, {2LL * k_second_ns, 3.0f} }); events.clear(); @@ -1645,9 +1645,9 @@ bool test_custom_layer_zero_gpu_window_invalidates_prior_upload_before_busy() auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); std::vector events; @@ -1699,8 +1699,8 @@ bool test_custom_layer_zero_gpu_window_invalidates_prior_upload_before_busy() "initial custom-layer frame should draw built-ins"); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, nan}, + { 0LL, 1.0f }, + { 1LL * k_second_ns, nan }, {2LL * k_second_ns, 3.0f} }); events.clear(); @@ -1735,9 +1735,9 @@ bool test_non_drawable_window_invalidates_prior_upload_before_fast_path() auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {10LL * k_second_ns, 10.0f} + { 0LL, 1.0f }, + { 1LL * k_second_ns, 2.0f }, + { 10LL * k_second_ns, 10.0f} }); auto series = std::make_shared(); @@ -1815,9 +1815,9 @@ bool test_non_rhi_prepare_invalidates_prior_upload_before_fast_path() auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {10LL * k_second_ns, 10.0f} + { 0LL, 1.0f }, + { 1LL * k_second_ns, 2.0f }, + { 10LL * k_second_ns, 10.0f} }); auto series = std::make_shared(); @@ -1900,10 +1900,10 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() }; const hold_case_t cases[] = { - {plot::Nonfinite_sample_policy::BREAK_SEGMENT, "hold-break", 106, false, 0, 0.0f}, - {plot::Nonfinite_sample_policy::SKIP, "hold-skip", 107, true, 0, 1.0f}, - {plot::Nonfinite_sample_policy::REJECT_WINDOW, "hold-reject", 108, false, 0, 0.0f}, - {plot::Nonfinite_sample_policy::REPLACE_WITH_ZERO, "hold-zero", 109, true, 1, 0.0f} + { plot::Nonfinite_sample_policy::BREAK_SEGMENT, "hold-break", 106, false, 0, 0.0f}, + { plot::Nonfinite_sample_policy::SKIP, "hold-skip", 107, true, 0, 1.0f}, + { plot::Nonfinite_sample_policy::REJECT_WINDOW, "hold-reject", 108, false, 0, 0.0f}, + { plot::Nonfinite_sample_policy::REPLACE_WITH_ZERO, "hold-zero", 109, true, 1, 0.0f} }; for (const auto& test_case : cases) { @@ -1913,7 +1913,7 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() std::string(test_case.layer_id), 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, + { 0LL, 1.0f }, {2LL * k_second_ns, nan} }); @@ -2006,8 +2006,8 @@ bool test_nonfinite_skip_hold_forward_preserves_earlier_held_sample_with_visible "hold-skip-visible", 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 7.0f}, - {2LL * k_second_ns, nan}, + { 0LL, 7.0f }, + { 2LL * k_second_ns, nan }, {5LL * k_second_ns, 9.0f} }); @@ -2097,8 +2097,8 @@ bool test_nonfinite_skip_hold_forward_ignores_future_padding_without_visible_dat "hold-skip-padding", 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 7.0f}, - {2LL * k_second_ns, nan}, + { 0LL, 7.0f }, + { 2LL * k_second_ns, nan }, {5LL * k_second_ns, 9.0f} }); @@ -2431,7 +2431,7 @@ bool test_builtin_upload_stages_visible_windows_for_dots_and_area() }; const upload_case_t cases[] = { - {plot::Display_style::DOTS, "visible-dots-upload", 33}, + { plot::Display_style::DOTS, "visible-dots-upload", 33 }, {plot::Display_style::AREA, "visible-area-upload", 34} }; @@ -2516,9 +2516,9 @@ bool test_builtin_upload_stages_single_synthetic_hold_sample() "hold-upload", 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); auto series = std::make_shared(); @@ -2588,7 +2588,7 @@ bool test_builtin_upload_stages_hold_windows_for_dots_and_area() }; const upload_case_t cases[] = { - {plot::Display_style::DOTS, "hold-dots-upload", 35}, + { plot::Display_style::DOTS, "hold-dots-upload", 35 }, {plot::Display_style::AREA, "hold-area-upload", 36} }; @@ -2599,9 +2599,9 @@ bool test_builtin_upload_stages_hold_windows_for_dots_and_area() std::string(test_case.layer_id), 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); auto series = std::make_shared(); @@ -2748,9 +2748,9 @@ bool test_resources_changed_tracks_hold_timestamp_changes() "hold-key", 1, 20, events, create_count); auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); auto series = std::make_shared(); @@ -2890,14 +2890,14 @@ bool test_busy_stale_fallback_rejects_changed_request_shape() std::vector events; auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f}, - {3LL * k_second_ns, 4.0f}, - {4LL * k_second_ns, 5.0f}, - {5LL * k_second_ns, 6.0f}, - {6LL * k_second_ns, 7.0f}, - {7LL * k_second_ns, 8.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f}, + { 3LL * k_second_ns, 4.0f}, + { 4LL * k_second_ns, 5.0f}, + { 5LL * k_second_ns, 6.0f}, + { 6LL * k_second_ns, 7.0f}, + { 7LL * k_second_ns, 8.0f} }); auto series = std::make_shared(); @@ -2984,9 +2984,9 @@ bool test_busy_hold_forward_does_not_prepare_stale_tmax() std::vector events; auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); auto series = std::make_shared(); @@ -3054,9 +3054,9 @@ bool test_busy_hold_forward_does_not_reuse_non_hold_window() std::vector events; auto source = std::make_shared(); source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f} }); auto series = std::make_shared(); @@ -3358,17 +3358,17 @@ bool test_range_only_access_skips_builtin_value_styles() auto range_source = std::make_shared(); range_source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f}, - {3LL * k_second_ns, 4.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f}, + { 3LL * k_second_ns, 4.0f} }); auto value_source = std::make_shared(); value_source->set_samples({ - {0LL, 1.0f}, - {1LL * k_second_ns, 2.0f}, - {2LL * k_second_ns, 3.0f}, - {3LL * k_second_ns, 4.0f} + { 0LL, 1.0f}, + { 1LL * k_second_ns, 2.0f}, + { 2LL * k_second_ns, 3.0f}, + { 3LL * k_second_ns, 4.0f} }); auto range_series = make_builtin_plus_layer_series( diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 41d2df7a..3bd34a7a 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -46,13 +46,15 @@ const plot::detail::series_window_planner_state_t& planner_state( return *view_state.planner; } -struct Test_sample { +struct Test_sample +{ // Timestamps are int64 nanoseconds (API convention). std::int64_t t; float v; }; -class Single_level_source final : public Data_source { +class Single_level_source final : public Data_source +{ public: std::vector samples; int snapshot_calls = 0; @@ -102,7 +104,8 @@ class Single_level_source final : public Data_source { plot::Time_order time_order(std::size_t /*lod*/) const override { return order; } }; -class Two_level_source final : public Data_source { +class Two_level_source final : public Data_source +{ public: std::vector lod0; std::vector lod1; @@ -138,7 +141,8 @@ class Two_level_source final : public Data_source { uint64_t current_sequence(size_t /*lod_level*/) const override { return 0; } }; -class Direct_window_source final : public Data_source { +class Direct_window_source final : public Data_source +{ public: std::vector samples; plot::sample_index_window_t query_window{}; @@ -467,8 +471,8 @@ bool test_direct_time_window_empty_falls_back_to_renderer_padding() { auto source = std::make_shared(); source->samples = { - {0, 1.0f}, - {10, 2.0f}, + { 0, 1.0f }, + { 10, 2.0f }, }; source->query_status = plot::Data_query_status::EMPTY; source->query_sequence = source->sequence; @@ -510,8 +514,8 @@ bool test_direct_time_window_single_match_expands_for_linear_segments() { auto source = std::make_shared(); source->samples = { - {0, 1.0f}, - {10, 2.0f}, + { 0, 1.0f }, + { 10, 2.0f }, }; source->query_window = {1, 1}; source->query_sequence = source->sequence; @@ -730,7 +734,7 @@ bool test_direct_time_window_unsupported_falls_back_to_snapshot_scan() bool test_ascending_time_order_skips_monotonicity_scan() { auto data_source = make_single_level_source( - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, plot::Time_order::ASCENDING); auto series = std::make_shared(); @@ -812,7 +816,7 @@ bool test_unknown_and_unordered_time_order_run_defensive_scan() { const bool unknown_ok = run_defensive_time_order_scan_case( plot::Time_order::UNKNOWN, - {0, 1, 2, 3, 4, 5, 6, 7, 8}, + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, plot::detail::Timestamp_window_search::BINARY, true, "UNKNOWN"); @@ -822,7 +826,7 @@ bool test_unknown_and_unordered_time_order_run_defensive_scan() return run_defensive_time_order_scan_case( plot::Time_order::UNORDERED, - {0, 5, 2, 7, 3, 8, 4, 9}, + { 0, 5, 2, 7, 3, 8, 4, 9 }, plot::detail::Timestamp_window_search::LINEAR, false, "UNORDERED"); @@ -831,7 +835,7 @@ bool test_unknown_and_unordered_time_order_run_defensive_scan() bool test_descending_time_order_uses_linear_window_search() { auto data_source = make_single_level_source( - {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, plot::Time_order::DESCENDING); auto series = std::make_shared(); @@ -870,7 +874,7 @@ bool test_descending_time_order_uses_linear_window_search() bool test_descending_time_order_does_not_hold_oldest_sample() { auto data_source = make_single_level_source( - {9, 7, 5, 3, 1}, + { 9, 7, 5, 3, 1 }, plot::Time_order::DESCENDING); auto series = std::make_shared(); @@ -910,7 +914,7 @@ bool test_descending_time_order_does_not_hold_oldest_sample() bool test_renderer_uses_lod_scales_metadata() { auto data_source = make_single_level_source( - {0, 1, 2, 3, 4, 5, 6, 7}, + { 0, 1, 2, 3, 4, 5, 6, 7 }, plot::Time_order::ASCENDING); data_source->scale_values = {0}; diff --git a/tests/test_text_lcd_resolver.cpp b/tests/test_text_lcd_resolver.cpp index d5abafe9..243a7ad2 100644 --- a/tests/test_text_lcd_resolver.cpp +++ b/tests/test_text_lcd_resolver.cpp @@ -116,11 +116,11 @@ bool test_explicit_orders_skip_probes() }; const explicit_request_case_t explicit_orders[] = { - {plot::text_lcd_none_request(), resolved_t::NONE}, - {plot::text_lcd_explicit_request(resolved_t::RGB), resolved_t::RGB}, - {plot::text_lcd_explicit_request(resolved_t::BGR), resolved_t::BGR}, - {plot::text_lcd_explicit_request(resolved_t::VRGB), resolved_t::VRGB}, - {plot::text_lcd_explicit_request(resolved_t::VBGR), resolved_t::VBGR}, + { plot::text_lcd_none_request(), resolved_t::NONE }, + { plot::text_lcd_explicit_request(resolved_t::RGB), resolved_t::RGB }, + { plot::text_lcd_explicit_request(resolved_t::BGR), resolved_t::BGR }, + { plot::text_lcd_explicit_request(resolved_t::VRGB), resolved_t::VRGB }, + { plot::text_lcd_explicit_request(resolved_t::VBGR), resolved_t::VBGR }, }; for (const explicit_request_case_t& item : explicit_orders) { @@ -137,11 +137,11 @@ bool test_explicit_orders_skip_probes() bool test_explicit_orders_for_null_window_are_deterministic() { const explicit_request_case_t explicit_orders[] = { - {plot::text_lcd_none_request(), resolved_t::NONE}, - {plot::text_lcd_explicit_request(resolved_t::RGB), resolved_t::RGB}, - {plot::text_lcd_explicit_request(resolved_t::BGR), resolved_t::BGR}, - {plot::text_lcd_explicit_request(resolved_t::VRGB), resolved_t::VRGB}, - {plot::text_lcd_explicit_request(resolved_t::VBGR), resolved_t::VBGR}, + { plot::text_lcd_none_request(), resolved_t::NONE }, + { plot::text_lcd_explicit_request(resolved_t::RGB), resolved_t::RGB }, + { plot::text_lcd_explicit_request(resolved_t::BGR), resolved_t::BGR }, + { plot::text_lcd_explicit_request(resolved_t::VRGB), resolved_t::VRGB }, + { plot::text_lcd_explicit_request(resolved_t::VBGR), resolved_t::VBGR }, }; for (const explicit_request_case_t& item : explicit_orders) { From 4a2280ee650af603906e605aa69970cf18cf8b0e Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:52:59 +0200 Subject: [PATCH 11/80] style: align struct member declarations --- include/vnm_plot/core/access_policy.h | 8 +- include/vnm_plot/core/algo.h | 22 +- include/vnm_plot/core/layout_calculator.h | 68 +++--- include/vnm_plot/core/plot_config.h | 50 ++--- include/vnm_plot/core/series_window.h | 135 ++++++------ include/vnm_plot/core/types.h | 224 ++++++++++---------- include/vnm_plot/qt/plot_interaction_item.h | 53 ++--- include/vnm_plot/qt/plot_time_axis.h | 39 ++-- include/vnm_plot/qt/plot_widget.h | 85 ++++---- include/vnm_plot/rhi/asset_loader.h | 4 +- include/vnm_plot/rhi/font_renderer.h | 16 +- include/vnm_plot/rhi/frame_context.h | 44 ++-- include/vnm_plot/rhi/primitive_renderer.h | 13 +- include/vnm_plot/rhi/qrhi_series_layer.h | 92 ++++---- include/vnm_plot/rhi/series_renderer.h | 86 ++++---- include/vnm_plot/rhi/text_renderer.h | 32 +-- src/core/auto_range_resolver.h | 38 ++-- src/core/font_renderer.cpp | 147 ++++++------- src/core/layout_calculator.cpp | 42 ++-- src/core/primitive_renderer.cpp | 68 +++--- src/core/rhi_helpers.h | 10 +- src/core/series_renderer.cpp | 190 +++++++++-------- src/core/series_window_planner.cpp | 18 +- src/core/series_window_planner.h | 98 +++++---- src/core/types.cpp | 26 +-- src/qt/plot_renderer.cpp | 39 ++-- src/qt/plot_widget.cpp | 8 +- src/qt/t_axis_adjust.h | 24 +-- src/qt/text_lcd_resolver.h | 2 +- tests/test_cache_invalidation.cpp | 34 +-- tests/test_concurrent_series.cpp | 21 +- tests/test_core_algo.cpp | 4 +- tests/test_data_source_queries.cpp | 14 +- tests/test_font_disk_cache.cpp | 16 +- tests/test_plot_interaction_item.cpp | 8 +- tests/test_qrhi_layer_lifecycle.cpp | 144 ++++++------- tests/test_qrhi_public_api.cpp | 18 +- tests/test_snapshot_caching.cpp | 48 ++--- tests/test_text_lcd_resolver.cpp | 2 +- tests/test_typed_api.cpp | 34 +-- 40 files changed, 1028 insertions(+), 996 deletions(-) diff --git a/include/vnm_plot/core/access_policy.h b/include/vnm_plot/core/access_policy.h index fd90e7a3..54384659 100644 --- a/include/vnm_plot/core/access_policy.h +++ b/include/vnm_plot/core/access_policy.h @@ -269,11 +269,11 @@ struct Data_access_policy_typed } // Timestamps are int64_t nanoseconds (API convention). - timestamp_accessor_t get_timestamp; - value_accessor_t get_value; - range_accessor_t get_range; + timestamp_accessor_t get_timestamp; + value_accessor_t get_value; + range_accessor_t get_range; - uint64_t layout_key = 0; + uint64_t layout_key = 0; sample_semantics_key_t semantics_key; bool is_valid() const diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 3ba915d4..744e2883 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -448,18 +448,18 @@ std::size_t upper_bound_timestamp( struct timestamp_bracket_t { - std::size_t i0 = 0; - std::size_t i1 = 0; - bool valid = false; + std::size_t i0 = 0; + std::size_t i1 = 0; + bool valid = false; explicit operator bool() const noexcept { return valid; } }; struct visible_sample_window_t { - std::size_t first = 0; - std::size_t last_exclusive = 0; - bool valid = false; + std::size_t first = 0; + std::size_t last_exclusive = 0; + bool valid = false; explicit operator bool() const noexcept { return valid; } }; @@ -521,11 +521,11 @@ visible_sample_window_t select_visible_sample_window( struct visible_sample_aggregate_t { - double vmin = 0.0; - double vmax = 0.0; - std::int64_t tmin_ns = 0; - std::int64_t tmax_ns = 0; - bool valid = false; + double vmin = 0.0; + double vmax = 0.0; + std::int64_t tmin_ns = 0; + std::int64_t tmax_ns = 0; + bool valid = false; explicit operator bool() const noexcept { return valid; } }; diff --git a/include/vnm_plot/core/layout_calculator.h b/include/vnm_plot/core/layout_calculator.h index c56a4380..9eb872c9 100644 --- a/include/vnm_plot/core/layout_calculator.h +++ b/include/vnm_plot/core/layout_calculator.h @@ -29,24 +29,24 @@ class Layout_calculator struct parameters_t { // Data ranges - float v_min; - float v_max; + float v_min; + float v_max; // Timestamps are int64_t nanoseconds (API convention). - std::int64_t t_min; - std::int64_t t_max; + std::int64_t t_min; + std::int64_t t_max; // Viewport dimensions - double usable_width; - double usable_height; - double vbar_width; - double label_visible_height; + double usable_width; + double usable_height; + double vbar_width; + double label_visible_height; // Font metrics - double adjusted_font_size_in_pixels; - float h_label_vertical_nudge_factor = 0.0f; - uint64_t measure_text_cache_key = 0; - float monospace_char_advance_px = 0.f; - bool monospace_advance_is_reliable = false; + double adjusted_font_size_in_pixels; + float h_label_vertical_nudge_factor = 0.0f; + uint64_t measure_text_cache_key = 0; + float monospace_char_advance_px = 0.f; + bool monospace_advance_is_reliable = false; // Callbacks for metrics and formatting std::function get_required_fixed_digits_func; @@ -54,21 +54,21 @@ class Layout_calculator std::function format_timestamp_func; std::uint64_t format_timestamp_revision = 0; std::function - format_value_func; + format_value_func; std::uint64_t format_value_revision = 0; std::function measure_text_func; // Optional profiler (from Plot_config) - vnm::plot::Profiler* profiler = nullptr; + vnm::plot::Profiler* profiler = nullptr; // Seed hints for incremental computation - bool has_vertical_seed = false; - int vertical_seed_index = -1; - double vertical_seed_step = 0.0; + bool has_vertical_seed = false; + int vertical_seed_index = -1; + double vertical_seed_step = 0.0; - bool has_horizontal_seed = false; - int horizontal_seed_index = -1; - double horizontal_seed_step = 0.0; + bool has_horizontal_seed = false; + int horizontal_seed_index = -1; + double horizontal_seed_step = 0.0; }; // Calculation result @@ -77,15 +77,15 @@ class Layout_calculator std::vector v_labels; std::vector h_labels; - int v_label_fixed_digits = 1; - bool h_labels_subsecond = false; - float max_v_label_text_width = 0.f; + int v_label_fixed_digits = 1; + bool h_labels_subsecond = false; + float max_v_label_text_width = 0.f; - int vertical_seed_index = -1; - double vertical_seed_step = 0.0; - double vertical_finest_step = 0.0; - int horizontal_seed_index = -1; - double horizontal_seed_step = 0.0; + int vertical_seed_index = -1; + double vertical_seed_step = 0.0; + double vertical_finest_step = 0.0; + int horizontal_seed_index = -1; + double horizontal_seed_step = 0.0; }; Layout_calculator() = default; @@ -101,11 +101,11 @@ class Layout_calculator float min_gap) const; // Scratch buffers (reused to avoid allocations) - mutable std::vector> m_scratch_vals; - mutable std::vector> m_scratch_level; - mutable std::vector> m_scratch_accepted_boxes; - mutable std::vector m_scratch_accepted_y; - mutable std::vector m_scratch_vals_d; + mutable std::vector> m_scratch_vals; + mutable std::vector> m_scratch_level; + mutable std::vector> m_scratch_accepted_boxes; + mutable std::vector m_scratch_accepted_y; + mutable std::vector m_scratch_vals_d; }; } // namespace vnm::plot diff --git a/include/vnm_plot/core/plot_config.h b/include/vnm_plot/core/plot_config.h index a5497aa6..701b113c 100644 --- a/include/vnm_plot/core/plot_config.h +++ b/include/vnm_plot/core/plot_config.h @@ -28,9 +28,9 @@ enum class Value_format_role struct value_format_context_t { - Value_format_role role = Value_format_role::AXIS_LABEL; - int suggested_fixed_digits = 0; - std::string_view series_label; + Value_format_role role = Value_format_role::AXIS_LABEL; + int suggested_fixed_digits = 0; + std::string_view series_label; }; // ----------------------------------------------------------------------------- @@ -105,12 +105,12 @@ class Profile_scope struct Plot_config { // --- Theme --- - bool dark_mode = false; - bool show_text = true; - double grid_visibility = 1.0; // 0..1 alpha; 0 = hidden (skipped), 1 = fully visible - double preview_visibility = 1.0; // 0..1 alpha; 0 = hidden (skipped), 1 = fully visible - Color_palette dark_color_palette = Color_palette::dark(); - Color_palette light_color_palette = Color_palette::light(); + bool dark_mode = false; + bool show_text = true; + double grid_visibility = 1.0; // 0..1 alpha; 0 = hidden (skipped), 1 = fully visible + double preview_visibility = 1.0; // 0..1 alpha; 0 = hidden (skipped), 1 = fully visible + Color_palette dark_color_palette = Color_palette::dark(); + Color_palette light_color_palette = Color_palette::light(); // --- Timestamp Formatting --- // Callback to format timestamps for axis labels. @@ -123,7 +123,7 @@ struct Plot_config // Revision for formatter behavior. Caller contract: increment when the // effective output of format_timestamp changes without replacing the // callback identity (e.g. captured/stateful data updates). - std::uint64_t format_timestamp_revision = 0; + std::uint64_t format_timestamp_revision = 0; // Generic value formatter for Y-axis labels, indicator values, and info // overlay values. Applications own units, locale, and domain-specific // precision. If null, vnm_plot uses its neutral numeric defaults. @@ -132,46 +132,46 @@ struct Plot_config // --- Profiling (optional) --- // If provided, profiling scopes will be recorded. - std::shared_ptr profiler; + std::shared_ptr profiler; // --- Font Configuration --- - double font_size_px = 10.0; - double base_label_height_px = 14.0; + double font_size_px = 10.0; + double base_label_height_px = 14.0; // --- Logging (optional) --- // Hook for debug messages (e.g., LOD selection). - std::function log_debug; - std::function log_error; + std::function log_debug; + std::function log_error; // --- Preview Bar --- - double preview_height_px = 0.0; // 0 = auto, >0 = fixed height + double preview_height_px = 0.0; // 0 = auto, >0 = fixed height // --- Clear Behavior --- // When true, clear to transparent so QML controls the background. - bool clear_to_transparent = false; + bool clear_to_transparent = false; // --- Line Rendering --- // When true, snap line vertices to pixel centers (can look jagged on // diagonals; default is false for smoother lines). - bool snap_lines_to_pixels = false; + bool snap_lines_to_pixels = false; // Line width in pixels (may be clamped by the driver). - double line_width_px = 1.0; + double line_width_px = 1.0; // Dot diameter in pixels for DOTS rendering. The shader floors at 1 px, // so values below 1.0 still render as a 1-pixel dot. - double point_diameter_px = 1.0; + double point_diameter_px = 1.0; // Area fill alpha multiplier (0..1). - double area_fill_alpha = 0.3; + double area_fill_alpha = 0.3; // --- Auto V-Range --- // Default is GLOBAL. - Auto_v_range_mode auto_v_range_mode = Auto_v_range_mode::GLOBAL; + Auto_v_range_mode auto_v_range_mode = Auto_v_range_mode::GLOBAL; // Extra scale applied to auto v-range (0 = no padding). - double auto_v_range_extra_scale = 0.0; + double auto_v_range_extra_scale = 0.0; // When true, padding cannot pull a nonnegative auto-computed range below zero. - bool floor_nonnegative_auto_v_range_at_zero = false; + bool floor_nonnegative_auto_v_range_at_zero = false; // --- Text LCD --- - text_lcd_request_t text_lcd_request = text_lcd_auto_request(); + text_lcd_request_t text_lcd_request = text_lcd_auto_request(); }; inline Color_palette resolved_color_palette(const Plot_config* config, bool dark_mode) diff --git a/include/vnm_plot/core/series_window.h b/include/vnm_plot/core/series_window.h index bd2ab880..16e61995 100644 --- a/include/vnm_plot/core/series_window.h +++ b/include/vnm_plot/core/series_window.h @@ -19,114 +19,115 @@ enum class Series_view_kind struct drawable_sample_span_t { - std::size_t source_first = 0; - std::size_t source_count = 0; - std::size_t gpu_first = 0; - std::size_t gpu_count = 0; + std::size_t source_first = 0; + std::size_t source_count = 0; + std::size_t gpu_first = 0; + std::size_t gpu_count = 0; }; struct sample_window_t { - Series_view_kind view_kind = Series_view_kind::MAIN; + Series_view_kind view_kind = Series_view_kind::MAIN; // Consumers receive a valid frame-scoped snapshot for drawable sample // windows. If the renderer cannot acquire one, it skips drawable windows // instead of passing empty data as drawable. - data_snapshot_t snapshot; - const Data_access_policy* access = nullptr; + data_snapshot_t snapshot; + const Data_access_policy* access = nullptr; // Source window in `snapshot`, before synthetic draw-only samples. // `source_count == 0` means there are no real source samples to draw. - std::size_t source_first = 0; - std::size_t source_count = 0; + std::size_t source_first = 0; + std::size_t source_count = 0; // Draw-only hold-forward samples appended after the source window. This is // currently zero or one. A synthetic hold sample copies the last source // sample's value/range and uses `hold_timestamp_ns` as its GPU timestamp. - std::size_t synthetic_hold_count = 0; + std::size_t synthetic_hold_count = 0; // Number of compact GPU samples staged by built-in rendering. Non-drawable // samples in the source window are omitted unless policy replaces them. - std::size_t gpu_count = 0; - std::vector drawable_spans; - std::size_t lod_level = 0; - double pixels_per_sample = 0.0; - std::uint64_t sample_sequence = 0; - Series_interpolation interpolation = Series_interpolation::LINEAR; + std::size_t gpu_count = 0; + std::vector drawable_spans; + std::size_t lod_level = 0; + double pixels_per_sample = 0.0; + std::uint64_t sample_sequence = 0; + Series_interpolation interpolation = Series_interpolation::LINEAR; Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - std::int64_t t_min_ns = 0; - std::int64_t t_max_ns = 0; - std::int64_t t_origin_ns = 0; + std::int64_t t_min_ns = 0; + std::int64_t t_max_ns = 0; + std::int64_t t_origin_ns = 0; - bool hold_last_forward = false; - std::int64_t hold_timestamp_ns = 0; + bool hold_last_forward = false; + std::int64_t hold_timestamp_ns = 0; - float v_min = 0.0f; - float v_max = 1.0f; - float width_px = 0.0f; - float height_px = 0.0f; - float y_offset_px = 0.0f; - float window_alpha = 1.0f; + float v_min = 0.0f; + float v_max = 1.0f; + float width_px = 0.0f; + float height_px = 0.0f; + float y_offset_px = 0.0f; + float window_alpha = 1.0f; }; struct value_range_plan_t { - float min = 0.0f; - float max = 1.0f; - bool valid = false; + float min = 0.0f; + float max = 1.0f; + bool valid = false; }; struct Planned_snapshot { - data_snapshot_t snapshot; - std::uint64_t sequence = 0; + data_snapshot_t snapshot; + std::uint64_t sequence = 0; }; struct Series_view_plan { - int series_id = 0; - Series_view_kind view_kind = Series_view_kind::MAIN; - Data_source* source = nullptr; - const Data_access_policy* access = nullptr; - - std::size_t lod_level = 0; - std::size_t lod_scale = 1; - Planned_snapshot snapshot; - - std::size_t source_first = 0; - std::size_t source_count = 0; - std::size_t synthetic_hold_count = 0; - std::size_t gpu_count = 0; - std::vector drawable_spans; - - std::int64_t t_min_ns = 0; - std::int64_t t_max_ns = 0; - std::int64_t t_origin_ns = 0; - - bool hold_last_forward = false; - std::int64_t hold_timestamp_ns = 0; - - Series_interpolation interpolation = Series_interpolation::LINEAR; - Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; + int series_id = 0; + Series_view_kind view_kind = Series_view_kind::MAIN; + Data_source* source = nullptr; + const Data_access_policy* access = nullptr; + + std::size_t lod_level = 0; + std::size_t lod_scale = 1; + Planned_snapshot snapshot; + + std::size_t source_first = 0; + std::size_t source_count = 0; + std::size_t synthetic_hold_count = 0; + std::size_t gpu_count = 0; + std::vector + drawable_spans; + + std::int64_t t_min_ns = 0; + std::int64_t t_max_ns = 0; + std::int64_t t_origin_ns = 0; + + bool hold_last_forward = false; + std::int64_t hold_timestamp_ns = 0; + + Series_interpolation interpolation = Series_interpolation::LINEAR; + Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - Display_style style = Display_style::NONE; - - float v_min = 0.0f; - float v_max = 1.0f; - float width_px = 0.0f; - float height_px = 0.0f; - float y_offset_px = 0.0f; - float window_alpha = 1.0f; - double pixels_per_sample = 0.0; + Display_style style = Display_style::NONE; + + float v_min = 0.0f; + float v_max = 1.0f; + float width_px = 0.0f; + float height_px = 0.0f; + float y_offset_px = 0.0f; + float window_alpha = 1.0f; + double pixels_per_sample = 0.0; }; struct Frame_range_plan { - value_range_plan_t main_v_range; - value_range_plan_t preview_v_range; + value_range_plan_t main_v_range; + value_range_plan_t preview_v_range; }; } // namespace vnm::plot diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 89d80c4a..12222b2c 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -27,9 +27,9 @@ struct Data_access_policy_typed; struct sample_semantics_key_t { - std::uint64_t value = 0; - std::uint64_t revision = 0; - bool conservative = true; + std::uint64_t value = 0; + std::uint64_t revision = 0; + bool conservative = true; }; namespace detail { @@ -51,16 +51,16 @@ struct erased_access_policy_t using range_fn_t = std::pair (*)(const erased_access_policy_t&, const void*); - const void* ctx = nullptr; - timestamp_fn_t get_timestamp = nullptr; - value_fn_t get_value = nullptr; - range_fn_t get_range = nullptr; + const void* ctx = nullptr; + timestamp_fn_t get_timestamp = nullptr; + value_fn_t get_value = nullptr; + range_fn_t get_range = nullptr; - access_dispatch_kind_t dispatch_kind = access_dispatch_kind_t::NONE; - std::size_t timestamp_offset = 0; - std::size_t value_offset = 0; - std::size_t range_min_offset = 0; - std::size_t range_max_offset = 0; + access_dispatch_kind_t dispatch_kind = access_dispatch_kind_t::NONE; + std::size_t timestamp_offset = 0; + std::size_t value_offset = 0; + std::size_t range_min_offset = 0; + std::size_t range_max_offset = 0; [[nodiscard]] bool has_timestamp() const noexcept { @@ -101,13 +101,13 @@ struct erased_access_policy_t struct access_policy_cache_key_t { - const Data_access_policy* identity = nullptr; - std::uint64_t layout_key = 0; - std::uint64_t revision = 0; - access_dispatch_kind_t dispatch_kind = access_dispatch_kind_t::NONE; - bool has_timestamp = false; - bool has_value = false; - bool has_range = false; + const Data_access_policy* identity = nullptr; + std::uint64_t layout_key = 0; + std::uint64_t revision = 0; + access_dispatch_kind_t dispatch_kind = access_dispatch_kind_t::NONE; + bool has_timestamp = false; + bool has_value = false; + bool has_range = false; [[nodiscard]] bool operator==( const access_policy_cache_key_t& other) const noexcept @@ -240,10 +240,10 @@ class access_function_slot_t } } - function_t m_function; - erased_access_policy_t* m_internal_access = nullptr; - std::uint64_t* m_revision = nullptr; - sample_semantics_key_t* m_semantics_key = nullptr; + function_t m_function; + erased_access_policy_t* m_internal_access = nullptr; + std::uint64_t* m_revision = nullptr; + sample_semantics_key_t* m_semantics_key = nullptr; }; inline sample_semantics_key_t make_explicit_sample_semantics_key( @@ -311,13 +311,13 @@ using Byte_view = std::string_view; // snapshot unless they also retain `hold`. struct data_snapshot_t { - const void* data = nullptr; ///< Pointer to first sample - size_t count = 0; ///< Number of samples - size_t stride = 0; ///< Bytes between consecutive samples - uint64_t sequence = 0; ///< Change counter for cache invalidation - const void* data2 = nullptr; ///< Optional second segment (wrap) - size_t count2 = 0; ///< Samples in second segment - std::shared_ptr hold; ///< Optional ownership/lock guard + const void* data = nullptr; ///< Pointer to first sample + size_t count = 0; ///< Number of samples + size_t stride = 0; ///< Bytes between consecutive samples + uint64_t sequence = 0; ///< Change counter for cache invalidation + const void* data2 = nullptr; ///< Optional second segment (wrap) + size_t count2 = 0; ///< Samples in second segment + std::shared_ptr hold; ///< Optional ownership/lock guard explicit operator bool() const { return is_valid(); } @@ -437,13 +437,13 @@ struct Data_access_policy // the bias inside the accessor so the remaining dynamic range survives. // Timestamps are int64_t nanoseconds (by API convention; the unit is the // accessor's contract with vnm_plot). - timestamp_accessor_t get_timestamp; ///< Extract timestamp (ns) - value_accessor_t get_value; ///< Extract primary value - range_accessor_t get_range; ///< Extract min/max range + timestamp_accessor_t get_timestamp; ///< Extract timestamp (ns) + value_accessor_t get_value; ///< Extract primary value + range_accessor_t get_range; ///< Extract min/max range ///< Byte-layout cache key for renderer-internal caches. It is not a ///< unique sample type identity and does not describe accessor semantics. - uint64_t layout_key = 0; + uint64_t layout_key = 0; ///< Accessor-transform identity for source query caches. Member-pointer ///< typed policies populate a stable key; callable policies stay @@ -501,7 +501,7 @@ struct Data_access_policy &semantics_key); } - detail::erased_access_policy_t internal_access; ///< Renderer/planner fast-path view + detail::erased_access_policy_t internal_access; ///< Renderer/planner fast-path view std::uint64_t access_revision = 1; }; @@ -655,14 +655,14 @@ enum class Data_query_status struct sample_index_window_t { - std::size_t first = 0; - std::size_t count = 0; + std::size_t first = 0; + std::size_t count = 0; }; struct value_range_t { - float min = 0.0f; - float max = 0.0f; + float min = 0.0f; + float max = 0.0f; }; namespace detail { @@ -676,7 +676,7 @@ enum class sample_draw_status_t struct sample_draw_value_t { - float y = 0.0f; + float y = 0.0f; float y_min = 0.0f; float y_max = 0.0f; }; @@ -698,21 +698,21 @@ sample_draw_status_t read_sample_draw_value( template struct data_query_result_t { - Data_query_status status = Data_query_status::UNSUPPORTED; + Data_query_status status = Data_query_status::UNSUPPORTED; T value{}; - std::uint64_t sequence = 0; + std::uint64_t sequence = 0; }; struct data_query_context_t { - const Data_access_policy* access = nullptr; + const Data_access_policy* access = nullptr; // Optional caller-owned profiler for query-internal work such as fallback scans. - Profiler* profiler = nullptr; - sample_semantics_key_t semantics_key; - time_range_t time_window{}; - Series_interpolation interpolation = Series_interpolation::LINEAR; - Empty_window_behavior empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; - Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; + Profiler* profiler = nullptr; + sample_semantics_key_t semantics_key; + time_range_t time_window{}; + Series_interpolation interpolation = Series_interpolation::LINEAR; + Empty_window_behavior empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; + Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; }; // ----------------------------------------------------------------------------- @@ -911,8 +911,8 @@ class Vector_data_source : public Data_source std::uint64_t sequence = 0; }; - mutable std::mutex m_mutex; - std::shared_ptr m_payload; + mutable std::mutex m_mutex; + std::shared_ptr m_payload; }; // ----------------------------------------------------------------------------- @@ -955,10 +955,12 @@ constexpr int k_visible_info_all = k_visible_info_value_range | k_visibl // ----------------------------------------------------------------------------- struct preview_config_t { - Data_source_ref data_source; // required when preview_config is set - Data_access_policy access; // optional; if invalid, fall back to main access - std::optional style; // nullopt means use main style - std::optional interpolation; // nullopt means use main interpolation + Data_source_ref data_source; // required when preview_config is set + Data_access_policy access; // optional; if invalid, fall back to main access + std::optional + style; // nullopt means use main style + std::optional + interpolation; // nullopt means use main interpolation }; // ----------------------------------------------------------------------------- @@ -966,10 +968,10 @@ struct preview_config_t // ----------------------------------------------------------------------------- struct data_config_t { - float v_min = -1.f; - float v_max = 1.f; - float v_manual_min = 0.f; - float v_manual_max = 5.f; + float v_min = -1.f; + float v_max = 1.f; + float v_manual_min = 0.f; + float v_manual_max = 5.f; // Timestamps are int64_t nanoseconds (API convention). The defaults // describe a 10-second view starting at 0 ns; every Plot_widget user @@ -978,12 +980,12 @@ struct data_config_t // sane 10-second window instead of a 5-microsecond one. The previous // 5000 / 10000 / 0 / 10000 literals were carried over from a pre-int64 // era when the unit was seconds and described a 10000-second view. - std::int64_t t_min = 0; - std::int64_t t_max = std::int64_t{10} * 1'000'000'000; - std::int64_t t_available_min = 0; - std::int64_t t_available_max = std::int64_t{10} * 1'000'000'000; + std::int64_t t_min = 0; + std::int64_t t_max = std::int64_t{10} * 1'000'000'000; + std::int64_t t_available_min = 0; + std::int64_t t_available_max = std::int64_t{10} * 1'000'000'000; - double vbar_width = 150.; + double vbar_width = 150.; }; // ----------------------------------------------------------------------------- @@ -993,19 +995,19 @@ struct series_data_t { virtual ~series_data_t() = default; - bool enabled = true; - Display_style style = Display_style::LINE; - Series_interpolation interpolation = Series_interpolation::LINEAR; - Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; - Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - glm::vec4 color = glm::vec4(0.16f, 0.45f, 0.64f, 1.0f); - std::string series_label; + bool enabled = true; + Display_style style = Display_style::LINE; + Series_interpolation interpolation = Series_interpolation::LINEAR; + Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; + Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; + glm::vec4 color = glm::vec4(0.16f, 0.45f, 0.64f, 1.0f); + std::string series_label; - Data_source_ref data_source; - Data_access_policy access; + Data_source_ref data_source; + Data_access_policy access; // Optional per-series preview configuration. When set, preview rendering can // use a distinct data source, access policy, and style. - std::optional preview_config; + std::optional preview_config; [[nodiscard]] virtual std::shared_ptr clone() const { @@ -1106,69 +1108,69 @@ struct series_data_t // ----------------------------------------------------------------------------- struct grid_layer_params_t { - static constexpr int k_max_levels = 32; - int count = 0; - float spacing_px[k_max_levels] = {}; - float start_px[k_max_levels] = {}; - float alpha[k_max_levels] = {}; - float thickness_px[k_max_levels] = {}; + static constexpr int k_max_levels = 32; + int count = 0; + float spacing_px[k_max_levels] = {}; + float start_px[k_max_levels] = {}; + float alpha[k_max_levels] = {}; + float thickness_px[k_max_levels] = {}; }; /// Vertical axis label (value bar on the right side of plot) struct v_label_t { - double value; ///< Data value this label represents - float y; ///< Y position in pixels (from bottom) - std::string text; ///< Formatted label text + double value; ///< Data value this label represents + float y; ///< Y position in pixels (from bottom) + std::string text; ///< Formatted label text }; /// Horizontal axis label (time bar below plot) struct h_label_t { - std::int64_t value; ///< Timestamp this label represents (nanoseconds) - glm::vec2 position; ///< Position in pixels (x, y from bottom-left) - std::string text; ///< Formatted label text + std::int64_t value; ///< Timestamp this label represents (nanoseconds) + glm::vec2 position; ///< Position in pixels (x, y from bottom-left) + std::string text; ///< Formatted label text }; /// Result of layout calculation for a single frame. /// Contains computed dimensions and pre-positioned labels. struct frame_layout_result_t { - double usable_width = 0.0; ///< Plot area width in pixels - double usable_height = 0.0; ///< Plot area height in pixels - double v_bar_width = 0.0; - double h_bar_height = 0.0; - float max_v_label_text_width = 0.f; + double usable_width = 0.0; ///< Plot area width in pixels + double usable_height = 0.0; ///< Plot area height in pixels + double v_bar_width = 0.0; + double h_bar_height = 0.0; + float max_v_label_text_width = 0.f; std::vector h_labels; std::vector v_labels; - int v_label_fixed_digits = 0; - bool h_labels_subsecond = false; + int v_label_fixed_digits = 0; + bool h_labels_subsecond = false; - int vertical_seed_index = -1; - double vertical_seed_step = 0.0; - double vertical_finest_step = 0.0; - int horizontal_seed_index = -1; - double horizontal_seed_step = 0.0; + int vertical_seed_index = -1; + double vertical_seed_step = 0.0; + double vertical_finest_step = 0.0; + int horizontal_seed_index = -1; + double horizontal_seed_step = 0.0; }; /// Key for layout caching. Layout is recomputed only when this key changes. struct layout_cache_key_t { - float v0 = 0.0f; - float v1 = 0.0f; - std::int64_t t0 = 0; // nanoseconds - std::int64_t t1 = 0; // nanoseconds - Size_2i viewport_size; - double adjusted_reserved_height = 0.0; - double adjusted_preview_height = 0.0; - double adjusted_font_size_in_pixels = 0.0; - double vbar_width_pixels = 0.0; - uint64_t font_metrics_key = 0; - uint64_t config_revision = 0; - uint64_t format_timestamp_revision = 0; - uint64_t format_value_revision = 0; + float v0 = 0.0f; + float v1 = 0.0f; + std::int64_t t0 = 0; // nanoseconds + std::int64_t t1 = 0; // nanoseconds + Size_2i viewport_size; + double adjusted_reserved_height = 0.0; + double adjusted_preview_height = 0.0; + double adjusted_font_size_in_pixels = 0.0; + double vbar_width_pixels = 0.0; + uint64_t font_metrics_key = 0; + uint64_t config_revision = 0; + uint64_t format_timestamp_revision = 0; + uint64_t format_value_revision = 0; [[nodiscard]] bool operator==(const layout_cache_key_t& other) const noexcept { diff --git a/include/vnm_plot/qt/plot_interaction_item.h b/include/vnm_plot/qt/plot_interaction_item.h index bd09c12f..2c0fd140 100644 --- a/include/vnm_plot/qt/plot_interaction_item.h +++ b/include/vnm_plot/qt/plot_interaction_item.h @@ -77,33 +77,34 @@ class Plot_interaction_item : public QQuickItem void apply_zoom_step(std::chrono::steady_clock::time_point now); Plot_widget* time_target_widget() const; - Plot_widget* m_plot_widget = nullptr; - Plot_widget* m_time_plot_widget = nullptr; - bool m_interaction_enabled = true; - bool m_pin_time_pivot_to_right = false; - - bool m_dragging = false; - bool m_dragging_preview = false; - bool m_click_candidate = false; - qreal m_press_x = 0; - qreal m_press_y = 0; - qreal m_drag_start_x = 0; - qreal m_drag_last_y = 0; - qreal m_drag_preview_start = 0; - - qreal m_zoom_vel_t = 0.0; - qreal m_zoom_vel_v = 0.0; - qreal m_last_pivot_x = 0.5; - qreal m_last_pivot_y = 0.5; - QBasicTimer m_zoom_timer; - std::chrono::steady_clock::time_point m_last_zoom_step_time; - - static constexpr qreal k_zoom_friction = 0.75; - static constexpr qreal k_zoom_impulse_per_step = 1.0; - static constexpr qreal k_zoom_max_vel = 5.0; - static constexpr qreal k_zoom_per_notch = 1.05; + Plot_widget* m_plot_widget = nullptr; + Plot_widget* m_time_plot_widget = nullptr; + bool m_interaction_enabled = true; + bool m_pin_time_pivot_to_right = false; + + bool m_dragging = false; + bool m_dragging_preview = false; + bool m_click_candidate = false; + qreal m_press_x = 0; + qreal m_press_y = 0; + qreal m_drag_start_x = 0; + qreal m_drag_last_y = 0; + qreal m_drag_preview_start = 0; + + qreal m_zoom_vel_t = 0.0; + qreal m_zoom_vel_v = 0.0; + qreal m_last_pivot_x = 0.5; + qreal m_last_pivot_y = 0.5; + QBasicTimer m_zoom_timer; + std::chrono::steady_clock::time_point + m_last_zoom_step_time; + + static constexpr qreal k_zoom_friction = 0.75; + static constexpr qreal k_zoom_impulse_per_step = 1.0; + static constexpr qreal k_zoom_max_vel = 5.0; + static constexpr qreal k_zoom_per_notch = 1.05; static constexpr qreal k_click_move_tolerance_px = 4.0; - static constexpr int k_zoom_timer_interval_ms = 16; + static constexpr int k_zoom_timer_interval_ms = 16; }; } // namespace vnm::plot diff --git a/include/vnm_plot/qt/plot_time_axis.h b/include/vnm_plot/qt/plot_time_axis.h index 18f2a7d0..9ac02dcd 100644 --- a/include/vnm_plot/qt/plot_time_axis.h +++ b/include/vnm_plot/qt/plot_time_axis.h @@ -137,25 +137,26 @@ class Plot_time_axis : public QObject bool t_available_min_initialized, bool t_available_max_initialized); - qint64 m_t_min = 0; - qint64 m_t_max = 0; - qint64 m_t_available_min = 0; - qint64 m_t_available_max = 0; - - bool m_t_min_initialized = false; - bool m_t_max_initialized = false; - bool m_t_available_min_initialized = false; - bool m_t_available_max_initialized = false; - - bool m_sync_vbar_width = false; - std::unordered_map m_vbar_width_by_owner; - double m_shared_vbar_width_px = 0.0; - - QObject* m_indicator_owner = nullptr; - bool m_indicator_active = false; - qint64 m_indicator_t = 0; - bool m_indicator_x_norm_valid = false; - double m_indicator_x_norm = 0.0; + qint64 m_t_min = 0; + qint64 m_t_max = 0; + qint64 m_t_available_min = 0; + qint64 m_t_available_max = 0; + + bool m_t_min_initialized = false; + bool m_t_max_initialized = false; + bool m_t_available_min_initialized = false; + bool m_t_available_max_initialized = false; + + bool m_sync_vbar_width = false; + std::unordered_map + m_vbar_width_by_owner; + double m_shared_vbar_width_px = 0.0; + + QObject* m_indicator_owner = nullptr; + bool m_indicator_active = false; + qint64 m_indicator_t = 0; + bool m_indicator_x_norm_valid = false; + double m_indicator_x_norm = 0.0; }; } // namespace vnm::plot diff --git a/include/vnm_plot/qt/plot_widget.h b/include/vnm_plot/qt/plot_widget.h index 1ed563a9..22f6f465 100644 --- a/include/vnm_plot/qt/plot_widget.h +++ b/include/vnm_plot/qt/plot_widget.h @@ -273,49 +273,50 @@ class Plot_widget : public QQuickRhiItem // Prefer holding only one lock at a time. // Configuration - Plot_config m_config; - std::atomic m_config_revision{0}; - mutable std::shared_mutex m_config_mutex; + Plot_config m_config; + std::atomic m_config_revision{0}; + mutable std::shared_mutex m_config_mutex; // Data configuration - data_config_t m_data_cfg; - mutable std::shared_mutex m_data_cfg_mutex; + data_config_t m_data_cfg; + mutable std::shared_mutex m_data_cfg_mutex; // Series data - std::map> m_series; - mutable std::shared_mutex m_series_mutex; + std::map> + m_series; + mutable std::shared_mutex m_series_mutex; // UI state - std::atomic m_v_auto{true}; - std::atomic m_visible_info_flags{k_visible_info_all}; - std::atomic m_view_state_reset_requested{false}; - mutable std::atomic m_rendered_v_min{0.0f}; - mutable std::atomic m_rendered_v_max{1.0f}; - mutable std::atomic m_rendered_v_range_valid{false}; + std::atomic m_v_auto{true}; + std::atomic m_visible_info_flags{k_visible_info_all}; + std::atomic m_view_state_reset_requested{false}; + mutable std::atomic m_rendered_v_min{0.0f}; + mutable std::atomic m_rendered_v_max{1.0f}; + mutable std::atomic m_rendered_v_range_valid{false}; // Rendered time range cached for QML/tooltips, in int64 nanoseconds. - mutable std::atomic m_rendered_t_min{0}; - mutable std::atomic m_rendered_t_max{1}; - mutable std::atomic m_rendered_t_range_valid{false}; - std::atomic m_vbar_width_px{0.0}; - QBasicTimer m_vbar_width_timer; - QElapsedTimer m_vbar_width_anim_elapsed; - double m_vbar_width_anim_start_px = 0.0; - double m_vbar_width_anim_target_px = 0.0; - std::atomic m_sync_vbar_width_active{false}; - - double m_preview_height = 0.0; - double m_preview_height_target = 0.0; - double m_adjusted_preview_height = 0.0; - bool m_preview_height_initialized = false; - float m_relative_preview_height = 0.0f; - double m_preview_height_min = 0.0; - double m_preview_height_max = 0.0; - bool m_show_if_calculated_preview_height_below_min = true; - int m_preview_height_steps = 0; - - double m_adjusted_font_size = 12.0; - double m_base_label_height = 14.0; - double m_scaling_factor = 1.0; + mutable std::atomic m_rendered_t_min{0}; + mutable std::atomic m_rendered_t_max{1}; + mutable std::atomic m_rendered_t_range_valid{false}; + std::atomic m_vbar_width_px{0.0}; + QBasicTimer m_vbar_width_timer; + QElapsedTimer m_vbar_width_anim_elapsed; + double m_vbar_width_anim_start_px = 0.0; + double m_vbar_width_anim_target_px = 0.0; + std::atomic m_sync_vbar_width_active{false}; + + double m_preview_height = 0.0; + double m_preview_height_target = 0.0; + double m_adjusted_preview_height = 0.0; + bool m_preview_height_initialized = false; + float m_relative_preview_height = 0.0f; + double m_preview_height_min = 0.0; + double m_preview_height_max = 0.0; + bool m_show_if_calculated_preview_height_below_min = true; + int m_preview_height_steps = 0; + + double m_adjusted_font_size = 12.0; + double m_base_label_height = 14.0; + double m_scaling_factor = 1.0; void recalculate_preview_height(); double compute_preview_height_px(double widget_height_px) const; @@ -351,12 +352,12 @@ class Plot_widget : public QQuickRhiItem void apply_vbar_width_target(double px, bool publish_shared = false); void publish_measured_vbar_width(double px) const; - QPointer m_time_axis; - QMetaObject::Connection m_time_axis_connection; - QMetaObject::Connection m_time_axis_destroyed_connection; - QMetaObject::Connection m_time_axis_vbar_connection; - QMetaObject::Connection m_time_axis_sync_vbar_connection; - QMetaObject::Connection m_window_screen_connection; + QPointer m_time_axis; + QMetaObject::Connection m_time_axis_connection; + QMetaObject::Connection m_time_axis_destroyed_connection; + QMetaObject::Connection m_time_axis_vbar_connection; + QMetaObject::Connection m_time_axis_sync_vbar_connection; + QMetaObject::Connection m_window_screen_connection; }; } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/asset_loader.h b/include/vnm_plot/rhi/asset_loader.h index 6bc3b191..39cd2697 100644 --- a/include/vnm_plot/rhi/asset_loader.h +++ b/include/vnm_plot/rhi/asset_loader.h @@ -49,8 +49,8 @@ class Asset_loader bool load_file(std::string_view path, Byte_buffer& out) const; void log_error(const std::string& message) const; - Log_callback m_log_callback; - std::string m_override_dir; + Log_callback m_log_callback; + std::string m_override_dir; // Map from asset name to embedded data view std::unordered_map m_embedded; diff --git a/include/vnm_plot/rhi/font_renderer.h b/include/vnm_plot/rhi/font_renderer.h index a1ca38e3..57f8138e 100644 --- a/include/vnm_plot/rhi/font_renderer.h +++ b/include/vnm_plot/rhi/font_renderer.h @@ -24,24 +24,24 @@ class Asset_loader; struct text_scissor_t { - bool enabled = false; - int x = 0; - int y = 0; - int width = 0; - int height = 0; + bool enabled = false; + int x = 0; + int y = 0; + int width = 0; + int height = 0; }; struct text_shadow_t { - glm::vec4 color = glm::vec4(0.f); - float radius_px = 0.0f; + glm::vec4 color = glm::vec4(0.f); + float radius_px = 0.0f; }; struct text_lcd_t { text_lcd_resolved_subpixel_order_t subpixel_order = text_lcd_resolved_subpixel_order_t::NONE; - glm::vec4 background_color = glm::vec4(0.f); + glm::vec4 background_color = glm::vec4(0.f); }; // ----------------------------------------------------------------------------- diff --git a/include/vnm_plot/rhi/frame_context.h b/include/vnm_plot/rhi/frame_context.h index 8910a577..19642cb6 100644 --- a/include/vnm_plot/rhi/frame_context.h +++ b/include/vnm_plot/rhi/frame_context.h @@ -19,51 +19,51 @@ struct frame_context_t { const frame_layout_result_t& layout; - float v0 = 0.0f; - float v1 = 1.0f; - float preview_v0 = 0.0f; - float preview_v1 = 0.0f; + float v0 = 0.0f; + float v1 = 1.0f; + float preview_v0 = 0.0f; + float preview_v1 = 0.0f; // Timestamps are int64_t nanoseconds (API convention). - std::int64_t t0 = 0; - std::int64_t t1 = 1; + std::int64_t t0 = 0; + std::int64_t t1 = 1; - std::int64_t t_available_min = 0; - std::int64_t t_available_max = 1; + std::int64_t t_available_min = 0; + std::int64_t t_available_max = 1; - int win_w = 0; - int win_h = 0; + int win_w = 0; + int win_h = 0; glm::mat4 pmv{1.0f}; - double adjusted_font_px = 10.0; - double base_label_height_px = 14.0; - double adjusted_reserved_height = 0.0; - double adjusted_preview_height = 0.0; + double adjusted_font_px = 10.0; + double base_label_height_px = 14.0; + double adjusted_reserved_height = 0.0; + double adjusted_preview_height = 0.0; - int visible_info_flags = k_visible_info_none; - bool dark_mode = false; - glm::vec4 plot_body_background = glm::vec4(0.f, 0.f, 0.f, 1.f); + int visible_info_flags = k_visible_info_none; + bool dark_mode = false; + glm::vec4 plot_body_background = glm::vec4(0.f, 0.f, 0.f, 1.f); // With config, this is the host-resolved AUTO order; explicit requests in // config still take precedence. Without config, it is a manual frame order. text_lcd_resolved_subpixel_order_t text_lcd_subpixel_order = text_lcd_resolved_subpixel_order_t::NONE; - const Plot_config* config = nullptr; + const Plot_config* config = nullptr; // RHI handles for the active frame. The renderer routes uploads through // the RHI resource-update batch and records draws through `cb`. - QRhi* rhi = nullptr; - QRhiCommandBuffer* cb = nullptr; + QRhi* rhi = nullptr; + QRhiCommandBuffer* cb = nullptr; // Render target the host already opened a pass on. The renderer reads // the render-pass descriptor and sample count off it when building // graphics-pipeline state objects. - QRhiRenderTarget* render_target = nullptr; + QRhiRenderTarget* render_target = nullptr; // Resource-update batch the host hands the renderer to fill. The host // owns its lifetime and submits it via beginPass's 4th argument; the // renderer must NOT call cb->resourceUpdate(batch) itself, because that // call is illegal once the host's render pass is open. - QRhiResourceUpdateBatch* rhi_updates = nullptr; + QRhiResourceUpdateBatch* rhi_updates = nullptr; }; } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/primitive_renderer.h b/include/vnm_plot/rhi/primitive_renderer.h index b9a68806..129b17d1 100644 --- a/include/vnm_plot/rhi/primitive_renderer.h +++ b/include/vnm_plot/rhi/primitive_renderer.h @@ -91,20 +91,21 @@ class Primitive_renderer private: struct rect_vertex_t { - glm::vec4 color; - glm::vec4 rect_coords; // x0, y0, x1, y1 + glm::vec4 color; + glm::vec4 rect_coords; // x0, y0, x1, y1 }; std::vector m_cpu_buffer; - vnm::plot::Profiler* m_profiler = nullptr; - std::function m_log_error; + vnm::plot::Profiler* m_profiler = nullptr; + std::function + m_log_error; // RHI-side state. Pipelines, UBO ring buffer, vertex buffer for rects, // a static unit-quad VBO for grid, and the per-frame draw-op plan. Lives // out-of-line in primitive_renderer.cpp so the public header stays free // of QRhi includes. struct rhi_state_t; - std::unique_ptr m_rhi_state; + std::unique_ptr m_rhi_state; // RHI pipeline and resource builders. Defined out-of-line in the .cpp so // they can touch QRhi types without dragging them into the public header. @@ -134,7 +135,7 @@ class Primitive_renderer static void rhi_reset_frame_plan( rhi_state_t& rhi_state); - static constexpr int k_rect_initial_quads = 256; + static constexpr int k_rect_initial_quads = 256; }; } // namespace vnm::plot diff --git a/include/vnm_plot/rhi/qrhi_series_layer.h b/include/vnm_plot/rhi/qrhi_series_layer.h index e7b01736..83642dd0 100644 --- a/include/vnm_plot/rhi/qrhi_series_layer.h +++ b/include/vnm_plot/rhi/qrhi_series_layer.h @@ -23,84 +23,84 @@ class Asset_loader; struct series_view_uniform_std140_t { - float pmv[16]; - float color[4]; - float t_min; - float t_max; - float v_min; - float v_max; - float width; - float height; - float y_offset; - float win_h; - std::int32_t framebuffer_y_up; - float pad0[3]; + float pmv[16]; + float color[4]; + float t_min; + float t_max; + float v_min; + float v_max; + float width; + float height; + float y_offset; + float win_h; + std::int32_t framebuffer_y_up; + float pad0[3]; }; struct qrhi_series_sample_buffer_layout_t { // Each lane is a 32-bit float. `t_rel_seconds` is relative to // qrhi_series_sample_buffer_t::t_origin_ns. - std::size_t stride_bytes = 0; - std::size_t t_rel_seconds_offset = 0; - std::size_t value_offset = 0; - std::size_t range_min_offset = 0; - std::size_t range_max_offset = 0; + std::size_t stride_bytes = 0; + std::size_t t_rel_seconds_offset = 0; + std::size_t value_offset = 0; + std::size_t range_min_offset = 0; + std::size_t range_max_offset = 0; }; struct qrhi_series_sample_buffer_t { - QRhiBuffer* buffer = nullptr; + QRhiBuffer* buffer = nullptr; - std::size_t first_sample = 0; - std::size_t sample_count = 0; + std::size_t first_sample = 0; + std::size_t sample_count = 0; - std::size_t source_first = 0; - std::size_t source_count = 0; - std::size_t synthetic_hold_count = 0; + std::size_t source_first = 0; + std::size_t source_count = 0; + std::size_t synthetic_hold_count = 0; - std::int64_t t_origin_ns = 0; - std::int64_t t_min_ns = 0; - std::int64_t t_max_ns = 0; + std::int64_t t_origin_ns = 0; + std::int64_t t_min_ns = 0; + std::int64_t t_max_ns = 0; - float v_min = 0.0f; - float v_max = 1.0f; + float v_min = 0.0f; + float v_max = 1.0f; - qrhi_series_sample_buffer_layout_t layout; + qrhi_series_sample_buffer_layout_t layout; }; struct qrhi_series_prepare_context_t { - QRhi* rhi = nullptr; - QRhiRenderTarget* render_target = nullptr; - QRhiResourceUpdateBatch* updates = nullptr; - Asset_loader* asset_loader = nullptr; + QRhi* rhi = nullptr; + QRhiRenderTarget* render_target = nullptr; + QRhiResourceUpdateBatch* updates = nullptr; + Asset_loader* asset_loader = nullptr; - const frame_context_t* frame = nullptr; - const series_data_t* series = nullptr; - sample_window_t window; + const frame_context_t* frame = nullptr; + const series_data_t* series = nullptr; + sample_window_t window; - const series_view_uniform_std140_t* view_uniform = nullptr; - QRhiBuffer* view_ubo = nullptr; + const series_view_uniform_std140_t* view_uniform = nullptr; + QRhiBuffer* view_ubo = nullptr; // Borrowed compact sample VBO for this window. Layers may copy this // descriptor into frame-local state for the matching record() call, but // must not retain the buffer pointer beyond the current frame/view. - qrhi_series_sample_buffer_t sample_buffer; + qrhi_series_sample_buffer_t sample_buffer; - bool resources_changed = false; + bool resources_changed = false; }; struct qrhi_series_record_context_t { - QRhiCommandBuffer* cb = nullptr; - QRhiRenderTarget* render_target = nullptr; + QRhiCommandBuffer* cb = nullptr; + QRhiRenderTarget* render_target = nullptr; - const frame_context_t* frame = nullptr; - const series_data_t* series = nullptr; - sample_window_t window; + const frame_context_t* frame = nullptr; + const series_data_t* series = nullptr; + sample_window_t window; - QRhiBuffer* view_ubo = nullptr; + QRhiBuffer* view_ubo = nullptr; }; class Qrhi_series_layer_state diff --git a/include/vnm_plot/rhi/series_renderer.h b/include/vnm_plot/rhi/series_renderer.h index 9573089e..0f351380 100644 --- a/include/vnm_plot/rhi/series_renderer.h +++ b/include/vnm_plot/rhi/series_renderer.h @@ -94,8 +94,8 @@ class Series_renderer { struct line_draw_span_t { - std::size_t gpu_first = 0; - std::size_t gpu_count = 0; + std::size_t gpu_first = 0; + std::size_t gpu_count = 0; std::size_t line_first = 0; std::size_t line_count = 0; }; @@ -106,26 +106,26 @@ class Series_renderer // Renderer-owned scratch buffer for VBO uploads. Holds the planned // visible gpu_sample_t values rebased against the active origin. // Reused across uploads to avoid reallocation. - std::vector staging; - std::size_t last_staged_sample_count = 0; - std::size_t last_sample_upload_bytes = 0; - std::size_t last_sample_upload_count = 0; - std::size_t last_primitive_prepare_count = 0; - std::size_t last_line_window_sample_count = 0; - std::size_t last_recorded_line_span_count = 0; - std::size_t last_recorded_line_segment_count = 0; - std::size_t last_recorded_area_span_count = 0; - std::size_t last_recorded_area_segment_count = 0; - std::size_t last_recorded_dot_sample_count = 0; - std::int64_t last_prepared_t_min_ns = 0; - std::int64_t last_prepared_t_max_ns = 0; - double last_prepared_width_px = 0.0; - std::size_t last_vbo_generation = 0; - QRhiBuffer* last_sample_buffer = nullptr; + std::vector staging; + std::size_t last_staged_sample_count = 0; + std::size_t last_sample_upload_bytes = 0; + std::size_t last_sample_upload_count = 0; + std::size_t last_primitive_prepare_count = 0; + std::size_t last_line_window_sample_count = 0; + std::size_t last_recorded_line_span_count = 0; + std::size_t last_recorded_line_segment_count = 0; + std::size_t last_recorded_area_span_count = 0; + std::size_t last_recorded_area_segment_count = 0; + std::size_t last_recorded_dot_sample_count = 0; + std::int64_t last_prepared_t_min_ns = 0; + std::int64_t last_prepared_t_max_ns = 0; + double last_prepared_width_px = 0.0; + std::size_t last_vbo_generation = 0; + QRhiBuffer* last_sample_buffer = nullptr; detail::access_dispatch_kind_t last_sample_access_dispatch_kind = detail::access_dispatch_kind_t::NONE; - std::vector line_window_staging; - std::vector line_draw_spans; + std::vector line_window_staging; + std::vector line_draw_spans; // Per-view RHI resources. Defined out-of-line in series_renderer.cpp // where QRhiBuffer is complete; the public header only sees the @@ -135,8 +135,8 @@ class Series_renderer struct rhi_buffers_t; std::unique_ptr rhi; - std::size_t rhi_vbo_capacity_bytes = 0; - std::size_t rhi_line_window_vbo_capacity_bytes = 0; + std::size_t rhi_vbo_capacity_bytes = 0; + std::size_t rhi_line_window_vbo_capacity_bytes = 0; vbo_view_state_t(); ~vbo_view_state_t(); @@ -150,9 +150,10 @@ class Series_renderer struct vbo_state_t { - vbo_view_state_t main_view; - vbo_view_state_t preview_view; - std::unique_ptr snapshot_cache; + vbo_view_state_t main_view; + vbo_view_state_t preview_view; + std::unique_ptr + snapshot_cache; vbo_state_t(); ~vbo_state_t(); @@ -168,33 +169,34 @@ class Series_renderer // own state (vbo_state) is owned by m_vbo_states. struct series_draw_state_t { - int id = 0; - std::size_t series_order = 0; - std::shared_ptr series; - vbo_state_t* vbo_state = nullptr; - Series_view_plan main_plan; - Series_view_plan preview_plan; - bool has_preview = false; + int id = 0; + std::size_t series_order = 0; + std::shared_ptr + series; + vbo_state_t* vbo_state = nullptr; + Series_view_plan main_plan; + Series_view_plan preview_plan; + bool has_preview = false; }; - Asset_loader* m_asset_loader = nullptr; - std::unordered_map m_vbo_states; + Asset_loader* m_asset_loader = nullptr; + std::unordered_map m_vbo_states; // Consolidated once-per-series error log deduplication. // Key encodes (series_id, error_category) as uint64_t. - std::unordered_set m_logged_errors; + std::unordered_set m_logged_errors; // Private test instrumentation for the QRhi prepare/render split. - std::vector m_last_recorded_draw_z_orders; - std::vector m_last_recorded_draw_styles; - std::vector m_last_recorded_draw_series_ids; - std::vector m_last_recorded_draw_view_kinds; - std::size_t m_last_qrhi_layer_cache_size = 0; + std::vector m_last_recorded_draw_z_orders; + std::vector m_last_recorded_draw_styles; + std::vector m_last_recorded_draw_series_ids; + std::vector m_last_recorded_draw_view_kinds; + std::size_t m_last_qrhi_layer_cache_size = 0; // The full implementation sits in series_renderer.cpp where the QRhi // types are complete. struct rhi_state_t; - std::unique_ptr m_rhi_state; + std::unique_ptr m_rhi_state; - uint64_t m_frame_id = 0; // Monotonic frame counter for snapshot caching + uint64_t m_frame_id = 0; // Monotonic frame counter for snapshot caching void clear_frame_snapshot_caches(); diff --git a/include/vnm_plot/rhi/text_renderer.h b/include/vnm_plot/rhi/text_renderer.h index 78c30292..798841bc 100644 --- a/include/vnm_plot/rhi/text_renderer.h +++ b/include/vnm_plot/rhi/text_renderer.h @@ -43,9 +43,9 @@ class Text_renderer struct label_fade_state_t { - float alpha = 0.0f; - int direction = 0; // +1 fade-in, -1 fade-out, 0 steady - std::string text; + float alpha = 0.0f; + int direction = 0; // +1 fade-in, -1 fade-out, 0 steady + std::string text; }; template @@ -53,29 +53,29 @@ class Text_renderer { using key_type = Key; - std::map states; - std::chrono::steady_clock::time_point last_update{}; - bool initialized = false; + std::map states; + std::chrono::steady_clock::time_point last_update{}; + bool initialized = false; }; using vertical_axis_fade_tracker_t = axis_fade_tracker_t; using horizontal_axis_fade_tracker_t = axis_fade_tracker_t; private: - Font_renderer* m_fonts = nullptr; + Font_renderer* m_fonts = nullptr; // Cached timestamps to avoid repeated allocation/formatting (int64 ns). - static constexpr std::int64_t k_invalid_cached_ts = std::numeric_limits::min(); - std::int64_t m_last_t0 = k_invalid_cached_ts; - std::int64_t m_last_t1 = k_invalid_cached_ts; - std::uint64_t m_last_timestamp_revision = 0; - bool m_last_subsecond = false; - std::string m_cached_from_ts; - std::string m_cached_to_ts; + static constexpr std::int64_t k_invalid_cached_ts = std::numeric_limits::min(); + std::int64_t m_last_t0 = k_invalid_cached_ts; + std::int64_t m_last_t1 = k_invalid_cached_ts; + std::uint64_t m_last_timestamp_revision = 0; + bool m_last_subsecond = false; + std::string m_cached_from_ts; + std::string m_cached_to_ts; - static constexpr float k_label_fade_duration_ms = 250.0f; + static constexpr float k_label_fade_duration_ms = 250.0f; - vertical_axis_fade_tracker_t m_vertical_fade; + vertical_axis_fade_tracker_t m_vertical_fade; horizontal_axis_fade_tracker_t m_horizontal_fade; bool render_axis_labels( diff --git a/src/core/auto_range_resolver.h b/src/core/auto_range_resolver.h index 2d0c80e2..a0df28be 100644 --- a/src/core/auto_range_resolver.h +++ b/src/core/auto_range_resolver.h @@ -12,29 +12,29 @@ namespace vnm::plot::detail { struct auto_range_cache_entry_t { - const void* source_identity = nullptr; - const Data_access_policy* access_identity = nullptr; - access_policy_cache_key_t access_key; - std::uint64_t layout_key = 0; - std::uint64_t semantics_value = 0; - std::uint64_t semantics_revision = 0; - bool semantics_conservative = true; - std::size_t lod_level = 0; - std::int64_t t_min_ns = 0; - std::int64_t t_max_ns = 0; - Series_interpolation interpolation = Series_interpolation::LINEAR; - Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; - Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - std::uint64_t sequence = 0; - value_range_t range{}; - Data_query_status status = Data_query_status::EMPTY; - bool valid = false; + const void* source_identity = nullptr; + const Data_access_policy* access_identity = nullptr; + access_policy_cache_key_t access_key; + std::uint64_t layout_key = 0; + std::uint64_t semantics_value = 0; + std::uint64_t semantics_revision = 0; + bool semantics_conservative = true; + std::size_t lod_level = 0; + std::int64_t t_min_ns = 0; + std::int64_t t_max_ns = 0; + Series_interpolation interpolation = Series_interpolation::LINEAR; + Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; + Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; + std::uint64_t sequence = 0; + value_range_t range{}; + Data_query_status status = Data_query_status::EMPTY; + bool valid = false; }; struct auto_range_cache_t { - std::map main_entries; - std::map preview_entries; + std::map main_entries; + std::map preview_entries; }; std::pair resolve_main_v_range( diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 16cc8470..cd3dedcf 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -74,7 +74,7 @@ namespace { struct vertex_buffer_t { // 10 floats per vertex: position, tex bounds, local glyph frame rect - std::vector vertex_data; + std::vector vertex_data; std::vector index_data; }; @@ -87,15 +87,15 @@ constexpr std::size_t k_text_vertex_float_count = 10u; struct rhi_text_vertex_t { - float x = 0.f; - float y = 0.f; - float s_min = 0.f; - float t_min = 0.f; - float s_max = 0.f; - float t_max = 0.f; - float frame_x = 0.f; - float frame_y = 0.f; - float frame_width = 0.f; + float x = 0.f; + float y = 0.f; + float s_min = 0.f; + float t_min = 0.f; + float s_max = 0.f; + float t_max = 0.f; + float frame_x = 0.f; + float frame_y = 0.f; + float frame_width = 0.f; float frame_height = 0.f; }; @@ -137,10 +137,10 @@ static std::mutex s_font_storage_mutex; struct thread_local_font_resources_t { - vertex_buffer_t* m_buffer = nullptr; - int m_pixel_height = 0; - std::uint64_t m_cache_epoch = 0; - msdf_atlas_t m_atlas; + vertex_buffer_t* m_buffer = nullptr; + int m_pixel_height = 0; + std::uint64_t m_cache_epoch = 0; + msdf_atlas_t m_atlas; ~thread_local_font_resources_t() { @@ -166,13 +166,13 @@ std::atomic s_next_cache_epoch{1}; struct cached_font_data_t { - msdf_atlas_t atlas; + msdf_atlas_t atlas; // The requested draw pixel height this cache entry was built for. The atlas // is baked at a (possibly larger) bucket, so this is tracked separately from // atlas.baked_pixel_height and is the cache-map key and disk-file height. - int draw_pixel_height = 0; - std::uint64_t cache_epoch = 0; - std::array font_digest{}; + int draw_pixel_height = 0; + std::uint64_t cache_epoch = 0; + std::array font_digest{}; }; static std::mutex s_cached_fonts_mutex; @@ -790,17 +790,17 @@ using detail::load_qsb; struct Text_block_std140 { - float pmv[16] = {}; - float color[4] = {}; - float shadow_color[4] = {}; - float px_range = 0.f; - float target_width = 0.f; - float target_height = 0.f; - float shadow_radius = 0.f; - float lcd_subpixel_order = 0.f; - std::int32_t framebuffer_y_up = 0; - float padding[2] = {}; - float background_color[4] = {}; + float pmv[16] = {}; + float color[4] = {}; + float shadow_color[4] = {}; + float px_range = 0.f; + float target_width = 0.f; + float target_height = 0.f; + float shadow_radius = 0.f; + float lcd_subpixel_order = 0.f; + std::int32_t framebuffer_y_up = 0; + float padding[2] = {}; + float background_color[4] = {}; }; static_assert(offsetof(Text_block_std140, pmv) == 0, "Text UBO pmv offset"); @@ -819,11 +819,13 @@ constexpr std::uint32_t k_text_ubo_bytes = sizeof(Text_block_std140); struct rhi_text_call_t { - std::unique_ptr ubo; - std::unique_ptr srb; - QRhiBuffer* srb_last_ubo = nullptr; - QRhiTexture* srb_last_texture = nullptr; - QRhiSampler* srb_last_sampler = nullptr; + std::unique_ptr + ubo; + std::unique_ptr + srb; + QRhiBuffer* srb_last_ubo = nullptr; + QRhiTexture* srb_last_texture = nullptr; + QRhiSampler* srb_last_sampler = nullptr; }; enum class rhi_text_pass_t : std::uint8_t @@ -834,38 +836,39 @@ enum class rhi_text_pass_t : std::uint8_t struct rhi_text_draw_op_t { - std::size_t call_index = 0; - quint32 index_start = 0; - quint32 index_count = 0; - text_scissor_t scissor; - rhi_text_pass_t pass = rhi_text_pass_t::FOREGROUND; + std::size_t call_index = 0; + quint32 index_start = 0; + quint32 index_count = 0; + text_scissor_t scissor; + rhi_text_pass_t pass = rhi_text_pass_t::FOREGROUND; }; struct rhi_text_state_t { - QRhi* last_rhi = nullptr; - - std::unique_ptr atlas_texture; - std::unique_ptr sampler; - int atlas_size = 0; - std::uint64_t uploaded_cache_epoch = 0; - - std::unique_ptr vbo; - std::unique_ptr ibo; - std::size_t vbo_capacity_bytes = 0; - std::size_t ibo_capacity_bytes = 0; - - std::vector calls; - std::vector ops; - std::size_t call_used = 0; - - std::unique_ptr pipeline; - QRhiRenderPassDescriptor* pipeline_rpd = nullptr; - int pipeline_samples = 0; - - QShader vert; - QShader frag; - bool shaders_loaded = false; + QRhi* last_rhi = nullptr; + + std::unique_ptr atlas_texture; + std::unique_ptr sampler; + int atlas_size = 0; + std::uint64_t uploaded_cache_epoch = 0; + + std::unique_ptr vbo; + std::unique_ptr ibo; + std::size_t vbo_capacity_bytes = 0; + std::size_t ibo_capacity_bytes = 0; + + std::vector calls; + std::vector ops; + std::size_t call_used = 0; + + std::unique_ptr + pipeline; + QRhiRenderPassDescriptor* pipeline_rpd = nullptr; + int pipeline_samples = 0; + + QShader vert; + QShader frag; + bool shaders_loaded = false; }; } // anonymous namespace @@ -873,16 +876,16 @@ struct rhi_text_state_t // --- PIMPL Definition --- struct Font_renderer::impl_t { - thread_local_font_resources_t* m_resources = nullptr; - std::shared_ptr m_font_cache; - int m_metric_pixel_height = 0; - std::function m_log_error; - std::function m_log_debug; - bool m_rhi_batch_active = false; - std::vector m_rhi_vertex_data; - std::vector m_rhi_index_data; - std::vector m_rhi_frame_vertex_data; - std::vector m_rhi_frame_index_data; + thread_local_font_resources_t* m_resources = nullptr; + std::shared_ptr m_font_cache; + int m_metric_pixel_height = 0; + std::function m_log_error; + std::function m_log_debug; + bool m_rhi_batch_active = false; + std::vector m_rhi_vertex_data; + std::vector m_rhi_index_data; + std::vector m_rhi_frame_vertex_data; + std::vector m_rhi_frame_index_data; rhi_text_state_t m_rhi; diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 51674d84..9590cfc3 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -90,8 +90,8 @@ std::int64_t saturating_seconds_to_ns(double seconds) noexcept struct Cached_label { - std::string bytes; - float width = 0.0f; + std::string bytes; + float width = 0.0f; }; // Thread-local timestamp label cache @@ -180,13 +180,13 @@ class Timestamp_label_cache private: struct Context_key { - uint64_t step_bits = 0; - uint64_t range_bits = 0; - uint32_t monospace_bits = 0; - uint8_t monospace_reliable = 0; - uint64_t measure_key = 0; - uint64_t font_size_bits = 0; - size_t format_signature = 0; + uint64_t step_bits = 0; + uint64_t range_bits = 0; + uint32_t monospace_bits = 0; + uint8_t monospace_reliable = 0; + uint64_t measure_key = 0; + uint64_t font_size_bits = 0; + size_t format_signature = 0; friend bool operator==(const Context_key& lhs, const Context_key& rhs) noexcept { @@ -224,12 +224,12 @@ class Timestamp_label_cache std::unordered_map labels; }; - static constexpr size_t k_max_entries = 4096; - static constexpr size_t k_max_contexts = 8; + static constexpr size_t k_max_entries = 4096; + static constexpr size_t k_max_contexts = 8; std::unordered_map m_contexts; std::vector m_lru; - Context_data* m_active = nullptr; + Context_data* m_active = nullptr; }; // Format signature cache @@ -289,11 +289,11 @@ class Format_signature_cache private: struct Key { - uint64_t step_bits = 0; - uint32_t coverage_bucket = 0; - uintptr_t formatter_identity = 0; - size_t formatter_type_hash = 0; - uint64_t formatter_revision = 0; + uint64_t step_bits = 0; + uint32_t coverage_bucket = 0; + uintptr_t formatter_identity = 0; + size_t formatter_type_hash = 0; + uint64_t formatter_revision = 0; friend bool operator==(const Key& lhs, const Key& rhs) noexcept { @@ -855,10 +855,10 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par struct cand { - double t; - float x0; - float x1; - float x_anchor; + double t; + float x0; + float x1; + float x_anchor; }; std::vector candidates; float right_vis = 0.0f; diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index 8b8cc4f5..be6e02a9 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -56,15 +56,15 @@ static_assert(sizeof(Rect_block_std140) == 64, // Verified against `qsb --dump shaders/qsb/grid_quad.frag.qsb`. struct Grid_block_std140 { - float plot_size_px[2]; // offset 0 - float region_origin_px[2]; // offset 8 - float grid_color[4]; // offset 16 - int32_t v_count; // offset 32 - int32_t t_count; // offset 36 - int32_t framebuffer_y_up; // offset 40 - float win_h; // offset 44 - float v_levels[32][4]; // offset 48 (32 * 16 = 512 bytes) - float t_levels[32][4]; // offset 560 (32 * 16 = 512 bytes) + float plot_size_px[2]; // offset 0 + float region_origin_px[2]; // offset 8 + float grid_color[4]; // offset 16 + int32_t v_count; // offset 32 + int32_t t_count; // offset 36 + int32_t framebuffer_y_up; // offset 40 + float win_h; // offset 44 + float v_levels[32][4]; // offset 48 (32 * 16 = 512 bytes) + float t_levels[32][4]; // offset 560 (32 * 16 = 512 bytes) }; static_assert(offsetof(Grid_block_std140, plot_size_px) == 0, "plot_size_px offset"); static_assert(offsetof(Grid_block_std140, region_origin_px) == 8, "region_origin_px offset"); @@ -116,20 +116,20 @@ struct Primitive_renderer::rhi_state_t struct grid_call_t { - std::unique_ptr ubo; - std::unique_ptr srb; - QRhiBuffer* srb_last_ubo = nullptr; + std::unique_ptr ubo; + std::unique_ptr srb; + QRhiBuffer* srb_last_ubo = nullptr; }; - enum class op_kind_t : uint8_t { RECT, GRID }; + enum class op_kind_t : uint8_t{ RECT, GRID }; struct draw_op_t { - op_kind_t kind; + op_kind_t kind; // Index into rect_calls / grid_calls depending on kind. Stored as // size_t because each op references exactly one preallocated call // resource; the indices are stable for the duration of the frame. - std::size_t resource_index; + std::size_t resource_index; // For RECT: number of instances (== quads) in vbo. // For GRID: scissor rectangle in QRhi's bottom-left coordinates. union @@ -145,42 +145,42 @@ struct Primitive_renderer::rhi_state_t }; }; - std::vector rect_calls; - std::vector grid_calls; - std::vector ops; - std::size_t rect_used = 0; - std::size_t grid_used = 0; + std::vector rect_calls; + std::vector grid_calls; + std::vector ops; + std::size_t rect_used = 0; + std::size_t grid_used = 0; // Position in `ops` where the next record_draws() call should start // playback. Lets the host interleave multiple record_draws() invocations // around a series.render() call so chrome paints both behind and in // front of the data series in a single frame. - std::size_t record_cursor = 0; + std::size_t record_cursor = 0; // Cached pipelines keyed only by primitive kind: the descriptor depends // on shader stages, vertex layout, blend, and sample count. Per-call // buffer handles ride the SRB on each draw. - std::unique_ptr rect_pipeline; - std::unique_ptr grid_pipeline; - QRhiRenderPassDescriptor* rect_pipeline_rpd = nullptr; - int rect_pipeline_samples = 0; - QRhiRenderPassDescriptor* grid_pipeline_rpd = nullptr; - int grid_pipeline_samples = 0; + std::unique_ptr rect_pipeline; + std::unique_ptr grid_pipeline; + QRhiRenderPassDescriptor* rect_pipeline_rpd = nullptr; + int rect_pipeline_samples = 0; + QRhiRenderPassDescriptor* grid_pipeline_rpd = nullptr; + int grid_pipeline_samples = 0; // Static unit-quad VBO consumed by the grid pipeline. Allocated once on // first prepare and reused forever; the same four vertices feed every // grid draw (the fragment shader resolves region clipping itself). - std::unique_ptr grid_quad_vbo; + std::unique_ptr grid_quad_vbo; - QShader rect_vert; - QShader rect_frag; - QShader grid_vert; - QShader grid_frag; - bool shaders_loaded = false; + QShader rect_vert; + QShader rect_frag; + QShader grid_vert; + QShader grid_frag; + bool shaders_loaded = false; // Last QRhi seen on the prepare path. A backend swap (rare; tests / host // teardown) invalidates every cached buffer and pipeline because they // belong to the previous QRhi instance. - QRhi* last_rhi = nullptr; + QRhi* last_rhi = nullptr; }; Primitive_renderer::Primitive_renderer() diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index 5c51d127..feb7b0b2 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -211,13 +211,13 @@ inline bool ensure_dynamic_ubo( // distinct binding+attribute set. struct alpha_blended_pipeline_desc_t { - QShader vert; - QShader frag; - QRhiVertexInputLayout vlayout; - quint32 ubo_bytes = 0; + QShader vert; + QShader frag; + QRhiVertexInputLayout vlayout; + quint32 ubo_bytes = 0; QRhiShaderResourceBinding::StageFlags ubo_stages = QRhiShaderResourceBinding::VertexStage; - QRhiGraphicsPipeline::Flags flags = {}; + QRhiGraphicsPipeline::Flags flags = {}; }; // Builds a graphics pipeline with the standard vnm_plot alpha blend and a diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index b080e5c7..c5e9be36 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -230,15 +230,15 @@ series_view_uniform_std140_t make_series_view_uniform( // longer match and the SRB is rebuilt before the next draw. struct Series_renderer::vbo_view_state_t::rhi_buffers_t { - std::unique_ptr vbo; - std::unique_ptr ubo; + std::unique_ptr vbo; + std::unique_ptr ubo; // LINE-specific per-frame buffer that holds the active sample window // padded with leading and trailing duplicates. Bound four times as a // vertex buffer at consecutive gpu_sample_t offsets with per-instance // stepping, so the vertex shader receives prev/p0/p1/next as plain // attributes. This side-steps the SM 5.0 UAV restriction that blocks // SSBOs in the D3D11 vertex stage. - std::unique_ptr line_window_vbo; + std::unique_ptr line_window_vbo; // Per-(view, primitive_style) UBO + SRB cache. Each drawable primitive // needs an independent UBO because every resource update is submitted @@ -247,14 +247,16 @@ struct Series_renderer::vbo_view_state_t::rhi_buffers_t // matching draw records. struct srb_entry_t { - std::unique_ptr ubo; - std::unique_ptr srb; - QRhiBuffer* last_ubo = nullptr; - std::size_t ubo_capacity_bytes = 0; + std::unique_ptr + ubo; + std::unique_ptr + srb; + QRhiBuffer* last_ubo = nullptr; + std::size_t ubo_capacity_bytes = 0; }; - srb_entry_t dots_srb; - srb_entry_t line_srb; - srb_entry_t area_fill_srb; + srb_entry_t dots_srb; + srb_entry_t line_srb; + srb_entry_t area_fill_srb; }; @@ -321,21 +323,21 @@ struct Series_renderer::rhi_state_t struct rhi_pipeline_t { - std::unique_ptr pipeline; - QShader vert; - QShader frag; + std::unique_ptr pipeline; + QShader vert; + QShader frag; // Render-pass descriptor captured at pipeline creation. If the host's // current render target carries a different descriptor (e.g. resize // recreated the FBO with a different color format or sample count), // the cached pipeline is no longer compatible and is rebuilt. - QRhiRenderPassDescriptor* last_rpd = nullptr; - int last_sample_count = 1; + QRhiRenderPassDescriptor* last_rpd = nullptr; + int last_sample_count = 1; }; struct view_ubo_key_t { - int series_id = 0; - Series_view_kind view_kind = Series_view_kind::MAIN; + int series_id = 0; + Series_view_kind view_kind = Series_view_kind::MAIN; bool operator==(const view_ubo_key_t& o) const noexcept { @@ -360,14 +362,15 @@ struct Series_renderer::rhi_state_t struct qrhi_layer_program_key_t { - int series_id = 0; - Series_view_kind view_kind = Series_view_kind::MAIN; - std::string layer_id; - std::uint64_t layer_revision = 0; - const void* data_identity = nullptr; - std::uint64_t layout_key = 0; - detail::access_policy_cache_key_t access_key; - QRhi* rhi = nullptr; + int series_id = 0; + Series_view_kind view_kind = Series_view_kind::MAIN; + std::string layer_id; + std::uint64_t layer_revision = 0; + const void* data_identity = nullptr; + std::uint64_t layout_key = 0; + detail::access_policy_cache_key_t + access_key; + QRhi* rhi = nullptr; bool operator==(const qrhi_layer_program_key_t& o) const noexcept { @@ -400,21 +403,22 @@ struct Series_renderer::rhi_state_t struct qrhi_layer_data_key_t { - std::size_t lod_level = 0; - std::uint64_t sample_sequence = 0; - std::int64_t t_origin_ns = 0; - std::size_t source_first = 0; - std::size_t source_count = 0; - std::size_t synthetic_hold_count = 0; - std::size_t gpu_count = 0; - bool hold_last_forward = false; - std::int64_t hold_timestamp_ns = 0; - Series_interpolation interpolation = Series_interpolation::LINEAR; + std::size_t lod_level = 0; + std::uint64_t sample_sequence = 0; + std::int64_t t_origin_ns = 0; + std::size_t source_first = 0; + std::size_t source_count = 0; + std::size_t synthetic_hold_count = 0; + std::size_t gpu_count = 0; + bool hold_last_forward = false; + std::int64_t hold_timestamp_ns = 0; + Series_interpolation interpolation = Series_interpolation::LINEAR; Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - std::size_t drawable_span_count = 0; - std::size_t drawable_spans_hash = 0; - detail::access_policy_cache_key_t access_key; + std::size_t drawable_span_count = 0; + std::size_t drawable_spans_hash = 0; + detail::access_policy_cache_key_t + access_key; bool operator==(const qrhi_layer_data_key_t& o) const noexcept { @@ -437,10 +441,11 @@ struct Series_renderer::rhi_state_t struct qrhi_layer_cache_entry_t { - std::unique_ptr state; - qrhi_layer_data_key_t data_key; - bool has_data_key = false; - std::uint64_t last_frame_used = 0; + std::unique_ptr + state; + qrhi_layer_data_key_t data_key; + bool has_data_key = false; + std::uint64_t last_frame_used = 0; }; struct prepared_draw_command_t @@ -451,40 +456,41 @@ struct Series_renderer::rhi_state_t CUSTOM }; - kind_t kind = kind_t::CUSTOM; - int z_order = 0; - int series_id = 0; - Series_view_kind view_kind = Series_view_kind::MAIN; - std::size_t series_order = 0; - std::size_t insertion_order = 0; - Qrhi_series_layer_state* state = nullptr; - const series_data_t* series = nullptr; - sample_window_t window; - QRhiBuffer* view_ubo = nullptr; - Display_style primitive_style = Display_style::LINE; - vbo_view_state_t* view_state = nullptr; + kind_t kind = kind_t::CUSTOM; + int z_order = 0; + int series_id = 0; + Series_view_kind view_kind = Series_view_kind::MAIN; + std::size_t series_order = 0; + std::size_t insertion_order = 0; + Qrhi_series_layer_state* state = nullptr; + const series_data_t* series = nullptr; + sample_window_t window; + QRhiBuffer* view_ubo = nullptr; + Display_style primitive_style = Display_style::LINE; + vbo_view_state_t* view_state = nullptr; // Built-in LINE/AREA strips, computed once in prepare and reused by the // record pass instead of recomputing from window. Empty for DOTS. - std::vector builtin_segment_spans; + std::vector + builtin_segment_spans; }; - std::unordered_map pipelines; - std::unordered_map view_ubos; + std::unordered_map pipelines; + std::unordered_map view_ubos; std::unordered_map< qrhi_layer_program_key_t, qrhi_layer_cache_entry_t, qrhi_layer_program_key_hash_t> qrhi_layer_cache; - std::vector prepared_draws; - QShader cached_dot_vert; - QShader cached_dot_frag; - QShader cached_line_vert; - QShader cached_line_frag; - QShader cached_area_vert; - QShader cached_area_frag; - bool shaders_loaded = false; - - QRhi* last_rhi = nullptr; - QRhiResourceUpdateBatch* pending_updates = nullptr; + std::vector prepared_draws; + QShader cached_dot_vert; + QShader cached_dot_frag; + QShader cached_line_vert; + QShader cached_line_frag; + QShader cached_area_vert; + QShader cached_area_frag; + bool shaders_loaded = false; + + QRhi* last_rhi = nullptr; + QRhiResourceUpdateBatch* pending_updates = nullptr; // Per-frame draw plan computed in prepare() and replayed in render(). // The vector lives on the renderer rather than in a stack @@ -493,11 +499,11 @@ struct Series_renderer::rhi_state_t // origins computed in prepare() ride inside the per-view UBO/staging // bytes already submitted to the resource-update batch, so they do // not need to be cached here for render() to read back. - std::vector frame_draw_states; - bool frame_preview_visible = false; + std::vector frame_draw_states; + bool frame_preview_visible = false; // True if prepare() filled this plan. Reset after render() consumes it // so a stray render() without a matching prepare() is a no-op. - bool frame_plan_ready = false; + bool frame_plan_ready = false; }; // ----------------------------------------------------------------------------- @@ -545,11 +551,12 @@ struct Series_renderer::rhi_state_t // vec4-aligned trailing element rule std140 enforces on the GLSL block. struct Line_block_std140 { - series_view_uniform_std140_t view; // offset 0 - float line_px; // offset 128 - int snap_to_pixels; // offset 132 - float _pad0; // offset 136 - float _pad1; // offset 140 + series_view_uniform_std140_t + view; // offset 0 + float line_px; // offset 128 + int snap_to_pixels; // offset 132 + float _pad0; // offset 136 + float _pad1; // offset 140 }; static_assert(sizeof(Line_block_std140) == 144, "Line_block_std140 must be a multiple of 16"); static_assert(offsetof(Line_block_std140, line_px) == 128, "Line_block line_px offset"); @@ -559,11 +566,12 @@ static_assert(offsetof(Line_block_std140, snap_to_pixels) == 132, "Line_block sn // Padded out to 144 bytes for the same reason as Line_block_std140. struct Dot_block_std140 { - series_view_uniform_std140_t view; // offset 0 - float point_diameter_px; // offset 128 - float _pad0; // offset 132 - float _pad1; // offset 136 - float _pad2; // offset 140 + series_view_uniform_std140_t + view; // offset 0 + float point_diameter_px; // offset 128 + float _pad0; // offset 132 + float _pad1; // offset 136 + float _pad2; // offset 140 }; static_assert(sizeof(Dot_block_std140) == 144, "Dot_block_std140 must be a multiple of 16"); static_assert(offsetof(Dot_block_std140, point_diameter_px) == 128, "Dot_block point_diameter_px offset"); @@ -572,11 +580,12 @@ static_assert(offsetof(Dot_block_std140, point_diameter_px) == 128, "Dot_block p // 16-byte multiple. struct Area_block_std140 { - series_view_uniform_std140_t view; // offset 0 - int interpolation; // offset 128 - int _pad0; // offset 132 - int _pad1; // offset 136 - int _pad2; // offset 140 + series_view_uniform_std140_t + view; // offset 0 + int interpolation; // offset 128 + int _pad0; // offset 132 + int _pad1; // offset 136 + int _pad2; // offset 140 }; static_assert(sizeof(Area_block_std140) == 144, "Area_block_std140 must be a multiple of 16"); static_assert(offsetof(Area_block_std140, interpolation) == 128, "Area_block interpolation offset"); @@ -1091,10 +1100,11 @@ void Series_renderer::prepare( struct planned_draw_t { - std::shared_ptr layer; - bool is_builtin = false; - Display_style primitive_style = Display_style::NONE; - int z_order = 0; + std::shared_ptr + layer; + bool is_builtin = false; + Display_style primitive_style = Display_style::NONE; + int z_order = 0; }; // Built-in LINE/DOTS/AREA all read the primary value lane. A range-only diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index e8e82fa7..ae303e10 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -38,18 +38,20 @@ bool checked_size_product(std::size_t lhs, std::size_t rhs, std::size_t& out) struct drawable_window_result_t { - std::size_t source_first = 0; - std::size_t source_count = 0; - std::size_t synthetic_hold_count = 0; - std::size_t gpu_count = 0; - std::vector spans; - bool valid = true; + std::size_t source_first = 0; + std::size_t source_count = 0; + std::size_t synthetic_hold_count = 0; + std::size_t gpu_count = 0; + std::vector + spans; + bool valid = true; }; struct direct_time_window_query_t { - data_query_result_t result; - bool attempted = false; + data_query_result_t + result; + bool attempted = false; }; drawable_window_result_t build_drawable_window( diff --git a/src/core/series_window_planner.h b/src/core/series_window_planner.h index 3731aa66..027dcedb 100644 --- a/src/core/series_window_planner.h +++ b/src/core/series_window_planner.h @@ -35,74 +35,78 @@ struct series_window_planner_state_t static constexpr std::int64_t k_no_timestamp = std::numeric_limits::min(); - std::size_t last_snapshot_elements = 0; - std::uint64_t last_sequence = 0; - const void* cached_data_identity = nullptr; - std::uint64_t last_timestamp_order_sequence = 0; - const void* last_timestamp_order_identity = nullptr; - access_policy_cache_key_t last_timestamp_order_access_key; - Time_order last_timestamp_source_order = Time_order::UNKNOWN; - bool last_timestamp_order_scan_performed = false; - std::size_t last_timestamp_order_scan_samples = 0; - bool last_timestamps_monotonic = true; + std::size_t last_snapshot_elements = 0; + std::uint64_t last_sequence = 0; + const void* cached_data_identity = nullptr; + std::uint64_t last_timestamp_order_sequence = 0; + const void* last_timestamp_order_identity = nullptr; + access_policy_cache_key_t last_timestamp_order_access_key; + Time_order last_timestamp_source_order = Time_order::UNKNOWN; + bool last_timestamp_order_scan_performed = false; + std::size_t last_timestamp_order_scan_samples = 0; + bool last_timestamps_monotonic = true; Timestamp_window_search last_timestamp_window_search = Timestamp_window_search::NONE; access_dispatch_kind_t last_access_dispatch_kind = access_dispatch_kind_t::NONE; - access_policy_cache_key_t last_access_key; + access_policy_cache_key_t last_access_key; - std::size_t last_first = 0; - std::size_t last_count = 0; - bool has_last_lod_level = false; - std::size_t last_lod_level = 0; - std::int64_t last_t_min = k_no_timestamp; - std::int64_t last_t_max = k_no_timestamp; - double last_width_px = std::numeric_limits::quiet_NaN(); + std::size_t last_first = 0; + std::size_t last_count = 0; + bool has_last_lod_level = false; + std::size_t last_lod_level = 0; + std::int64_t last_t_min = k_no_timestamp; + std::int64_t last_t_max = k_no_timestamp; + double last_width_px = std::numeric_limits::quiet_NaN(); Empty_window_behavior last_empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; Nonfinite_sample_policy last_nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - double last_applied_pps = 0.0; - bool last_hold_last_forward = false; - Series_interpolation last_interpolation = Series_interpolation::LINEAR; - std::size_t last_source_count = 0; - std::size_t last_synthetic_hold_count = 0; - std::vector last_drawable_spans; - std::int64_t uploaded_t_origin_ns = k_no_timestamp; + double last_applied_pps = 0.0; + bool last_hold_last_forward = false; + Series_interpolation last_interpolation = Series_interpolation::LINEAR; + std::size_t last_source_count = 0; + std::size_t last_synthetic_hold_count = 0; + std::vector + last_drawable_spans; + std::int64_t uploaded_t_origin_ns = k_no_timestamp; }; struct Series_window_snapshot_cache { - std::uint64_t cached_snapshot_frame_id = 0; - std::size_t cached_snapshot_level = std::numeric_limits::max(); - const Data_source* cached_snapshot_source = nullptr; - data_snapshot_t cached_snapshot; - std::shared_ptr cached_snapshot_hold; + std::uint64_t cached_snapshot_frame_id = 0; + std::size_t cached_snapshot_level = std::numeric_limits::max(); + const Data_source* cached_snapshot_source = nullptr; + data_snapshot_t cached_snapshot; + std::shared_ptr cached_snapshot_hold; }; struct series_window_plan_request_t { - int series_id = 0; - Series_view_kind view_kind = Series_view_kind::MAIN; - series_window_planner_state_t* planner_state = nullptr; - Series_window_snapshot_cache* snapshot_cache = nullptr; - std::uint64_t frame_id = 0; - Data_source* data_source = nullptr; - const Data_access_policy* access = nullptr; - const std::vector* scales = nullptr; - std::int64_t t_min_ns = 0; - std::int64_t t_max_ns = 0; - std::int64_t t_origin_ns = 0; - double width_px = 0.0; + int series_id = 0; + Series_view_kind view_kind = Series_view_kind::MAIN; + series_window_planner_state_t* + planner_state = nullptr; + Series_window_snapshot_cache* + snapshot_cache = nullptr; + std::uint64_t frame_id = 0; + Data_source* data_source = nullptr; + const Data_access_policy* access = nullptr; + const std::vector* + scales = nullptr; + std::int64_t t_min_ns = 0; + std::int64_t t_max_ns = 0; + std::int64_t t_origin_ns = 0; + double width_px = 0.0; Empty_window_behavior empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; Nonfinite_sample_policy nonfinite_policy = Nonfinite_sample_policy::BREAK_SEGMENT; - Display_style style = Display_style::NONE; - Series_interpolation interpolation = Series_interpolation::LINEAR; - Snapshot_requirement snapshot_requirement = Snapshot_requirement::Optional; - bool has_uploaded_vbo = false; - Profiler* profiler = nullptr; + Display_style style = Display_style::NONE; + Series_interpolation interpolation = Series_interpolation::LINEAR; + Snapshot_requirement snapshot_requirement = Snapshot_requirement::Optional; + bool has_uploaded_vbo = false; + Profiler* profiler = nullptr; }; Series_view_plan plan_series_window(const series_window_plan_request_t& request); diff --git a/src/core/types.cpp b/src/core/types.cpp index 0427b5a2..23261dae 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -22,23 +22,23 @@ enum class sample_scan_status struct validated_time_window_t { - std::size_t first = 0; - std::size_t last_exclusive = 0; - std::size_t match_first = 0; - std::size_t match_last_exclusive = 0; - std::size_t held_index = 0; - bool has_match = false; - bool has_held = false; - bool valid = true; + std::size_t first = 0; + std::size_t last_exclusive = 0; + std::size_t match_first = 0; + std::size_t match_last_exclusive = 0; + std::size_t held_index = 0; + bool has_match = false; + bool has_held = false; + bool valid = true; }; struct time_window_candidates_t { - std::size_t match_first = 0; - std::size_t match_last_exclusive = 0; - std::size_t held_index = 0; - bool has_held = false; - bool valid = true; + std::size_t match_first = 0; + std::size_t match_last_exclusive = 0; + std::size_t held_index = 0; + bool has_held = false; + bool valid = true; }; Data_query_status status_from_snapshot(snapshot_result_t::Snapshot_status status) diff --git a/src/qt/plot_renderer.cpp b/src/qt/plot_renderer.cpp index ba4829af..3905bfbd 100644 --- a/src/qt/plot_renderer.cpp +++ b/src/qt/plot_renderer.cpp @@ -140,36 +140,37 @@ struct Plot_renderer::impl_t { Plot_config config; data_config_t data_cfg; - std::map> series; - bool v_auto = true; - int visible_info_flags = k_visible_info_none; - double adjusted_font_px = 10.0; - double base_label_height_px = 14.0; + std::map> + series; + bool v_auto = true; + int visible_info_flags = k_visible_info_none; + double adjusted_font_px = 10.0; + double base_label_height_px = 14.0; double adjusted_preview_height = 0.0; - double vbar_width_pixels = 0.0; - glm::vec4 window_background = glm::vec4(0.f, 0.f, 0.f, 1.f); + double vbar_width_pixels = 0.0; + glm::vec4 window_background = glm::vec4(0.f, 0.f, 0.f, 1.f); text_lcd_resolved_subpixel_order_t auto_text_lcd_subpixel_order = text_lcd_resolved_subpixel_order_t::NONE; std::uint64_t config_revision = 0; }; - const Plot_widget* owner = nullptr; - render_snapshot_t snapshot; - - Asset_loader asset_loader; - Series_renderer series; - Primitive_renderer primitives; - Chrome_renderer chrome; - Layout_calculator layout_calc; - Layout_cache layout_cache; - detail::Frame_range_planner frame_range_planner; - double last_vbar_width_pixels = detail::k_vbar_min_width_px_d; + const Plot_widget* owner = nullptr; + render_snapshot_t snapshot; + + Asset_loader asset_loader; + Series_renderer series; + Primitive_renderer primitives; + Chrome_renderer chrome; + Layout_calculator layout_calc; + Layout_cache layout_cache; + detail::Frame_range_planner frame_range_planner; + double last_vbar_width_pixels = detail::k_vbar_min_width_px_d; #if defined(VNM_PLOT_ENABLE_TEXT) std::unique_ptr fonts; std::unique_ptr text; #endif std::chrono::steady_clock::time_point last_render_callback; - bool series_initialized = false; + bool series_initialized = false; }; Plot_renderer::Plot_renderer(const Plot_widget* owner) diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index f6fb134d..387d1523 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -1059,10 +1059,10 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anc struct aggregated_range_t { - double vmin; - double vmax; - std::int64_t tmin_ns; - std::int64_t tmax_ns; + double vmin; + double vmax; + std::int64_t tmin_ns; + std::int64_t tmax_ns; }; bool have_any = false; diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index 530d710f..779d2450 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -16,16 +16,16 @@ namespace vnm::plot::detail { // data_config_t in Plot_widget, plain members in Plot_time_axis). struct t_view_snapshot_t { - qint64 t_min = 0; - qint64 t_max = 0; + qint64 t_min = 0; + qint64 t_max = 0; qint64 t_available_min = 0; qint64 t_available_max = 0; }; struct time_axis_update_result_t { - bool accepted = false; - bool changed = false; + bool accepted = false; + bool changed = false; }; // Translate the view by `diff` pixels of horizontal motion expressed @@ -583,15 +583,15 @@ class Time_axis_model return {true, changed}; } - qint64 m_t_min = 0; - qint64 m_t_max = 0; - qint64 m_t_available_min = 0; - qint64 m_t_available_max = 0; + qint64 m_t_min = 0; + qint64 m_t_max = 0; + qint64 m_t_available_min = 0; + qint64 m_t_available_max = 0; - bool m_t_min_initialized = false; - bool m_t_max_initialized = false; - bool m_t_available_min_initialized = false; - bool m_t_available_max_initialized = false; + bool m_t_min_initialized = false; + bool m_t_max_initialized = false; + bool m_t_available_min_initialized = false; + bool m_t_available_max_initialized = false; }; } // namespace vnm::plot::detail diff --git a/src/qt/text_lcd_resolver.h b/src/qt/text_lcd_resolver.h index d6e6ed63..1bb674d4 100644 --- a/src/qt/text_lcd_resolver.h +++ b/src/qt/text_lcd_resolver.h @@ -12,7 +12,7 @@ struct text_lcd_resolver_probes_t { using probe_t = std::function; - probe_t qt_probe = nullptr; + probe_t qt_probe = nullptr; probe_t windows_probe = nullptr; }; diff --git a/tests/test_cache_invalidation.cpp b/tests/test_cache_invalidation.cpp index 08ff435f..67af287c 100644 --- a/tests/test_cache_invalidation.cpp +++ b/tests/test_cache_invalidation.cpp @@ -39,8 +39,8 @@ namespace { struct Test_sample { - std::int64_t t; - float v; + std::int64_t t; + float v; }; constexpr std::uint64_t k_stable_policy_semantics = 0x535441424C45; @@ -48,17 +48,17 @@ constexpr std::uint64_t k_stable_policy_semantics = 0x535441424C45; class Query_range_source final : public Data_source { public: - std::vector samples; - Data_query_status query_status = Data_query_status::UNSUPPORTED; - value_range_t query_range{0.0f, 0.0f}; - std::uint64_t query_sequence = 1; - std::uint64_t current_sequence_value = 1; - std::uint64_t snapshot_sequence = 1; - std::size_t levels = 1; - int query_calls = 0; - int snapshot_calls = 0; - std::size_t last_query_lod = 0; - data_query_context_t last_query; + std::vector samples; + Data_query_status query_status = Data_query_status::UNSUPPORTED; + value_range_t query_range{0.0f, 0.0f}; + std::uint64_t query_sequence = 1; + std::uint64_t current_sequence_value = 1; + std::uint64_t snapshot_sequence = 1; + std::size_t levels = 1; + int query_calls = 0; + int snapshot_calls = 0; + std::size_t last_query_lod = 0; + data_query_context_t last_query; snapshot_result_t try_snapshot(std::size_t lod_level) override { @@ -108,10 +108,10 @@ class Query_range_source final : public Data_source class Snapshot_range_source final : public Data_source { public: - std::vector samples; - std::uint64_t snapshot_sequence = 1; - std::uint64_t current_sequence_value = 1; - int snapshot_calls = 0; + std::vector samples; + std::uint64_t snapshot_sequence = 1; + std::uint64_t current_sequence_value = 1; + int snapshot_calls = 0; snapshot_result_t try_snapshot(std::size_t /*lod_level*/) override { diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index b323fe03..e19e5acf 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -19,22 +19,23 @@ namespace { struct sample_t { - double t = 0.0; - float v = 0.0f; + double t = 0.0; + float v = 0.0f; }; struct Blocking_publication_probe { - std::atomic block_next_destroy{false}; - std::atomic destroy_entered{false}; - std::atomic release_destroy{false}; + std::atomic block_next_destroy{false}; + std::atomic destroy_entered{false}; + std::atomic release_destroy{false}; }; struct Blocking_sample { double t = 0.0; - float v = 0.0f; - std::shared_ptr probe; + float v = 0.0f; + std::shared_ptr + probe; ~Blocking_sample() { @@ -390,9 +391,9 @@ class Ring_source final : public plot::Data_source } private: - mutable std::mutex m_mutex; - std::vector m_samples; - std::uint64_t m_sequence = 0; + mutable std::mutex m_mutex; + std::vector m_samples; + std::uint64_t m_sequence = 0; }; bool test_ring_source_snapshots_are_consistent_under_concurrent_writes() diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index 1af25432..a28bdc12 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -48,8 +48,8 @@ namespace { struct sample_t { // Timestamps are int64 nanoseconds (API convention). - std::int64_t t = 0; - float v = 0.0f; + std::int64_t t = 0; + float v = 0.0f; }; class Lod_source final : public plot::Data_source diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 54dcc052..2f33d14d 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -17,8 +17,8 @@ namespace { struct sample_t { - std::int64_t t = 0; - float v = 0.0f; + std::int64_t t = 0; + float v = 0.0f; }; constexpr std::uint64_t k_query_semantics_key = 0x5155455259; @@ -65,13 +65,13 @@ class Query_source final : public plot::Data_source int snapshot_calls() const { return m_snapshot_calls; } private: - std::vector m_samples; - std::vector m_scales = {1}; + std::vector m_samples; + std::vector m_scales = {1}; plot::snapshot_result_t::Snapshot_status m_status = plot::snapshot_result_t::Snapshot_status::READY; - plot::Time_order m_time_order = plot::Time_order::UNKNOWN; - std::uint64_t m_sequence = 11; - int m_snapshot_calls = 0; + plot::Time_order m_time_order = plot::Time_order::UNKNOWN; + std::uint64_t m_sequence = 11; + int m_snapshot_calls = 0; }; plot::Data_access_policy make_value_access( diff --git a/tests/test_font_disk_cache.cpp b/tests/test_font_disk_cache.cpp index 51c67790..6342a812 100644 --- a/tests/test_font_disk_cache.cpp +++ b/tests/test_font_disk_cache.cpp @@ -53,14 +53,14 @@ struct Scoped_temp_dir struct cache_file_options_t { - digest_t digest{}; - std::uint32_t cache_version = k_cache_version; - std::uint32_t pixel_height = k_pixel_height; - std::uint32_t atlas_size = k_atlas_texture_size; - std::uint32_t glyph_count = 0; - std::uint32_t kerning_count = 0; - std::uint32_t atlas_bytes = k_expected_atlas_bytes; - bool write_atlas_payload = false; + digest_t digest{}; + std::uint32_t cache_version = k_cache_version; + std::uint32_t pixel_height = k_pixel_height; + std::uint32_t atlas_size = k_atlas_texture_size; + std::uint32_t glyph_count = 0; + std::uint32_t kerning_count = 0; + std::uint32_t atlas_bytes = k_expected_atlas_bytes; + bool write_atlas_payload = false; }; digest_t make_digest(std::uint8_t seed) diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index b20def26..eddffa87 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -32,14 +32,14 @@ class test_interaction_item_t : public plot::Plot_interaction_item struct zoom_state_t { - double scale = 1.0; - double velocity = 0.0; + double scale = 1.0; + double velocity = 0.0; }; struct indicator_sample_t { - std::int64_t t_ns = 0; - float value = 0.0f; + std::int64_t t_ns = 0; + float value = 0.0f; }; bool nearly_equal(double a, double b, double epsilon = 1e-12) diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 43961a4c..e8a0f005 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -31,50 +31,51 @@ namespace { struct test_sample_t { - std::int64_t timestamp_ns; - float value; - float range_min; - float range_max; + std::int64_t timestamp_ns; + float value; + float range_min; + float range_max; }; struct layer_event_t { - std::string layer_id; - std::string action; - bool resources_changed = false; - bool snapshot_valid = false; - std::size_t snapshot_count = 0; - plot::Series_view_kind view_kind = plot::Series_view_kind::MAIN; - std::size_t source_first = 0; - std::size_t source_count = 0; - std::size_t synthetic_hold_count = 0; - std::size_t gpu_count = 0; - std::vector drawable_spans; - std::uint64_t sample_sequence = 0; - std::uint64_t snapshot_sequence = 0; - std::int64_t t_min_ns = 0; - std::int64_t t_max_ns = 0; - std::int64_t t_origin_ns = 0; - float v_min = 0.0f; - float v_max = 0.0f; + std::string layer_id; + std::string action; + bool resources_changed = false; + bool snapshot_valid = false; + std::size_t snapshot_count = 0; + plot::Series_view_kind view_kind = plot::Series_view_kind::MAIN; + std::size_t source_first = 0; + std::size_t source_count = 0; + std::size_t synthetic_hold_count = 0; + std::size_t gpu_count = 0; + std::vector + drawable_spans; + std::uint64_t sample_sequence = 0; + std::uint64_t snapshot_sequence = 0; + std::int64_t t_min_ns = 0; + std::int64_t t_max_ns = 0; + std::int64_t t_origin_ns = 0; + float v_min = 0.0f; + float v_max = 0.0f; plot::Nonfinite_sample_policy nonfinite_policy = plot::Nonfinite_sample_policy::BREAK_SEGMENT; - QRhiBuffer* sample_buffer = nullptr; - std::size_t sample_buffer_first_sample = 0; - std::size_t sample_buffer_sample_count = 0; - std::size_t sample_buffer_source_first = 0; - std::size_t sample_buffer_source_count = 0; - std::size_t sample_buffer_synthetic_hold_count = 0; - std::int64_t sample_buffer_t_origin_ns = 0; - std::int64_t sample_buffer_t_min_ns = 0; - std::int64_t sample_buffer_t_max_ns = 0; - float sample_buffer_v_min = 0.0f; - float sample_buffer_v_max = 0.0f; - std::size_t sample_buffer_stride_bytes = 0; - std::size_t sample_buffer_t_rel_seconds_offset = 0; - std::size_t sample_buffer_value_offset = 0; - std::size_t sample_buffer_range_min_offset = 0; - std::size_t sample_buffer_range_max_offset = 0; + QRhiBuffer* sample_buffer = nullptr; + std::size_t sample_buffer_first_sample = 0; + std::size_t sample_buffer_sample_count = 0; + std::size_t sample_buffer_source_first = 0; + std::size_t sample_buffer_source_count = 0; + std::size_t sample_buffer_synthetic_hold_count = 0; + std::int64_t sample_buffer_t_origin_ns = 0; + std::int64_t sample_buffer_t_min_ns = 0; + std::int64_t sample_buffer_t_max_ns = 0; + float sample_buffer_v_min = 0.0f; + float sample_buffer_v_max = 0.0f; + std::size_t sample_buffer_stride_bytes = 0; + std::size_t sample_buffer_t_rel_seconds_offset = 0; + std::size_t sample_buffer_value_offset = 0; + std::size_t sample_buffer_range_min_offset = 0; + std::size_t sample_buffer_range_max_offset = 0; }; class Test_source final : public plot::Data_source @@ -154,12 +155,12 @@ class Test_source final : public plot::Data_source private: std::vector m_samples; - std::weak_ptr m_last_hold; - const void* m_identity = this; - std::uint64_t m_sequence = 0; - int m_snapshot_calls = 0; - int m_busy_snapshots_remaining = 0; - bool m_advance_during_next_snapshot = false; + std::weak_ptr m_last_hold; + const void* m_identity = this; + std::uint64_t m_sequence = 0; + int m_snapshot_calls = 0; + int m_busy_snapshots_remaining = 0; + bool m_advance_during_next_snapshot = false; }; plot::Data_access_policy make_access_policy() @@ -212,8 +213,8 @@ plot::Data_access_policy make_range_only_access_policy() struct access_call_counts_t { int timestamp = 0; - int value = 0; - int range = 0; + int value = 0; + int range = 0; }; plot::Data_access_policy make_direct_member_access_policy() @@ -375,11 +376,12 @@ class Recording_layer final : public plot::Qrhi_series_layer void set_revision(std::uint64_t revision) { m_revision = revision; } private: - std::string m_id; - std::uint64_t m_revision = 0; - int m_z_order = 0; - std::vector& m_events; - int& m_create_count; + std::string m_id; + std::uint64_t m_revision = 0; + int m_z_order = 0; + std::vector& + m_events; + int& m_create_count; }; class Offscreen_rhi_fixture @@ -1296,8 +1298,8 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() { plot::Nonfinite_sample_policy policy = plot::Nonfinite_sample_policy::BREAK_SEGMENT; - std::string_view layer_id; - int series_id = 0; + std::string_view layer_id; + int series_id = 0; }; const policy_case_t cases[] = { @@ -1892,11 +1894,11 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() { plot::Nonfinite_sample_policy policy = plot::Nonfinite_sample_policy::BREAK_SEGMENT; - std::string_view layer_id; - int series_id = 0; - bool expect_prepare = false; - std::size_t expected_source_first = 0; - float expected_value = 0.0f; + std::string_view layer_id; + int series_id = 0; + bool expect_prepare = false; + std::size_t expected_source_first = 0; + float expected_value = 0.0f; }; const hold_case_t cases[] = { @@ -2425,9 +2427,9 @@ bool test_builtin_upload_stages_visible_windows_for_dots_and_area() struct upload_case_t { - plot::Display_style style = plot::Display_style::DOTS; - std::string_view layer_id; - int series_id = 0; + plot::Display_style style = plot::Display_style::DOTS; + std::string_view layer_id; + int series_id = 0; }; const upload_case_t cases[] = { @@ -2582,9 +2584,9 @@ bool test_builtin_upload_stages_hold_windows_for_dots_and_area() struct upload_case_t { - plot::Display_style style = plot::Display_style::DOTS; - std::string_view layer_id; - int series_id = 0; + plot::Display_style style = plot::Display_style::DOTS; + std::string_view layer_id; + int series_id = 0; }; const upload_case_t cases[] = { @@ -2825,17 +2827,17 @@ bool test_busy_stale_fallback_rejects_changed_request_shape() struct stale_case_t { - std::string label; + std::string label; plot::Empty_window_behavior empty_behavior = plot::Empty_window_behavior::DRAW_NOTHING; plot::Series_interpolation interpolation = plot::Series_interpolation::LINEAR; - std::int64_t initial_t0 = 0; - std::int64_t initial_t1 = 0; - std::int64_t busy_t0 = 0; - std::int64_t busy_t1 = 0; - double initial_width = 240.0; - double busy_width = 240.0; + std::int64_t initial_t0 = 0; + std::int64_t initial_t1 = 0; + std::int64_t busy_t0 = 0; + std::int64_t busy_t1 = 0; + double initial_width = 240.0; + double busy_width = 240.0; }; const std::vector cases = { diff --git a/tests/test_qrhi_public_api.cpp b/tests/test_qrhi_public_api.cpp index 4a13e9b6..d3fda18c 100644 --- a/tests/test_qrhi_public_api.cpp +++ b/tests/test_qrhi_public_api.cpp @@ -30,10 +30,10 @@ namespace { struct sample_t { - std::int64_t timestamp_ns = 0; - float value = 0.0f; - float range_min = 0.0f; - float range_max = 0.0f; + std::int64_t timestamp_ns = 0; + float value = 0.0f; + float range_min = 0.0f; + float range_max = 0.0f; }; template @@ -189,8 +189,8 @@ class Test_layer_state final : public plot::Qrhi_series_layer_state last_record_context = ctx; } - plot::qrhi_series_prepare_context_t last_prepare_context; - plot::qrhi_series_record_context_t last_record_context; + plot::qrhi_series_prepare_context_t last_prepare_context; + plot::qrhi_series_record_context_t last_record_context; }; class Test_layer final : public plot::Qrhi_series_layer @@ -219,9 +219,9 @@ class Test_layer final : public plot::Qrhi_series_layer } private: - std::string m_id; - std::uint64_t m_revision = 0; - int m_z_order = 0; + std::string m_id; + std::uint64_t m_revision = 0; + int m_z_order = 0; }; bool nearly_equal(float a, float b) diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 3bd34a7a..1f6d1b52 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -49,21 +49,21 @@ const plot::detail::series_window_planner_state_t& planner_state( struct Test_sample { // Timestamps are int64 nanoseconds (API convention). - std::int64_t t; - float v; + std::int64_t t; + float v; }; class Single_level_source final : public Data_source { public: - std::vector samples; - int snapshot_calls = 0; - mutable int lod_scales_calls = 0; - mutable int lod_scale_calls = 0; - uint64_t sequence = 1; - std::weak_ptr last_hold; - std::vector scale_values = {1}; - plot::Time_order order = plot::Time_order::UNKNOWN; + std::vector samples; + int snapshot_calls = 0; + mutable int lod_scales_calls = 0; + mutable int lod_scale_calls = 0; + uint64_t sequence = 1; + std::weak_ptr last_hold; + std::vector scale_values = {1}; + plot::Time_order order = plot::Time_order::UNKNOWN; snapshot_result_t try_snapshot(size_t lod_level) override { @@ -107,10 +107,10 @@ class Single_level_source final : public Data_source class Two_level_source final : public Data_source { public: - std::vector lod0; - std::vector lod1; - std::array snapshot_calls{{0, 0}}; - std::array sequences{{1, 1}}; + std::vector lod0; + std::vector lod1; + std::array snapshot_calls{{0, 0}}; + std::array sequences{{1, 1}}; snapshot_result_t try_snapshot(size_t lod_level) override { @@ -144,15 +144,15 @@ class Two_level_source final : public Data_source class Direct_window_source final : public Data_source { public: - std::vector samples; - plot::sample_index_window_t query_window{}; - plot::Data_query_status query_status = plot::Data_query_status::READY; - uint64_t sequence = 77; - uint64_t query_sequence = 77; - int snapshot_calls = 0; - int query_calls = 0; - plot::time_range_t last_query_time_window{}; - plot::sample_semantics_key_t last_query_semantics_key{}; + std::vector samples; + plot::sample_index_window_t query_window{}; + plot::Data_query_status query_status = plot::Data_query_status::READY; + uint64_t sequence = 77; + uint64_t query_sequence = 77; + int snapshot_calls = 0; + int query_calls = 0; + plot::time_range_t last_query_time_window{}; + plot::sample_semantics_key_t last_query_semantics_key{}; snapshot_result_t try_snapshot(size_t lod_level) override { @@ -220,7 +220,7 @@ Data_access_policy make_policy() struct Access_call_counts { int timestamp = 0; - int value = 0; + int value = 0; }; Data_access_policy make_direct_member_policy() diff --git a/tests/test_text_lcd_resolver.cpp b/tests/test_text_lcd_resolver.cpp index 243a7ad2..45a878e2 100644 --- a/tests/test_text_lcd_resolver.cpp +++ b/tests/test_text_lcd_resolver.cpp @@ -14,7 +14,7 @@ using resolved_t = plot::text_lcd_resolved_subpixel_order_t; struct explicit_request_case_t { - request_t request; + request_t request; resolved_t expected; }; diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 21974b3d..8e26f786 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -21,17 +21,17 @@ namespace { struct sample_t { // Timestamps are int64 nanoseconds (API convention). - std::int64_t t; - float v; - std::int32_t pad; - float v_min; - float v_max; + std::int64_t t; + float v; + std::int32_t pad; + float v_min; + float v_max; }; struct default_member_initializer_sample_t { - std::int64_t t = 0; - float v = 0.0f; + std::int64_t t = 0; + float v = 0.0f; }; struct Non_trivial_sample @@ -42,18 +42,18 @@ struct Non_trivial_sample v(0.0f) {} - std::int64_t t; - float v; + std::int64_t t; + float v; }; struct sample_base_t { - std::int64_t t; + std::int64_t t; }; struct Non_standard_layout_sample : sample_base_t { - float v; + float v; }; static_assert(plot::detail::supports_member_pointer_access_v, @@ -94,8 +94,8 @@ bool test_layout_key_distinguishes_sample_types() // keys so the renderer's caches do not collide across types. struct other_sample_t { - std::int64_t t; - float v; + std::int64_t t; + float v; }; const auto policy_a = plot::make_access_policy( @@ -120,14 +120,14 @@ bool test_member_pointer_semantics_key_is_distinct_from_layout_key() { struct int_timestamp_sample_t { - std::int64_t t; - float v; + std::int64_t t; + float v; }; struct fp_timestamp_sample_t { - double t_seconds; - float v; + double t_seconds; + float v; }; const auto int_policy = plot::make_access_policy( From fa00af2746bac670915183295dd27e7094d6ac04 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:54:09 +0200 Subject: [PATCH 12/80] style: align using declarations --- include/vnm_plot/core/access_policy.h | 4 ++-- include/vnm_plot/core/types.h | 12 ++++++------ include/vnm_plot/rhi/text_renderer.h | 2 +- src/core/font_renderer.cpp | 6 +++--- tests/test_core_algo.cpp | 4 ++-- tests/test_qrhi_public_api.cpp | 4 ++-- tests/test_text_lcd_resolver.cpp | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/vnm_plot/core/access_policy.h b/include/vnm_plot/core/access_policy.h index 54384659..f5d0b311 100644 --- a/include/vnm_plot/core/access_policy.h +++ b/include/vnm_plot/core/access_policy.h @@ -202,9 +202,9 @@ struct Data_access_policy_typed { using timestamp_accessor_t = detail::access_function_slot_t; - using value_accessor_t = + using value_accessor_t = detail::access_function_slot_t; - using range_accessor_t = + using range_accessor_t = detail::access_function_slot_t(const Sample&)>; Data_access_policy_typed() diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 12222b2c..e4ddb00c 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -46,9 +46,9 @@ struct erased_access_policy_t { using timestamp_fn_t = std::int64_t (*)(const erased_access_policy_t&, const void*); - using value_fn_t = + using value_fn_t = float (*)(const erased_access_policy_t&, const void*); - using range_fn_t = + using range_fn_t = std::pair (*)(const erased_access_policy_t&, const void*); const void* ctx = nullptr; @@ -290,7 +290,7 @@ struct Size_2i // with file I/O. std::vector is an alternative but std::string is more // convenient for text-based asset formats (shaders, JSON). using Byte_buffer = std::string; -using Byte_view = std::string_view; +using Byte_view = std::string_view; // ----------------------------------------------------------------------------- // data_snapshot_t: A view of sample data (optionally split into two segments) @@ -366,9 +366,9 @@ struct Data_access_policy { using timestamp_accessor_t = detail::access_function_slot_t; - using value_accessor_t = + using value_accessor_t = detail::access_function_slot_t; - using range_accessor_t = + using range_accessor_t = detail::access_function_slot_t(const void*)>; Data_access_policy() @@ -1194,7 +1194,7 @@ struct layout_cache_key_t class Layout_cache { public: - using key_t = layout_cache_key_t; + using key_t = layout_cache_key_t; using value_type = frame_layout_result_t; [[nodiscard]] const value_type* try_get(const key_t& query) const noexcept diff --git a/include/vnm_plot/rhi/text_renderer.h b/include/vnm_plot/rhi/text_renderer.h index 798841bc..f963864d 100644 --- a/include/vnm_plot/rhi/text_renderer.h +++ b/include/vnm_plot/rhi/text_renderer.h @@ -58,7 +58,7 @@ class Text_renderer bool initialized = false; }; - using vertical_axis_fade_tracker_t = axis_fade_tracker_t; + using vertical_axis_fade_tracker_t = axis_fade_tracker_t; using horizontal_axis_fade_tracker_t = axis_fade_tracker_t; private: diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index cd3dedcf..2f9f4cc3 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -78,10 +78,10 @@ struct vertex_buffer_t std::vector index_data; }; -using msdf_atlas_t = vnm::msdf_text::atlas_t; -using msdf_glyph_t = vnm::msdf_text::glyph_t; +using msdf_atlas_t = vnm::msdf_text::atlas_t; +using msdf_glyph_t = vnm::msdf_text::glyph_t; using msdf_kerning_key_t = vnm::msdf_text::kerning_key_t; -using text_vertex_t = vnm::msdf_text::text_vertex_t; +using text_vertex_t = vnm::msdf_text::text_vertex_t; constexpr std::size_t k_text_vertex_float_count = 10u; diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index a28bdc12..5441ea3f 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -685,9 +685,9 @@ bool test_horizontal_label_fade_keys_preserve_int64_timestamps() bool test_text_lcd_policy_helpers() { - using request_t = plot::text_lcd_request_t; + using request_t = plot::text_lcd_request_t; using resolved_t = plot::text_lcd_resolved_subpixel_order_t; - using surface_t = plot::detail::text_lcd_draw_surface_t; + using surface_t = plot::detail::text_lcd_draw_surface_t; const request_t auto_request = plot::text_lcd_auto_request(); const request_t none_request = plot::text_lcd_none_request(); diff --git a/tests/test_qrhi_public_api.cpp b/tests/test_qrhi_public_api.cpp index d3fda18c..3e6c1ef5 100644 --- a/tests/test_qrhi_public_api.cpp +++ b/tests/test_qrhi_public_api.cpp @@ -82,9 +82,9 @@ struct has_bind_internal_access< using erased_timestamp_accessor_t = decltype(std::declval().get_timestamp); -using erased_value_accessor_t = +using erased_value_accessor_t = decltype(std::declval().get_value); -using erased_range_accessor_t = +using erased_range_accessor_t = decltype(std::declval().get_range); static_assert(std::is_assignable_v< diff --git a/tests/test_text_lcd_resolver.cpp b/tests/test_text_lcd_resolver.cpp index 45a878e2..32d5f716 100644 --- a/tests/test_text_lcd_resolver.cpp +++ b/tests/test_text_lcd_resolver.cpp @@ -9,7 +9,7 @@ namespace plot = vnm::plot; namespace { -using request_t = plot::text_lcd_request_t; +using request_t = plot::text_lcd_request_t; using resolved_t = plot::text_lcd_resolved_subpixel_order_t; struct explicit_request_case_t From 7bf094b3e012e2634b353c8af22f93f241f88102 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:55:36 +0200 Subject: [PATCH 13/80] style: align local declarations --- include/vnm_plot/core/access_policy.h | 14 ++-- include/vnm_plot/core/algo.h | 56 +++++++------- include/vnm_plot/core/constants.h | 32 ++++---- include/vnm_plot/core/time_units.h | 16 ++-- include/vnm_plot/core/types.h | 4 +- src/core/auto_range_resolver.cpp | 16 ++-- src/core/chrome_renderer.cpp | 47 ++++++------ src/core/font_renderer.cpp | 92 +++++++++++------------ src/core/layout_calculator.cpp | 88 +++++++++++----------- src/core/primitive_renderer.cpp | 10 +-- src/core/rhi_helpers.h | 4 +- src/core/series_renderer.cpp | 95 ++++++++++++------------ src/core/series_window_planner.cpp | 61 +++++++-------- src/core/text_renderer.cpp | 36 ++++----- src/core/time_grid.cpp | 8 +- src/core/types.cpp | 61 +++++++-------- src/qt/plot_interaction_item.cpp | 40 +++++----- src/qt/plot_renderer.cpp | 12 +-- src/qt/plot_widget.cpp | 65 ++++++++-------- src/qt/t_axis_adjust.h | 2 +- src/qt/text_lcd_resolver.cpp | 6 +- tests/test_cache_invalidation.cpp | 16 ++-- tests/test_concurrent_series.cpp | 4 +- tests/test_core_algo.cpp | 16 ++-- tests/test_data_source_queries.cpp | 17 +++-- tests/test_font_disk_cache.cpp | 49 ++++++------ tests/test_font_renderer_bounds.cpp | 10 +-- tests/test_gpu_sample_origin.cpp | 8 +- tests/test_layout_calculator.cpp | 10 +-- tests/test_msdf_lcd_shader_reference.cpp | 10 +-- tests/test_plot_interaction_item.cpp | 4 +- tests/test_qrhi_layer_lifecycle.cpp | 38 +++++----- tests/test_rhi_helpers.cpp | 4 +- tests/test_snapshot_caching.cpp | 46 ++++++------ tests/test_time_grid.cpp | 2 +- tests/test_typed_api.cpp | 17 +++-- 36 files changed, 514 insertions(+), 502 deletions(-) diff --git a/include/vnm_plot/core/access_policy.h b/include/vnm_plot/core/access_policy.h index f5d0b311..8a8a2862 100644 --- a/include/vnm_plot/core/access_policy.h +++ b/include/vnm_plot/core/access_policy.h @@ -19,7 +19,7 @@ template struct always_false : std::false_type {}; constexpr std::uint64_t k_fnv_offset_basis = 1469598103934665603ULL; -constexpr std::uint64_t k_fnv_prime = 1099511628211ULL; +constexpr std::uint64_t k_fnv_prime = 1099511628211ULL; // Member-pointer policies derive offsets from a real object; keep support to // sample shapes whose default-initialization cannot execute user code. @@ -147,10 +147,10 @@ template constexpr std::uint64_t member_semantics_tag() { using member_t = std::decay_t; - constexpr std::uint64_t k_floating_tag = 1ULL << 56; - constexpr std::uint64_t k_signed_integral_tag = 2ULL << 56; + constexpr std::uint64_t k_floating_tag = 1ULL << 56; + constexpr std::uint64_t k_signed_integral_tag = 2ULL << 56; constexpr std::uint64_t k_unsigned_integral_tag = 3ULL << 56; - constexpr std::uint64_t k_other_arithmetic_tag = 4ULL << 56; + constexpr std::uint64_t k_other_arithmetic_tag = 4ULL << 56; if constexpr (std::is_floating_point_v) { return k_floating_tag | sizeof(member_t); @@ -397,13 +397,13 @@ inline Data_access_policy_typed make_access_policy( { Data_access_policy_typed policy; const std::size_t timestamp_offset = detail::member_offset(timestamp_member); - const std::size_t value_offset = detail::member_offset(value_member); + const std::size_t value_offset = detail::member_offset(value_member); const std::size_t range_min_offset = detail::member_offset(range_min_member); const std::size_t range_max_offset = detail::member_offset(range_max_member); assign_standard_accessors(policy, timestamp_member, value_member); policy.get_range = [range_min_member, range_max_member](const Sample& sample) { - const float low = static_cast(sample.*range_min_member); + const float low = static_cast(sample.*range_min_member); const float high = static_cast(sample.*range_max_member); return std::make_pair(low, high); }; @@ -451,7 +451,7 @@ inline Data_access_policy_typed make_access_policy( { Data_access_policy_typed policy; const std::size_t timestamp_offset = detail::member_offset(timestamp_member); - const std::size_t value_offset = detail::member_offset(value_member); + const std::size_t value_offset = detail::member_offset(value_member); assign_standard_accessors(policy, timestamp_member, value_member); policy.layout_key = detail::compute_sample_layout_key( diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 744e2883..9602ff31 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -41,7 +41,7 @@ inline std::string format_axis_fixed_or_int(double v, int digits) } if (digits <= 0) { - const double rounded = std::round(v); + const double rounded = std::round(v); const long double rounded_ld = static_cast(rounded); if (rounded_ld < static_cast(std::numeric_limits::min()) || rounded_ld > static_cast(std::numeric_limits::max())) @@ -60,7 +60,7 @@ inline std::string format_axis_fixed_or_int(double v, int digits) return "0"; } const long double scale_ld = static_cast(scale); - const long double scaled = static_cast(v) * scale_ld; + const long double scaled = static_cast(v) * scale_ld; if (!std::isfinite(scaled) || std::abs(scaled) > static_cast(std::numeric_limits::max())) { @@ -68,14 +68,14 @@ inline std::string format_axis_fixed_or_int(double v, int digits) } const long double rounded_scaled = std::round(scaled); - const long double rounded = rounded_scaled / scale_ld; + const long double rounded = rounded_scaled / scale_ld; if (!std::isfinite(rounded) || std::abs(rounded) > static_cast(std::numeric_limits::max())) { return "0"; } - double r = static_cast(rounded); + double r = static_cast(rounded); const double eps = 0.5 / scale; if (std::abs(r) < eps) { @@ -131,7 +131,7 @@ inline bool any_fractional_at_precision(const std::vector& values, int d return false; } - const double r = rounded_scaled / scale; + const double r = rounded_scaled / scale; const double rounded = std::round(r); if (!std::isfinite(r) || !std::isfinite(rounded)) { return false; @@ -190,7 +190,7 @@ inline std::size_t circular_index(const ContainerT& c, int index) } const auto size_as_int = static_cast(c.size()); - int remainder = index % size_as_int; + int remainder = index % size_as_int; if (remainder < 0) { remainder += size_as_int; } @@ -221,7 +221,7 @@ inline double get_shift(double section_size, double minval) } } - const double denom = section_size * m; + const double denom = section_size * m; const double scaled_min = minval * m; if (!(denom > 0.0) || !std::isfinite(denom) || !std::isfinite(scaled_min)) { return 0.0; @@ -266,7 +266,7 @@ inline std::vector build_time_steps_covering(double max_span) steps.insert(steps.end(), std::begin(exact), std::end(exact)); // Power-of-two chain beyond 2 days to keep exact multiples. - double s = 172800.0; // 2 days + double s = 172800.0; // 2 days const double limit = std::max(max_span * 2.0, s * 2.0); while (s < limit && s < 1e12) { s *= 2.0; @@ -296,8 +296,8 @@ inline int find_time_step_start_index(const std::vector& steps, double t // Minimal usable span for the vertical axis (prevents float precision collapse). inline float min_v_span_for(float a, float b) { - float mag = std::max(std::abs(a), std::abs(b)); - float ulps = 64.0f * std::numeric_limits::epsilon() * std::max(1.0f, mag); + float mag = std::max(std::abs(a), std::abs(b)); + float ulps = 64.0f * std::numeric_limits::epsilon() * std::max(1.0f, mag); float floor_abs = 1e-6f * std::max(1.0f, mag); return std::max(ulps, floor_abs); } @@ -346,7 +346,7 @@ std::optional bsearch_ts_impl( std::size_t lo = 0; std::size_t hi = count; while (lo < hi) { - std::size_t mid = lo + (hi - lo) / 2; + std::size_t mid = lo + (hi - lo) / 2; const void* sample = addr(mid); if (!sample) { return std::nullopt; @@ -482,7 +482,7 @@ visible_sample_window_t select_visible_sample_window( if (!timestamps_monotonic) { std::size_t match_first = snapshot.count; - std::size_t match_last = 0; + std::size_t match_last = 0; for (std::size_t i = 0; i < snapshot.count; ++i) { const void* sample = snapshot.at(i); if (!sample) { @@ -550,7 +550,7 @@ visible_sample_aggregate_t aggregate_visible_sample_range( if (!std::isfinite(low) || !std::isfinite(high)) { return; } - const double dlow = std::min(low, high); + const double dlow = std::min(low, high); const double dhigh = std::max(low, high); if (!aggregate.valid) { aggregate = {dlow, dhigh, ts_ns, ts_ns, true}; @@ -562,8 +562,8 @@ visible_sample_aggregate_t aggregate_visible_sample_range( aggregate.tmax_ns = std::max(aggregate.tmax_ns, ts_ns); }; - const void* held_sample = nullptr; - bool have_sample_at_or_after_window_start = false; + const void* held_sample = nullptr; + bool have_sample_at_or_after_window_start = false; for (std::size_t i = 0; i < snapshot.count; ++i) { const void* sample = snapshot.at(i); if (!sample) { @@ -616,20 +616,20 @@ timestamp_bracket_t bracket_timestamp_impl( } const void* first_sample = addr(0); - const void* last_sample = addr(count - 1); + const void* last_sample = addr(count - 1); if (!first_sample || !last_sample) { return {}; } - const double first_ts = get_timestamp(first_sample); - const double last_ts = get_timestamp(last_sample); - const bool ascending = first_ts <= last_ts; + const double first_ts = get_timestamp(first_sample); + const double last_ts = get_timestamp(last_sample); + const bool ascending = first_ts <= last_ts; std::size_t lo = 0; std::size_t hi = count - 1; while (lo < hi) { - const std::size_t mid = lo + (hi - lo) / 2; - const void* mid_sample = addr(mid); + const std::size_t mid = lo + (hi - lo) / 2; + const void* mid_sample = addr(mid); if (!mid_sample) { return {}; } @@ -708,7 +708,7 @@ inline std::int64_t choose_snap_ns(std::int64_t span_ns) constexpr std::int64_t k_ns_per_us = 1000LL; constexpr std::int64_t k_ns_per_ms = 1000000LL; constexpr std::int64_t k_ns_per_second = 1000000000LL; - constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; + constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; constexpr std::int64_t k_ns_per_day = 86400LL * k_ns_per_second; constexpr std::int64_t k_ns_per_year = 365LL * k_ns_per_day; @@ -742,9 +742,9 @@ inline std::int64_t floor_div_i64(std::int64_t a, std::int64_t b) // on signed wrap. inline std::int64_t choose_origin_ns(std::int64_t t_view_min_ns, std::int64_t span_ns) { - const std::int64_t snap_ns = choose_snap_ns(span_ns); - const std::int64_t q = floor_div_i64(t_view_min_ns, snap_ns); - constexpr std::int64_t k_min = std::numeric_limits::min(); + const std::int64_t snap_ns = choose_snap_ns(span_ns); + const std::int64_t q = floor_div_i64(t_view_min_ns, snap_ns); + constexpr std::int64_t k_min = std::numeric_limits::min(); if (snap_ns > 1 && q < k_min / snap_ns) { return k_min; } @@ -766,11 +766,11 @@ inline std::size_t choose_lod_level( } constexpr double target_pps = 1.0; - std::size_t best_level = 0; - double best_error = std::abs(base_pps * static_cast(scales[0]) - target_pps); + std::size_t best_level = 0; + double best_error = std::abs(base_pps * static_cast(scales[0]) - target_pps); for (std::size_t i = 1; i < scales.size(); ++i) { - const double pps = base_pps * static_cast(scales[i]); + const double pps = base_pps * static_cast(scales[i]); const double error = std::abs(pps - target_pps); if (error < best_error) { best_error = error; diff --git a/include/vnm_plot/core/constants.h b/include/vnm_plot/core/constants.h index 54e6bb7a..4f5afc1c 100644 --- a/include/vnm_plot/core/constants.h +++ b/include/vnm_plot/core/constants.h @@ -15,12 +15,12 @@ namespace detail { constexpr float k_v_label_horizontal_padding_px = 6.0f; // Grid & preview metrics -constexpr float k_cell_span_min_factor = 0.1f; -constexpr float k_cell_span_max_factor = 6.0f; +constexpr float k_cell_span_min_factor = 0.1f; +constexpr float k_cell_span_max_factor = 6.0f; // Label nudge factors -constexpr float k_v_label_vertical_nudge_px = 0.1f; -constexpr float k_h_label_vertical_nudge_px = 1.05f; +constexpr float k_v_label_vertical_nudge_px = 0.1f; +constexpr float k_h_label_vertical_nudge_px = 1.05f; // Hit testing constexpr float k_hit_test_px = 1.0f; @@ -32,29 +32,29 @@ constexpr float k_grid_line_alpha_base = 0.75f; constexpr int k_value_decimals = 3; // Text margins -constexpr float k_text_margin_px = 3.0f; -constexpr float k_overlay_left_px = 10.0f; -constexpr float k_line_spacing = 1.5f; +constexpr float k_text_margin_px = 3.0f; +constexpr float k_overlay_left_px = 10.0f; +constexpr float k_line_spacing = 1.5f; // Scissor padding constexpr float k_scissor_pad_px = 1.0f; // Preview bar -constexpr double k_preview_band_max_px = 5.0; -constexpr int k_preview_min_window_px = 60; +constexpr double k_preview_band_max_px = 5.0; +constexpr int k_preview_min_window_px = 60; // Font defaults -constexpr double k_default_font_px = 10.0; -constexpr double k_default_base_label_height_px = 14.0; +constexpr double k_default_font_px = 10.0; +constexpr double k_default_base_label_height_px = 14.0; // Internal constants -constexpr double k_vbar_width_change_threshold_d = 0.5; -constexpr double k_vbar_min_width_px_d = 1.0; -constexpr int k_rect_initial_quads = 256; +constexpr double k_vbar_width_change_threshold_d = 0.5; +constexpr double k_vbar_min_width_px_d = 1.0; +constexpr int k_rect_initial_quads = 256; // Precision constants -constexpr float k_pixel_snap = 0.5f; -constexpr double k_eps = 1e-6; +constexpr float k_pixel_snap = 0.5f; +constexpr double k_eps = 1e-6; } // namespace detail } // namespace vnm::plot diff --git a/include/vnm_plot/core/time_units.h b/include/vnm_plot/core/time_units.h index 323db3f2..6731c74e 100644 --- a/include/vnm_plot/core/time_units.h +++ b/include/vnm_plot/core/time_units.h @@ -10,7 +10,7 @@ namespace vnm::plot { -inline constexpr std::int64_t k_ns_per_ms = 1'000'000; +inline constexpr std::int64_t k_ns_per_ms = 1'000'000; inline constexpr std::int64_t k_ns_per_second = 1'000'000'000; struct time_range_t @@ -89,15 +89,15 @@ inline std::int64_t saturating_add_duration_ns( std::int64_t value_ns, std::uint64_t duration_ns) noexcept { - std::int64_t result = value_ns; + std::int64_t result = value_ns; std::uint64_t remaining = duration_ns; constexpr std::uint64_t k_max_chunk = static_cast(std::numeric_limits::max()); while (remaining > 0) { const std::uint64_t chunk_u = (remaining > k_max_chunk) ? k_max_chunk : remaining; - const auto chunk = static_cast(chunk_u); - const auto next = checked_add_ns(result, chunk); + const auto chunk = static_cast(chunk_u); + const auto next = checked_add_ns(result, chunk); if (!next) { return std::numeric_limits::max(); } @@ -112,15 +112,15 @@ inline std::int64_t saturating_sub_duration_ns( std::int64_t value_ns, std::uint64_t duration_ns) noexcept { - std::int64_t result = value_ns; + std::int64_t result = value_ns; std::uint64_t remaining = duration_ns; constexpr std::uint64_t k_max_chunk = static_cast(std::numeric_limits::max()); while (remaining > 0) { const std::uint64_t chunk_u = (remaining > k_max_chunk) ? k_max_chunk : remaining; - const auto chunk = static_cast(chunk_u); - const auto next = checked_sub_ns(result, chunk); + const auto chunk = static_cast(chunk_u); + const auto next = checked_sub_ns(result, chunk); if (!next) { return std::numeric_limits::min(); } @@ -210,7 +210,7 @@ inline time_range_t centered_time_range_ns( }; } - const std::uint64_t left_span_ns = span_ns / 2; + const std::uint64_t left_span_ns = span_ns / 2; const std::uint64_t right_span_ns = span_ns - left_span_ns; time_range_t range{ saturating_sub_duration_ns(center_ns, left_span_ns), diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index e4ddb00c..10de6cd3 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -538,8 +538,8 @@ inline std::pair std_function_access_range( inline erased_access_policy_t make_erased_access_policy_view( const Data_access_policy& policy) { - erased_access_policy_t view = policy.internal_access; - bool uses_std_function = false; + erased_access_policy_t view = policy.internal_access; + bool uses_std_function = false; if (!view.get_timestamp && policy.get_timestamp) { view.get_timestamp = &std_function_access_timestamp; diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index 6d2e958e..9242ffd1 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -62,11 +62,12 @@ bool scan_series_range( return false; } - bool have_any = false; - const void* held_sample = nullptr; - bool have_held_sample = false; - bool have_held_candidate = false; - std::int64_t held_timestamp_ns = 0; + bool have_any = false; + const void* held_sample = nullptr; + bool have_held_sample = false; + bool have_held_candidate = false; + std::int64_t held_timestamp_ns = 0; + bool have_sample_at_or_after_visible_start = false; for (std::size_t i = 0; i < snapshot.count; ++i) { const void* sample = snapshot.at(i); @@ -164,7 +165,7 @@ void apply_auto_v_range_padding( if (config.auto_v_range_extra_scale > 0.0) { const double span = double(v_max) - double(v_min); if (span > 0.0) { - const double center = 0.5 * (double(v_min) + double(v_max)); + const double center = 0.5 * (double(v_min) + double(v_max)); const double padded_span = span * (1.0 + config.auto_v_range_extra_scale); v_min = static_cast(center - padded_span * 0.5); v_max = static_cast(center + padded_span * 0.5); @@ -321,6 +322,7 @@ bool query_or_scan_series_range( std::map* entries = cache_entries(cache, preview); const std::uint64_t current_sequence = source.current_sequence(level); + const bool cacheable_query = entries && current_sequence != 0 && !query.semantics_key.conservative; if (cacheable_query) { @@ -408,7 +410,7 @@ bool resolve_series_collection_range( float& out_min, float& out_max) { - bool have_any = false; + bool have_any = false; Profiler* profiler = config.profiler.get(); const bool visible_only = !preview && config.auto_v_range_mode == Auto_v_range_mode::VISIBLE; diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index 525a8d63..6fca795c 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -79,8 +79,9 @@ grid_layer_params_t Chrome_renderer::calculate_grid_params( } static const std::array om_div = {5, 2}; - double step = 1.0; - int idx = 16; + + double step = 1.0; + int idx = 16; double probe = 0.0; for (; (probe = step * om_div[circular_index(om_div, idx)]) < range; ++idx) { step = probe; @@ -90,11 +91,11 @@ grid_layer_params_t Chrome_renderer::calculate_grid_params( } const double cell_span_min = font_px * k_cell_span_min_factor; - const double fade_den = std::max(1e-6, font_px * (k_cell_span_max_factor - k_cell_span_min_factor)); - const double px_per_unit = pixel_span / range; + const double fade_den = std::max(1e-6, font_px * (k_cell_span_max_factor - k_cell_span_min_factor)); + const double px_per_unit = pixel_span / range; while (levels.count < grid_layer_params_t::k_max_levels && step * px_per_unit >= cell_span_min) { - const float spacing_px = static_cast(step * px_per_unit); + const float spacing_px = static_cast(step * px_per_unit); const double shift_units = get_shift(step, min); append_grid_level(levels, spacing_px, static_cast(pixel_span - shift_units * px_per_unit), cell_span_min, fade_den); @@ -114,20 +115,20 @@ void Chrome_renderer::render_grid_and_backgrounds( profiler, "renderer.frame.chrome.grid_and_backgrounds"); - const auto& pl = ctx.layout; + const auto& pl = ctx.layout; const Color_palette palette = resolved_color_palette(ctx.config, ctx.dark_mode); - const glm::vec4 h_label_color = palette.h_label_background; - const glm::vec4 v_label_color = palette.v_label_background; - const double grid_visibility = ctx.config ? ctx.config->grid_visibility : 1.0; + const glm::vec4 h_label_color = palette.h_label_background; + const glm::vec4 v_label_color = palette.v_label_background; + const double grid_visibility = ctx.config ? ctx.config->grid_visibility : 1.0; const glm::vec4 grid_rgb = glm::vec4( palette.grid_line.r, palette.grid_line.g, palette.grid_line.b, palette.grid_line.a * static_cast(grid_visibility)); - const glm::vec4 tick_rgb = grid_rgb; + const glm::vec4 tick_rgb = grid_rgb; const glm::vec4 preview_background = palette.preview_background; - const glm::vec4 separator_color = palette.separator; + const glm::vec4 separator_color = palette.separator; // Background panes and separators (batch_rect is CPU work) prims.batch_rect(preview_background, @@ -158,10 +159,10 @@ void Chrome_renderer::render_grid_and_backgrounds( double(ctx.v0), double(ctx.v1), pl.usable_height, ctx.adjusted_font_px); // Grid spacing math runs in fp64 seconds; the shift origin is the // (rebased) seconds-domain t_min that the axis uniforms already use. - constexpr double k_seconds_per_ns = 1.0e-9; - const double t0_seconds = static_cast(ctx.t0) * k_seconds_per_ns; - const double t1_seconds = static_cast(ctx.t1) * k_seconds_per_ns; - bool dropped_non_multiple_step = false; + constexpr double k_seconds_per_ns = 1.0e-9; + const double t0_seconds = static_cast(ctx.t0) * k_seconds_per_ns; + const double t1_seconds = static_cast(ctx.t1) * k_seconds_per_ns; + bool dropped_non_multiple_step = false; const grid_layer_params_t horizontal_levels = build_time_grid_layers( t0_seconds, t1_seconds, @@ -208,8 +209,8 @@ void Chrome_renderer::render_grid_and_backgrounds( if (ticks.count >= grid_layer_params_t::k_max_levels) { break; } - const float pos = get_pos(label); - const auto props = match_level_properties(pos, main_levels); + const float pos = get_pos(label); + const auto props = match_level_properties(pos, main_levels); ticks.spacing_px[ticks.count] = 1e6f; ticks.start_px[ticks.count] = pos; ticks.alpha[ticks.count] = props.first; @@ -259,7 +260,7 @@ void Chrome_renderer::render_zero_line( } const Color_palette palette = resolved_color_palette(ctx.config, ctx.dark_mode); - const glm::vec4 color = palette.grid_line; + const glm::vec4 color = palette.grid_line; const auto& pl = ctx.layout; const glm::vec2 main_top_left{0.0f, 0.0f}; @@ -305,10 +306,10 @@ void Chrome_renderer::render_preview_overlay( } const long double t_avail_span = *t_avail_span_ns; - const Color_palette palette = resolved_color_palette(ctx.config, ctx.dark_mode); - const glm::vec4 cover_color = palette.preview_cover; - const glm::vec4 cover_color2 = palette.preview_cover_secondary; - const glm::vec4 separator_color = palette.separator; + const Color_palette palette = resolved_color_palette(ctx.config, ctx.dark_mode); + const glm::vec4 cover_color = palette.preview_cover; + const glm::vec4 cover_color2 = palette.preview_cover_secondary; + const glm::vec4 separator_color = palette.separator; // CPU calculations const double x0 = static_cast( @@ -318,7 +319,7 @@ void Chrome_renderer::render_preview_overlay( static_cast(ctx.win_w) * (1.0L - span_ns_as_long_double(ctx.t1, ctx.t_available_max) / t_avail_span)); - const double dd = x1 - x0; + const double dd = x1 - x0; const double win_w = ctx.win_w; // Top of the preview band, derived directly from win_h and the band's // own height. The earlier formulation went via usable_height + label diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 2f9f4cc3..d28db895 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -37,14 +37,14 @@ namespace vnm::plot { namespace { -constexpr std::uint32_t k_cache_version = 4; -constexpr double k_min_atlas_font_size = 48.0; -constexpr float k_atlas_px_range = 10.0f; +constexpr std::uint32_t k_cache_version = 4; +constexpr double k_min_atlas_font_size = 48.0; +constexpr float k_atlas_px_range = 10.0f; // 1.0 is a one-output-pixel anti-aliasing ramp now that vnm_msdf_text encodes // atlas_px_range in true atlas pixels; 2.5 compensated for the shallow // font-dependent encode the builder produced before that conversion. -constexpr float k_sharpness_bias = 1.0f; -constexpr int k_atlas_texture_size = 2048; +constexpr float k_sharpness_bias = 1.0f; +constexpr int k_atlas_texture_size = 2048; // Hashed into the font digest so a change in the builder's bake semantics // re-keys the cache. The atlas_px_range suffix marks the corrected encode // (range converted to msdfgen shape units, so SDF slope is font-independent). @@ -298,17 +298,16 @@ void add_text_to_vectors( std::vector vertices; vertices.reserve(source_vertices.size()); for (std::size_t i = 0; i < source_vertices.size(); i += 4u) { - const text_vertex_t& a = source_vertices[i + 0u]; - const text_vertex_t& b = source_vertices[i + 1u]; - const text_vertex_t& c = source_vertices[i + 2u]; - const text_vertex_t& d = source_vertices[i + 3u]; - - const float frame_left = std::min(std::min(a.x, b.x), std::min(c.x, d.x)); - const float frame_top = std::min(std::min(a.y, b.y), std::min(c.y, d.y)); - const float frame_right = std::max(std::max(a.x, b.x), std::max(c.x, d.x)); - const float frame_bottom = std::max(std::max(a.y, b.y), std::max(c.y, d.y)); - const float frame_width = frame_right - frame_left; - const float frame_height = frame_bottom - frame_top; + const text_vertex_t& a = source_vertices[i + 0u]; + const text_vertex_t& b = source_vertices[i + 1u]; + const text_vertex_t& c = source_vertices[i + 2u]; + const text_vertex_t& d = source_vertices[i + 3u]; + const float frame_left = std::min(std::min(a.x, b.x), std::min(c.x, d.x)); + const float frame_top = std::min(std::min(a.y, b.y), std::min(c.y, d.y)); + const float frame_right = std::max(std::max(a.x, b.x), std::max(c.x, d.x)); + const float frame_bottom = std::max(std::max(a.y, b.y), std::max(c.y, d.y)); + const float frame_width = frame_right - frame_left; + const float frame_height = frame_bottom - frame_top; const auto append_vertex = [&](const text_vertex_t& vertex) { vertices.push_back(rhi_text_vertex_t{ @@ -340,11 +339,11 @@ void add_text_to_vectors( return; } - std::size_t added_float_count = 0; - std::size_t new_float_count = 0; - std::size_t new_index_count = 0; - std::size_t new_vertex_count = 0; - quint32 checked_qrhi_value = 0; + std::size_t added_float_count = 0; + std::size_t new_float_count = 0; + std::size_t new_index_count = 0; + std::size_t new_vertex_count = 0; + quint32 checked_qrhi_value = 0; if (!detail::checked_size_product( vertices.size(), k_text_vertex_float_count, added_float_count) || !detail::checked_size_add(vertex_data.size(), added_float_count, new_float_count) || @@ -488,9 +487,9 @@ std::shared_ptr load_cached_font_from_disk( return bool(in); }; - std::uint32_t magic = 0; + std::uint32_t magic = 0; std::uint32_t version = 0; - std::uint32_t height = 0; + std::uint32_t height = 0; if (!read(magic) || !read(version) || !read(height)) { return nullptr; } @@ -559,8 +558,8 @@ std::shared_ptr load_cached_font_from_disk( return nullptr; } for (std::uint32_t i = 0; i < glyph_count; ++i) { - std::uint32_t code = 0; - std::uint8_t visible = 0; + std::uint32_t code = 0; + std::uint8_t visible = 0; msdf_glyph_t g{}; if (!read(code) || !read(g.advance_units) || @@ -743,7 +742,7 @@ std::shared_ptr load_or_build_font_cache( } const auto font_digest = compute_font_digest(); - const bool disk_cache = s_disk_cache_enabled.load(std::memory_order_relaxed); + const bool disk_cache = s_disk_cache_enabled.load(std::memory_order_relaxed); auto cached = get_cached_font(pixel_height, font_digest); if (!cached && disk_cache) { @@ -1066,9 +1065,9 @@ float Font_renderer::compute_numeric_bottom() const if (!atlas) { return 0.0f; } - static const char* k_sample = "0123456789-+.,"; - const int draw_px = m_impl->current_draw_pixel_height(); - float max_bottom = -std::numeric_limits::infinity(); + static const char* k_sample = "0123456789-+.,"; + const int draw_px = m_impl->current_draw_pixel_height(); + float max_bottom = -std::numeric_limits::infinity(); for (const char* p = k_sample; *p; ++p) { const auto it = atlas->glyphs.find(static_cast(*p)); if (it != atlas->glyphs.end()) { @@ -1181,9 +1180,9 @@ void Font_renderer::rhi_queue_draw( } std::size_t new_vertex_float_count = 0; - std::size_t new_index_count = 0; - std::size_t queued_vertex_count = 0; - quint32 checked_qrhi_bytes = 0; + std::size_t new_index_count = 0; + std::size_t queued_vertex_count = 0; + quint32 checked_qrhi_bytes = 0; if (!detail::checked_size_add( m_impl->m_rhi_frame_vertex_data.size(), m_impl->m_rhi_vertex_data.size(), @@ -1217,7 +1216,8 @@ void Font_renderer::rhi_queue_draw( } auto& rhi_state = m_impl->m_rhi; - QRhi* rhi = ctx.rhi; + QRhi* rhi = ctx.rhi; + QRhiResourceUpdateBatch* updates = ctx.rhi_updates; if (rhi_state.last_rhi != rhi) { @@ -1280,7 +1280,7 @@ void Font_renderer::rhi_queue_draw( rhi_state.calls.emplace_back(); } const std::size_t call_index = rhi_state.call_used++; - auto& call = rhi_state.calls[call_index]; + auto& call = rhi_state.calls[call_index]; if (!call.ubo) { call.ubo.reset(rhi->newBuffer( @@ -1327,7 +1327,7 @@ void Font_renderer::rhi_queue_draw( return call_index; }; - const bool has_shadow = shadow.radius_px > 0.0f && shadow.color.a > 0.0f; + const bool has_shadow = shadow.radius_px > 0.0f && shadow.color.a > 0.0f; text_lcd_t effective_lcd = lcd; if (has_shadow) { effective_lcd.subpixel_order = text_lcd_resolved_subpixel_order_t::NONE; @@ -1340,7 +1340,7 @@ void Font_renderer::rhi_queue_draw( return; } - std::size_t shadow_call_index = std::numeric_limits::max(); + std::size_t shadow_call_index = std::numeric_limits::max(); std::size_t foreground_call_index = first_call_index; if (has_shadow) { shadow_call_index = first_call_index; @@ -1354,8 +1354,8 @@ void Font_renderer::rhi_queue_draw( auto& first_call = rhi_state.calls[first_call_index]; - QRhiRenderPassDescriptor* current_rpd = ctx.render_target->renderPassDescriptor(); - const int current_samples = ctx.render_target->sampleCount(); + QRhiRenderPassDescriptor* current_rpd = ctx.render_target->renderPassDescriptor(); + const int current_samples = ctx.render_target->sampleCount(); if (rhi_state.pipeline && (rhi_state.pipeline_rpd != current_rpd || rhi_state.pipeline_samples != current_samples)) @@ -1504,10 +1504,10 @@ void Font_renderer::rhi_finalize_frame(const frame_context_t& ctx) QRhi* rhi = ctx.rhi; QRhiResourceUpdateBatch* updates = ctx.rhi_updates; - std::size_t vertex_bytes = 0; - std::size_t index_bytes = 0; - quint32 qrhi_vertex_bytes = 0; - quint32 qrhi_index_bytes = 0; + std::size_t vertex_bytes = 0; + std::size_t index_bytes = 0; + quint32 qrhi_vertex_bytes = 0; + quint32 qrhi_index_bytes = 0; if (!detail::qrhi_byte_size( m_impl->m_rhi_frame_vertex_data.size(), sizeof(float), vertex_bytes, qrhi_vertex_bytes) || @@ -1520,8 +1520,8 @@ void Font_renderer::rhi_finalize_frame(const frame_context_t& ctx) } if (!rhi_state.vbo || rhi_state.vbo_capacity_bytes < vertex_bytes) { - std::size_t alloc = 0; - quint32 qrhi_alloc = 0; + std::size_t alloc = 0; + quint32 qrhi_alloc = 0; if (!detail::qrhi_grown_capacity_bytes(vertex_bytes, alloc, qrhi_alloc)) { rhi_reset_frame(); return; @@ -1539,8 +1539,8 @@ void Font_renderer::rhi_finalize_frame(const frame_context_t& ctx) } if (!rhi_state.ibo || rhi_state.ibo_capacity_bytes < index_bytes) { - std::size_t alloc = 0; - quint32 qrhi_alloc = 0; + std::size_t alloc = 0; + quint32 qrhi_alloc = 0; if (!detail::qrhi_grown_capacity_bytes(index_bytes, alloc, qrhi_alloc)) { rhi_reset_frame(); return; diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 9590cfc3..2055e3e6 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -484,15 +484,16 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par "renderer.frame.calculate_layout.impl.cache_miss.pass1.vertical_axis"); const int divs[2] = {5, 2}; - double step = 1.0; - double test = 0.0; - int i = 16; - int initial_level_index = 0; - double initial_level_step = 0.0; - double px_per_unit = 0.0; - float label_box_height_px = 0.0f; - float label_gap_px = 0.0f; - float min_label_spacing_px = 0.0f; + double step = 1.0; + double test = 0.0; + int i = 16; + int initial_level_index = 0; + + double initial_level_step = 0.0; + double px_per_unit = 0.0; + float label_box_height_px = 0.0f; + float label_gap_px = 0.0f; + float min_label_spacing_px = 0.0f; double finest_step_accepted = 0.0; auto& accepted_boxes = m_scratch_accepted_boxes; @@ -557,11 +558,12 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par }; for (int guard = 0; guard < 64; ++guard) { - double shift = 0.0; - double extend = 0.0; - int j_min = 0; - int j_max = 0; - auto& this_vals = m_scratch_vals; + double shift = 0.0; + double extend = 0.0; + int j_min = 0; + int j_max = 0; + auto& this_vals = m_scratch_vals; + bool skip_level_due_to_conflict = false; { @@ -583,7 +585,7 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par "renderer.frame.calculate_layout.impl.cache_miss.pass1.vertical_axis.scan"); for (int j = j_min; j <= j_max; ++j) { const double v = double(params.v_min) + shift + j * step; - const float y = y_of(v); + const float y = y_of(v); if (y <= 0.f || y >= float(params.label_visible_height)) { continue; @@ -703,8 +705,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par } // Format and measure labels - float advance = 0.f; - bool use_monospace = false; + float advance = 0.f; + bool use_monospace = false; { VNM_PLOT_PROFILE_SCOPE( profiler, @@ -761,8 +763,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par // timestamp bounds cannot overflow before the double-domain layout math. constexpr double k_ns_per_second_d = 1.0e9; constexpr double k_seconds_per_ns = 1.0 / k_ns_per_second_d; - double t_range = 0.0; - const double t_min_seconds = static_cast(params.t_min) * k_seconds_per_ns; + double t_range = 0.0; + const double t_min_seconds = static_cast(params.t_min) * k_seconds_per_ns; { VNM_PLOT_PROFILE_SCOPE( profiler, @@ -779,11 +781,11 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis"); constexpr float k_coincide = 1.0f; - const float min_gap = 10.0f; + const float min_gap = 10.0f; - double px_per_t = 0.0; - float advance = 0.f; - bool use_monospace = false; + double px_per_t = 0.0; + float advance = 0.f; + bool use_monospace = false; std::vector steps; { VNM_PLOT_PROFILE_SCOPE( @@ -834,11 +836,11 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par level.reserve(32); } - const int start_si = si; + const int start_si = si; const double start_step = (si >= 0 && si < static_cast(steps.size())) ? steps[si] : 0.0; - bool any_level = false; - bool any_subsec = false; + bool any_level = false; + bool any_subsec = false; double finest_step = 0.0; for (; si >= 0; --si) { @@ -861,11 +863,11 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par float x_anchor; }; std::vector candidates; - float right_vis = 0.0f; - float pixel_step = 0.0f; - float optimistic_width = 0.0f; - float estimated_label_width = 0.0f; - double t_start = 0.0; + float right_vis = 0.0f; + float pixel_step = 0.0f; + float optimistic_width = 0.0f; + float estimated_label_width = 0.0f; + double t_start = 0.0; { VNM_PLOT_PROFILE_SCOPE( profiler, @@ -920,13 +922,13 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par format_signature); } - int64_t tick_index = 0; - double t = t_start; - const double t_max_seconds = static_cast(params.t_max) * k_seconds_per_ns; - float last_width = estimated_label_width; - bool have_prev_candidate = false; - float prev_candidate_x1 = std::numeric_limits::lowest(); - bool step_invalid = false; + int64_t tick_index = 0; + double t = t_start; + const double t_max_seconds = static_cast(params.t_max) * k_seconds_per_ns; + float last_width = estimated_label_width; + bool have_prev_candidate = false; + float prev_candidate_x1 = std::numeric_limits::lowest(); + bool step_invalid = false; { VNM_PLOT_PROFILE_SCOPE( @@ -975,9 +977,9 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par break; } - float w = 0.0f; - const Cached_label* cached = nullptr; - const bool cache_hit = timestamp_label_cache().try_get(t, cached); + float w = 0.0f; + const Cached_label* cached = nullptr; + const bool cache_hit = timestamp_label_cache().try_get(t, cached); if (cache_hit) { VNM_PLOT_PROFILE_SCOPE( @@ -1049,7 +1051,7 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par prev_candidate_x1 = x + w; const float required_spacing = w + min_gap; - const int skip = std::max(1, int(std::ceil(required_spacing / pixel_step))); + const int skip = std::max(1, int(std::ceil(required_spacing / pixel_step))); tick_index += skip; t = t_start + tick_index * step; } @@ -1188,7 +1190,7 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par }); float prev_right = -std::numeric_limits::max(); - auto write = res.h_labels.begin(); + auto write = res.h_labels.begin(); for (auto it = res.h_labels.begin(); it != res.h_labels.end(); ++it) { float w = 0.f; if (use_monospace && advance > 0.f) { diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index be6e02a9..248d0719 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -404,9 +404,9 @@ void Primitive_renderer::flush_rects(const frame_context_t& ctx, const glm::mat4 return; } - std::size_t bytes_needed = 0; - quint32 upload_bytes = 0; - quint32 instance_count = 0; + std::size_t bytes_needed = 0; + quint32 upload_bytes = 0; + quint32 instance_count = 0; if (!detail::qrhi_byte_size( m_cpu_buffer.size(), sizeof(rect_vertex_t), bytes_needed, upload_bytes) || @@ -430,8 +430,8 @@ void Primitive_renderer::flush_rects(const frame_context_t& ctx, const glm::mat4 // where the rect count drifts slightly. The grow reseats call.vbo, // which invalidates the SRB's last_ubo handle (UBO is unchanged), // and forces ensure-* to upload fresh contents. - std::size_t alloc = 0; - quint32 qrhi_alloc = 0; + std::size_t alloc = 0; + quint32 qrhi_alloc = 0; if (!detail::qrhi_grown_capacity_bytes( bytes_needed, alloc, qrhi_alloc)) { diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index feb7b0b2..866957a7 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -148,8 +148,8 @@ inline bool qrhi_grown_capacity_bytes( const std::size_t max_qrhi_bytes = static_cast(std::numeric_limits::max()); - const std::size_t headroom = bytes_needed / 4u; - std::size_t capacity_bytes = 0; + const std::size_t headroom = bytes_needed / 4u; + std::size_t capacity_bytes = 0; if (!checked_size_add(bytes_needed, headroom, capacity_bytes) || capacity_bytes > max_qrhi_bytes) { diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index c5e9be36..aa1afcf3 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -39,8 +39,8 @@ constexpr float k_default_color_epsilon = 0.01f; std::vector source_lod_scales(const Data_source& source) { - const std::size_t level_count = source.lod_levels(); - std::vector scales = source.lod_scales(); + const std::size_t level_count = source.lod_levels(); + std::vector scales = source.lod_scales(); if (scales.size() != level_count) { scales = compute_lod_scales(source); } @@ -701,7 +701,7 @@ void Series_renderer::prepare( VNM_PLOT_PROFILE_SCOPE(profiler, "renderer.frame.execute_passes.render_data_series.prepare"); - QRhi* rhi = ctx.rhi; + QRhi* rhi = ctx.rhi; QRhiResourceUpdateBatch* rhi_updates = ctx.rhi_updates; if (m_rhi_state->last_rhi && m_rhi_state->last_rhi != rhi) { for (auto& [key, entry] : m_rhi_state->qrhi_layer_cache) { @@ -730,7 +730,7 @@ void Series_renderer::prepare( draw_states.reserve(series.size()); const double preview_visibility = ctx.config ? ctx.config->preview_visibility : 1.0; - const bool preview_visible = ctx.adjusted_preview_height > 0.0 && preview_visibility > 0.0; + const bool preview_visible = ctx.adjusted_preview_height > 0.0 && preview_visibility > 0.0; m_rhi_state->frame_preview_visible = preview_visible; const std::int64_t main_span_ns = positive_span_ns_for_signed_api(ctx.t0, ctx.t1); @@ -774,9 +774,9 @@ void Series_renderer::prepare( const Data_access_policy& main_access = s->main_access(); - Display_style main_style = s->style; + Display_style main_style = s->style; Series_interpolation main_interpolation = s->interpolation; - const auto& qrhi_layers = qrhi_layers_for(*s); + const auto& qrhi_layers = qrhi_layers_for(*s); const auto has_layer_for_view = [&](Series_view_kind view_kind) { return std::any_of( qrhi_layers.begin(), @@ -790,13 +790,14 @@ void Series_renderer::prepare( continue; } - const bool has_preview_config = s->has_preview_config(); - Data_source* preview_source = nullptr; - const Data_access_policy* preview_access = nullptr; - Display_style preview_style = Display_style::NONE; - Series_interpolation preview_interpolation = Series_interpolation::LINEAR; - bool preview_matches_main = false; - bool preview_valid = false; + const bool has_preview_config = s->has_preview_config(); + Data_source* preview_source = nullptr; + const Data_access_policy* preview_access = nullptr; + Display_style preview_style = Display_style::NONE; + Series_interpolation preview_interpolation = Series_interpolation::LINEAR; + bool preview_matches_main = false; + + bool preview_valid = false; bool has_preview_layer = false; if (preview_visible) { @@ -1326,8 +1327,8 @@ void Series_renderer::prepare( hash_drawable_spans(window.drawable_spans); data_key.access_key = layer_access_key; - auto& cache_entry = m_rhi_state->qrhi_layer_cache[program_key]; - bool resources_changed = false; + auto& cache_entry = m_rhi_state->qrhi_layer_cache[program_key]; + bool resources_changed = false; if (!cache_entry.state) { cache_entry.state = layer->create_state(*rhi); resources_changed = true; @@ -1439,9 +1440,9 @@ void Series_renderer::prepare( return false; } - const series_data_t& series_data = *series_it->second; - const Data_source* source = nullptr; - const Data_access_policy* access = nullptr; + const series_data_t& series_data = *series_it->second; + const Data_source* source = nullptr; + const Data_access_policy* access = nullptr; if (key.view_kind == Series_view_kind::MAIN) { source = series_data.main_source(); access = &series_data.main_access(); @@ -1650,8 +1651,8 @@ bool Series_renderer::rhi_prepare_series_view_samples( return false; } - std::size_t expected_gpu_count = 0; - bool synthetic_hold_seen = false; + std::size_t expected_gpu_count = 0; + bool synthetic_hold_seen = false; for (std::size_t span_index = 0; span_index < window.drawable_spans.size(); ++span_index) @@ -1703,8 +1704,8 @@ bool Series_renderer::rhi_prepare_series_view_samples( } std::size_t needed_elements = 0; - std::size_t needed_bytes = 0; - quint32 upload_bytes = 0; + std::size_t needed_bytes = 0; + quint32 upload_bytes = 0; if (!detail::checked_size_add(window.gpu_count, 0u, needed_elements) || !detail::qrhi_byte_size( needed_elements, sizeof(gpu_sample_t), @@ -1739,7 +1740,7 @@ bool Series_renderer::rhi_prepare_series_view_samples( for (const drawable_sample_span_t& span : window.drawable_spans) { for (std::size_t i = 0; i < span.source_count; ++i) { const std::size_t source_index = span.source_first + i; - const void* src = snapshot.at(source_index); + const void* src = snapshot.at(source_index); if (!src || !stage_one_sample( staging[span.gpu_first + i], @@ -1766,8 +1767,8 @@ bool Series_renderer::rhi_prepare_series_view_samples( } } - std::size_t alloc_bytes = 0; - quint32 qrhi_alloc_bytes = 0; + std::size_t alloc_bytes = 0; + quint32 qrhi_alloc_bytes = 0; if (!detail::qrhi_grown_capacity_bytes( needed_bytes, alloc_bytes, qrhi_alloc_bytes)) { @@ -1830,9 +1831,9 @@ bool Series_renderer::rhi_prepare_series_primitive( QRhi* rhi = ctx.rhi; QRhiResourceUpdateBatch* updates = ctx.rhi_updates; - const bool is_dots = (primitive_style == Display_style::DOTS); - const bool is_area = (primitive_style == Display_style::AREA); - const std::size_t count = window.gpu_count; + const bool is_dots = (primitive_style == Display_style::DOTS); + const bool is_area = (primitive_style == Display_style::AREA); + const std::size_t count = window.gpu_count; if (count == 0) { return false; } @@ -1951,15 +1952,15 @@ bool Series_renderer::rhi_prepare_series_primitive( } std::size_t needed_bytes = 0; - quint32 upload_bytes = 0; + quint32 upload_bytes = 0; if (!detail::qrhi_byte_size( total_padded_count, sizeof(gpu_sample_t), needed_bytes, upload_bytes)) { return false; } - std::size_t alloc_bytes = 0; - quint32 qrhi_alloc_bytes = 0; + std::size_t alloc_bytes = 0; + quint32 qrhi_alloc_bytes = 0; if (!detail::qrhi_grown_capacity_bytes( needed_bytes, alloc_bytes, qrhi_alloc_bytes)) { @@ -2079,8 +2080,8 @@ bool Series_renderer::rhi_prepare_series_primitive( // the FBO can swap the descriptor out from under us, leaving the cached // pipeline incompatible with the new pass; rebuild when the descriptor // or sample count moves. - QRhiRenderPassDescriptor* current_rpd = rt->renderPassDescriptor(); - const int current_samples = rt->sampleCount(); + QRhiRenderPassDescriptor* current_rpd = rt->renderPassDescriptor(); + const int current_samples = rt->sampleCount(); if (cached.pipeline && (cached.last_rpd != current_rpd || cached.last_sample_count != current_samples)) @@ -2288,9 +2289,9 @@ void Series_renderer::rhi_record_series_primitive( return; } - const bool is_dots = (primitive_style == Display_style::DOTS); - const bool is_area = (primitive_style == Display_style::AREA); - const std::size_t count = window.gpu_count; + const bool is_dots = (primitive_style == Display_style::DOTS); + const bool is_area = (primitive_style == Display_style::AREA); + const std::size_t count = window.gpu_count; if (count == 0) { return; } @@ -2351,8 +2352,8 @@ void Series_renderer::rhi_record_series_primitive( return; } quint32 instance_count = 0; - quint32 first_offset = 0; - quint32 next_offset = 0; + quint32 first_offset = 0; + quint32 next_offset = 0; if (!detail::to_qrhi_count(span.gpu_count - 1u, instance_count) || !detail::qrhi_buffer_offset( span.gpu_first, @@ -2390,15 +2391,15 @@ void Series_renderer::rhi_record_series_primitive( if (line_span.line_count < 2) { continue; } - const std::size_t offset0 = line_span.line_first; - std::size_t offset1 = 0; - std::size_t offset2 = 0; - std::size_t offset3 = 0; - quint32 qrhi_offset0 = 0; - quint32 qrhi_offset1 = 0; - quint32 qrhi_offset2 = 0; - quint32 qrhi_offset3 = 0; - quint32 instance_count = 0; + const std::size_t offset0 = line_span.line_first; + std::size_t offset1 = 0; + std::size_t offset2 = 0; + std::size_t offset3 = 0; + quint32 qrhi_offset0 = 0; + quint32 qrhi_offset1 = 0; + quint32 qrhi_offset2 = 0; + quint32 qrhi_offset3 = 0; + quint32 instance_count = 0; if (!detail::checked_size_add( line_span.line_first, 1u, diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index ae303e10..3cdaa40b 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -153,7 +153,7 @@ bool select_hold_source_index( if (nonfinite_policy == Nonfinite_sample_policy::SKIP) { for (std::size_t offset = candidate_index + 1u; offset > 0; --offset) { - const std::size_t index = offset - 1u; + const std::size_t index = offset - 1u; const sample_draw_status_t status = status_at(index); if (status == sample_draw_status_t::DRAWABLE) { out_index = index; @@ -202,9 +202,10 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) return plan; } - auto& state = *request.planner_state; - auto& snapshot_cache = *request.snapshot_cache; - Data_source& data_source = *request.data_source; + auto& state = *request.planner_state; + auto& snapshot_cache = *request.snapshot_cache; + Data_source& data_source = *request.data_source; + const Data_access_policy& access = *request.access; const erased_access_policy_t access_view = make_erased_access_policy_view(access); @@ -224,7 +225,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) reset_snapshot_cache(snapshot_cache); } - const std::size_t level_count = scales.size(); + const std::size_t level_count = scales.size(); const std::size_t max_level_index = level_count > 0 ? level_count - 1 : 0; std::size_t target_level = std::min( state.has_last_lod_level ? state.last_lod_level : 0, @@ -358,8 +359,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) break; } mark_tried(applied_level); - const std::size_t applied_scale = scales[applied_level]; - bool hold_last_forward = false; + const std::size_t applied_scale = scales[applied_level]; + bool hold_last_forward = false; const std::uint64_t current_seq = data_source.current_sequence(applied_level); if (current_seq != 0 && @@ -420,13 +421,13 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) break; } - const auto& snapshot = snapshot_result.snapshot; - bool have_direct_time_window = false; - bool direct_time_window_empty = false; - bool direct_time_window_failed = false; - std::size_t direct_first_idx = 0; - std::size_t direct_last_idx = 0; - bool direct_hold_last_forward = false; + const auto& snapshot = snapshot_result.snapshot; + bool have_direct_time_window = false; + bool direct_time_window_empty = false; + bool direct_time_window_failed = false; + std::size_t direct_first_idx = 0; + std::size_t direct_last_idx = 0; + bool direct_hold_last_forward = false; if (direct_time_window.attempted && direct_time_window.result.sequence != 0 && direct_time_window.result.sequence == snapshot.sequence) @@ -438,9 +439,9 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) } else if (direct_time_window.result.status == Data_query_status::READY) { - const std::size_t first = direct_time_window.result.value.first; - const std::size_t count = direct_time_window.result.value.count; - std::size_t last_exclusive = first; + const std::size_t first = direct_time_window.result.value.first; + const std::size_t count = direct_time_window.result.value.count; + std::size_t last_exclusive = first; if (count == 0) { have_direct_time_window = true; direct_time_window_empty = true; @@ -455,7 +456,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) direct_last_idx = last_exclusive; if (access_view.has_timestamp()) { bool has_match_in_requested_window = false; - bool direct_window_valid = true; + bool direct_window_valid = true; for (std::size_t index = first; index < last_exclusive; ++index) @@ -569,8 +570,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) } else if (access_view.has_timestamp()) { - const void* current_identity = data_source.identity(); - const Time_order source_order = data_source.time_order(applied_level); + const void* current_identity = data_source.identity(); + const Time_order source_order = data_source.time_order(applied_level); if (source_order == Time_order::ASCENDING) { state.last_timestamp_order_sequence = snapshot.sequence; state.last_timestamp_order_identity = current_identity; @@ -631,10 +632,10 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) timestamps_monotonic = state.last_timestamps_monotonic; } - std::size_t first_idx = 0; - std::size_t last_idx = snapshot.count; - std::int64_t last_ts = 0; - bool have_last_ts = false; + std::size_t first_idx = 0; + std::size_t last_idx = snapshot.count; + std::int64_t last_ts = 0; + bool have_last_ts = false; if (have_direct_time_window) { if (direct_time_window_empty) { first_idx = snapshot.count; @@ -700,7 +701,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) if (first_idx >= last_idx) { if (can_hold_last_forward) { std::size_t hold_source_index = 0; - bool hold_failed = false; + bool hold_failed = false; if (select_hold_source_index( snapshot, access_view, @@ -749,7 +750,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) first_idx < last_idx) { bool has_drawable_sample_in_requested_window = false; - bool failed_sample_in_requested_window = false; + bool failed_sample_in_requested_window = false; for (std::size_t index = first_idx; index < last_idx; ++index) { const void* sample = snapshot.at(index); if (!sample) { @@ -783,7 +784,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) get_timestamp(first_sample) < request.t_min_ns) { std::size_t hold_source_index = 0; - bool hold_failed = false; + bool hold_failed = false; if (select_hold_source_index( snapshot, access_view, @@ -827,7 +828,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) last_idx > 0) { std::size_t hold_source_index = 0; - bool hold_failed = false; + bool hold_failed = false; if (select_hold_source_index( snapshot, access_view, @@ -855,8 +856,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) break; } - const std::size_t source_count = last_idx - first_idx; - std::size_t count_for_lod = 0; + const std::size_t source_count = last_idx - first_idx; + std::size_t count_for_lod = 0; if (!checked_size_add( source_count, hold_last_forward ? 1u : 0u, diff --git a/src/core/text_renderer.cpp b/src/core/text_renderer.cpp index 5a112e2b..7112f28d 100644 --- a/src/core/text_renderer.cpp +++ b/src/core/text_renderer.cpp @@ -29,7 +29,7 @@ using detail::k_value_decimals; namespace { -constexpr float k_text_shadow_alpha = 0.76f; +constexpr float k_text_shadow_alpha = 0.76f; constexpr float k_text_shadow_min_radius_px = 1.05f; constexpr float k_text_shadow_max_radius_px = 2.25f; constexpr float k_text_shadow_radius_factor = 0.19f; @@ -120,8 +120,8 @@ bool update_and_draw_faded_labels( { using key_t = typename Tracker::key_type; - const auto now = std::chrono::steady_clock::now(); - float dt_ms = 0.0f; + const auto now = std::chrono::steady_clock::now(); + float dt_ms = 0.0f; if (tracker.initialized) { dt_ms = std::chrono::duration_cast>(now - tracker.last_update).count(); } @@ -252,10 +252,10 @@ bool Text_renderer::render_axis_labels( bool fade_labels, bool vertical_axis_label_pane_is_opaque) { - const auto& pl = ctx.layout; - const bool dark_mode = ctx.dark_mode; - const glm::vec4 font_color = text_color_for_theme(dark_mode); - const Color_palette palette = resolved_color_palette(ctx.config, dark_mode); + const auto& pl = ctx.layout; + const bool dark_mode = ctx.dark_mode; + const glm::vec4 font_color = text_color_for_theme(dark_mode); + const Color_palette palette = resolved_color_palette(ctx.config, dark_mode); const text_lcd_resolved_subpixel_order_t frame_order = text_lcd_frame_order(ctx); const bool label_lcd_possible = detail::text_lcd_draw_is_eligible( detail::text_lcd_draw_surface_t::VERTICAL_AXIS_LABEL, @@ -265,9 +265,9 @@ bool Text_renderer::render_axis_labels( const float right_edge_x = static_cast( pl.usable_width + pl.v_bar_width - k_v_label_horizontal_padding_px); - const float min_x = static_cast(pl.usable_width + k_text_margin_px); - const float baseline_off = m_fonts->baseline_offset_px(); - const double v_span = double(ctx.v1) - double(ctx.v0); + const float min_x = static_cast(pl.usable_width + k_text_margin_px); + const float baseline_off = m_fonts->baseline_offset_px(); + const double v_span = double(ctx.v1) - double(ctx.v0); text_scissor_t label_scissor; glm::vec4 label_backing_rect; @@ -300,7 +300,7 @@ bool Text_renderer::render_axis_labels( } const double px_per_unit = pl.usable_height / v_span; - const float label_y = static_cast(pl.usable_height - (value - double(ctx.v0)) * px_per_unit); + const float label_y = static_cast(pl.usable_height - (value - double(ctx.v0)) * px_per_unit); const float baseline_target = label_y - k_scissor_pad_px @@ -308,7 +308,7 @@ bool Text_renderer::render_axis_labels( const float pen_y = baseline_target - baseline_off; const float text_width = m_fonts->measure_text_px(state.text.c_str()); - float pen_x = right_edge_x - text_width; + float pen_x = right_edge_x - text_width; if (pen_x < min_x) { pen_x = min_x; } @@ -317,7 +317,7 @@ bool Text_renderer::render_axis_labels( const float snapped_y = std::floor(pen_y + k_pixel_snap); glm::vec4 text_bounds; - bool have_text_bounds = false; + bool have_text_bounds = false; bool text_fits_label_backing = false; if (label_lcd_possible && label_scissor.enabled && @@ -380,10 +380,10 @@ bool Text_renderer::render_info_overlay( bool fade_labels, bool horizontal_axis_label_pane_is_opaque) { - const auto& pl = ctx.layout; - const bool dark_mode = ctx.dark_mode; - const glm::vec4 font_color = text_color_for_theme(dark_mode); - const Color_palette palette = resolved_color_palette(ctx.config, dark_mode); + const auto& pl = ctx.layout; + const bool dark_mode = ctx.dark_mode; + const glm::vec4 font_color = text_color_for_theme(dark_mode); + const Color_palette palette = resolved_color_palette(ctx.config, dark_mode); const text_lcd_resolved_subpixel_order_t frame_order = text_lcd_frame_order(ctx); const bool label_lcd_possible = detail::text_lcd_draw_is_eligible( detail::text_lcd_draw_surface_t::HORIZONTAL_AXIS_LABEL, @@ -420,7 +420,7 @@ bool Text_renderer::render_info_overlay( pl.usable_height + k_h_label_vertical_nudge_px * ctx.adjusted_font_px); glm::vec4 text_bounds; - bool have_text_bounds = false; + bool have_text_bounds = false; bool text_fits_label_scissor = false; bool text_fits_label_backing = false; if (ctx.rhi && label_scissor.enabled && have_label_backing) { diff --git a/src/core/time_grid.cpp b/src/core/time_grid.cpp index 6f8d84d9..3e8fe4aa 100644 --- a/src/core/time_grid.cpp +++ b/src/core/time_grid.cpp @@ -70,8 +70,8 @@ grid_layer_params_t build_time_grid_layers( font_px * (detail::k_cell_span_max_factor - detail::k_cell_span_min_factor)); const double px_per_unit = width_px / range; - const auto steps = detail::build_time_steps_covering(range); - int idx = std::max(0, detail::find_time_step_start_index(steps, range)); + const auto steps = detail::build_time_steps_covering(range); + int idx = std::max(0, detail::find_time_step_start_index(steps, range)); while (idx + 1 < static_cast(steps.size()) && steps[idx] * px_per_unit < cell_span_min) { @@ -80,8 +80,8 @@ grid_layer_params_t build_time_grid_layers( double last_step = 0.0; for (; idx >= 0 && levels.count < grid_layer_params_t::k_max_levels; --idx) { - const double step = steps[idx]; - const float spacing_px = static_cast(step * px_per_unit); + const double step = steps[idx]; + const float spacing_px = static_cast(step * px_per_unit); if (spacing_px < cell_span_min) { break; } diff --git a/src/core/types.cpp b/src/core/types.cpp index 23261dae..bda35d76 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -163,9 +163,9 @@ std::size_t ascending_first_ge( std::size_t first = 0; std::size_t count = snapshot.count; while (count > 0) { - const std::size_t step = count / 2; - const std::size_t index = first + step; - std::int64_t timestamp_ns = 0; + const std::size_t step = count / 2; + const std::size_t index = first + step; + std::int64_t timestamp_ns = 0; if (!timestamp_at(snapshot, access, index, timestamp_ns)) { valid = false; return 0; @@ -190,9 +190,9 @@ std::size_t ascending_first_gt( std::size_t first = 0; std::size_t count = snapshot.count; while (count > 0) { - const std::size_t step = count / 2; - const std::size_t index = first + step; - std::int64_t timestamp_ns = 0; + const std::size_t step = count / 2; + const std::size_t index = first + step; + std::int64_t timestamp_ns = 0; if (!timestamp_at(snapshot, access, index, timestamp_ns)) { valid = false; return 0; @@ -217,9 +217,9 @@ std::size_t descending_first_le( std::size_t first = 0; std::size_t count = snapshot.count; while (count > 0) { - const std::size_t step = count / 2; - const std::size_t index = first + step; - std::int64_t timestamp_ns = 0; + const std::size_t step = count / 2; + const std::size_t index = first + step; + std::int64_t timestamp_ns = 0; if (!timestamp_at(snapshot, access, index, timestamp_ns)) { valid = false; return 0; @@ -244,9 +244,9 @@ std::size_t descending_first_lt( std::size_t first = 0; std::size_t count = snapshot.count; while (count > 0) { - const std::size_t step = count / 2; - const std::size_t index = first + step; - std::int64_t timestamp_ns = 0; + const std::size_t step = count / 2; + const std::size_t index = first + step; + std::int64_t timestamp_ns = 0; if (!timestamp_at(snapshot, access, index, timestamp_ns)) { valid = false; return 0; @@ -315,11 +315,12 @@ time_window_candidates_t linear_candidates( const Data_access_policy& access, const data_query_context_t& query) { - bool found = false; - bool gap_after_match = false; - bool discontinuous = false; - bool held_found = false; - std::size_t held_index = 0; + bool found = false; + bool gap_after_match = false; + bool discontinuous = false; + bool held_found = false; + std::size_t held_index = 0; + std::int64_t held_timestamp_ns = 0; time_window_candidates_t out; const bool hold_forward = wants_hold_forward(query); @@ -419,11 +420,11 @@ bool scan_value_range( bool& has_value) { value_range_t held_range; - bool has_held_candidate = false; - bool has_held_value = false; - bool held_candidate_failed = false; - std::int64_t held_timestamp_ns = 0; - const bool hold_forward = wants_hold_forward(query); + bool has_held_candidate = false; + bool has_held_value = false; + bool held_candidate_failed = false; + std::int64_t held_timestamp_ns = 0; + const bool hold_forward = wants_hold_forward(query); for (std::size_t index = 0; index < snapshot.count; ++index) { const void* sample = snapshot.at(index); @@ -431,9 +432,9 @@ bool scan_value_range( return false; } - const std::int64_t timestamp_ns = query.access->get_timestamp(sample); - const bool in_window = time_window_contains(query.time_window, timestamp_ns); - const bool before_window = timestamp_ns < query.time_window.min_ns; + const std::int64_t timestamp_ns = query.access->get_timestamp(sample); + const bool in_window = time_window_contains(query.time_window, timestamp_ns); + const bool before_window = timestamp_ns < query.time_window.min_ns; if (!in_window && !(hold_forward && before_window)) { continue; } @@ -635,8 +636,8 @@ validated_time_window_t validated_time_window( return out; } - bool held_accepted = false; - std::size_t held_index = candidates.held_index; + bool held_accepted = false; + std::size_t held_index = candidates.held_index; if (candidates.has_held) { bool held_failed = false; held_accepted = select_held_sample_index( @@ -733,7 +734,7 @@ sample_draw_status_t read_sample_draw_value( return status_for_nonfinite(policy); } - float low = y; + float low = y; float high = y; if (access.has_range()) { std::tie(low, high) = access.range(sample); @@ -870,8 +871,8 @@ data_query_result_t Data_source::query_v_range( } value_range_t range; - bool has_value = false; - const Time_order order = time_order(lod); + bool has_value = false; + const Time_order order = time_order(lod); if (order == Time_order::UNKNOWN || order == Time_order::UNORDERED) { if (!scan_value_range( snapshot_result.snapshot, diff --git a/src/qt/plot_interaction_item.cpp b/src/qt/plot_interaction_item.cpp index 18a7d68b..3ccdd8f2 100644 --- a/src/qt/plot_interaction_item.cpp +++ b/src/qt/plot_interaction_item.cpp @@ -186,9 +186,9 @@ void Plot_interaction_item::apply_zoom_step(std::chrono::steady_clock::time_poin return; } - constexpr qreal eps = 1e-3; - bool active = false; - qreal elapsed_ms = std::chrono::duration(now - m_last_zoom_step_time).count(); + constexpr qreal eps = 1e-3; + bool active = false; + qreal elapsed_ms = std::chrono::duration(now - m_last_zoom_step_time).count(); m_last_zoom_step_time = now; if (elapsed_ms <= 0.0) { @@ -244,8 +244,8 @@ void Plot_interaction_item::mousePressEvent(QMouseEvent* event) return; } - const qreal y = event->position().y(); - const qreal x = event->position().x(); + const qreal y = event->position().y(); + const qreal x = event->position().x(); const qreal uw = usable_width(); const qreal uh = usable_height(); const qreal ph = preview_height(); @@ -304,9 +304,9 @@ void Plot_interaction_item::mouseMoveEvent(QMouseEvent* event) m_click_candidate = false; } - const auto mods = event->modifiers(); + const auto mods = event->modifiers(); const bool ctrl_held = mods & Qt::ControlModifier; - const bool alt_held = mods & Qt::AltModifier; + const bool alt_held = mods & Qt::AltModifier; if (ctrl_held || alt_held) { const qreal dy = y - m_drag_last_y; @@ -332,8 +332,8 @@ void Plot_interaction_item::mouseMoveEvent(QMouseEvent* event) void Plot_interaction_item::mouseReleaseEvent(QMouseEvent* event) { - const qreal x = event->position().x(); - const qreal y = event->position().y(); + const qreal x = event->position().x(); + const qreal y = event->position().y(); const qreal move_dx = x - m_press_x; const qreal move_dy = y - m_press_y; const bool within_click_tolerance = @@ -408,17 +408,17 @@ bool Plot_interaction_item::handle_wheel( if (dy == 0.0) { dy = pixel_delta_x; } if (dy == 0.0) { return false; } - const auto mods = Qt::KeyboardModifiers::fromInt(modifiers); - const qreal steps = dy / 120.0; - const qreal impulse = -steps * k_zoom_impulse_per_step; - const bool zoom_both = mods.testFlag(Qt::ControlModifier); - const bool zoom_alt = mods.testFlag(Qt::AltModifier); - const bool zoom_value = zoom_both || zoom_alt; - const bool zoom_time = zoom_both || !zoom_value; - - Plot_widget* time_target = time_target_widget(); - const bool time_allowed = zoom_time && time_target && (impulse >= 0 || time_target->can_zoom_in()); - const bool value_allowed = zoom_value; + const auto mods = Qt::KeyboardModifiers::fromInt(modifiers); + const qreal steps = dy / 120.0; + const qreal impulse = -steps * k_zoom_impulse_per_step; + const bool zoom_both = mods.testFlag(Qt::ControlModifier); + const bool zoom_alt = mods.testFlag(Qt::AltModifier); + const bool zoom_value = zoom_both || zoom_alt; + const bool zoom_time = zoom_both || !zoom_value; + + Plot_widget* time_target = time_target_widget(); + const bool time_allowed = zoom_time && time_target && (impulse >= 0 || time_target->can_zoom_in()); + const bool value_allowed = zoom_value; if (!time_allowed && !value_allowed) { return false; } diff --git a/src/qt/plot_renderer.cpp b/src/qt/plot_renderer.cpp index 3905bfbd..c78670ee 100644 --- a/src/qt/plot_renderer.cpp +++ b/src/qt/plot_renderer.cpp @@ -245,10 +245,10 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) } QRhi* const rhi_ptr = rhi(); - const auto& snapshot = m_impl->snapshot; - const Plot_config& config = snapshot.config; - vnm::plot::Profiler* profiler = config.profiler.get(); - const auto callback_now = std::chrono::steady_clock::now(); + const auto& snapshot = m_impl->snapshot; + const Plot_config& config = snapshot.config; + vnm::plot::Profiler* profiler = config.profiler.get(); + const auto callback_now = std::chrono::steady_clock::now(); if (profiler && m_impl->last_render_callback.time_since_epoch().count() != 0) { const double elapsed_ms = std::chrono::duration( @@ -299,8 +299,8 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) config, snapshot.v_auto, preview_enabled); - const float v_min = frame_plan.main_v_range.min; - const float v_max = frame_plan.main_v_range.max; + const float v_min = frame_plan.main_v_range.min; + const float v_max = frame_plan.main_v_range.max; const float preview_v_min = frame_plan.preview_v_range.min; const float preview_v_max = frame_plan.preview_v_range.max; diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index 387d1523..c993e56d 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -99,7 +99,7 @@ void apply_time_axis_model_to_data_config( template bool apply_time_axis_update_to_data_config(data_config_t& cfg, Update&& update) { - auto model = widget_time_axis_model(cfg); + auto model = widget_time_axis_model(cfg); const auto result = std::forward(update)(model); if (!result.accepted) { return false; @@ -222,9 +222,9 @@ void Plot_widget::set_config(const Plot_config& config) { std::unique_lock lock(m_config_mutex); - const double prev_grid_visibility = m_config.grid_visibility; + const double prev_grid_visibility = m_config.grid_visibility; const double prev_preview_visibility = m_config.preview_visibility; - const double prev_line_width_px = m_config.line_width_px; + const double prev_line_width_px = m_config.line_width_px; m_config = config; m_config.grid_visibility = prev_grid_visibility; // Preserve QML-controlled setting m_config.preview_visibility = prev_preview_visibility; // Preserve QML-controlled setting @@ -863,7 +863,7 @@ void Plot_widget::handle_window_changed(QQuickWindow* window) void Plot_widget::set_visible_info(int flags) { const int visible_flags = flags & k_visible_info_all; - const int prev = m_visible_info_flags.exchange(visible_flags, std::memory_order_acq_rel); + const int prev = m_visible_info_flags.exchange(visible_flags, std::memory_order_acq_rel); if (prev != visible_flags) { update(); } @@ -1002,7 +1002,7 @@ void Plot_widget::adjust_v_from_mouse_diff(float ref_height, float diff) } const auto [vmin, vmax] = current_v_range(); - const float span = vmax - vmin; + const float span = vmax - vmin; const float delta = diff * span / ref_height; adjust_v_to_target(vmin + delta, vmax + delta); } @@ -1015,8 +1015,8 @@ void Plot_widget::adjust_v_from_pivot_and_scale(float pivot, float scale) const auto [vmin, vmax] = current_v_range(); const float v_pivot = vmin + (vmax - vmin) * (1.0f - pivot); - const float v0 = v_pivot - (v_pivot - vmin) * scale; - const float v1 = v_pivot + (vmax - v_pivot) * scale; + const float v0 = v_pivot - (v_pivot - vmin) * scale; + const float v1 = v_pivot + (vmax - v_pivot) * scale; adjust_v_to_target(v0, v1); } @@ -1049,7 +1049,7 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale) void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anchor_zero) { - const auto cfg = data_cfg_snapshot(); + const auto cfg = data_cfg_snapshot(); const qint64 window_tmin_ns = cfg.t_min; const qint64 window_tmax_ns = cfg.t_max; @@ -1111,7 +1111,7 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anc const auto read_range = [series](const void* sample) -> std::optional> { - float low = 0.0f; + float low = 0.0f; float high = 0.0f; if (series->access.get_range) { std::tie(low, high) = series->get_range(sample); @@ -1151,9 +1151,9 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anc agg.vmax = std::max(agg.vmax, 0.0); } - const double scale = std::max(0.0, 1.0 + extra_v_scale); + const double scale = std::max(0.0, 1.0 + extra_v_scale); const double base_span = std::max(0.0, agg.vmax - agg.vmin); - double span = base_span * scale; + double span = base_span * scale; const double min_span = static_cast( min_v_span_for(static_cast(agg.vmin), static_cast(agg.vmax))); if (!(span > min_span)) { @@ -1260,9 +1260,9 @@ QVariantList Plot_widget::get_samples_for_time( return result; } - const auto cfg = data_cfg_snapshot(); - qint64 tmin_ns = 0; - qint64 tmax_ns = 0; + const auto cfg = data_cfg_snapshot(); + qint64 tmin_ns = 0; + qint64 tmax_ns = 0; if (!rendered_t_range(tmin_ns, tmax_ns)) { tmin_ns = cfg.t_min; tmax_ns = cfg.t_max; @@ -1272,11 +1272,11 @@ QVariantList Plot_widget::get_samples_for_time( // onto the same axis up front. entry["x"] is converted back to ms at the // end so the QML side stays on the ms surface end-to-end. constexpr double k_ns_per_ms = 1'000'000.0; - double x = x_ms * k_ns_per_ms; - const double tmin = static_cast(tmin_ns); - const double tmax = static_cast(tmax_ns); - float vmin = 0.0f; - float vmax = 0.0f; + double x = x_ms * k_ns_per_ms; + const double tmin = static_cast(tmin_ns); + const double tmax = static_cast(tmax_ns); + float vmin = 0.0f; + float vmax = 0.0f; if (m_v_auto.load(std::memory_order_acquire)) { if (!rendered_v_range(vmin, vmax)) { vmin = cfg.v_min; @@ -1289,7 +1289,7 @@ QVariantList Plot_widget::get_samples_for_time( } const double t_span = tmax - tmin; - const float v_span = vmax - vmin; + const float v_span = vmax - vmin; if (t_span <= 0.0 || v_span <= 0.0f) { return result; @@ -1302,9 +1302,9 @@ QVariantList Plot_widget::get_samples_for_time( x = tmin + (mouse_px / plot_width) * t_span; } - const auto plot_cfg = config(); + const auto plot_cfg = config(); const auto value_formatter = plot_cfg.format_value; - auto series_map = get_series_snapshot(); + auto series_map = get_series_snapshot(); for (const auto& [id, series] : series_map) { if (!series || !series->enabled) { @@ -1344,7 +1344,7 @@ QVariantList Plot_widget::get_samples_for_time( const double y0 = static_cast(series->get_value(sample0)); const double y1 = static_cast(series->get_value(sample1)); - double y = y0; + double y = y0; double resolved_x = x; if (mode == Indicator_sample_mode::Nearest) { @@ -1405,7 +1405,7 @@ QVariantList Plot_widget::get_samples_for_time( QString Plot_widget::format_timestamp_precise(qint64 timestamp_ms) const { - const auto cfg = config(); + const auto cfg = config(); const auto formatter = cfg.format_timestamp ? cfg.format_timestamp : default_format_timestamp; // QML passes timestamp_ms (milliseconds-since-epoch); the formatter // expects nanoseconds. Convert at the boundary. @@ -1451,7 +1451,7 @@ void Plot_widget::sync_time_axis_state() // attached axis has no initialized ranges; pulling default values into // m_data_cfg would silently overwrite a view that was set via set_view // before the axis was attached. - const bool view_init = m_time_axis->view_initialized(); + const bool view_init = m_time_axis->view_initialized(); const bool available_init = m_time_axis->available_initialized(); if (!view_init && !available_init) { return; @@ -1564,7 +1564,7 @@ double Plot_widget::compute_preview_height_px(double widget_height_px) const return 0.0; } - const double font_h = m_base_label_height; + const double font_h = m_base_label_height; const double available = std::max(0.0, widget_height_px - font_h); if (available <= 0.0) { return 0.0; @@ -1594,12 +1594,12 @@ double Plot_widget::compute_preview_height_px(double widget_height_px) const } if (m_preview_height_steps > 0 && max_px > min_px) { - const int steps = m_preview_height_steps; + const int steps = m_preview_height_steps; const double delta = (max_px - min_px) / static_cast(steps); if (delta > 0.0) { - double clamped = std::clamp(preview_px, min_px, max_px); - const double t = (clamped - min_px) / delta; - int idx = static_cast(std::floor(t)); + double clamped = std::clamp(preview_px, min_px, max_px); + const double t = (clamped - min_px) / delta; + int idx = static_cast(std::floor(t)); if (idx < 0) { idx = 0; } @@ -1617,9 +1617,8 @@ double Plot_widget::compute_preview_height_px(double widget_height_px) const void Plot_widget::recalculate_preview_height() { - const double widget_h_dp = height(); - const double widget_h_px = widget_h_dp * m_scaling_factor; - + const double widget_h_dp = height(); + const double widget_h_px = widget_h_dp * m_scaling_factor; const double new_adjusted = compute_preview_height_px(widget_h_px); const double new_dp = (m_scaling_factor > 0.0) ? new_adjusted / m_scaling_factor diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index 779d2450..cf4a283d 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -152,7 +152,7 @@ inline void adjust_t_from_pivot_and_scale_impl( return; } - const auto left_span_ns = positive_span_ns(view.t_min, *t_pivot_ns); + const auto left_span_ns = positive_span_ns(view.t_min, *t_pivot_ns); const auto right_span_ns = positive_span_ns(*t_pivot_ns, view.t_max); const std::uint64_t left_ns = left_span_ns ? scaled_duration_ns(*left_span_ns, static_cast(scale)) diff --git a/src/qt/text_lcd_resolver.cpp b/src/qt/text_lcd_resolver.cpp index c2094d03..dd939ca0 100644 --- a/src/qt/text_lcd_resolver.cpp +++ b/src/qt/text_lcd_resolver.cpp @@ -22,9 +22,9 @@ constexpr unsigned int k_win_spi_get_font_smoothing_type = 0x200AU; constexpr unsigned int k_win_spi_get_font_smoothing_orientation = 0x2012U; #endif -constexpr unsigned int k_win_font_smoothing_cleartype = 0x0002U; -constexpr unsigned int k_win_font_smoothing_orientation_bgr = 0x0000U; -constexpr unsigned int k_win_font_smoothing_orientation_rgb = 0x0001U; +constexpr unsigned int k_win_font_smoothing_cleartype = 0x0002U; +constexpr unsigned int k_win_font_smoothing_orientation_bgr = 0x0000U; +constexpr unsigned int k_win_font_smoothing_orientation_rgb = 0x0001U; text_lcd_resolved_subpixel_order_t text_lcd_subpixel_order_from_qt(QQuickWindow* window) { diff --git a/tests/test_cache_invalidation.cpp b/tests/test_cache_invalidation.cpp index 67af287c..297f7b53 100644 --- a/tests/test_cache_invalidation.cpp +++ b/tests/test_cache_invalidation.cpp @@ -381,7 +381,7 @@ bool test_unsupported_query_falls_back_to_snapshot_scan() bool test_ready_query_profiler_counts_query_without_scan() { auto profiler = std::make_shared(); - auto source = std::make_shared(); + auto source = std::make_shared(); source->query_status = Data_query_status::READY; source->query_range = {2.0f, 5.0f}; @@ -410,7 +410,7 @@ bool test_ready_query_profiler_counts_query_without_scan() bool test_default_query_profiler_counts_snapshot_scan() { auto profiler = std::make_shared(); - auto source = std::make_shared(); + auto source = std::make_shared(); source->samples = { { 0, 6.0f }, { 5, 8.0f }, @@ -646,7 +646,7 @@ bool test_ready_query_result_is_cached_by_current_sequence() source->query_sequence = 5; source->current_sequence_value = 5; - auto series = make_stable_series(source); + auto series = make_stable_series(source); auto series_map = make_series_map(series); plot::detail::auto_range_cache_t cache; Plot_config config; @@ -683,7 +683,7 @@ bool test_conservative_query_result_is_not_cached() source->query_sequence = 5; source->current_sequence_value = 5; - auto series = make_series(source); + auto series = make_series(source); auto series_map = make_series_map(series); plot::detail::auto_range_cache_t cache; Plot_config config; @@ -717,7 +717,7 @@ bool test_empty_query_result_is_cached_by_current_sequence() source->query_sequence = 5; source->current_sequence_value = 5; - auto series = make_stable_series(source); + auto series = make_stable_series(source); auto series_map = make_series_map(series); plot::detail::auto_range_cache_t cache; Plot_config config; @@ -755,7 +755,7 @@ bool test_sequence_change_invalidates_auto_range_cache() source->query_sequence = 5; source->current_sequence_value = 5; - auto series = make_stable_series(source); + auto series = make_stable_series(source); auto series_map = make_series_map(series); plot::detail::auto_range_cache_t cache; Plot_config config; @@ -794,7 +794,7 @@ bool test_visible_window_change_invalidates_auto_range_cache() source->query_sequence = 5; source->current_sequence_value = 5; - auto series = make_stable_series(source); + auto series = make_stable_series(source); auto series_map = make_series_map(series); plot::detail::auto_range_cache_t cache; Plot_config config; @@ -938,7 +938,7 @@ bool test_removed_series_prunes_auto_range_cache() bool test_preview_auto_range_uses_preview_query_source() { - auto main_source = std::make_shared(); + auto main_source = std::make_shared(); auto preview_source = std::make_shared(); preview_source->query_status = Data_query_status::READY; preview_source->query_range = {-2.0f, 11.0f}; diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index e19e5acf..cc2611e3 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -415,9 +415,9 @@ bool test_ring_source_snapshots_are_consistent_under_concurrent_writes() if (!result) { continue; } - const auto& snap = result.snapshot; + const auto& snap = result.snapshot; const auto* first = reinterpret_cast(snap.data); - double prev = first->t; + double prev = first->t; for (std::size_t i = 1; i < snap.count; ++i) { const auto* cur = reinterpret_cast( reinterpret_cast(snap.data) + i * snap.stride); diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index 5441ea3f..2bc60176 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -471,7 +471,7 @@ bool test_snapshot_truthiness_requires_usable_stride() bool test_snapshot_count1_clamps_malformed_count2() { - std::vector first = {{0, 1.0f}}; + std::vector first = {{0, 1.0f}}; std::vector second = {{1, 2.0f}}; plot::data_snapshot_t snap; @@ -669,10 +669,10 @@ bool test_horizontal_label_fade_keys_preserve_int64_timestamps() TEST_ASSERT(full_span && std::isfinite(*full_span), "horizontal label span math should represent the full int64 range"); - const long double center_delta = plot::span_ns_as_long_double(k_min, -1); - const long double right_delta = plot::span_ns_as_long_double(k_min, k_max); + const long double center_delta = plot::span_ns_as_long_double(k_min, -1); + const long double right_delta = plot::span_ns_as_long_double(k_min, k_max); const long double center_fraction = center_delta / *full_span; - const long double right_fraction = right_delta / *full_span; + const long double right_fraction = right_delta / *full_span; TEST_ASSERT(center_fraction > 0.499999999999999L && center_fraction < 0.500000000000001L, @@ -691,7 +691,7 @@ bool test_text_lcd_policy_helpers() const request_t auto_request = plot::text_lcd_auto_request(); const request_t none_request = plot::text_lcd_none_request(); - const request_t bgr_request = plot::text_lcd_explicit_request(resolved_t::BGR); + const request_t bgr_request = plot::text_lcd_explicit_request(resolved_t::BGR); const request_t invalid_request{false, static_cast(255)}; TEST_ASSERT(auto_request.automatic, "LCD request should model AUTO as request state"); @@ -814,9 +814,9 @@ bool test_text_lcd_policy_helpers() bool test_built_in_label_backgrounds_are_opaque_for_lcd() { - const plot::Color_palette dark = plot::Color_palette::dark(); - const plot::Color_palette light = plot::Color_palette::light(); - const auto expected_light_vertical = plot::hex_to_vec4("ff959595"); + const plot::Color_palette dark = plot::Color_palette::dark(); + const plot::Color_palette light = plot::Color_palette::light(); + const auto expected_light_vertical = plot::hex_to_vec4("ff959595"); TEST_ASSERT(dark.h_label_background.a >= 0.999f, "dark horizontal label background should be opaque for LCD backing"); diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 2f33d14d..93a455b6 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -165,8 +165,8 @@ bool test_ready_value_range_scan_populates_sequence() source.set_sequence(123); const plot::Data_access_policy access = make_value_access(); - const auto query = make_query(access, 0, 2); - const auto result = source.query_v_range(0, query); + const auto query = make_query(access, 0, 2); + const auto result = source.query_v_range(0, query); TEST_ASSERT(result.status == plot::Data_query_status::READY, "finite value-range query should be READY"); TEST_ASSERT(result.sequence == 123, @@ -189,7 +189,8 @@ bool test_ascending_value_range_scans_only_selected_time_window() source.set_time_order(plot::Time_order::ASCENDING); int timestamp_calls = 0; - int value_calls = 0; + int value_calls = 0; + const plot::Data_access_policy access = make_value_access(×tamp_calls, &value_calls); const auto result = source.query_v_range(0, make_query(access, 500, 501)); @@ -220,7 +221,8 @@ bool test_ascending_skip_hold_value_range_scans_bounded_prefix() source.set_time_order(plot::Time_order::ASCENDING); int timestamp_calls = 0; - int value_calls = 0; + int value_calls = 0; + const plot::Data_access_policy access = make_value_access(×tamp_calls, &value_calls); auto query = make_hold_query(access, 500, 501); @@ -314,6 +316,7 @@ bool test_nonfinite_values_are_skipped_or_zeroed_by_policy() { const float nan = std::numeric_limits::quiet_NaN(); const float inf = std::numeric_limits::infinity(); + const plot::Data_access_policy access = make_value_access(); Query_source mixed_source({ @@ -365,9 +368,9 @@ bool test_query_time_window_returns_simple_ascending_window() source.set_sequence(321); source.set_time_order(plot::Time_order::ASCENDING); - int timestamp_calls = 0; - const plot::Data_access_policy access = make_timestamp_access(×tamp_calls); - const auto result = source.query_time_window(0, make_draw_query(access, 20, 30)); + int timestamp_calls = 0; + const plot::Data_access_policy access = make_timestamp_access(×tamp_calls); + const auto result = source.query_time_window(0, make_draw_query(access, 20, 30)); TEST_ASSERT(result.status == plot::Data_query_status::READY, "query_time_window should be READY for matching ascending samples"); TEST_ASSERT(result.sequence == 321, diff --git a/tests/test_font_disk_cache.cpp b/tests/test_font_disk_cache.cpp index 6342a812..f578ca52 100644 --- a/tests/test_font_disk_cache.cpp +++ b/tests/test_font_disk_cache.cpp @@ -19,12 +19,12 @@ namespace plot = vnm::plot; namespace { -constexpr std::uint32_t k_magic = 0x4d534446; // 'MSDF' -constexpr std::uint32_t k_cache_version = 4; +constexpr std::uint32_t k_magic = 0x4d534446; // 'MSDF' +constexpr std::uint32_t k_cache_version = 4; constexpr std::uint32_t k_previous_cache_version = 3; -constexpr std::uint32_t k_pixel_height = 18; -constexpr std::uint32_t k_atlas_texture_size = 2048; -constexpr std::uint32_t k_expected_atlas_bytes = +constexpr std::uint32_t k_pixel_height = 18; +constexpr std::uint32_t k_atlas_texture_size = 2048; +constexpr std::uint32_t k_expected_atlas_bytes = k_atlas_texture_size * k_atlas_texture_size * 4u; using digest_t = plot::detail::font_disk_cache_digest_t; @@ -96,17 +96,17 @@ void write_valid_glyph(std::ofstream& out) // Scale-independent geometry in font units: bounds_right >= bounds_left and // bounds_top >= bounds_bottom, with the visibility flag last (matches the // renderer's on-disk glyph layout). - const std::uint32_t codepoint = static_cast('A'); - const float advance_units = 10.0f; - const float bounds_left_units = 0.0f; - const float bounds_bottom_units = 0.0f; - const float bounds_right_units = 1.0f; - const float bounds_top_units = 1.0f; - const float uv_left = 0.0f; - const float uv_bottom = 1.0f; - const float uv_right = 1.0f; - const float uv_top = 0.0f; - const std::uint8_t visible = 1u; + const std::uint32_t codepoint = static_cast('A'); + const float advance_units = 10.0f; + const float bounds_left_units = 0.0f; + const float bounds_bottom_units = 0.0f; + const float bounds_right_units = 1.0f; + const float bounds_top_units = 1.0f; + const float uv_left = 0.0f; + const float uv_bottom = 1.0f; + const float uv_right = 1.0f; + const float uv_top = 0.0f; + const std::uint8_t visible = 1u; write_value(out, codepoint); write_value(out, advance_units); @@ -142,13 +142,14 @@ bool write_cache_file( // projection parameters. atlas_px_range, bitmap_scale, and ascender must be // strictly positive for the loader to accept the file. const std::uint32_t baked_pixel_height = 48u; - const double atlas_px_range = 10.0; - const double bitmap_scale = 1.0; - const float sharpness_bias = 2.5f; - const float ascender = 14.0f; - const float descender = -4.0f; - const float line_height = 20.0f; - const float em_size = 18.0f; + const double atlas_px_range = 10.0; + const double bitmap_scale = 1.0; + const float sharpness_bias = 2.5f; + const float ascender = 14.0f; + const float descender = -4.0f; + const float line_height = 20.0f; + + const float em_size = 18.0f; const float zero_advance_units = 9.0f; write_value(out, baked_pixel_height); write_value(out, atlas_px_range); @@ -247,7 +248,7 @@ bool test_corrupt_atlas_size_and_bytes_are_rejected() bool test_same_height_changed_digest_does_not_reuse_old_cache() { Scoped_temp_dir tmp; - const auto old_digest = make_digest(0x50u); + const auto old_digest = make_digest(0x50u); const auto changed_digest = make_digest(0x90u); cache_file_options_t options; diff --git a/tests/test_font_renderer_bounds.cpp b/tests/test_font_renderer_bounds.cpp index be4384ea..504be4c8 100644 --- a/tests/test_font_renderer_bounds.cpp +++ b/tests/test_font_renderer_bounds.cpp @@ -15,7 +15,7 @@ namespace plot = vnm::plot; namespace { -constexpr int k_test_font_px = 18; +constexpr int k_test_font_px = 18; constexpr float k_bounds_epsilon = 1.0e-4f; bool finite_ordered(const glm::vec4& bounds) @@ -92,10 +92,10 @@ bool test_visible_bounds_are_finite_ordered_and_translation_invariant() renderer.initialize_metrics(loader, k_test_font_px, true); constexpr const char* k_text = "Axis 123"; - constexpr float x = 12.25f; - constexpr float y = 34.5f; - constexpr float dx = 7.75f; - constexpr float dy = -3.5f; + constexpr float x = 12.25f; + constexpr float y = 34.5f; + constexpr float dx = 7.75f; + constexpr float dy = -3.5f; glm::vec4 first; glm::vec4 translated; diff --git a/tests/test_gpu_sample_origin.cpp b/tests/test_gpu_sample_origin.cpp index 00408234..9f3a3d50 100644 --- a/tests/test_gpu_sample_origin.cpp +++ b/tests/test_gpu_sample_origin.cpp @@ -18,7 +18,7 @@ namespace { constexpr std::int64_t k_ns_per_us = 1000LL; constexpr std::int64_t k_ns_per_ms = 1000000LL; constexpr std::int64_t k_ns_per_second = 1000000000LL; -constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; +constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; constexpr std::int64_t k_ns_per_day = 86400LL * k_ns_per_second; constexpr std::int64_t k_ns_per_year = 365LL * k_ns_per_day; @@ -146,7 +146,7 @@ bool test_fp32_round_trip_within_2e24_for_bounded_spans() for (std::int64_t t_view_min_ns : t_view_min_candidates) { const std::int64_t origin_ns = plot::detail::choose_origin_ns(t_view_min_ns, span_ns); const std::int64_t t_end_ns = t_view_min_ns + span_ns; - const float t_end_rel = static_cast(t_end_ns - origin_ns) * 1e-9f; + const float t_end_rel = static_cast(t_end_ns - origin_ns) * 1e-9f; TEST_ASSERT(std::fabs(t_end_rel) < k_fp32_integer_bound, "rebased end-of-view seconds must fit inside fp32's exact-integer range"); @@ -187,11 +187,11 @@ bool test_fp32_snap_step_resolution_at_bucket_boundaries() const std::int64_t origin_ns = plot::detail::choose_origin_ns(c.t_view_min_ns, c.span_ns); const std::int64_t t_end_ns = c.t_view_min_ns + c.span_ns; - const float t_end_rel = static_cast(t_end_ns - origin_ns) * 1e-9f; + const float t_end_rel = static_cast(t_end_ns - origin_ns) * 1e-9f; // ulp at |t_end_rel| in fp32. std::nextafter gives the next // representable float; subtracting yields the local step size. - const float ulp = std::nextafter(t_end_rel, std::numeric_limits::infinity()) - t_end_rel; + const float ulp = std::nextafter(t_end_rel, std::numeric_limits::infinity()) - t_end_rel; const float snap_seconds = static_cast(snap_ns) * 1e-9f; TEST_ASSERT(ulp <= snap_seconds, diff --git a/tests/test_layout_calculator.cpp b/tests/test_layout_calculator.cpp index 899de998..e7be265e 100644 --- a/tests/test_layout_calculator.cpp +++ b/tests/test_layout_calculator.cpp @@ -119,8 +119,8 @@ bool test_format_timestamp_receives_nanosecond_units() // confirms ns scale (a seconds-scale unit slip would compress the // values into a ~60 ns range starting near zero, far below the // expected ~1.7e18 magnitude). - const std::int64_t margin_ns = (k_t_max_ns - k_t_min_ns); - bool saw_label_in_window = false; + const std::int64_t margin_ns = (k_t_max_ns - k_t_min_ns); + bool saw_label_in_window = false; for (const auto& call : recorded) { if (call.timestamp_ns >= k_t_min_ns - margin_ns && call.timestamp_ns <= k_t_max_ns + margin_ns) @@ -225,10 +225,10 @@ bool test_horizontal_axis_handles_full_int64_time_span() TEST_ASSERT(result.h_labels.size() > 1, "formatter-enabled full int64 timestamp range should emit multiple horizontal labels"); - bool saw_signature_zero = false; + bool saw_signature_zero = false; bool saw_signature_subsecond = false; - bool saw_signature_large = false; - bool saw_saturated_step = false; + bool saw_signature_large = false; + bool saw_saturated_step = false; for (const auto& call : recorded) { saw_signature_zero = saw_signature_zero || call.timestamp_ns == 0; saw_signature_subsecond = diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index a1216054..10436a88 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -207,7 +207,7 @@ std::string lcd_order_bool_name(lcd::Resolved_lcd_subpixel_order order) std::string decode_threshold_statement(const ref::decode_threshold_t& threshold) { const std::string condition(threshold.glsl_condition); - const std::string separator = " && "; + const std::string separator = " && "; const std::size_t separator_pos = condition.find(separator); if (separator_pos == std::string::npos) { return {}; @@ -229,7 +229,7 @@ std::string decode_threshold_statement(const ref::decode_threshold_t& threshold) std::string sample_statement_for_offset(float offset) { const std::string sample_name = sample_name_for_offset(offset); - const std::string expression = sample_expression_for_offset(offset); + const std::string expression = sample_expression_for_offset(offset); return expression.empty() ? std::string{} : "float " + sample_name + " = glyph_alpha_at_ratio(" + @@ -247,9 +247,9 @@ std::string filter_window_statement(const ref::filter_window_t& window) "float " + std::string(window.channel_name) + "_coverage =\n"; for (std::size_t i = 0; i < window.taps.size(); ++i) { - const ref::filter_tap_t& tap = window.taps[i]; - const std::string sample_name = sample_name_for_offset(tap.offset); - const std::string weight_name = weight_name_for_value(tap.weight); + const ref::filter_tap_t& tap = window.taps[i]; + const std::string sample_name = sample_name_for_offset(tap.offset); + const std::string weight_name = weight_name_for_value(tap.weight); if (weight_name.empty()) { return {}; } diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index eddffa87..b4c0e875 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -128,7 +128,7 @@ void configure_indicator_widget( bool test_zoom_math_is_invariant_to_timer_cadence() { const zoom_state_t single_gap = advance_zoom(4.0, {10.0}); - const zoom_state_t split_gap = advance_zoom(4.0, {4.0, 6.0}); + const zoom_state_t split_gap = advance_zoom(4.0, {4.0, 6.0}); const zoom_state_t fine_steps = advance_zoom( 4.0, {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}); @@ -157,7 +157,7 @@ bool test_zoom_math_stays_composable_across_small_velocity_decay() bool test_zoom_math_handles_negative_velocity() { const zoom_state_t single_gap = advance_zoom(-4.0, {10.0}); - const zoom_state_t split_gap = advance_zoom(-4.0, {4.0, 6.0}); + const zoom_state_t split_gap = advance_zoom(-4.0, {4.0, 6.0}); const zoom_state_t fractional_steps = advance_zoom( -4.0, {0.3, 0.7, 1.5, 2.5, 5.0}); diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index e8a0f005..37b8e15f 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -636,9 +636,9 @@ bool assert_drawable_span( bool test_layer_only_zero_style_prepare_record_order() { std::vector events; - int low_create_count = 0; + int low_create_count = 0; int high_create_count = 0; - auto low_layer = std::make_shared( + auto low_layer = std::make_shared( "low", 1, -5, events, low_create_count); auto high_layer = std::make_shared( "high", 1, 10, events, high_create_count); @@ -665,11 +665,11 @@ bool test_layer_only_zero_style_prepare_record_order() TEST_ASSERT(low_create_count == 1, "low z-order layer state should be created once"); TEST_ASSERT(high_create_count == 1, "high z-order layer state should be created once"); - const std::size_t low_prepare = find_event_index(events, "low", "prepare"); + const std::size_t low_prepare = find_event_index(events, "low", "prepare"); const std::size_t high_prepare = find_event_index(events, "high", "prepare"); - const std::size_t begin_pass = find_event_index(events, "frame", "begin_pass"); - const std::size_t low_record = find_event_index(events, "low", "record"); - const std::size_t high_record = find_event_index(events, "high", "record"); + const std::size_t begin_pass = find_event_index(events, "frame", "begin_pass"); + const std::size_t low_record = find_event_index(events, "low", "record"); + const std::size_t high_record = find_event_index(events, "high", "record"); TEST_ASSERT(low_prepare < events.size(), "expected low layer prepare event"); TEST_ASSERT(high_prepare < events.size(), "expected high layer prepare event"); @@ -884,8 +884,8 @@ bool test_builtin_upload_stages_visible_window_only() bool test_builtin_upload_reuses_vbo_capacity_headroom() { - constexpr std::int64_t k_second_ns = 1'000'000'000LL; - constexpr std::size_t k_gpu_sample_bytes = sizeof(float) * 4u; + constexpr std::int64_t k_second_ns = 1'000'000'000LL; + constexpr std::size_t k_gpu_sample_bytes = sizeof(float) * 4u; std::vector events; int create_count = 0; @@ -967,8 +967,8 @@ bool test_builtin_upload_reuses_vbo_capacity_headroom() bool test_combined_builtin_uploads_samples_once_per_view() { - constexpr std::int64_t k_second_ns = 1'000'000'000LL; - constexpr std::size_t k_gpu_sample_bytes = sizeof(float) * 4u; + constexpr std::int64_t k_second_ns = 1'000'000'000LL; + constexpr std::size_t k_gpu_sample_bytes = sizeof(float) * 4u; std::vector events; int create_count = 0; @@ -1092,7 +1092,7 @@ bool test_direct_member_policy_uses_member_dispatch_in_renderer_staging() make_fallback_access_policy_with_counted_public_accessors(fallback_calls); std::map> series_map; - const int direct_series_id = 51; + const int direct_series_id = 51; const int fallback_series_id = 52; series_map[direct_series_id] = direct_series; series_map[fallback_series_id] = fallback_series; @@ -1276,7 +1276,7 @@ bool test_builtin_staging_normalizes_finite_reversed_ranges() TEST_ASSERT(view_state.last_staged_sample_count == 4, "reversed-range series should stage all visible samples"); for (std::size_t i = 0; i < view_state.last_staged_sample_count; ++i) { - const float expected_low = static_cast(i + 1u); + const float expected_low = static_cast(i + 1u); const float expected_high = static_cast(i + 3u); TEST_ASSERT(view_state.staging[i].y_min == expected_low, "staged finite reversed range low endpoint should be normalized exactly"); @@ -2202,7 +2202,7 @@ bool test_global_draw_order_sorts_builtins_across_series_and_custom_layers() {}); std::map> series_map; - const int first_series_id = 70; + const int first_series_id = 70; const int second_series_id = 80; series_map[first_series_id] = first_series; series_map[second_series_id] = second_series; @@ -2271,10 +2271,10 @@ bool test_builtin_draw_commands_sort_relative_to_custom_layers() constexpr std::int64_t k_second_ns = 1'000'000'000LL; std::vector events; - int under_create_count = 0; + int under_create_count = 0; int middle_create_count = 0; - int top_create_count = 0; - auto under_layer = std::make_shared( + int top_create_count = 0; + auto under_layer = std::make_shared( "under", 1, -20, events, under_create_count); auto middle_layer = std::make_shared( "middle", 1, 5, events, middle_create_count); @@ -2795,8 +2795,8 @@ bool test_resources_changed_tracks_hold_timestamp_changes() first_prepare->gpu_count == 2, "first hold-forward prepare should draw one real and one synthetic sample"); - const layer_event_t first = *first_prepare; - const std::int64_t first_origin = first.t_origin_ns; + const layer_event_t first = *first_prepare; + const std::int64_t first_origin = first.t_origin_ns; events.clear(); ctx.t1 = 13LL * k_second_ns; @@ -3032,7 +3032,7 @@ bool test_busy_hold_forward_does_not_prepare_stale_tmax() "initial hold-forward frame should prepare at its visible t_max"); const std::int64_t prepared_t_max = initial_view_state.last_prepared_t_max_ns; - const std::size_t vbo_generation = initial_view_state.last_vbo_generation; + const std::size_t vbo_generation = initial_view_state.last_vbo_generation; source->return_busy_once(); ctx.t1 = 13LL * k_second_ns; ctx.t_available_max = ctx.t1; diff --git a/tests/test_rhi_helpers.cpp b/tests/test_rhi_helpers.cpp index 281c2e15..76168a35 100644 --- a/tests/test_rhi_helpers.cpp +++ b/tests/test_rhi_helpers.cpp @@ -59,8 +59,8 @@ bool test_qrhi_byte_size_rejects_size_t_product_overflow() bool test_qrhi_grown_capacity_bytes_checks_headroom_overflow() { - std::size_t capacity = 0; - quint32 qrhi_capacity = 0; + std::size_t capacity = 0; + quint32 qrhi_capacity = 0; const std::size_t max_qrhi = static_cast(std::numeric_limits::max()); diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 1f6d1b52..1797b5c4 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -1025,7 +1025,7 @@ bool test_access_policy_change_invalidates_planner_fast_path_cache() } const int series_id = 63; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_direct_member_policy(); @@ -1083,7 +1083,7 @@ bool test_frame_scoped_cache_reuse() } const int series_id = 7; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1118,7 +1118,7 @@ bool test_frame_scoped_cache_reuse() bool test_preview_uses_distinct_source_snapshot() { - auto main_source = std::make_shared(); + auto main_source = std::make_shared(); auto preview_source = std::make_shared(); main_source->samples.resize(8, Test_sample{}); preview_source->samples.resize(8, Test_sample{}); @@ -1130,7 +1130,7 @@ bool test_preview_uses_distinct_source_snapshot() } const int series_id = 14; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = main_source; series->access = make_policy(); @@ -1169,13 +1169,13 @@ bool test_preview_uses_distinct_source_snapshot() bool test_preview_disabled_skips_preview_snapshot() { - auto main_source = std::make_shared(); + auto main_source = std::make_shared(); auto preview_source = std::make_shared(); main_source->samples.resize(8); preview_source->samples.resize(8); const int series_id = 15; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = main_source; series->access = make_policy(); @@ -1222,7 +1222,7 @@ bool test_frame_change_invalidates_snapshot_cache() } const int series_id = 8; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1261,7 +1261,7 @@ bool test_empty_window_behavior_invalidates_fast_path_cache() } const int series_id = 18; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1313,7 +1313,7 @@ bool test_preview_honors_hold_last_forward() } const int series_id = 19; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1355,7 +1355,7 @@ bool test_lod_level_separation() fill_lod_samples(*data_source); const int series_id = 9; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1409,7 +1409,7 @@ bool test_lod_selection_has_no_hysteresis() Two_level_source source; fill_lod_samples(source); - const Data_access_policy access = make_policy(); + const Data_access_policy access = make_policy(); const std::vector scales = {1, 4}; plot::detail::series_window_planner_state_t state; plot::detail::Series_window_snapshot_cache cache; @@ -1453,7 +1453,7 @@ bool test_snapshot_released_after_render() } const int series_id = 3; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1498,7 +1498,7 @@ bool test_upload_origin_records_per_view_origin() } const int series_id = 41; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1565,7 +1565,7 @@ bool test_upload_invalidates_when_origin_changes_across_snap_bucket() } const int series_id = 42; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1602,7 +1602,7 @@ bool test_upload_invalidates_when_origin_changes_across_snap_bucket() } }; - constexpr std::int64_t k_one_hour_ns = 3'600LL * 1'000'000'000LL; + constexpr std::int64_t k_one_hour_ns = 3'600LL * 1'000'000'000LL; constexpr std::int64_t k_one_second_ns = 1'000'000'000LL; // Frame 1: bucket-aligned origin = 0. @@ -1673,9 +1673,9 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() // Sparse 10-year coverage: one sample per day is enough for the // renderer to find data within both windows without ballooning memory. constexpr std::int64_t k_ns_per_second = 1'000'000'000LL; - constexpr std::int64_t k_ns_per_day = 86'400LL * k_ns_per_second; - constexpr std::int64_t k_ns_per_hour = 3'600LL * k_ns_per_second; - constexpr int k_num_samples = 365 * 10; + constexpr std::int64_t k_ns_per_day = 86'400LL * k_ns_per_second; + constexpr std::int64_t k_ns_per_hour = 3'600LL * k_ns_per_second; + constexpr int k_num_samples = 365 * 10; data_source->samples.resize(k_num_samples); for (int i = 0; i < k_num_samples; ++i) { data_source->samples[i].t = static_cast(i) * k_ns_per_day; @@ -1683,7 +1683,7 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() } const int series_id = 43; - auto series = std::make_shared(); + auto series = std::make_shared(); series->style = Display_style::LINE; series->data_source = data_source; series->access = make_policy(); @@ -1762,15 +1762,15 @@ bool test_render_skips_invalid_series() auto data_source = std::make_shared(); data_source->samples.resize(4, Test_sample{}); - const int disabled_id = 12; - auto disabled_series = std::make_shared(); + const int disabled_id = 12; + auto disabled_series = std::make_shared(); disabled_series->enabled = false; disabled_series->style = Display_style::LINE; disabled_series->data_source = data_source; disabled_series->access = make_policy(); - const int null_source_id = 13; - auto null_source_series = std::make_shared(); + const int null_source_id = 13; + auto null_source_series = std::make_shared(); null_source_series->enabled = true; null_source_series->style = Display_style::LINE; null_source_series->data_source.reset(); diff --git a/tests/test_time_grid.cpp b/tests/test_time_grid.cpp index ee7db6e5..8d47a2da 100644 --- a/tests/test_time_grid.cpp +++ b/tests/test_time_grid.cpp @@ -23,7 +23,7 @@ float expected_alpha(float spacing_px) constexpr double k_cell_span_min = 1.0; constexpr double k_fade_den = 59.0; constexpr double k_alpha_base = 0.75; - const double fade = (double(spacing_px) - k_cell_span_min) / k_fade_den; + const double fade = (double(spacing_px) - k_cell_span_min) / k_fade_den; return static_cast(std::clamp(fade, 0.0, 1.0) * k_alpha_base); } diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 8e26f786..05638522 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -341,10 +341,11 @@ bool test_erased_access_view_uses_direct_member_accessors() TEST_ASSERT(timestamp_calls == 1, "fallback erased accessor should invoke the public callable once"); - plot::Data_access_policy mutated = erased; - int mutated_timestamp_calls = 0; - int mutated_value_calls = 0; - int mutated_range_calls = 0; + plot::Data_access_policy mutated = erased; + int mutated_timestamp_calls = 0; + int mutated_value_calls = 0; + int mutated_range_calls = 0; + constexpr std::int64_t k_replacement_timestamp_ns = 21'000'000'000; mutated.get_timestamp = [&mutated_timestamp_calls](const void*) { ++mutated_timestamp_calls; @@ -418,8 +419,8 @@ bool test_erased_access_view_uses_direct_member_accessors() k_sample_timestamp_ns, "detached accessor mutation must not affect source policy semantics"); - plot::Data_access_policy move_source = erased; - auto moved_timestamp_slot = std::move(move_source.get_timestamp); + plot::Data_access_policy move_source = erased; + auto moved_timestamp_slot = std::move(move_source.get_timestamp); (void)moved_timestamp_slot; const auto after_slot_move_view = plot::detail::make_erased_access_policy_view(move_source); @@ -441,8 +442,8 @@ bool test_erased_access_view_uses_direct_member_accessors() k_sample_timestamp_ns, "whole-policy move should preserve direct timestamp semantics"); - auto typed_mutated = policy; - int typed_mutated_timestamp_calls = 0; + auto typed_mutated = policy; + int typed_mutated_timestamp_calls = 0; typed_mutated.get_timestamp = [&typed_mutated_timestamp_calls]( const sample_t& sample) { ++typed_mutated_timestamp_calls; From a4b4f8ddcbee2c891005a7ec5b4c1969764e0fa8 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:56:58 +0200 Subject: [PATCH 14/80] style: align assignment tables --- include/vnm_plot/core/access_policy.h | 36 +- include/vnm_plot/core/algo.h | 6 +- include/vnm_plot/core/color_palette.h | 16 +- include/vnm_plot/core/plot_config.h | 2 +- include/vnm_plot/core/types.h | 42 +-- include/vnm_plot/rhi/font_renderer.h | 6 +- include/vnm_plot/rhi/primitive_renderer.h | 2 +- include/vnm_plot/rhi/series_renderer.h | 6 +- src/core/asset_loader.cpp | 2 +- src/core/auto_range_resolver.cpp | 62 +-- src/core/chrome_renderer.cpp | 14 +- src/core/font_renderer.cpp | 50 +-- src/core/font_renderer_stub.cpp | 2 +- src/core/frame_range_planner.cpp | 4 +- src/core/label_pane_geometry.h | 8 +- src/core/layout_calculator.cpp | 52 +-- src/core/primitive_renderer.cpp | 94 ++--- src/core/rhi_helpers.h | 2 +- src/core/series_renderer.cpp | 380 +++++++++---------- src/core/series_window_planner.cpp | 190 +++++----- src/core/text_renderer.cpp | 36 +- src/core/types.cpp | 62 +-- src/qt/plot_interaction_item.cpp | 18 +- src/qt/plot_renderer.cpp | 90 ++--- src/qt/plot_renderer.h | 2 +- src/qt/plot_time_axis.cpp | 22 +- src/qt/plot_widget.cpp | 76 ++-- src/qt/t_axis_adjust.h | 22 +- tests/test_asset_loader.cpp | 2 +- tests/test_cache_invalidation.cpp | 174 ++++----- tests/test_concurrent_series.cpp | 8 +- tests/test_core_algo.cpp | 50 +-- tests/test_data_source_queries.cpp | 12 +- tests/test_font_disk_cache.cpp | 18 +- tests/test_layout_calculator.cpp | 30 +- tests/test_plot_interaction_item.cpp | 18 +- tests/test_qrhi_layer_lifecycle.cpp | 438 +++++++++++----------- tests/test_qrhi_public_api.cpp | 68 ++-- tests/test_snapshot_caching.cpp | 314 ++++++++-------- tests/test_typed_api.cpp | 20 +- 40 files changed, 1228 insertions(+), 1228 deletions(-) diff --git a/include/vnm_plot/core/access_policy.h b/include/vnm_plot/core/access_policy.h index 8a8a2862..86be8454 100644 --- a/include/vnm_plot/core/access_policy.h +++ b/include/vnm_plot/core/access_policy.h @@ -241,11 +241,11 @@ struct Data_access_policy_typed Data_access_policy_typed& operator=(const Data_access_policy_typed& other) { if (this != &other) { - get_timestamp = other.get_timestamp; - get_value = other.get_value; - get_range = other.get_range; - layout_key = other.layout_key; - semantics_key = other.semantics_key; + get_timestamp = other.get_timestamp; + get_value = other.get_value; + get_range = other.get_range; + layout_key = other.layout_key; + semantics_key = other.semantics_key; internal_access = other.internal_access; ++access_revision; bind_accessor_slots(); @@ -256,11 +256,11 @@ struct Data_access_policy_typed Data_access_policy_typed& operator=(Data_access_policy_typed&& other) { if (this != &other) { - get_timestamp = other.get_timestamp; - get_value = other.get_value; - get_range = other.get_range; - layout_key = other.layout_key; - semantics_key = other.semantics_key; + get_timestamp = other.get_timestamp; + get_value = other.get_value; + get_range = other.get_range; + layout_key = other.layout_key; + semantics_key = other.semantics_key; internal_access = other.internal_access; ++access_revision; bind_accessor_slots(); @@ -308,7 +308,7 @@ struct Data_access_policy_typed if (get_range) { policy.get_range = erase_accessor(get_range); } - policy.layout_key = layout_key; + policy.layout_key = layout_key; policy.semantics_key = semantics_key; policy.set_internal_access(internal_access); return policy; @@ -415,20 +415,20 @@ inline Data_access_policy_typed make_access_policy( internal_access.get_range = &detail::member_range_access; internal_access.timestamp_offset = timestamp_offset; - internal_access.value_offset = value_offset; + internal_access.value_offset = value_offset; internal_access.range_min_offset = range_min_offset; internal_access.range_max_offset = range_max_offset; internal_access.dispatch_kind = detail::access_dispatch_kind_t::MEMBER_POINTER; policy.set_internal_access(internal_access); - policy.layout_key = detail::compute_sample_layout_key( + policy.layout_key = detail::compute_sample_layout_key( sizeof(Sample), timestamp_offset, value_offset, true, range_min_offset, range_max_offset); - policy.semantics_key.value = detail::compute_sample_semantics_key( + policy.semantics_key.value = detail::compute_sample_semantics_key( sizeof(Sample), timestamp_offset, detail::member_semantics_tag(), @@ -439,7 +439,7 @@ inline Data_access_policy_typed make_access_policy( detail::member_semantics_tag(), range_max_offset, detail::member_semantics_tag()); - policy.semantics_key.revision = 0; + policy.semantics_key.revision = 0; policy.semantics_key.conservative = false; return policy; } @@ -454,14 +454,14 @@ inline Data_access_policy_typed make_access_policy( const std::size_t value_offset = detail::member_offset(value_member); assign_standard_accessors(policy, timestamp_member, value_member); - policy.layout_key = detail::compute_sample_layout_key( + policy.layout_key = detail::compute_sample_layout_key( sizeof(Sample), timestamp_offset, value_offset, false, 0, 0); - policy.semantics_key.value = detail::compute_sample_semantics_key( + policy.semantics_key.value = detail::compute_sample_semantics_key( sizeof(Sample), timestamp_offset, detail::member_semantics_tag(), @@ -472,7 +472,7 @@ inline Data_access_policy_typed make_access_policy( 0, 0, 0); - policy.semantics_key.revision = 0; + policy.semantics_key.revision = 0; policy.semantics_key.conservative = false; return policy; } diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 9602ff31..4d4f90ea 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -556,8 +556,8 @@ visible_sample_aggregate_t aggregate_visible_sample_range( aggregate = {dlow, dhigh, ts_ns, ts_ns, true}; return; } - aggregate.vmin = std::min(aggregate.vmin, dlow); - aggregate.vmax = std::max(aggregate.vmax, dhigh); + aggregate.vmin = std::min(aggregate.vmin, dlow); + aggregate.vmax = std::max(aggregate.vmax, dhigh); aggregate.tmin_ns = std::min(aggregate.tmin_ns, ts_ns); aggregate.tmax_ns = std::max(aggregate.tmax_ns, ts_ns); }; @@ -708,7 +708,7 @@ inline std::int64_t choose_snap_ns(std::int64_t span_ns) constexpr std::int64_t k_ns_per_us = 1000LL; constexpr std::int64_t k_ns_per_ms = 1000000LL; constexpr std::int64_t k_ns_per_second = 1000000000LL; - constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; + constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; constexpr std::int64_t k_ns_per_day = 86400LL * k_ns_per_second; constexpr std::int64_t k_ns_per_year = 365LL * k_ns_per_day; diff --git a/include/vnm_plot/core/color_palette.h b/include/vnm_plot/core/color_palette.h index 3e1a3911..4a537cf0 100644 --- a/include/vnm_plot/core/color_palette.h +++ b/include/vnm_plot/core/color_palette.h @@ -67,14 +67,14 @@ struct Color_palette static Color_palette light() { Color_palette p; - p.background = hex_to_vec4("ffffffff"); - p.h_label_background = hex_to_vec4("ffbadaef"); - p.v_label_background = hex_to_vec4("ff959595"); - p.preview_background = hex_to_vec4("ffeeeeee"); - p.separator = hex_to_vec4("ff999999"); - p.grid_line = hex_to_vec4("ff000000"); - p.preview_cover = hex_to_vec4("99707070"); - p.preview_cover_secondary = hex_to_vec4("85707070"); + p.background = hex_to_vec4("ffffffff"); + p.h_label_background = hex_to_vec4("ffbadaef"); + p.v_label_background = hex_to_vec4("ff959595"); + p.preview_background = hex_to_vec4("ffeeeeee"); + p.separator = hex_to_vec4("ff999999"); + p.grid_line = hex_to_vec4("ff000000"); + p.preview_cover = hex_to_vec4("99707070"); + p.preview_cover_secondary = hex_to_vec4("85707070"); return p; } diff --git a/include/vnm_plot/core/plot_config.h b/include/vnm_plot/core/plot_config.h index 701b113c..174dd564 100644 --- a/include/vnm_plot/core/plot_config.h +++ b/include/vnm_plot/core/plot_config.h @@ -82,7 +82,7 @@ class Profile_scope } } - Profile_scope(const Profile_scope&) = delete; + Profile_scope(const Profile_scope&) = delete; Profile_scope& operator=(const Profile_scope&) = delete; private: diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 10de6cd3..60cc2ab3 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -223,8 +223,8 @@ class access_function_slot_t sample_semantics_key_t* semantics_key = nullptr) noexcept { m_internal_access = access; - m_revision = revision; - m_semantics_key = semantics_key; + m_revision = revision; + m_semantics_key = semantics_key; } void clear_internal_access() noexcept @@ -252,8 +252,8 @@ inline sample_semantics_key_t make_explicit_sample_semantics_key( { sample_semantics_key_t key; if (value != 0) { - key.value = value; - key.revision = revision; + key.value = value; + key.revision = revision; key.conservative = false; } return key; @@ -405,11 +405,11 @@ struct Data_access_policy Data_access_policy& operator=(const Data_access_policy& other) { if (this != &other) { - get_timestamp = other.get_timestamp; - get_value = other.get_value; - get_range = other.get_range; - layout_key = other.layout_key; - semantics_key = other.semantics_key; + get_timestamp = other.get_timestamp; + get_value = other.get_value; + get_range = other.get_range; + layout_key = other.layout_key; + semantics_key = other.semantics_key; internal_access = other.internal_access; ++access_revision; bind_accessor_slots(); @@ -420,11 +420,11 @@ struct Data_access_policy Data_access_policy& operator=(Data_access_policy&& other) { if (this != &other) { - get_timestamp = other.get_timestamp; - get_value = other.get_value; - get_range = other.get_range; - layout_key = other.layout_key; - semantics_key = other.semantics_key; + get_timestamp = other.get_timestamp; + get_value = other.get_value; + get_range = other.get_range; + layout_key = other.layout_key; + semantics_key = other.semantics_key; internal_access = other.internal_access; ++access_revision; bind_accessor_slots(); @@ -572,13 +572,13 @@ inline access_policy_cache_key_t make_access_policy_cache_key( const erased_access_policy_t& view) { access_policy_cache_key_t key; - key.identity = policy; - key.layout_key = policy ? policy->layout_key : 0; - key.revision = policy ? policy->access_revision : 0; + key.identity = policy; + key.layout_key = policy ? policy->layout_key : 0; + key.revision = policy ? policy->access_revision : 0; key.dispatch_kind = view.dispatch_kind; key.has_timestamp = view.has_timestamp(); - key.has_value = view.has_value(); - key.has_range = view.has_range(); + key.has_value = view.has_value(); + key.has_range = view.has_range(); return key; } @@ -891,8 +891,8 @@ class Vector_data_source : public Data_source { std::lock_guard lock(m_mutex); new_payload->sequence = m_payload->sequence + 1; - old_payload = std::move(m_payload); - m_payload = std::move(new_payload); + old_payload = std::move(m_payload); + m_payload = std::move(new_payload); } } diff --git a/include/vnm_plot/rhi/font_renderer.h b/include/vnm_plot/rhi/font_renderer.h index 57f8138e..4e722a7e 100644 --- a/include/vnm_plot/rhi/font_renderer.h +++ b/include/vnm_plot/rhi/font_renderer.h @@ -81,10 +81,10 @@ class Font_renderer ~Font_renderer(); // Non-copyable and non-movable due to renderer resource ownership. - Font_renderer(const Font_renderer&) = delete; + Font_renderer(const Font_renderer&) = delete; Font_renderer& operator=(const Font_renderer&) = delete; - Font_renderer(Font_renderer&&) = delete; - Font_renderer& operator=(Font_renderer&&) = delete; + Font_renderer(Font_renderer&&) = delete; + Font_renderer& operator=(Font_renderer&&) = delete; // Initializes the font system and ensures text metrics are ready. // asset_loader: Provider for font and shader assets diff --git a/include/vnm_plot/rhi/primitive_renderer.h b/include/vnm_plot/rhi/primitive_renderer.h index 129b17d1..b48be56a 100644 --- a/include/vnm_plot/rhi/primitive_renderer.h +++ b/include/vnm_plot/rhi/primitive_renderer.h @@ -39,7 +39,7 @@ class Primitive_renderer ~Primitive_renderer(); // Non-copyable (owns GPU resources) - Primitive_renderer(const Primitive_renderer&) = delete; + Primitive_renderer(const Primitive_renderer&) = delete; Primitive_renderer& operator=(const Primitive_renderer&) = delete; void cleanup_resources(); diff --git a/include/vnm_plot/rhi/series_renderer.h b/include/vnm_plot/rhi/series_renderer.h index 0f351380..090098f9 100644 --- a/include/vnm_plot/rhi/series_renderer.h +++ b/include/vnm_plot/rhi/series_renderer.h @@ -51,7 +51,7 @@ class Series_renderer Series_renderer(); ~Series_renderer(); - Series_renderer(const Series_renderer&) = delete; + Series_renderer(const Series_renderer&) = delete; Series_renderer& operator=(const Series_renderer&) = delete; // Keep parity with the rest of the renderer initialization path. QSB @@ -140,7 +140,7 @@ class Series_renderer vbo_view_state_t(); ~vbo_view_state_t(); - vbo_view_state_t(const vbo_view_state_t&) = delete; + vbo_view_state_t(const vbo_view_state_t&) = delete; vbo_view_state_t& operator=(const vbo_view_state_t&) = delete; vbo_view_state_t(vbo_view_state_t&&) noexcept; vbo_view_state_t& operator=(vbo_view_state_t&&) noexcept; @@ -157,7 +157,7 @@ class Series_renderer vbo_state_t(); ~vbo_state_t(); - vbo_state_t(const vbo_state_t&) = delete; + vbo_state_t(const vbo_state_t&) = delete; vbo_state_t& operator=(const vbo_state_t&) = delete; vbo_state_t(vbo_state_t&&) noexcept; vbo_state_t& operator=(vbo_state_t&&) noexcept; diff --git a/src/core/asset_loader.cpp b/src/core/asset_loader.cpp index 3255329c..f112a76d 100644 --- a/src/core/asset_loader.cpp +++ b/src/core/asset_loader.cpp @@ -7,7 +7,7 @@ namespace vnm::plot { -Asset_loader::Asset_loader() = default; +Asset_loader::Asset_loader() = default; Asset_loader::~Asset_loader() = default; void Asset_loader::set_log_callback(Log_callback callback) diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index 9242ffd1..b4ffd2b6 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -33,8 +33,8 @@ sample_draw_status_t include_sample_range( } if (!have_any) { - out_min = draw_value.y_min; - out_max = draw_value.y_max; + out_min = draw_value.y_min; + out_max = draw_value.y_max; have_any = true; return sample_draw_status_t::DRAWABLE; } @@ -91,19 +91,19 @@ bool scan_series_range( } if (status == sample_draw_status_t::DRAWABLE) { if (!have_held_candidate || t > held_timestamp_ns) { - held_sample = sample; - have_held_sample = true; + held_sample = sample; + have_held_sample = true; have_held_candidate = true; - held_timestamp_ns = t; + held_timestamp_ns = t; } } else if (nonfinite_policy == Nonfinite_sample_policy::BREAK_SEGMENT) { if (!have_held_candidate || t > held_timestamp_ns) { - held_sample = nullptr; - have_held_sample = false; + held_sample = nullptr; + have_held_sample = false; have_held_candidate = true; - held_timestamp_ns = t; + held_timestamp_ns = t; } } continue; @@ -188,12 +188,12 @@ data_query_context_t make_query( Nonfinite_sample_policy nonfinite_policy) { data_query_context_t query; - query.access = &access; - query.semantics_key = make_sample_semantics_key(&access); - query.time_window = time_window; - query.interpolation = interpolation; + query.access = &access; + query.semantics_key = make_sample_semantics_key(&access); + query.time_window = time_window; + query.interpolation = interpolation; query.empty_window_behavior = empty_window_behavior; - query.nonfinite_policy = nonfinite_policy; + query.nonfinite_policy = nonfinite_policy; return query; } @@ -238,23 +238,23 @@ auto_range_cache_entry_t make_cache_entry( auto_range_cache_entry_t entry; const erased_access_policy_t access_view = make_erased_access_policy_view(access); - entry.source_identity = source.identity(); - entry.access_identity = &access; - entry.access_key = make_access_policy_cache_key(&access, access_view); - entry.layout_key = access.layout_key; - entry.semantics_value = query.semantics_key.value; - entry.semantics_revision = query.semantics_key.revision; + entry.source_identity = source.identity(); + entry.access_identity = &access; + entry.access_key = make_access_policy_cache_key(&access, access_view); + entry.layout_key = access.layout_key; + entry.semantics_value = query.semantics_key.value; + entry.semantics_revision = query.semantics_key.revision; entry.semantics_conservative = query.semantics_key.conservative; - entry.lod_level = lod_level; - entry.t_min_ns = query.time_window.min_ns; - entry.t_max_ns = query.time_window.max_ns; - entry.interpolation = query.interpolation; - entry.empty_window_behavior = query.empty_window_behavior; - entry.nonfinite_policy = query.nonfinite_policy; - entry.sequence = sequence; - entry.range = range; - entry.status = status; - entry.valid = true; + entry.lod_level = lod_level; + entry.t_min_ns = query.time_window.min_ns; + entry.t_max_ns = query.time_window.max_ns; + entry.interpolation = query.interpolation; + entry.empty_window_behavior = query.empty_window_behavior; + entry.nonfinite_policy = query.nonfinite_policy; + entry.sequence = sequence; + entry.range = range; + entry.status = status; + entry.valid = true; return entry; } @@ -463,8 +463,8 @@ bool resolve_series_collection_range( continue; } - out_min = std::min(out_min, series_min); - out_max = std::max(out_max, series_max); + out_min = std::min(out_min, series_min); + out_max = std::max(out_max, series_max); have_any = true; } diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index 6fca795c..d839832f 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -211,9 +211,9 @@ void Chrome_renderer::render_grid_and_backgrounds( } const float pos = get_pos(label); const auto props = match_level_properties(pos, main_levels); - ticks.spacing_px[ticks.count] = 1e6f; - ticks.start_px[ticks.count] = pos; - ticks.alpha[ticks.count] = props.first; + ticks.spacing_px[ticks.count] = 1e6f; + ticks.start_px[ticks.count] = pos; + ticks.alpha[ticks.count] = props.first; ticks.thickness_px[ticks.count] = props.second; ++ticks.count; } @@ -268,10 +268,10 @@ void Chrome_renderer::render_zero_line( const glm::vec2 main_origin = to_gl_origin(ctx, main_top_left, main_size); grid_layer_params_t zero_level; - zero_level.count = 1; - zero_level.spacing_px[0] = 1e6f; - zero_level.start_px[0] = zero_y_gl; - zero_level.alpha[0] = k_grid_line_alpha_base; + zero_level.count = 1; + zero_level.spacing_px[0] = 1e6f; + zero_level.start_px[0] = zero_y_gl; + zero_level.alpha[0] = k_grid_line_alpha_base; zero_level.thickness_px[0] = 1.2f; grid_layer_params_t empty_levels; diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index d28db895..aa615ad6 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -213,10 +213,10 @@ void store_cached_font(const std::shared_ptr& font) vnm::msdf_text::options_t atlas_options() { vnm::msdf_text::options_t options; - options.atlas_size = k_atlas_texture_size; + options.atlas_size = k_atlas_texture_size; options.min_atlas_font_size = k_min_atlas_font_size; - options.atlas_px_range = k_atlas_px_range; - options.sharpness_bias = k_sharpness_bias; + options.atlas_px_range = k_atlas_px_range; + options.sharpness_bias = k_sharpness_bias; options.build_kerning_table = true; return options; } @@ -506,7 +506,7 @@ std::shared_ptr load_cached_font_from_disk( auto font = std::make_shared(); font->draw_pixel_height = pixel_height; - font->font_digest = digest; + font->font_digest = digest; std::uint32_t atlas_size = 0; if (!read(atlas_size)) { return nullptr; } @@ -695,7 +695,7 @@ std::shared_ptr build_font_cache( const std::function& log_debug) { auto font = std::make_shared(); - font->font_digest = font_digest; + font->font_digest = font_digest; font->draw_pixel_height = pixel_height; auto result = vnm::msdf_text::build_font_atlas( @@ -712,7 +712,7 @@ std::shared_ptr build_font_cache( return nullptr; } - font->atlas = std::move(result.atlas); + font->atlas = std::move(result.atlas); font->cache_epoch = s_next_cache_epoch.fetch_add(1, std::memory_order_relaxed); return font; @@ -954,11 +954,11 @@ void Font_renderer::initialize(Asset_loader& asset_loader, int pixel_height, boo return; } - const auto& cached = *m_impl->m_font_cache; + const auto& cached = *m_impl->m_font_cache; resources.m_pixel_height = pixel_height; - resources.m_cache_epoch = cached.cache_epoch; - resources.m_atlas = cached.atlas; - m_impl->m_resources = &resources; + resources.m_cache_epoch = cached.cache_epoch; + resources.m_atlas = cached.atlas; + m_impl->m_resources = &resources; } void Font_renderer::initialize_metrics( @@ -982,7 +982,7 @@ void Font_renderer::initialize_metrics( return; } - m_impl->m_font_cache = std::move(cached); + m_impl->m_font_cache = std::move(cached); m_impl->m_metric_pixel_height = pixel_height; } @@ -1226,8 +1226,8 @@ void Font_renderer::rhi_queue_draw( } if (!rhi_state.shaders_loaded) { - rhi_state.vert = load_qsb("msdf_text.vert.qsb"); - rhi_state.frag = load_qsb("msdf_text.frag.qsb"); + rhi_state.vert = load_qsb("msdf_text.vert.qsb"); + rhi_state.frag = load_qsb("msdf_text.frag.qsb"); rhi_state.shaders_loaded = true; } @@ -1252,7 +1252,7 @@ void Font_renderer::rhi_queue_draw( cached.atlas.atlas_size * 4, QImage::Format_RGBA8888); updates->uploadTexture(rhi_state.atlas_texture.get(), image); - rhi_state.atlas_size = cached.atlas.atlas_size; + rhi_state.atlas_size = cached.atlas.atlas_size; rhi_state.uploaded_cache_epoch = cached.cache_epoch; for (auto& call : rhi_state.calls) { call.srb.reset(); @@ -1411,7 +1411,7 @@ void Font_renderer::rhi_queue_draw( rhi_state.pipeline->setTopology(QRhiGraphicsPipeline::Triangles); QRhiGraphicsPipeline::TargetBlend blend; - blend.enable = true; + blend.enable = true; blend.srcColor = QRhiGraphicsPipeline::SrcAlpha; blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha; blend.srcAlpha = QRhiGraphicsPipeline::One; @@ -1427,7 +1427,7 @@ void Font_renderer::rhi_queue_draw( m_impl->m_rhi_index_data.clear(); return; } - rhi_state.pipeline_rpd = current_rpd; + rhi_state.pipeline_rpd = current_rpd; rhi_state.pipeline_samples = current_samples; } @@ -1439,19 +1439,19 @@ void Font_renderer::rhi_queue_draw( Text_block_std140 block{}; std::memcpy(block.pmv, glm::value_ptr(pmv), sizeof(block.pmv)); - block.color[0] = draw_color.r; - block.color[1] = draw_color.g; - block.color[2] = draw_color.b; - block.color[3] = draw_color.a; + block.color[0] = draw_color.r; + block.color[1] = draw_color.g; + block.color[2] = draw_color.b; + block.color[3] = draw_color.a; block.shadow_color[0] = draw_shadow.color.r; block.shadow_color[1] = draw_shadow.color.g; block.shadow_color[2] = draw_shadow.color.b; block.shadow_color[3] = draw_shadow.color.a; - block.px_range = vnm::msdf_text::px_range_for_pixel_height( + block.px_range = vnm::msdf_text::px_range_for_pixel_height( cached.atlas, cached.draw_pixel_height); - block.target_width = static_cast(std::max(1, ctx.win_w)); - block.target_height = static_cast(std::max(1, ctx.win_h)); - block.shadow_radius = draw_shadow.radius_px; + block.target_width = static_cast(std::max(1, ctx.win_w)); + block.target_height = static_cast(std::max(1, ctx.win_h)); + block.shadow_radius = draw_shadow.radius_px; block.lcd_subpixel_order = vnm::msdf_text::lcd::shader_uniform_value(effective_lcd.subpixel_order); block.framebuffer_y_up = @@ -1473,7 +1473,7 @@ void Font_renderer::rhi_queue_draw( if (has_shadow) { glm::vec4 transparent_text = color; - transparent_text.a = 0.0f; + transparent_text.a = 0.0f; queue_text_pass( shadow_call_index, transparent_text, diff --git a/src/core/font_renderer_stub.cpp b/src/core/font_renderer_stub.cpp index f3096cfc..60d84427 100644 --- a/src/core/font_renderer_stub.cpp +++ b/src/core/font_renderer_stub.cpp @@ -35,7 +35,7 @@ bool font_disk_cache_enabled() // Font Renderer (stub) // ----------------------------------------------------------------------------- -Font_renderer::Font_renderer() = default; +Font_renderer::Font_renderer() = default; Font_renderer::~Font_renderer() = default; void Font_renderer::initialize(Asset_loader&, int, bool) diff --git a/src/core/frame_range_planner.cpp b/src/core/frame_range_planner.cpp index 9ad83567..06aa0fba 100644 --- a/src/core/frame_range_planner.cpp +++ b/src/core/frame_range_planner.cpp @@ -10,8 +10,8 @@ namespace { value_range_plan_t make_value_range_plan(std::pair range) { value_range_plan_t plan; - plan.min = range.first; - plan.max = range.second; + plan.min = range.first; + plan.max = range.second; plan.valid = std::isfinite(plan.min) && std::isfinite(plan.max) && plan.min <= plan.max; return plan; } diff --git a/src/core/label_pane_geometry.h b/src/core/label_pane_geometry.h index 1182f07f..c151ec47 100644 --- a/src/core/label_pane_geometry.h +++ b/src/core/label_pane_geometry.h @@ -133,10 +133,10 @@ namespace vnm::plot::detail { } scissor.enabled = true; - scissor.x = left; - scissor.y = window_height - bottom; - scissor.width = right - left; - scissor.height = bottom - top; + scissor.x = left; + scissor.y = window_height - bottom; + scissor.width = right - left; + scissor.height = bottom - top; const bool contained = scissor.x >= 0 && diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 2055e3e6..9040a2db 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -522,8 +522,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par bool used_seed = false; if (params.has_vertical_seed && params.vertical_seed_index >= 0) { if (validate_seed(params.vertical_seed_step, params.vertical_seed_index)) { - step = params.vertical_seed_step; - i = params.vertical_seed_index; + step = params.vertical_seed_step; + i = params.vertical_seed_index; used_seed = true; } } @@ -538,17 +538,17 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par } initial_level_index = i; - initial_level_step = step; - px_per_unit = params.usable_height / v_span; + initial_level_step = step; + px_per_unit = params.usable_height / v_span; accepted_boxes.clear(); level.clear(); accepted_y.clear(); - label_box_height_px = std::max( + label_box_height_px = std::max( 1.0f, static_cast(params.adjusted_font_size_in_pixels)); - label_gap_px = 10.0f; + label_gap_px = 10.0f; min_label_spacing_px = label_box_height_px + label_gap_px; finest_step_accepted = step; } @@ -571,10 +571,10 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par profiler, "renderer.frame.calculate_layout.impl.cache_miss.pass1.vertical_axis.iter_prep"); level.clear(); - shift = get_shift(step, double(params.v_min)); + shift = get_shift(step, double(params.v_min)); extend = step; - j_min = static_cast(std::ceil((-extend - shift) / step - 1e-9)); - j_max = static_cast(std::floor((v_span + extend - shift) / step + 1e-9)); + j_min = static_cast(std::ceil((-extend - shift) / step - 1e-9)); + j_max = static_cast(std::floor((v_span + extend - shift) / step + 1e-9)); this_vals.clear(); this_vals.reserve(j_max - j_min + 1); } @@ -675,8 +675,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par VNM_PLOT_PROFILE_SCOPE( profiler, "renderer.frame.calculate_layout.impl.cache_miss.pass1.vertical_axis.finalize"); - res.vertical_seed_index = initial_level_index; - res.vertical_seed_step = initial_level_step; + res.vertical_seed_index = initial_level_index; + res.vertical_seed_step = initial_level_step; res.vertical_finest_step = finest_step_accepted; } @@ -712,8 +712,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par profiler, "renderer.frame.calculate_layout.impl.cache_miss.pass1.vertical_axis.label_prep"); res.max_v_label_text_width = 0.f; - advance = std::max(params.monospace_char_advance_px, 0.f); - use_monospace = params.monospace_advance_is_reliable && advance > 0.f; + advance = std::max(params.monospace_char_advance_px, 0.f); + use_monospace = params.monospace_advance_is_reliable && advance > 0.f; } { @@ -722,7 +722,7 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par "renderer.frame.calculate_layout.impl.cache_miss.pass1.vertical_axis.measure_text"); for (auto& e : res.v_labels) { value_format_context_t context; - context.role = Value_format_role::AXIS_LABEL; + context.role = Value_format_role::AXIS_LABEL; context.suggested_fixed_digits = res.v_label_fixed_digits; std::string text = params.format_value_func @@ -791,10 +791,10 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par VNM_PLOT_PROFILE_SCOPE( profiler, "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.prep"); - px_per_t = params.usable_width / t_range; - advance = std::max(params.monospace_char_advance_px, 0.f); + px_per_t = params.usable_width / t_range; + advance = std::max(params.monospace_char_advance_px, 0.f); use_monospace = params.monospace_advance_is_reliable && advance > 0.f; - steps = build_time_steps_covering(t_range); + steps = build_time_steps_covering(t_range); } const auto x_of_t = [&](double tt_seconds) -> float { @@ -950,9 +950,9 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par // Account for text margin: visual right edge is at x + k_text_margin_px + width. // Skip only when visual right edge is fully offscreen (< 0). if (x + k_text_margin_px + skip_width <= 0.f) { - const int skip = std::max(1, int(std::ceil(skip_width / pixel_step))); - tick_index += skip; - t = t_start + tick_index * step; + const int skip = std::max(1, int(std::ceil(skip_width / pixel_step))); + tick_index += skip; + t = t_start + tick_index * step; continue; } @@ -965,9 +965,9 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par } if (anchor_taken) { - const int skip = std::max(1, int(std::ceil(min_gap / pixel_step))); - tick_index += skip; - t = t_start + tick_index * step; + const int skip = std::max(1, int(std::ceil(min_gap / pixel_step))); + tick_index += skip; + t = t_start + tick_index * step; continue; } @@ -1034,9 +1034,9 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par // Account for text margin: visual right edge is at x + k_text_margin_px + w. // Cull only when visual right edge is fully offscreen (< 0). if (x + k_text_margin_px + w <= 0.f) { - const int skip = std::max(1, int(std::ceil(w / pixel_step))); - tick_index += skip; - t = t_start + tick_index * step; + const int skip = std::max(1, int(std::ceil(w / pixel_step))); + tick_index += skip; + t = t_start + tick_index * step; continue; } if (have_prev_candidate && x < prev_candidate_x1 + min_gap) { diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index 248d0719..c2dff605 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -201,21 +201,21 @@ void Primitive_renderer::cleanup_resources() m_rhi_state->rect_calls.clear(); m_rhi_state->grid_calls.clear(); m_rhi_state->ops.clear(); - m_rhi_state->rect_used = 0; - m_rhi_state->grid_used = 0; + m_rhi_state->rect_used = 0; + m_rhi_state->grid_used = 0; m_rhi_state->rect_pipeline.reset(); m_rhi_state->grid_pipeline.reset(); - m_rhi_state->rect_pipeline_rpd = nullptr; + m_rhi_state->rect_pipeline_rpd = nullptr; m_rhi_state->rect_pipeline_samples = 0; - m_rhi_state->grid_pipeline_rpd = nullptr; + m_rhi_state->grid_pipeline_rpd = nullptr; m_rhi_state->grid_pipeline_samples = 0; m_rhi_state->grid_quad_vbo.reset(); - m_rhi_state->shaders_loaded = false; - m_rhi_state->rect_vert = {}; - m_rhi_state->rect_frag = {}; - m_rhi_state->grid_vert = {}; - m_rhi_state->grid_frag = {}; - m_rhi_state->last_rhi = nullptr; + m_rhi_state->shaders_loaded = false; + m_rhi_state->rect_vert = {}; + m_rhi_state->rect_frag = {}; + m_rhi_state->grid_vert = {}; + m_rhi_state->grid_frag = {}; + m_rhi_state->last_rhi = nullptr; } void Primitive_renderer::batch_rect(const glm::vec4& color, const glm::vec4& rect_coords) @@ -259,16 +259,16 @@ bool Primitive_renderer::rhi_ensure_rect_pipeline( vlayout.setAttributes({a_color, a_rect}); detail::alpha_blended_pipeline_desc_t desc; - desc.vert = rhi_state.rect_vert; - desc.frag = rhi_state.rect_frag; - desc.vlayout = vlayout; - desc.ubo_bytes = k_rect_ubo_bytes; - desc.ubo_stages = QRhiShaderResourceBinding::VertexStage; + desc.vert = rhi_state.rect_vert; + desc.frag = rhi_state.rect_frag; + desc.vlayout = vlayout; + desc.ubo_bytes = k_rect_ubo_bytes; + desc.ubo_stages = QRhiShaderResourceBinding::VertexStage; rhi_state.rect_pipeline = detail::build_alpha_blended_pipeline(rhi, rt, desc); if (!rhi_state.rect_pipeline) { return false; } - rhi_state.rect_pipeline_rpd = rpd; + rhi_state.rect_pipeline_rpd = rpd; rhi_state.rect_pipeline_samples = samples; return true; } @@ -302,17 +302,17 @@ bool Primitive_renderer::rhi_ensure_grid_pipeline( // grid_quad.frag is the only stage that reads the UBO; the .vert just // forwards the unit-quad vertex through gl_Position. detail::alpha_blended_pipeline_desc_t desc; - desc.vert = rhi_state.grid_vert; - desc.frag = rhi_state.grid_frag; - desc.vlayout = vlayout; - desc.ubo_bytes = k_grid_ubo_bytes; - desc.ubo_stages = QRhiShaderResourceBinding::FragmentStage; - desc.flags = QRhiGraphicsPipeline::UsesScissor; + desc.vert = rhi_state.grid_vert; + desc.frag = rhi_state.grid_frag; + desc.vlayout = vlayout; + desc.ubo_bytes = k_grid_ubo_bytes; + desc.ubo_stages = QRhiShaderResourceBinding::FragmentStage; + desc.flags = QRhiGraphicsPipeline::UsesScissor; rhi_state.grid_pipeline = detail::build_alpha_blended_pipeline(rhi, rt, desc); if (!rhi_state.grid_pipeline) { return false; } - rhi_state.grid_pipeline_rpd = rpd; + rhi_state.grid_pipeline_rpd = rpd; rhi_state.grid_pipeline_samples = samples; return true; } @@ -352,8 +352,8 @@ bool Primitive_renderer::rhi_ensure_grid_quad_vbo( void Primitive_renderer::rhi_reset_frame_plan(rhi_state_t& rhi_state) { rhi_state.ops.clear(); - rhi_state.rect_used = 0; - rhi_state.grid_used = 0; + rhi_state.rect_used = 0; + rhi_state.grid_used = 0; rhi_state.record_cursor = 0; } @@ -392,10 +392,10 @@ void Primitive_renderer::flush_rects(const frame_context_t& ctx, const glm::mat4 rhi_on_backend_change(*m_rhi_state, rhi); if (!m_rhi_state->shaders_loaded) { - m_rhi_state->rect_vert = load_qsb("generic_rect.vert.qsb"); - m_rhi_state->rect_frag = load_qsb("generic_rect.frag.qsb"); - m_rhi_state->grid_vert = load_qsb("grid_quad.vert.qsb"); - m_rhi_state->grid_frag = load_qsb("grid_quad.frag.qsb"); + m_rhi_state->rect_vert = load_qsb("generic_rect.vert.qsb"); + m_rhi_state->rect_frag = load_qsb("generic_rect.frag.qsb"); + m_rhi_state->grid_vert = load_qsb("grid_quad.vert.qsb"); + m_rhi_state->grid_frag = load_qsb("grid_quad.frag.qsb"); m_rhi_state->shaders_loaded = true; } @@ -483,8 +483,8 @@ void Primitive_renderer::flush_rects(const frame_context_t& ctx, const glm::mat4 updates->updateDynamicBuffer(call.ubo.get(), 0, sizeof(block), &block); rhi_state_t::draw_op_t op{}; - op.kind = rhi_state_t::op_kind_t::RECT; - op.resource_index = slot; + op.kind = rhi_state_t::op_kind_t::RECT; + op.resource_index = slot; op.rect.instance_count = instance_count; m_rhi_state->ops.push_back(op); @@ -520,10 +520,10 @@ void Primitive_renderer::draw_grid_shader( rhi_on_backend_change(*m_rhi_state, rhi); if (!m_rhi_state->shaders_loaded) { - m_rhi_state->rect_vert = load_qsb("generic_rect.vert.qsb"); - m_rhi_state->rect_frag = load_qsb("generic_rect.frag.qsb"); - m_rhi_state->grid_vert = load_qsb("grid_quad.vert.qsb"); - m_rhi_state->grid_frag = load_qsb("grid_quad.frag.qsb"); + m_rhi_state->rect_vert = load_qsb("generic_rect.vert.qsb"); + m_rhi_state->rect_frag = load_qsb("generic_rect.frag.qsb"); + m_rhi_state->grid_vert = load_qsb("grid_quad.vert.qsb"); + m_rhi_state->grid_frag = load_qsb("grid_quad.frag.qsb"); m_rhi_state->shaders_loaded = true; } @@ -592,14 +592,14 @@ void Primitive_renderer::draw_grid_shader( block.region_origin_px[0] = origin.x; block.region_origin_px[1] = static_cast(ctx.win_h) - (origin.y + size.y); - block.grid_color[0] = color.r; - block.grid_color[1] = color.g; - block.grid_color[2] = color.b; - block.grid_color[3] = color.a; - block.v_count = std::min(vertical_levels.count, grid_layer_params_t::k_max_levels); - block.t_count = std::min(horizontal_levels.count, grid_layer_params_t::k_max_levels); + block.grid_color[0] = color.r; + block.grid_color[1] = color.g; + block.grid_color[2] = color.b; + block.grid_color[3] = color.a; + block.v_count = std::min(vertical_levels.count, grid_layer_params_t::k_max_levels); + block.t_count = std::min(horizontal_levels.count, grid_layer_params_t::k_max_levels); block.framebuffer_y_up = rhi->isYUpInFramebuffer() ? 1 : 0; - block.win_h = static_cast(ctx.win_h); + block.win_h = static_cast(ctx.win_h); for (int i = 0; i < block.v_count; ++i) { block.v_levels[i][0] = vertical_levels.spacing_px[i]; block.v_levels[i][1] = size.y - vertical_levels.start_px[i]; @@ -616,12 +616,12 @@ void Primitive_renderer::draw_grid_shader( updates->updateDynamicBuffer(call.ubo.get(), 0, sizeof(block), &block); rhi_state_t::draw_op_t op{}; - op.kind = rhi_state_t::op_kind_t::GRID; + op.kind = rhi_state_t::op_kind_t::GRID; op.resource_index = slot; - op.grid.x = sx; - op.grid.y = sy; - op.grid.w = sw; - op.grid.h = sh; + op.grid.x = sx; + op.grid.y = sy; + op.grid.w = sw; + op.grid.h = sh; m_rhi_state->ops.push_back(op); return; } diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index 866957a7..bf6f2f0e 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -263,7 +263,7 @@ inline std::unique_ptr build_alpha_blended_pipeline( pipeline->setTopology(QRhiGraphicsPipeline::TriangleStrip); QRhiGraphicsPipeline::TargetBlend blend; - blend.enable = true; + blend.enable = true; blend.srcColor = QRhiGraphicsPipeline::SrcAlpha; blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha; blend.srcAlpha = QRhiGraphicsPipeline::One; diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index aa1afcf3..fa4ca017 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -200,20 +200,20 @@ series_view_uniform_std140_t make_series_view_uniform( std::memcpy(uniform.pmv, glm::value_ptr(frame.pmv), sizeof(float) * 16); glm::vec4 draw_color = series.color; - draw_color.w *= window.window_alpha; - uniform.color[0] = draw_color.r; - uniform.color[1] = draw_color.g; - uniform.color[2] = draw_color.b; - uniform.color[3] = draw_color.a; - - uniform.t_min = detail::to_view_seconds(window.t_min_ns, window.t_origin_ns); - uniform.t_max = detail::to_view_seconds(window.t_max_ns, window.t_origin_ns); - uniform.v_min = window.v_min; - uniform.v_max = window.v_max; - uniform.width = window.width_px; - uniform.height = window.height_px; + draw_color.w *= window.window_alpha; + uniform.color[0] = draw_color.r; + uniform.color[1] = draw_color.g; + uniform.color[2] = draw_color.b; + uniform.color[3] = draw_color.a; + + uniform.t_min = detail::to_view_seconds(window.t_min_ns, window.t_origin_ns); + uniform.t_max = detail::to_view_seconds(window.t_max_ns, window.t_origin_ns); + uniform.v_min = window.v_min; + uniform.v_max = window.v_max; + uniform.width = window.width_px; + uniform.height = window.height_px; uniform.y_offset = window.y_offset_px; - uniform.win_h = static_cast(frame.win_h); + uniform.win_h = static_cast(frame.win_h); uniform.framebuffer_y_up = (frame.rhi && frame.rhi->isYUpInFramebuffer()) ? 1 : 0; return uniform; @@ -264,7 +264,7 @@ Series_renderer::vbo_view_state_t::vbo_view_state_t() : planner(std::make_unique()) {} -Series_renderer::vbo_view_state_t::~vbo_view_state_t() = default; +Series_renderer::vbo_view_state_t::~vbo_view_state_t() = default; Series_renderer::vbo_view_state_t::vbo_view_state_t(vbo_view_state_t&&) noexcept = default; Series_renderer::vbo_view_state_t& Series_renderer::vbo_view_state_t::operator=(vbo_view_state_t&&) noexcept = default; @@ -278,7 +278,7 @@ Series_renderer::vbo_state_t::vbo_state_t() : snapshot_cache(std::make_unique()) {} -Series_renderer::vbo_state_t::~vbo_state_t() = default; +Series_renderer::vbo_state_t::~vbo_state_t() = default; Series_renderer::vbo_state_t::vbo_state_t(vbo_state_t&&) noexcept = default; Series_renderer::vbo_state_t& Series_renderer::vbo_state_t::operator=(vbo_state_t&&) noexcept = default; @@ -626,15 +626,15 @@ void Series_renderer::cleanup_resources() m_rhi_state->qrhi_layer_cache.clear(); m_rhi_state->view_ubos.clear(); m_rhi_state->prepared_draws.clear(); - m_rhi_state->shaders_loaded = false; - m_rhi_state->cached_dot_vert = {}; - m_rhi_state->cached_dot_frag = {}; + m_rhi_state->shaders_loaded = false; + m_rhi_state->cached_dot_vert = {}; + m_rhi_state->cached_dot_frag = {}; m_rhi_state->cached_line_vert = {}; m_rhi_state->cached_line_frag = {}; m_rhi_state->cached_area_vert = {}; m_rhi_state->cached_area_frag = {}; - m_rhi_state->last_rhi = nullptr; - m_rhi_state->pending_updates = nullptr; + m_rhi_state->last_rhi = nullptr; + m_rhi_state->pending_updates = nullptr; m_rhi_state->frame_draw_states.clear(); m_rhi_state->prepared_draws.clear(); m_rhi_state->frame_plan_ready = false; @@ -714,7 +714,7 @@ void Series_renderer::prepare( m_rhi_state->prepared_draws.clear(); m_last_qrhi_layer_cache_size = 0; } - m_rhi_state->last_rhi = rhi; + m_rhi_state->last_rhi = rhi; m_rhi_state->pending_updates = rhi_updates; for (auto it = m_vbo_states.begin(); it != m_vbo_states.end(); ) { @@ -801,12 +801,12 @@ void Series_renderer::prepare( bool has_preview_layer = false; if (preview_visible) { - preview_source = s->preview_source(); - preview_access = &s->preview_access(); - preview_style = s->effective_preview_style(); + preview_source = s->preview_source(); + preview_access = &s->preview_access(); + preview_style = s->effective_preview_style(); preview_interpolation = s->effective_preview_interpolation(); - preview_matches_main = s->preview_matches_main(); - has_preview_layer = has_layer_for_view(Series_view_kind::PREVIEW); + preview_matches_main = s->preview_matches_main(); + has_preview_layer = has_layer_for_view(Series_view_kind::PREVIEW); if (has_preview_config && !preview_source) { log_error_once(Error_cat::PREVIEW_MISSING_SOURCE, id, @@ -854,25 +854,25 @@ void Series_renderer::prepare( detail::Snapshot_requirement snapshot_requirement) { detail::series_window_plan_request_t request; - request.series_id = id; - request.view_kind = view_kind; - request.planner_state = view_state.planner.get(); - request.snapshot_cache = vbo_state.snapshot_cache.get(); - request.frame_id = m_frame_id; - request.data_source = &data_source; - request.access = &access; - request.scales = &scales; - request.t_min_ns = t_min_ns; - request.t_max_ns = t_max_ns; - request.t_origin_ns = t_origin_ns; - request.width_px = width_px; + request.series_id = id; + request.view_kind = view_kind; + request.planner_state = view_state.planner.get(); + request.snapshot_cache = vbo_state.snapshot_cache.get(); + request.frame_id = m_frame_id; + request.data_source = &data_source; + request.access = &access; + request.scales = &scales; + request.t_min_ns = t_min_ns; + request.t_max_ns = t_max_ns; + request.t_origin_ns = t_origin_ns; + request.width_px = width_px; request.empty_window_behavior = s->empty_window_behavior; - request.nonfinite_policy = s->nonfinite_policy; - request.style = style; - request.interpolation = interpolation; - request.snapshot_requirement = snapshot_requirement; - request.has_uploaded_vbo = view_state.has_uploaded_vbo; - request.profiler = profiler; + request.nonfinite_policy = s->nonfinite_policy; + request.style = style; + request.interpolation = interpolation; + request.snapshot_requirement = snapshot_requirement; + request.has_uploaded_vbo = view_state.has_uploaded_vbo; + request.profiler = profiler; return detail::plan_series_window(request); }; @@ -894,10 +894,10 @@ void Series_renderer::prepare( has_main_layer ? detail::Snapshot_requirement::Frame_snapshot_required : detail::Snapshot_requirement::Optional); - main_plan.v_min = ctx.v0; - main_plan.v_max = ctx.v1; - main_plan.height_px = static_cast(layout.usable_height); - main_plan.y_offset_px = 0.0f; + main_plan.v_min = ctx.v0; + main_plan.v_max = ctx.v1; + main_plan.height_px = static_cast(layout.usable_height); + main_plan.y_offset_px = 0.0f; main_plan.window_alpha = 1.0f; if (ctx.config && ctx.config->log_debug && main_plan.gpu_count > 0 && @@ -910,14 +910,14 @@ void Series_renderer::prepare( } Series_view_plan preview_plan; - preview_plan.series_id = id; - preview_plan.view_kind = Series_view_kind::PREVIEW; - preview_plan.source = preview_source; - preview_plan.access = preview_access; + preview_plan.series_id = id; + preview_plan.view_kind = Series_view_kind::PREVIEW; + preview_plan.source = preview_source; + preview_plan.access = preview_access; preview_plan.empty_window_behavior = s->empty_window_behavior; - preview_plan.nonfinite_policy = s->nonfinite_policy; - preview_plan.style = preview_style; - preview_plan.interpolation = preview_interpolation; + preview_plan.nonfinite_policy = s->nonfinite_policy; + preview_plan.style = preview_style; + preview_plan.interpolation = preview_interpolation; if (preview_visible && preview_valid) { preview_plan = plan_series_view( Series_view_kind::PREVIEW, @@ -936,27 +936,27 @@ void Series_renderer::prepare( : detail::Snapshot_requirement::Optional); const double preview_top = double(ctx.win_h) - ctx.adjusted_preview_height; - preview_plan.v_min = ctx.preview_v0; - preview_plan.v_max = ctx.preview_v1; - preview_plan.height_px = static_cast(ctx.adjusted_preview_height); - preview_plan.y_offset_px = static_cast(preview_top); + preview_plan.v_min = ctx.preview_v0; + preview_plan.v_max = ctx.preview_v1; + preview_plan.height_px = static_cast(ctx.adjusted_preview_height); + preview_plan.y_offset_px = static_cast(preview_top); preview_plan.window_alpha = static_cast(preview_visibility); } series_draw_state_t draw_state; - draw_state.id = id; + draw_state.id = id; draw_state.series_order = next_series_order++; - draw_state.series = s; - draw_state.vbo_state = &vbo_state; - draw_state.main_plan = std::move(main_plan); + draw_state.series = s; + draw_state.vbo_state = &vbo_state; + draw_state.main_plan = std::move(main_plan); draw_state.preview_plan = std::move(preview_plan); - draw_state.has_preview = preview_visible && preview_valid; + draw_state.has_preview = preview_visible && preview_valid; draw_states.push_back(std::move(draw_state)); } const auto invalidate_view_upload_state = [](vbo_view_state_t& view_state) { - view_state.has_uploaded_vbo = false; - view_state.last_sample_buffer = nullptr; + view_state.has_uploaded_vbo = false; + view_state.last_sample_buffer = nullptr; view_state.last_staged_sample_count = 0; view_state.last_sample_upload_bytes = 0; view_state.line_draw_spans.clear(); @@ -979,30 +979,30 @@ void Series_renderer::prepare( const auto make_window = [](const Series_view_plan& plan) { sample_window_t window; - window.view_kind = plan.view_kind; - window.snapshot = plan.snapshot.snapshot; - window.access = plan.access; - window.source_first = plan.source_first; - window.source_count = plan.source_count; + window.view_kind = plan.view_kind; + window.snapshot = plan.snapshot.snapshot; + window.access = plan.access; + window.source_first = plan.source_first; + window.source_count = plan.source_count; window.synthetic_hold_count = plan.synthetic_hold_count; - window.gpu_count = plan.gpu_count; - window.drawable_spans = plan.drawable_spans; - window.lod_level = plan.lod_level; - window.pixels_per_sample = plan.pixels_per_sample; - window.sample_sequence = plan.snapshot.sequence; - window.interpolation = plan.interpolation; - window.nonfinite_policy = plan.nonfinite_policy; - window.t_min_ns = plan.t_min_ns; - window.t_max_ns = plan.t_max_ns; - window.t_origin_ns = plan.t_origin_ns; - window.hold_last_forward = plan.hold_last_forward; - window.hold_timestamp_ns = plan.hold_timestamp_ns; - window.v_min = plan.v_min; - window.v_max = plan.v_max; - window.width_px = plan.width_px; - window.height_px = plan.height_px; - window.y_offset_px = plan.y_offset_px; - window.window_alpha = plan.window_alpha; + window.gpu_count = plan.gpu_count; + window.drawable_spans = plan.drawable_spans; + window.lod_level = plan.lod_level; + window.pixels_per_sample = plan.pixels_per_sample; + window.sample_sequence = plan.snapshot.sequence; + window.interpolation = plan.interpolation; + window.nonfinite_policy = plan.nonfinite_policy; + window.t_min_ns = plan.t_min_ns; + window.t_max_ns = plan.t_max_ns; + window.t_origin_ns = plan.t_origin_ns; + window.hold_last_forward = plan.hold_last_forward; + window.hold_timestamp_ns = plan.hold_timestamp_ns; + window.v_min = plan.v_min; + window.v_max = plan.v_max; + window.width_px = plan.width_px; + window.height_px = plan.height_px; + window.y_offset_px = plan.y_offset_px; + window.window_alpha = plan.window_alpha; return window; }; @@ -1019,21 +1019,21 @@ void Series_renderer::prepare( return sample_buffer; } - sample_buffer.buffer = view_state.rhi->vbo.get(); - sample_buffer.first_sample = 0; - sample_buffer.sample_count = window.gpu_count; - sample_buffer.source_first = window.source_first; - sample_buffer.source_count = window.source_count; + sample_buffer.buffer = view_state.rhi->vbo.get(); + sample_buffer.first_sample = 0; + sample_buffer.sample_count = window.gpu_count; + sample_buffer.source_first = window.source_first; + sample_buffer.source_count = window.source_count; sample_buffer.synthetic_hold_count = window.synthetic_hold_count; - sample_buffer.t_origin_ns = window.t_origin_ns; - sample_buffer.t_min_ns = window.t_min_ns; - sample_buffer.t_max_ns = window.t_max_ns; - sample_buffer.v_min = window.v_min; - sample_buffer.v_max = window.v_max; - sample_buffer.layout.stride_bytes = sizeof(gpu_sample_t); + sample_buffer.t_origin_ns = window.t_origin_ns; + sample_buffer.t_min_ns = window.t_min_ns; + sample_buffer.t_max_ns = window.t_max_ns; + sample_buffer.v_min = window.v_min; + sample_buffer.v_max = window.v_max; + sample_buffer.layout.stride_bytes = sizeof(gpu_sample_t); sample_buffer.layout.t_rel_seconds_offset = offsetof(gpu_sample_t, t_rel); - sample_buffer.layout.value_offset = offsetof(gpu_sample_t, y); + sample_buffer.layout.value_offset = offsetof(gpu_sample_t, y); sample_buffer.layout.range_min_offset = offsetof(gpu_sample_t, y_min); sample_buffer.layout.range_max_offset = offsetof(gpu_sample_t, y_max); return sample_buffer; @@ -1078,14 +1078,14 @@ void Series_renderer::prepare( const Series_view_plan& plan, vbo_view_state_t& view_state) { - view_state.last_sample_upload_count = 0; - view_state.last_primitive_prepare_count = 0; - view_state.last_line_window_sample_count = 0; - view_state.last_recorded_line_span_count = 0; + view_state.last_sample_upload_count = 0; + view_state.last_primitive_prepare_count = 0; + view_state.last_line_window_sample_count = 0; + view_state.last_recorded_line_span_count = 0; view_state.last_recorded_line_segment_count = 0; - view_state.last_recorded_area_span_count = 0; + view_state.last_recorded_area_span_count = 0; view_state.last_recorded_area_segment_count = 0; - view_state.last_recorded_dot_sample_count = 0; + view_state.last_recorded_dot_sample_count = 0; view_state.last_sample_access_dispatch_kind = detail::access_dispatch_kind_t::NONE; view_state.last_sample_buffer = nullptr; @@ -1210,9 +1210,9 @@ void Series_renderer::prepare( const series_view_uniform_std140_t* view_uniform = nullptr; QRhiBuffer* view_ubo = nullptr; if (needs_view_ubo) { - uniform = make_series_view_uniform(ctx, *draw_state.series, window); + uniform = make_series_view_uniform(ctx, *draw_state.series, window); view_uniform = &uniform; - view_ubo = ensure_view_ubo( + view_ubo = ensure_view_ubo( draw_state.id, plan.view_kind, *draw_state.series, @@ -1251,15 +1251,15 @@ void Series_renderer::prepare( rhi_state_t::prepared_draw_command_t command; command.kind = rhi_state_t::prepared_draw_command_t::kind_t::BUILTIN; - command.z_order = planned_draw.z_order; - command.series_id = draw_state.id; - command.view_kind = plan.view_kind; - command.series_order = draw_state.series_order; + command.z_order = planned_draw.z_order; + command.series_id = draw_state.id; + command.view_kind = plan.view_kind; + command.series_order = draw_state.series_order; command.insertion_order = next_draw_insertion_order++; - command.series = draw_state.series.get(); - command.window = window; + command.series = draw_state.series.get(); + command.window = window; command.primitive_style = planned_draw.primitive_style; - command.view_state = &view_state; + command.view_state = &view_state; command.builtin_segment_spans = std::move(prepared_segment_spans); m_rhi_state->prepared_draws.push_back(std::move(command)); @@ -1282,14 +1282,14 @@ void Series_renderer::prepare( layer_access_view); rhi_state_t::qrhi_layer_program_key_t program_key; - program_key.series_id = draw_state.id; - program_key.view_kind = plan.view_kind; - program_key.layer_id = std::string(layer->id()); + program_key.series_id = draw_state.id; + program_key.view_kind = plan.view_kind; + program_key.layer_id = std::string(layer->id()); program_key.layer_revision = layer->revision(); - program_key.data_identity = plan.source ? plan.source->identity() : nullptr; - program_key.layout_key = plan.access ? plan.access->layout_key : 0; - program_key.access_key = layer_access_key; - program_key.rhi = rhi; + program_key.data_identity = plan.source ? plan.source->identity() : nullptr; + program_key.layout_key = plan.access ? plan.access->layout_key : 0; + program_key.access_key = layer_access_key; + program_key.rhi = rhi; if (!window.snapshot) { for (auto& [cached_key, cache_entry] : m_rhi_state->qrhi_layer_cache) { @@ -1311,18 +1311,18 @@ void Series_renderer::prepare( } rhi_state_t::qrhi_layer_data_key_t data_key; - data_key.lod_level = window.lod_level; - data_key.sample_sequence = window.sample_sequence; - data_key.t_origin_ns = window.t_origin_ns; - data_key.source_first = window.source_first; - data_key.source_count = window.source_count; + data_key.lod_level = window.lod_level; + data_key.sample_sequence = window.sample_sequence; + data_key.t_origin_ns = window.t_origin_ns; + data_key.source_first = window.source_first; + data_key.source_count = window.source_count; data_key.synthetic_hold_count = window.synthetic_hold_count; - data_key.gpu_count = window.gpu_count; - data_key.hold_last_forward = window.hold_last_forward; - data_key.hold_timestamp_ns = window.hold_timestamp_ns; - data_key.interpolation = window.interpolation; - data_key.nonfinite_policy = window.nonfinite_policy; - data_key.drawable_span_count = window.drawable_spans.size(); + data_key.gpu_count = window.gpu_count; + data_key.hold_last_forward = window.hold_last_forward; + data_key.hold_timestamp_ns = window.hold_timestamp_ns; + data_key.interpolation = window.interpolation; + data_key.nonfinite_policy = window.nonfinite_policy; + data_key.drawable_span_count = window.drawable_spans.size(); data_key.drawable_spans_hash = hash_drawable_spans(window.drawable_spans); data_key.access_key = layer_access_key; @@ -1336,8 +1336,8 @@ void Series_renderer::prepare( if (!cache_entry.has_data_key || !(cache_entry.data_key == data_key)) { resources_changed = true; } - cache_entry.data_key = data_key; - cache_entry.has_data_key = true; + cache_entry.data_key = data_key; + cache_entry.has_data_key = true; cache_entry.last_frame_used = m_frame_id; if (!cache_entry.state) { @@ -1345,31 +1345,31 @@ void Series_renderer::prepare( } qrhi_series_prepare_context_t prepare_ctx; - prepare_ctx.rhi = rhi; - prepare_ctx.render_target = ctx.render_target; - prepare_ctx.updates = rhi_updates; - prepare_ctx.asset_loader = m_asset_loader; - prepare_ctx.frame = &ctx; - prepare_ctx.series = draw_state.series.get(); - prepare_ctx.window = window; - prepare_ctx.view_uniform = view_uniform; - prepare_ctx.view_ubo = view_ubo; - prepare_ctx.sample_buffer = sample_buffer; + prepare_ctx.rhi = rhi; + prepare_ctx.render_target = ctx.render_target; + prepare_ctx.updates = rhi_updates; + prepare_ctx.asset_loader = m_asset_loader; + prepare_ctx.frame = &ctx; + prepare_ctx.series = draw_state.series.get(); + prepare_ctx.window = window; + prepare_ctx.view_uniform = view_uniform; + prepare_ctx.view_ubo = view_ubo; + prepare_ctx.sample_buffer = sample_buffer; prepare_ctx.resources_changed = resources_changed; if (cache_entry.state->prepare(prepare_ctx)) { rhi_state_t::prepared_draw_command_t command; command.kind = rhi_state_t::prepared_draw_command_t::kind_t::CUSTOM; - command.z_order = planned_draw.z_order; - command.series_id = draw_state.id; - command.view_kind = plan.view_kind; - command.series_order = draw_state.series_order; + command.z_order = planned_draw.z_order; + command.series_id = draw_state.id; + command.view_kind = plan.view_kind; + command.series_order = draw_state.series_order; command.insertion_order = next_draw_insertion_order++; - command.state = cache_entry.state.get(); - command.series = draw_state.series.get(); - command.window = window; - command.view_ubo = view_ubo; + command.state = cache_entry.state.get(); + command.series = draw_state.series.get(); + command.window = window; + command.view_ubo = view_ubo; m_rhi_state->prepared_draws.push_back(std::move(command)); } } @@ -1577,12 +1577,12 @@ void Series_renderer::render( continue; } qrhi_series_record_context_t record_ctx; - record_ctx.cb = ctx.cb; + record_ctx.cb = ctx.cb; record_ctx.render_target = ctx.render_target; - record_ctx.frame = &ctx; - record_ctx.series = command.series; - record_ctx.window = command.window; - record_ctx.view_ubo = command.view_ubo; + record_ctx.frame = &ctx; + record_ctx.series = command.series; + record_ctx.window = command.window; + record_ctx.view_ubo = command.view_ubo; command.state->record(record_ctx); } @@ -1609,13 +1609,13 @@ bool Series_renderer::rhi_prepare_series_view_samples( } view_state.staging.clear(); view_state.line_draw_spans.clear(); - view_state.last_staged_sample_count = 0; - view_state.last_sample_upload_bytes = 0; + view_state.last_staged_sample_count = 0; + view_state.last_sample_upload_bytes = 0; view_state.last_line_window_sample_count = 0; - view_state.last_prepared_t_min_ns = 0; - view_state.last_prepared_t_max_ns = 0; - view_state.last_prepared_width_px = 0.0; - view_state.last_sample_buffer = nullptr; + view_state.last_prepared_t_min_ns = 0; + view_state.last_prepared_t_max_ns = 0; + view_state.last_prepared_width_px = 0.0; + view_state.last_sample_buffer = nullptr; }; if (window.gpu_count == 0) { @@ -1731,7 +1731,7 @@ bool Series_renderer::rhi_prepare_series_view_samples( return false; } dst.t_rel = detail::to_view_seconds(ts_ns, window.t_origin_ns); - dst.y = draw_value.y; + dst.y = draw_value.y; dst.y_min = draw_value.y_min; dst.y_max = draw_value.y_max; return true; @@ -1807,7 +1807,7 @@ bool Series_renderer::rhi_prepare_series_view_samples( if (!view_state.rhi->vbo) { return false; } - view_state.last_sample_buffer = view_state.rhi->vbo.get(); + view_state.last_sample_buffer = view_state.rhi->vbo.get(); view_state.last_prepared_t_min_ns = window.t_min_ns; view_state.last_prepared_t_max_ns = window.t_max_ns; view_state.last_prepared_width_px = window.width_px; @@ -2017,8 +2017,8 @@ bool Series_renderer::rhi_prepare_series_primitive( } vbo_view_state_t::line_draw_span_t line_span; - line_span.gpu_first = span.gpu_first; - line_span.gpu_count = span.gpu_count; + line_span.gpu_first = span.gpu_first; + line_span.gpu_count = span.gpu_count; line_span.line_first = write_idx; line_span.line_count = span_window_count; view_state.line_draw_spans.push_back(line_span); @@ -2036,10 +2036,10 @@ bool Series_renderer::rhi_prepare_series_primitive( view_state.staging[span.gpu_first + i - 1u]; const gpu_sample_t current = view_state.staging[span.gpu_first + i]; - gpu_sample_t held = current; - held.y = previous.y; - held.y_min = previous.y_min; - held.y_max = previous.y_max; + gpu_sample_t held = current; + held.y = previous.y; + held.y_min = previous.y_min; + held.y_max = previous.y_max; padded[span_write++] = held; padded[span_write++] = current; } @@ -2161,18 +2161,18 @@ bool Series_renderer::rhi_prepare_series_primitive( // rides vertex attributes instead of SSBOs so the D3D11 backend's // SM 5.0 vertex shader has zero UAVs. detail::alpha_blended_pipeline_desc_t desc; - desc.vert = cached.vert; - desc.frag = cached.frag; - desc.vlayout = vlayout; - desc.ubo_bytes = k_series_ubo_bytes; + desc.vert = cached.vert; + desc.frag = cached.frag; + desc.vlayout = vlayout; + desc.ubo_bytes = k_series_ubo_bytes; desc.ubo_stages = QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage; - desc.flags = QRhiGraphicsPipeline::UsesScissor; + desc.flags = QRhiGraphicsPipeline::UsesScissor; cached.pipeline = detail::build_alpha_blended_pipeline(rhi, rt, desc); if (!cached.pipeline) { return false; } - cached.last_rpd = current_rpd; + cached.last_rpd = current_rpd; cached.last_sample_count = current_samples; } @@ -2220,22 +2220,22 @@ bool Series_renderer::rhi_prepare_series_primitive( draw_color.w *= area_fill_alpha; } } - draw_color.w *= window.window_alpha; - view_block.color[0] = draw_color.r; - view_block.color[1] = draw_color.g; - view_block.color[2] = draw_color.b; - view_block.color[3] = draw_color.a; + draw_color.w *= window.window_alpha; + view_block.color[0] = draw_color.r; + view_block.color[1] = draw_color.g; + view_block.color[2] = draw_color.b; + view_block.color[3] = draw_color.a; - view_block.t_min = detail::to_view_seconds( + view_block.t_min = detail::to_view_seconds( window.t_min_ns, window.t_origin_ns); - view_block.t_max = detail::to_view_seconds( + view_block.t_max = detail::to_view_seconds( window.t_max_ns, window.t_origin_ns); - view_block.v_min = window.v_min; - view_block.v_max = window.v_max; + view_block.v_min = window.v_min; + view_block.v_max = window.v_max; view_block.y_offset = window.y_offset_px; view_block.width = window.width_px; view_block.height = window.height_px; - view_block.win_h = static_cast(ctx.win_h); + view_block.win_h = static_cast(ctx.win_h); view_block.framebuffer_y_up = (ctx.rhi && ctx.rhi->isYUpInFramebuffer()) ? 1 : 0; @@ -2263,7 +2263,7 @@ bool Series_renderer::rhi_prepare_series_primitive( } else { Line_block_std140 block{}; - block.view = view_block; + block.view = view_block; block.line_px = line_width_px; block.snap_to_pixels = (ctx.config && ctx.config->snap_lines_to_pixels) ? 1 : 0; diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index 3cdaa40b..18f82c93 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -89,7 +89,7 @@ drawable_window_result_t build_drawable_window( { drawable_sample_span_t span; span.source_first = source_index; - span.gpu_first = result.gpu_count; + span.gpu_first = result.gpu_count; result.spans.push_back(span); } @@ -183,15 +183,15 @@ bool select_hold_source_index( Series_view_plan plan_series_window(const series_window_plan_request_t& request) { Series_view_plan plan; - plan.series_id = request.series_id; - plan.view_kind = request.view_kind; - plan.source = request.data_source; - plan.access = request.access; - plan.lod_scale = 1; - plan.interpolation = request.interpolation; + plan.series_id = request.series_id; + plan.view_kind = request.view_kind; + plan.source = request.data_source; + plan.access = request.access; + plan.lod_scale = 1; + plan.interpolation = request.interpolation; plan.empty_window_behavior = request.empty_window_behavior; - plan.nonfinite_policy = request.nonfinite_policy; - plan.style = request.style; + plan.nonfinite_policy = request.nonfinite_policy; + plan.style = request.style; if (!request.planner_state || !request.snapshot_cache || @@ -253,30 +253,30 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) snapshot_cache.cached_snapshot) { snapshot_result.snapshot = snapshot_cache.cached_snapshot; - snapshot_result.status = snapshot_result_t::Snapshot_status::READY; + snapshot_result.status = snapshot_result_t::Snapshot_status::READY; return snapshot_result; } snapshot_result = data_source.try_snapshot(level); if (snapshot_result) { snapshot_cache.cached_snapshot_frame_id = request.frame_id; - snapshot_cache.cached_snapshot_level = level; - snapshot_cache.cached_snapshot_source = &data_source; - snapshot_cache.cached_snapshot = snapshot_result.snapshot; - snapshot_cache.cached_snapshot_hold = snapshot_result.snapshot.hold; + snapshot_cache.cached_snapshot_level = level; + snapshot_cache.cached_snapshot_source = &data_source; + snapshot_cache.cached_snapshot = snapshot_result.snapshot; + snapshot_cache.cached_snapshot_hold = snapshot_result.snapshot.hold; } return snapshot_result; }; const auto make_query_context = [&]() { data_query_context_t query; - query.access = &access; - query.profiler = request.profiler; - query.semantics_key = make_sample_semantics_key(&access); - query.time_window = {request.t_min_ns, request.t_max_ns}; - query.interpolation = request.interpolation; + query.access = &access; + query.profiler = request.profiler; + query.semantics_key = make_sample_semantics_key(&access); + query.time_window = {request.t_min_ns, request.t_max_ns}; + query.interpolation = request.interpolation; query.empty_window_behavior = request.empty_window_behavior; - query.nonfinite_policy = request.nonfinite_policy; + query.nonfinite_policy = request.nonfinite_policy; return query; }; @@ -288,7 +288,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) VNM_PLOT_PROFILE_SCOPE( request.profiler, "process_view.query_time_window"); - query.result = data_source.query_time_window(level, make_query_context()); + query.result = data_source.query_time_window(level, make_query_context()); query.attempted = true; return query; }; @@ -303,23 +303,23 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) }; const auto load_cached_plan = [&](Series_view_plan& p, std::size_t level) { - p.source_first = state.last_first; - p.source_count = state.last_source_count; + p.source_first = state.last_first; + p.source_count = state.last_source_count; p.synthetic_hold_count = state.last_synthetic_hold_count; - p.gpu_count = state.last_count; - p.drawable_spans = state.last_drawable_spans; - p.lod_level = level; - p.lod_scale = level < scales.size() ? scales[level] : std::size_t{1}; - p.pixels_per_sample = state.last_applied_pps; - p.snapshot.sequence = state.last_sequence; - p.t_min_ns = request.t_min_ns; - p.t_max_ns = request.t_max_ns; - p.t_origin_ns = request.t_origin_ns; - p.hold_last_forward = state.last_hold_last_forward; - p.hold_timestamp_ns = state.last_hold_last_forward ? request.t_max_ns : 0; - p.width_px = static_cast(request.width_px); - p.interpolation = request.interpolation; - p.nonfinite_policy = request.nonfinite_policy; + p.gpu_count = state.last_count; + p.drawable_spans = state.last_drawable_spans; + p.lod_level = level; + p.lod_scale = level < scales.size() ? scales[level] : std::size_t{1}; + p.pixels_per_sample = state.last_applied_pps; + p.snapshot.sequence = state.last_sequence; + p.t_min_ns = request.t_min_ns; + p.t_max_ns = request.t_max_ns; + p.t_origin_ns = request.t_origin_ns; + p.hold_last_forward = state.last_hold_last_forward; + p.hold_timestamp_ns = state.last_hold_last_forward ? request.t_max_ns : 0; + p.width_px = static_cast(request.width_px); + p.interpolation = request.interpolation; + p.nonfinite_policy = request.nonfinite_policy; }; const auto try_stale_fallback = @@ -452,8 +452,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) last_exclusive <= snapshot.count) { have_direct_time_window = true; - direct_first_idx = first; - direct_last_idx = last_exclusive; + direct_first_idx = first; + direct_last_idx = last_exclusive; if (access_view.has_timestamp()) { bool has_match_in_requested_window = false; bool direct_window_valid = true; @@ -557,8 +557,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) bool timestamps_monotonic = true; state.last_timestamp_order_scan_performed = false; - state.last_timestamp_order_scan_samples = 0; - state.last_timestamp_window_search = Timestamp_window_search::NONE; + state.last_timestamp_order_scan_samples = 0; + state.last_timestamp_window_search = Timestamp_window_search::NONE; if (direct_time_window_failed) { state.last_timestamp_window_search = Timestamp_window_search::QUERY; @@ -573,19 +573,19 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) const void* current_identity = data_source.identity(); const Time_order source_order = data_source.time_order(applied_level); if (source_order == Time_order::ASCENDING) { - state.last_timestamp_order_sequence = snapshot.sequence; - state.last_timestamp_order_identity = current_identity; + state.last_timestamp_order_sequence = snapshot.sequence; + state.last_timestamp_order_identity = current_identity; state.last_timestamp_order_access_key = access_key; - state.last_timestamp_source_order = source_order; - state.last_timestamps_monotonic = true; + state.last_timestamp_source_order = source_order; + state.last_timestamps_monotonic = true; } else if (source_order == Time_order::DESCENDING) { - state.last_timestamp_order_sequence = snapshot.sequence; - state.last_timestamp_order_identity = current_identity; + state.last_timestamp_order_sequence = snapshot.sequence; + state.last_timestamp_order_identity = current_identity; state.last_timestamp_order_access_key = access_key; - state.last_timestamp_source_order = source_order; - state.last_timestamps_monotonic = false; + state.last_timestamp_source_order = source_order; + state.last_timestamps_monotonic = false; } else { const bool need_monotonicity_scan = @@ -618,11 +618,11 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) prev_ts = ts; } } - state.last_timestamp_order_sequence = snapshot.sequence; - state.last_timestamp_order_identity = current_identity; + state.last_timestamp_order_sequence = snapshot.sequence; + state.last_timestamp_order_identity = current_identity; state.last_timestamp_order_access_key = access_key; - state.last_timestamp_source_order = source_order; - state.last_timestamps_monotonic = is_monotonic; + state.last_timestamp_source_order = source_order; + state.last_timestamps_monotonic = is_monotonic; if (request.profiler) { request.profiler->record_counter( "renderer.series_window.monotonicity_scan_count"); @@ -642,8 +642,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) last_idx = snapshot.count; } else { - first_idx = direct_first_idx; - last_idx = direct_last_idx; + first_idx = direct_first_idx; + last_idx = direct_last_idx; hold_last_forward = direct_hold_last_forward; } } @@ -710,8 +710,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) hold_source_index, hold_failed)) { - first_idx = hold_source_index; - last_idx = hold_source_index + 1u; + first_idx = hold_source_index; + last_idx = hold_source_index + 1u; hold_last_forward = true; } else @@ -797,8 +797,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) first_idx = std::min(first_idx, hold_source_index); } else { - first_idx = hold_source_index; - last_idx = hold_source_index + 1u; + first_idx = hold_source_index; + last_idx = hold_source_index + 1u; hold_last_forward = true; } } @@ -837,8 +837,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) hold_source_index, hold_failed)) { - first_idx = hold_source_index; - last_idx = hold_source_index + 1u; + first_idx = hold_source_index; + last_idx = hold_source_index + 1u; drawable_window = build_drawable_window( snapshot, access_view, @@ -887,22 +887,22 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) state.cached_data_identity == data_source.identity() && state.last_lod_level != applied_level; - state.last_sequence = snapshot.sequence; - state.cached_data_identity = data_source.identity(); - state.last_access_key = access_key; - state.uploaded_t_origin_ns = request.t_origin_ns; + state.last_sequence = snapshot.sequence; + state.cached_data_identity = data_source.identity(); + state.last_access_key = access_key; + state.uploaded_t_origin_ns = request.t_origin_ns; state.last_snapshot_elements = snapshot.count; - state.last_first = first_idx; - state.last_count = drawable_window.gpu_count; - - state.last_lod_level = applied_level; - state.has_last_lod_level = true; - state.last_t_min = request.t_min_ns; - state.last_t_max = request.t_max_ns; - state.last_width_px = request.width_px; + state.last_first = first_idx; + state.last_count = drawable_window.gpu_count; + + state.last_lod_level = applied_level; + state.has_last_lod_level = true; + state.last_t_min = request.t_min_ns; + state.last_t_max = request.t_max_ns; + state.last_width_px = request.width_px; state.last_empty_window_behavior = request.empty_window_behavior; - state.last_nonfinite_policy = request.nonfinite_policy; - state.last_interpolation = request.interpolation; + state.last_nonfinite_policy = request.nonfinite_policy; + state.last_interpolation = request.interpolation; if (lod_switched && request.profiler) { request.profiler->record_counter( "renderer.series_window.lod_switch_count"); @@ -911,31 +911,31 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) const bool effective_hold_last_forward = drawable_window.synthetic_hold_count > 0; - plan.source_first = state.last_first; - plan.source_count = drawable_window.source_count; - plan.synthetic_hold_count = drawable_window.synthetic_hold_count; - plan.gpu_count = drawable_window.gpu_count; - plan.drawable_spans = drawable_window.spans; - plan.lod_level = applied_level; - plan.lod_scale = applied_scale; - plan.pixels_per_sample = base_pps * static_cast(applied_scale); - state.last_applied_pps = plan.pixels_per_sample; + plan.source_first = state.last_first; + plan.source_count = drawable_window.source_count; + plan.synthetic_hold_count = drawable_window.synthetic_hold_count; + plan.gpu_count = drawable_window.gpu_count; + plan.drawable_spans = drawable_window.spans; + plan.lod_level = applied_level; + plan.lod_scale = applied_scale; + plan.pixels_per_sample = base_pps * static_cast(applied_scale); + state.last_applied_pps = plan.pixels_per_sample; state.last_hold_last_forward = effective_hold_last_forward; - plan.snapshot.snapshot = snapshot; - plan.snapshot.sequence = snapshot.sequence; - plan.t_min_ns = request.t_min_ns; - plan.t_max_ns = request.t_max_ns; - plan.t_origin_ns = request.t_origin_ns; - plan.hold_last_forward = effective_hold_last_forward; - plan.hold_timestamp_ns = effective_hold_last_forward + plan.snapshot.snapshot = snapshot; + plan.snapshot.sequence = snapshot.sequence; + plan.t_min_ns = request.t_min_ns; + plan.t_max_ns = request.t_max_ns; + plan.t_origin_ns = request.t_origin_ns; + plan.hold_last_forward = effective_hold_last_forward; + plan.hold_timestamp_ns = effective_hold_last_forward ? request.t_max_ns : 0; - plan.width_px = static_cast(request.width_px); - plan.interpolation = request.interpolation; + plan.width_px = static_cast(request.width_px); + plan.interpolation = request.interpolation; - state.last_source_count = plan.source_count; + state.last_source_count = plan.source_count; state.last_synthetic_hold_count = plan.synthetic_hold_count; - state.last_drawable_spans = plan.drawable_spans; + state.last_drawable_spans = plan.drawable_spans; break; } diff --git a/src/core/text_renderer.cpp b/src/core/text_renderer.cpp index 7112f28d..86ea2c0d 100644 --- a/src/core/text_renderer.cpp +++ b/src/core/text_renderer.cpp @@ -79,9 +79,9 @@ glm::vec4 text_color_for_theme(bool dark_mode) text_shadow_t text_shadow_for_background(const glm::vec4& background, double font_px) { text_shadow_t shadow; - shadow.color = background; - shadow.color.a *= k_text_shadow_alpha; - shadow.radius_px = std::clamp( + shadow.color = background; + shadow.color.a *= k_text_shadow_alpha; + shadow.radius_px = std::clamp( static_cast(font_px) * k_text_shadow_radius_factor, k_text_shadow_min_radius_px, k_text_shadow_max_radius_px); @@ -103,7 +103,7 @@ text_lcd_t text_lcd_for_background( bool draw_lcd_eligible) { text_lcd_t lcd; - lcd.subpixel_order = draw_lcd_eligible + lcd.subpixel_order = draw_lcd_eligible ? text_lcd_frame_order(ctx) : text_lcd_resolved_subpixel_order_t::NONE; lcd.background_color = background; @@ -142,14 +142,14 @@ bool update_and_draw_faded_labels( auto it = tracker.states.find(key); if (it == tracker.states.end()) { Text_renderer::label_fade_state_t state; - state.alpha = 0.0f; + state.alpha = 0.0f; state.direction = 1; - state.text = label.text; + state.text = label.text; tracker.states.emplace(key, std::move(state)); } else { auto& state = it->second; - state.text = label.text; + state.text = label.text; if (state.direction < 0) { state.direction = 1; } @@ -176,7 +176,7 @@ bool update_and_draw_faded_labels( state.alpha = std::clamp(state.alpha, 0.0f, 1.0f); if (state.direction > 0 && state.alpha >= 1.0f - k_alpha_eps) { - state.alpha = 1.0f; + state.alpha = 1.0f; state.direction = 0; } if (state.direction < 0 && state.alpha <= 0.0f + k_alpha_eps) { @@ -362,9 +362,9 @@ bool Text_renderer::render_axis_labels( m_vertical_fade.states.clear(); for (const auto& label : pl.v_labels) { label_fade_state_t state; - state.alpha = 1.0f; + state.alpha = 1.0f; state.direction = 0; - state.text = label.text; + state.text = label.text; m_vertical_fade.states.emplace(label.value, state); draw_label(label.value, state); } @@ -468,9 +468,9 @@ bool Text_renderer::render_info_overlay( m_horizontal_fade.states.clear(); for (const auto& label : pl.h_labels) { label_fade_state_t state; - state.alpha = 1.0f; + state.alpha = 1.0f; state.direction = 0; - state.text = label.text; + state.text = label.text; const std::int64_t key = label.value; m_horizontal_fade.states.emplace(key, state); draw_label(key, state); @@ -497,7 +497,7 @@ bool Text_renderer::render_info_overlay( const auto format_info_value = [&](double value) { if (ctx.config && ctx.config->format_value) { value_format_context_t context; - context.role = Value_format_role::INFO_OVERLAY; + context.role = Value_format_role::INFO_OVERLAY; context.suggested_fixed_digits = k_value_decimals; const std::string text = ctx.config->format_value(value, context); if (!text.empty()) { @@ -540,12 +540,12 @@ bool Text_renderer::render_info_overlay( const auto format_ts = (ctx.config && ctx.config->format_timestamp) ? ctx.config->format_timestamp : default_format_timestamp; - m_cached_from_ts = format_ts(ctx.t0, 0); - m_cached_to_ts = format_ts(ctx.t1, 0); - m_last_t0 = ctx.t0; - m_last_t1 = ctx.t1; + m_cached_from_ts = format_ts(ctx.t0, 0); + m_cached_to_ts = format_ts(ctx.t1, 0); + m_last_t0 = ctx.t0; + m_last_t1 = ctx.t1; m_last_timestamp_revision = timestamp_revision; - m_last_subsecond = pl.h_labels_subsecond; + m_last_subsecond = pl.h_labels_subsecond; } m_fonts->batch_text(k_overlay_left_px + offset_from, llt, m_cached_from_ts.c_str()); diff --git a/src/core/types.cpp b/src/core/types.cpp index bda35d76..81b904ea 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -280,7 +280,7 @@ time_window_candidates_t ascending_candidates( return out; } if (wants_hold_forward(query) && out.match_first > 0) { - out.has_held = true; + out.has_held = true; out.held_index = out.match_first - 1; } return out; @@ -304,7 +304,7 @@ time_window_candidates_t descending_candidates( return out; } if (wants_hold_forward(query) && out.match_last_exclusive < snapshot.count) { - out.has_held = true; + out.has_held = true; out.held_index = out.match_last_exclusive; } return out; @@ -352,8 +352,8 @@ time_window_candidates_t linear_candidates( if (hold_forward && timestamp_ns < query.time_window.min_ns && (!held_found || timestamp_ns > held_timestamp_ns)) { - held_found = true; - held_index = index; + held_found = true; + held_index = index; held_timestamp_ns = timestamp_ns; } } @@ -369,7 +369,7 @@ time_window_candidates_t linear_candidates( out.valid = false; return out; } - out.has_held = true; + out.has_held = true; out.held_index = held_index; } return out; @@ -463,25 +463,25 @@ bool scan_value_range( } if (scan_status == sample_scan_status::ACCEPTED) { - has_held_candidate = true; - has_held_value = true; + has_held_candidate = true; + has_held_value = true; held_candidate_failed = false; - held_timestamp_ns = timestamp_ns; - held_range = sample_range; + held_timestamp_ns = timestamp_ns; + held_range = sample_range; } else if (query.nonfinite_policy == Nonfinite_sample_policy::BREAK_SEGMENT) { - has_held_candidate = true; - has_held_value = false; + has_held_candidate = true; + has_held_value = false; held_candidate_failed = false; - held_timestamp_ns = timestamp_ns; + held_timestamp_ns = timestamp_ns; } else if (scan_status == sample_scan_status::FAILED) { - has_held_candidate = true; - has_held_value = false; + has_held_candidate = true; + has_held_value = false; held_candidate_failed = true; - held_timestamp_ns = timestamp_ns; + held_timestamp_ns = timestamp_ns; } } @@ -581,9 +581,9 @@ bool select_held_sample_index( index); if (status == sample_scan_status::ACCEPTED) { if (!found || timestamp_ns > held_timestamp_ns) { - found = true; + found = true; held_timestamp_ns = timestamp_ns; - out_index = index; + out_index = index; } continue; } @@ -659,23 +659,23 @@ validated_time_window_t validated_time_window( } if (!has_match) { - out.first = held_index; + out.first = held_index; out.last_exclusive = held_index + 1; - out.held_index = held_index; - out.has_held = true; + out.held_index = held_index; + out.has_held = true; return out; } - out.first = candidates.match_first; - out.last_exclusive = candidates.match_last_exclusive; - out.match_first = candidates.match_first; + out.first = candidates.match_first; + out.last_exclusive = candidates.match_last_exclusive; + out.match_first = candidates.match_first; out.match_last_exclusive = candidates.match_last_exclusive; - out.has_match = true; + out.has_match = true; if (held_accepted) { - out.first = std::min(out.first, held_index); + out.first = std::min(out.first, held_index); out.last_exclusive = std::max(out.last_exclusive, held_index + 1); - out.held_index = held_index; - out.has_held = true; + out.held_index = held_index; + out.has_held = true; } return out; } @@ -748,7 +748,7 @@ sample_draw_status_t read_sample_draw_value( std::swap(low, high); } - out.y = y; + out.y = y; out.y_min = low; out.y_max = high; return sample_draw_status_t::DRAWABLE; @@ -838,7 +838,7 @@ data_query_result_t Data_source::query_time_window( } result.status = Data_query_status::READY; - result.value = {window.first, window.last_exclusive - window.first}; + result.value = {window.first, window.last_exclusive - window.first}; return result; } @@ -890,7 +890,7 @@ data_query_result_t Data_source::query_v_range( } result.status = Data_query_status::READY; - result.value = range; + result.value = range; return result; } @@ -944,7 +944,7 @@ data_query_result_t Data_source::query_v_range( } result.status = Data_query_status::READY; - result.value = range; + result.value = range; return result; } diff --git a/src/qt/plot_interaction_item.cpp b/src/qt/plot_interaction_item.cpp index 3ccdd8f2..8e45d636 100644 --- a/src/qt/plot_interaction_item.cpp +++ b/src/qt/plot_interaction_item.cpp @@ -251,12 +251,12 @@ void Plot_interaction_item::mousePressEvent(QMouseEvent* event) const qreal ph = preview_height(); if (x >= 0.0 && x <= uw && y >= 0.0 && y < uh) { - m_dragging = true; + m_dragging = true; m_click_candidate = true; - m_press_x = x; - m_press_y = y; - m_drag_start_x = x; - m_drag_last_y = y; + m_press_x = x; + m_press_y = y; + m_drag_start_x = x; + m_drag_last_y = y; event->accept(); } else @@ -346,10 +346,10 @@ void Plot_interaction_item::mouseReleaseEvent(QMouseEvent* event) m_press_x >= 0.0 && m_press_x <= usable_width() && m_press_y >= 0.0 && m_press_y < usable_height(); - m_dragging = false; - m_dragging_preview = false; - m_click_candidate = false; - m_drag_start_x = 0; + m_dragging = false; + m_dragging_preview = false; + m_click_candidate = false; + m_drag_start_x = 0; m_drag_preview_start = 0; if (clicked) { diff --git a/src/qt/plot_renderer.cpp b/src/qt/plot_renderer.cpp index c78670ee..48c4b8dd 100644 --- a/src/qt/plot_renderer.cpp +++ b/src/qt/plot_renderer.cpp @@ -89,22 +89,22 @@ Layout_calculator::parameters_t build_layout_params( const Font_renderer* fonts) { Layout_calculator::parameters_t params; - params.v_min = v_min; - params.v_max = v_max; - params.t_min = t_min_ns; - params.t_max = t_max_ns; - params.usable_width = std::max(0.0, double(win_w) - vbar_width); - params.usable_height = usable_height; - params.vbar_width = vbar_width; - params.label_visible_height = usable_height + preview_height; - params.adjusted_font_size_in_pixels = font_px; + params.v_min = v_min; + params.v_max = v_max; + params.t_min = t_min_ns; + params.t_max = t_max_ns; + params.usable_width = std::max(0.0, double(win_w) - vbar_width); + params.usable_height = usable_height; + params.vbar_width = vbar_width; + params.label_visible_height = usable_height + preview_height; + params.adjusted_font_size_in_pixels = font_px; params.h_label_vertical_nudge_factor = detail::k_h_label_vertical_nudge_px; if (fonts) { - params.monospace_char_advance_px = fonts->monospace_advance_px(); + params.monospace_char_advance_px = fonts->monospace_advance_px(); params.monospace_advance_is_reliable = fonts->monospace_advance_is_reliable(); - params.measure_text_cache_key = fonts->text_measure_cache_key(); - params.measure_text_func = [fonts](const char* text) { + params.measure_text_cache_key = fonts->text_measure_cache_key(); + params.measure_text_func = [fonts](const char* text) { return fonts->measure_text_px(text); }; } @@ -125,7 +125,7 @@ Layout_calculator::parameters_t build_layout_params( return {}; }; params.format_value_revision = config.format_value_revision; - params.profiler = config.profiler.get(); + params.profiler = config.profiler.get(); return params; } @@ -191,7 +191,7 @@ void Plot_renderer::initialize(QRhiCommandBuffer* /*cb*/) #if defined(VNM_PLOT_ENABLE_TEXT) if (!m_impl->fonts) { m_impl->fonts = std::make_unique(); - m_impl->text = std::make_unique(m_impl->fonts.get()); + m_impl->text = std::make_unique(m_impl->fonts.get()); } #endif } @@ -218,10 +218,10 @@ void Plot_renderer::synchronize(QQuickRhiItem* item) m_impl->snapshot.v_auto = widget->m_v_auto.load(std::memory_order_acquire); m_impl->snapshot.visible_info_flags = widget->m_visible_info_flags.load(std::memory_order_acquire); - m_impl->snapshot.adjusted_font_px = widget->m_adjusted_font_size; - m_impl->snapshot.base_label_height_px = widget->m_base_label_height; + m_impl->snapshot.adjusted_font_px = widget->m_adjusted_font_size; + m_impl->snapshot.base_label_height_px = widget->m_base_label_height; m_impl->snapshot.adjusted_preview_height = widget->m_adjusted_preview_height; - m_impl->snapshot.vbar_width_pixels = widget->vbar_width_pixels(); + m_impl->snapshot.vbar_width_pixels = widget->vbar_width_pixels(); if (QQuickWindow* window = widget->window()) { m_impl->snapshot.window_background = qcolor_to_vec4(window->color()); } @@ -337,19 +337,19 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) const auto make_cache_key = [&](double width_px) { layout_cache_key_t key; - key.v0 = v_min; - key.v1 = v_max; - key.t0 = snapshot.data_cfg.t_min; - key.t1 = snapshot.data_cfg.t_max; - key.viewport_size = Size_2i{win_w, win_h}; - key.adjusted_reserved_height = reserved_h; - key.adjusted_preview_height = snapshot.adjusted_preview_height; + key.v0 = v_min; + key.v1 = v_max; + key.t0 = snapshot.data_cfg.t_min; + key.t1 = snapshot.data_cfg.t_max; + key.viewport_size = Size_2i{win_w, win_h}; + key.adjusted_reserved_height = reserved_h; + key.adjusted_preview_height = snapshot.adjusted_preview_height; key.adjusted_font_size_in_pixels = snapshot.adjusted_font_px; - key.vbar_width_pixels = width_px; - key.font_metrics_key = layout_fonts ? layout_fonts->text_measure_cache_key() : 0; - key.config_revision = snapshot.config_revision; - key.format_timestamp_revision = config.format_timestamp_revision; - key.format_value_revision = config.format_value_revision; + key.vbar_width_pixels = width_px; + key.font_metrics_key = layout_fonts ? layout_fonts->text_measure_cache_key() : 0; + key.config_revision = snapshot.config_revision; + key.format_timestamp_revision = config.format_timestamp_revision; + key.format_value_revision = config.format_value_revision; return key; }; @@ -424,8 +424,8 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) } frame_context_t ctx{*layout_ptr}; - ctx.v0 = v_min; - ctx.v1 = v_max; + ctx.v0 = v_min; + ctx.v1 = v_max; ctx.preview_v0 = preview_v_min; ctx.preview_v1 = preview_v_max; if (m_impl->owner) { @@ -438,8 +438,8 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) } ctx.t_available_min = snapshot.data_cfg.t_available_min; ctx.t_available_max = snapshot.data_cfg.t_available_max; - ctx.win_w = win_w; - ctx.win_h = win_h; + ctx.win_w = win_w; + ctx.win_h = win_h; // Pixel-space ortho with origin at top-left. QRhi's correction matrix // adapts it to the active backend's clip-space conventions. const glm::mat4 pixel_ortho = glm::ortho( @@ -449,21 +449,21 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) 0.0f, -1.0f, 1.0f); - ctx.pmv = rhi_ptr + ctx.pmv = rhi_ptr ? to_glm_mat4(rhi_ptr->clipSpaceCorrMatrix()) * pixel_ortho : pixel_ortho; - ctx.adjusted_font_px = snapshot.adjusted_font_px; - ctx.base_label_height_px = snapshot.base_label_height_px; + ctx.adjusted_font_px = snapshot.adjusted_font_px; + ctx.base_label_height_px = snapshot.base_label_height_px; ctx.adjusted_reserved_height = reserved_h; - ctx.adjusted_preview_height = snapshot.adjusted_preview_height; - ctx.visible_info_flags = snapshot.visible_info_flags; - ctx.dark_mode = config.dark_mode; - ctx.plot_body_background = plot_body_background; - ctx.text_lcd_subpixel_order = snapshot.auto_text_lcd_subpixel_order; - ctx.config = &config; - ctx.rhi = rhi_ptr; - ctx.cb = cb; - ctx.render_target = rt; + ctx.adjusted_preview_height = snapshot.adjusted_preview_height; + ctx.visible_info_flags = snapshot.visible_info_flags; + ctx.dark_mode = config.dark_mode; + ctx.plot_body_background = plot_body_background; + ctx.text_lcd_subpixel_order = snapshot.auto_text_lcd_subpixel_order; + ctx.config = &config; + ctx.rhi = rhi_ptr; + ctx.cb = cb; + ctx.render_target = rt; // Open the resource-update batch BEFORE the render pass. Both series and // primitives fill it (series via prepare(), primitives via flush_rects / diff --git a/src/qt/plot_renderer.h b/src/qt/plot_renderer.h index 5bc63c64..fd6ac89d 100644 --- a/src/qt/plot_renderer.h +++ b/src/qt/plot_renderer.h @@ -19,7 +19,7 @@ class Plot_renderer : public QQuickRhiItemRenderer explicit Plot_renderer(const Plot_widget* owner); ~Plot_renderer() override; - Plot_renderer(const Plot_renderer&) = delete; + Plot_renderer(const Plot_renderer&) = delete; Plot_renderer& operator=(const Plot_renderer&) = delete; void initialize(QRhiCommandBuffer* cb) override; diff --git a/src/qt/plot_time_axis.cpp b/src/qt/plot_time_axis.cpp index 8c037f31..72700856 100644 --- a/src/qt/plot_time_axis.cpp +++ b/src/qt/plot_time_axis.cpp @@ -474,8 +474,8 @@ void Plot_time_axis::set_indicator_state(QObject* owner, bool active, qint64 t_m bool owner_changed = false; if (m_indicator_owner != owner) { m_indicator_owner = owner; - owner_changed = true; - changed = true; + owner_changed = true; + changed = true; } if (!m_indicator_active) { m_indicator_active = true; @@ -504,10 +504,10 @@ void Plot_time_axis::set_indicator_state(QObject* owner, bool active, qint64 t_m } else { if (m_indicator_owner == owner && (m_indicator_active || m_indicator_x_norm_valid)) { - m_indicator_owner = nullptr; - m_indicator_active = false; + m_indicator_owner = nullptr; + m_indicator_active = false; m_indicator_x_norm_valid = false; - changed = true; + changed = true; } } @@ -573,12 +573,12 @@ bool Plot_time_axis::apply_time_axis_limits_if_changed( return false; } - m_t_min = t_min_ns; - m_t_max = t_max_ns; - m_t_available_min = t_available_min_ns; - m_t_available_max = t_available_max_ns; - m_t_min_initialized = t_min_initialized; - m_t_max_initialized = t_max_initialized; + m_t_min = t_min_ns; + m_t_max = t_max_ns; + m_t_available_min = t_available_min_ns; + m_t_available_max = t_available_max_ns; + m_t_min_initialized = t_min_initialized; + m_t_max_initialized = t_max_initialized; m_t_available_min_initialized = t_available_min_initialized; m_t_available_max_initialized = t_available_max_initialized; emit t_limits_changed(); diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index c993e56d..61500eb8 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -115,11 +115,11 @@ Plot_widget::Plot_widget() { vnm_plot_init_qt_resources(); - m_relative_preview_height = 0.3f; - m_preview_height_min = 30.0; - m_preview_height_max = 150.0; + m_relative_preview_height = 0.3f; + m_preview_height_min = 30.0; + m_preview_height_max = 150.0; m_show_if_calculated_preview_height_below_min = false; - m_preview_height_steps = 2; + m_preview_height_steps = 2; update_dpi_scaling_factor(); @@ -155,9 +155,9 @@ Plot_widget::~Plot_widget() m_time_axis->set_indicator_state(this, false, 0.0); } QObject::disconnect(m_time_axis, nullptr, this, nullptr); - m_time_axis_connection = {}; + m_time_axis_connection = {}; m_time_axis_destroyed_connection = {}; - m_time_axis_vbar_connection = {}; + m_time_axis_vbar_connection = {}; m_time_axis_sync_vbar_connection = {}; m_sync_vbar_width_active.store(false, std::memory_order_release); m_time_axis = nullptr; @@ -225,10 +225,10 @@ void Plot_widget::set_config(const Plot_config& config) const double prev_grid_visibility = m_config.grid_visibility; const double prev_preview_visibility = m_config.preview_visibility; const double prev_line_width_px = m_config.line_width_px; - m_config = config; - m_config.grid_visibility = prev_grid_visibility; // Preserve QML-controlled setting - m_config.preview_visibility = prev_preview_visibility; // Preserve QML-controlled setting - m_config.line_width_px = prev_line_width_px; // Preserve QML-controlled setting + m_config = config; + m_config.grid_visibility = prev_grid_visibility; // Preserve QML-controlled setting + m_config.preview_visibility = prev_preview_visibility; // Preserve QML-controlled setting + m_config.line_width_px = prev_line_width_px; // Preserve QML-controlled setting m_config_revision.fetch_add(1, std::memory_order_relaxed); effective_config = m_config; } @@ -456,11 +456,11 @@ void Plot_widget::set_view(const Plot_view& view) if (view.v_range && v_range_valid(*view.v_range)) { std::unique_lock lock(m_data_cfg_mutex); - m_data_cfg.v_min = view.v_range->first; - m_data_cfg.v_max = view.v_range->second; + m_data_cfg.v_min = view.v_range->first; + m_data_cfg.v_max = view.v_range->second; m_data_cfg.v_manual_min = view.v_range->first; m_data_cfg.v_manual_max = view.v_range->second; - v_changed = true; + v_changed = true; } bool v_auto_changed_flag = false; @@ -500,9 +500,9 @@ void Plot_widget::set_time_axis(Plot_time_axis* axis) m_time_axis->clear_shared_vbar_width(this); } QObject::disconnect(m_time_axis, nullptr, this, nullptr); - m_time_axis_connection = {}; + m_time_axis_connection = {}; m_time_axis_destroyed_connection = {}; - m_time_axis_vbar_connection = {}; + m_time_axis_vbar_connection = {}; m_time_axis_sync_vbar_connection = {}; m_sync_vbar_width_active.store(false, std::memory_order_release); } @@ -513,7 +513,7 @@ void Plot_widget::set_time_axis(Plot_time_axis* axis) m_sync_vbar_width_active.store( m_time_axis->sync_vbar_width(), std::memory_order_release); - m_time_axis_connection = QObject::connect( + m_time_axis_connection = QObject::connect( m_time_axis, &Plot_time_axis::t_limits_changed, this, @@ -523,7 +523,7 @@ void Plot_widget::set_time_axis(Plot_time_axis* axis) &QObject::destroyed, this, [this]() { clear_time_axis(); }); - m_time_axis_vbar_connection = QObject::connect( + m_time_axis_vbar_connection = QObject::connect( m_time_axis, &Plot_time_axis::shared_vbar_width_changed, this, @@ -647,8 +647,8 @@ void Plot_widget::set_v_range(float v_min, float v_max) } { std::unique_lock lock(m_data_cfg_mutex); - m_data_cfg.v_min = v_min; - m_data_cfg.v_max = v_max; + m_data_cfg.v_min = v_min; + m_data_cfg.v_max = v_max; m_data_cfg.v_manual_min = v_min; m_data_cfg.v_manual_max = v_max; } @@ -1025,16 +1025,16 @@ void Plot_widget::adjust_v_to_target(float target_vmin, float target_vmax) const float min_span = min_v_span_for(target_vmin, target_vmax); if (target_vmax - target_vmin < min_span) { const float mid = 0.5f * (target_vmax + target_vmin); - target_vmin = mid - 0.5f * min_span; - target_vmax = mid + 0.5f * min_span; + target_vmin = mid - 0.5f * min_span; + target_vmax = mid + 0.5f * min_span; } { std::unique_lock lock(m_data_cfg_mutex); m_data_cfg.v_manual_min = target_vmin; m_data_cfg.v_manual_max = target_vmax; - m_data_cfg.v_min = target_vmin; - m_data_cfg.v_max = target_vmax; + m_data_cfg.v_min = target_vmin; + m_data_cfg.v_max = target_vmax; } set_v_auto(false); @@ -1082,8 +1082,8 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anc have_any = true; return; } - agg.vmin = std::min(agg.vmin, series_agg.vmin); - agg.vmax = std::max(agg.vmax, series_agg.vmax); + agg.vmin = std::min(agg.vmin, series_agg.vmin); + agg.vmax = std::max(agg.vmax, series_agg.vmax); agg.tmin_ns = std::min(agg.tmin_ns, series_agg.tmin_ns); agg.tmax_ns = std::max(agg.tmax_ns, series_agg.tmax_ns); }; @@ -1183,8 +1183,8 @@ void Plot_widget::auto_adjust_view(bool adjust_t, double extra_v_scale, bool anc std::unique_lock lock(m_data_cfg_mutex); m_data_cfg.v_manual_min = static_cast(new_vmin); m_data_cfg.v_manual_max = static_cast(new_vmax); - m_data_cfg.v_min = static_cast(new_vmin); - m_data_cfg.v_max = static_cast(new_vmax); + m_data_cfg.v_min = static_cast(new_vmin); + m_data_cfg.v_max = static_cast(new_vmax); } if (adjust_t && has_time_axis) { @@ -1388,14 +1388,14 @@ QVariantList Plot_widget::get_samples_for_time( entry["y"] = y; if (value_formatter) { value_format_context_t context; - context.role = Value_format_role::INDICATOR; + context.role = Value_format_role::INDICATOR; context.suggested_fixed_digits = 3; - context.series_label = series->series_label; - entry["y_text"] = QString::fromStdString(value_formatter(y, context)); + context.series_label = series->series_label; + entry["y_text"] = QString::fromStdString(value_formatter(y, context)); } - entry["px"] = px; - entry["py"] = py; - entry["color"] = color; + entry["px"] = px; + entry["py"] = py; + entry["color"] = color; entry["series_label"] = QString::fromStdString(series->series_label); result.append(entry); } @@ -1475,10 +1475,10 @@ void Plot_widget::sync_time_axis_state() void Plot_widget::clear_time_axis() { - m_time_axis = nullptr; - m_time_axis_connection = {}; + m_time_axis = nullptr; + m_time_axis_connection = {}; m_time_axis_destroyed_connection = {}; - m_time_axis_vbar_connection = {}; + m_time_axis_vbar_connection = {}; m_time_axis_sync_vbar_connection = {}; m_sync_vbar_width_active.store(false, std::memory_order_release); emit time_axis_changed(); @@ -1636,8 +1636,8 @@ void Plot_widget::recalculate_preview_height() if (!m_preview_height_initialized) { m_preview_height_initialized = true; - m_preview_height = new_dp; - m_adjusted_preview_height = new_adjusted; + m_preview_height = new_dp; + m_adjusted_preview_height = new_adjusted; emit preview_height_changed(); } diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index cf4a283d..1f02e160 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -396,16 +396,16 @@ class Time_axis_model return {}; } - qint64 new_t_min = m_t_min; - qint64 new_t_max = m_t_max; + qint64 new_t_min = m_t_min; + qint64 new_t_max = m_t_max; bool new_t_min_initialized = m_t_min_initialized; bool new_t_max_initialized = m_t_max_initialized; - const bool view_unset = !m_t_min_initialized && !m_t_max_initialized; + const bool view_unset = !m_t_min_initialized && !m_t_max_initialized; if (view_unset) { // A fully unset view adopts the first complete available range so // subsequent interactions have a real window to operate on. - new_t_min = t_available_min_ns; - new_t_max = t_available_max_ns; + new_t_min = t_available_min_ns; + new_t_max = t_available_max_ns; new_t_min_initialized = true; new_t_max_initialized = true; } @@ -570,12 +570,12 @@ class Time_axis_model m_t_available_max_initialized != t_available_max_initialized; if (changed) { - m_t_min = t_min_ns; - m_t_max = t_max_ns; - m_t_available_min = t_available_min_ns; - m_t_available_max = t_available_max_ns; - m_t_min_initialized = t_min_initialized; - m_t_max_initialized = t_max_initialized; + m_t_min = t_min_ns; + m_t_max = t_max_ns; + m_t_available_min = t_available_min_ns; + m_t_available_max = t_available_max_ns; + m_t_min_initialized = t_min_initialized; + m_t_max_initialized = t_max_initialized; m_t_available_min_initialized = t_available_min_initialized; m_t_available_max_initialized = t_available_max_initialized; } diff --git a/tests/test_asset_loader.cpp b/tests/test_asset_loader.cpp index 8eb6ab83..62e16526 100644 --- a/tests/test_asset_loader.cpp +++ b/tests/test_asset_loader.cpp @@ -31,7 +31,7 @@ struct Scoped_temp_dir std::filesystem::remove_all(path, ec); } - Scoped_temp_dir(const Scoped_temp_dir&) = delete; + Scoped_temp_dir(const Scoped_temp_dir&) = delete; Scoped_temp_dir& operator=(const Scoped_temp_dir&) = delete; }; diff --git a/tests/test_cache_invalidation.cpp b/tests/test_cache_invalidation.cpp index 297f7b53..faace568 100644 --- a/tests/test_cache_invalidation.cpp +++ b/tests/test_cache_invalidation.cpp @@ -89,9 +89,9 @@ class Query_range_source final : public Data_source last_query_lod = lod; last_query = query; data_query_result_t result; - result.status = query_status; + result.status = query_status; result.sequence = query_sequence; - result.value = query_range; + result.value = query_range; return result; } @@ -200,26 +200,26 @@ Data_access_policy make_value_only_policy() std::shared_ptr make_series(const std::shared_ptr& source) { - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = source; - series->access = make_policy(); + series->access = make_policy(); return series; } std::shared_ptr make_series(const std::shared_ptr& source) { - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = source; - series->access = make_policy(); + series->access = make_policy(); return series; } std::shared_ptr make_stable_series( const std::shared_ptr& source) { - auto series = make_series(source); + auto series = make_series(source); series->access = make_stable_policy(); return series; } @@ -235,14 +235,14 @@ std::map> make_series_map( data_config_t make_data_config() { data_config_t cfg; - cfg.t_min = 10; - cfg.t_max = 20; + cfg.t_min = 10; + cfg.t_max = 20; cfg.t_available_min = 0; cfg.t_available_max = 100; - cfg.v_min = -100.0f; - cfg.v_max = 100.0f; - cfg.v_manual_min = -10.0f; - cfg.v_manual_max = 10.0f; + cfg.v_min = -100.0f; + cfg.v_max = 100.0f; + cfg.v_manual_min = -10.0f; + cfg.v_manual_max = 10.0f; return cfg; } @@ -250,10 +250,10 @@ bool test_visible_auto_range_uses_source_query_without_snapshot_fallback() { auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {2.0f, 5.0f}; + source->query_range = {2.0f, 5.0f}; auto series = make_series(source); - series->interpolation = Series_interpolation::STEP_AFTER; + series->interpolation = Series_interpolation::STEP_AFTER; series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; Plot_config config; @@ -295,9 +295,9 @@ bool test_member_pointer_query_uses_stable_semantics_key() { auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {2.0f, 5.0f}; + source->query_range = {2.0f, 5.0f}; - auto series = make_series(source); + auto series = make_series(source); series->access = make_member_pointer_policy(); Plot_config config; @@ -326,9 +326,9 @@ bool test_member_pointer_query_uses_stable_semantics_key() bool test_global_lod_auto_range_uses_query_when_no_legacy_range_exists() { auto source = std::make_shared(); - source->levels = 2; + source->levels = 2; source->query_status = Data_query_status::READY; - source->query_range = {-4.0f, 9.0f}; + source->query_range = {-4.0f, 9.0f}; Plot_config config; config.auto_v_range_mode = Auto_v_range_mode::GLOBAL_LOD; @@ -353,7 +353,7 @@ bool test_unsupported_query_falls_back_to_snapshot_scan() { auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; - source->samples = { + source->samples = { { 0, 6.0f }, { 5, 8.0f }, { 10, 12.0f }, @@ -383,11 +383,11 @@ bool test_ready_query_profiler_counts_query_without_scan() auto profiler = std::make_shared(); auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {2.0f, 5.0f}; + source->query_range = {2.0f, 5.0f}; Plot_config config; config.auto_v_range_mode = Auto_v_range_mode::GLOBAL; - config.profiler = profiler; + config.profiler = profiler; const auto range = plot::detail::resolve_main_v_range( make_series_map(make_series(source)), @@ -419,7 +419,7 @@ bool test_default_query_profiler_counts_snapshot_scan() Plot_config config; config.auto_v_range_mode = Auto_v_range_mode::GLOBAL; - config.profiler = profiler; + config.profiler = profiler; const auto range = plot::detail::resolve_main_v_range( make_series_map(make_series(source)), @@ -443,7 +443,7 @@ bool test_positive_auto_range_excludes_zero_by_default() { auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {2.0f, 8.0f}; + source->query_range = {2.0f, 8.0f}; Plot_config config; config.auto_v_range_mode = Auto_v_range_mode::GLOBAL; @@ -466,7 +466,7 @@ bool test_negative_auto_range_excludes_zero_by_default() { auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {-8.0f, -2.0f}; + source->query_range = {-8.0f, -2.0f}; Plot_config config; config.auto_v_range_mode = Auto_v_range_mode::GLOBAL; @@ -489,11 +489,11 @@ bool test_nonnegative_auto_range_floor_policy_includes_zero() { auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 3.0f}; + source->query_range = {1.0f, 3.0f}; Plot_config config; - config.auto_v_range_mode = Auto_v_range_mode::GLOBAL; - config.auto_v_range_extra_scale = 2.0; + config.auto_v_range_mode = Auto_v_range_mode::GLOBAL; + config.auto_v_range_extra_scale = 2.0; config.floor_nonnegative_auto_v_range_at_zero = true; const auto range = plot::detail::resolve_main_v_range( @@ -512,14 +512,14 @@ bool test_visible_step_after_hold_forward_contributes_held_sample() { auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; - source->samples = { + source->samples = { { 5, -4.0f }, { 15, 6.0f }, { 25, 100.0f }, }; auto series = make_series(source); - series->interpolation = Series_interpolation::STEP_AFTER; + series->interpolation = Series_interpolation::STEP_AFTER; series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; Plot_config config; @@ -547,16 +547,16 @@ bool test_visible_step_after_skip_fallback_keeps_earlier_drawable_held_sample() auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; - source->samples = { + source->samples = { { 5, -4.0f }, { 9, nan }, { 15, 6.0f }, }; auto series = make_series(source); - series->interpolation = Series_interpolation::STEP_AFTER; + series->interpolation = Series_interpolation::STEP_AFTER; series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; - series->nonfinite_policy = plot::Nonfinite_sample_policy::SKIP; + series->nonfinite_policy = plot::Nonfinite_sample_policy::SKIP; Plot_config config; config.auto_v_range_mode = Auto_v_range_mode::VISIBLE; @@ -581,13 +581,13 @@ bool test_global_value_only_access_falls_back_to_snapshot_scan() { auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; - source->samples = { + source->samples = { { 0, -3.0f }, { 0, 8.0f }, { 0, 2.0f }, }; - auto series = make_series(source); + auto series = make_series(source); series->access = make_value_only_policy(); Plot_config config; @@ -613,7 +613,7 @@ bool test_failed_query_does_not_fall_back_to_stale_scan() { auto source = std::make_shared(); source->query_status = Data_query_status::FAILED; - source->samples = { + source->samples = { { 0, 1.0f }, { 5, 2.0f }, }; @@ -641,9 +641,9 @@ bool test_failed_query_does_not_fall_back_to_stale_scan() bool test_ready_query_result_is_cached_by_current_sequence() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -678,9 +678,9 @@ bool test_ready_query_result_is_cached_by_current_sequence() bool test_conservative_query_result_is_not_cached() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_series(source); @@ -713,8 +713,8 @@ bool test_conservative_query_result_is_not_cached() bool test_empty_query_result_is_cached_by_current_sequence() { auto source = std::make_shared(); - source->query_status = Data_query_status::EMPTY; - source->query_sequence = 5; + source->query_status = Data_query_status::EMPTY; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -750,9 +750,9 @@ bool test_empty_query_result_is_cached_by_current_sequence() bool test_sequence_change_invalidates_auto_range_cache() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -768,8 +768,8 @@ bool test_sequence_change_invalidates_auto_range_cache() true, &cache); - source->query_range = {-3.0f, 9.0f}; - source->query_sequence = 6; + source->query_range = {-3.0f, 9.0f}; + source->query_sequence = 6; source->current_sequence_value = 6; const auto range = plot::detail::resolve_main_v_range( series_map, @@ -789,9 +789,9 @@ bool test_sequence_change_invalidates_auto_range_cache() bool test_visible_window_change_invalidates_auto_range_cache() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -808,8 +808,8 @@ bool test_visible_window_change_invalidates_auto_range_cache() true, &cache); - cfg.t_min = 30; - cfg.t_max = 40; + cfg.t_min = 30; + cfg.t_max = 40; source->query_range = {-6.0f, -2.0f}; const auto range = plot::detail::resolve_main_v_range( series_map, @@ -829,9 +829,9 @@ bool test_visible_window_change_invalidates_auto_range_cache() bool test_access_policy_change_invalidates_auto_range_cache() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -867,9 +867,9 @@ bool test_access_policy_change_invalidates_auto_range_cache() bool test_semantics_revision_change_invalidates_auto_range_cache() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -904,9 +904,9 @@ bool test_semantics_revision_change_invalidates_auto_range_cache() bool test_removed_series_prunes_auto_range_cache() { auto source = std::make_shared(); - source->query_status = Data_query_status::READY; - source->query_range = {1.0f, 4.0f}; - source->query_sequence = 5; + source->query_status = Data_query_status::READY; + source->query_range = {1.0f, 4.0f}; + source->query_sequence = 5; source->current_sequence_value = 5; auto series = make_stable_series(source); @@ -941,13 +941,13 @@ bool test_preview_auto_range_uses_preview_query_source() auto main_source = std::make_shared(); auto preview_source = std::make_shared(); preview_source->query_status = Data_query_status::READY; - preview_source->query_range = {-2.0f, 11.0f}; + preview_source->query_range = {-2.0f, 11.0f}; auto series = make_series(main_source); plot::preview_config_t preview; - preview.data_source = preview_source; - preview.access = make_policy(); - preview.style = Display_style::AREA; + preview.data_source = preview_source; + preview.access = make_policy(); + preview.style = Display_style::AREA; series->preview_config = preview; Plot_config config; @@ -973,22 +973,22 @@ bool test_preview_auto_range_uses_preview_query_source() bool test_frame_range_planner_populates_ranges_and_reuses_cache() { auto main_source = std::make_shared(); - main_source->query_status = Data_query_status::READY; - main_source->query_range = {2.0f, 5.0f}; - main_source->query_sequence = 8; + main_source->query_status = Data_query_status::READY; + main_source->query_range = {2.0f, 5.0f}; + main_source->query_sequence = 8; main_source->current_sequence_value = 8; auto preview_source = std::make_shared(); - preview_source->query_status = Data_query_status::READY; - preview_source->query_range = {-2.0f, 11.0f}; - preview_source->query_sequence = 9; + preview_source->query_status = Data_query_status::READY; + preview_source->query_range = {-2.0f, 11.0f}; + preview_source->query_sequence = 9; preview_source->current_sequence_value = 9; auto series = make_stable_series(main_source); plot::preview_config_t preview; - preview.data_source = preview_source; - preview.access = make_stable_policy(); - preview.style = Display_style::AREA; + preview.data_source = preview_source; + preview.access = make_stable_policy(); + preview.style = Display_style::AREA; series->preview_config = preview; auto series_map = make_series_map(series); @@ -1024,8 +1024,8 @@ bool test_frame_range_planner_populates_ranges_and_reuses_cache() TEST_ASSERT(preview_source->query_calls == 1, "frame planner should preserve preview range cache reuse"); - main_source->query_range = {-4.0f, 12.0f}; - main_source->query_sequence = 10; + main_source->query_range = {-4.0f, 12.0f}; + main_source->query_sequence = 10; main_source->current_sequence_value = 10; const auto after_sequence_change = planner.plan( series_map, @@ -1049,16 +1049,16 @@ bool test_frame_range_planner_skips_preview_when_disabled() { auto main_source = std::make_shared(); main_source->query_status = Data_query_status::READY; - main_source->query_range = {1.0f, 4.0f}; + main_source->query_range = {1.0f, 4.0f}; auto preview_source = std::make_shared(); preview_source->query_status = Data_query_status::READY; - preview_source->query_range = {-2.0f, 11.0f}; + preview_source->query_range = {-2.0f, 11.0f}; auto series = make_series(main_source); plot::preview_config_t preview; - preview.data_source = preview_source; - preview.access = make_policy(); + preview.data_source = preview_source; + preview.access = make_policy(); series->preview_config = preview; plot::detail::Frame_range_planner planner; @@ -1086,14 +1086,14 @@ bool test_frame_range_planner_preserves_step_after_visible_scan() { auto source = std::make_shared(); source->query_status = Data_query_status::UNSUPPORTED; - source->samples = { + source->samples = { { 5, -3.0f }, { 15, 8.0f }, { 25, 100.0f }, }; auto series = make_series(source); - series->interpolation = Series_interpolation::STEP_AFTER; + series->interpolation = Series_interpolation::STEP_AFTER; series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; Plot_config config; @@ -1121,7 +1121,7 @@ bool test_manual_range_skips_queries() { auto source = std::make_shared(); source->query_status = Data_query_status::READY; - source->query_range = {-2.0f, 11.0f}; + source->query_range = {-2.0f, 11.0f}; const data_config_t cfg = make_data_config(); Plot_config config; diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index cc2611e3..42d6e415 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -368,11 +368,11 @@ class Ring_source final : public plot::Data_source } auto buffer = std::make_shared>(m_samples); plot::data_snapshot_t snapshot; - snapshot.data = buffer->data(); - snapshot.count = buffer->size(); - snapshot.stride = sizeof(sample_t); + snapshot.data = buffer->data(); + snapshot.count = buffer->size(); + snapshot.stride = sizeof(sample_t); snapshot.sequence = m_sequence; - snapshot.hold = buffer; + snapshot.hold = buffer; return {snapshot, plot::snapshot_result_t::Snapshot_status::READY}; } diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index 2bc60176..379c1630 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -271,10 +271,10 @@ bool test_bounds_on_segmented_snapshot() } plot::data_snapshot_t snap; - snap.data = tail.data(); - snap.count = 10; + snap.data = tail.data(); + snap.count = 10; snap.stride = sizeof(sample_t); - snap.data2 = head.data(); + snap.data2 = head.data(); snap.count2 = head.size(); const auto get_ts = [](const void* p) -> std::int64_t { @@ -301,8 +301,8 @@ bool test_select_visible_sample_window_monotonic_extends_bounds() } plot::data_snapshot_t snap; - snap.data = samples.data(); - snap.count = samples.size(); + snap.data = samples.data(); + snap.count = samples.size(); snap.stride = sizeof(sample_t); const auto get_ts = [](const void* p) -> std::int64_t { @@ -343,8 +343,8 @@ bool test_select_visible_sample_window_non_monotonic_scans() }; plot::data_snapshot_t snap; - snap.data = samples.data(); - snap.count = samples.size(); + snap.data = samples.data(); + snap.count = samples.size(); snap.stride = sizeof(sample_t); const auto get_ts = [](const void* p) -> std::int64_t { @@ -382,8 +382,8 @@ bool test_aggregate_visible_sample_range_includes_step_after_hold() }; plot::data_snapshot_t snap; - snap.data = samples.data(); - snap.count = samples.size(); + snap.data = samples.data(); + snap.count = samples.size(); snap.stride = sizeof(sample_t); const auto get_ts = [](const void* p) -> std::int64_t { @@ -419,8 +419,8 @@ bool test_aggregate_visible_sample_range_rejects_nonfinite_range_endpoints() }; plot::data_snapshot_t snap; - snap.data = samples.data(); - snap.count = samples.size(); + snap.data = samples.data(); + snap.count = samples.size(); snap.stride = sizeof(sample_t); const auto get_ts = [](const void* p) -> std::int64_t { @@ -452,8 +452,8 @@ bool test_snapshot_truthiness_requires_usable_stride() std::vector samples = {{0, 1.0f}}; plot::data_snapshot_t snap; - snap.data = samples.data(); - snap.count = samples.size(); + snap.data = samples.data(); + snap.count = samples.size(); snap.stride = 0; TEST_ASSERT(!snap.is_valid(), "stride-zero snapshot should be invalid"); @@ -475,10 +475,10 @@ bool test_snapshot_count1_clamps_malformed_count2() std::vector second = {{1, 2.0f}}; plot::data_snapshot_t snap; - snap.data = first.data(); - snap.count = first.size(); + snap.data = first.data(); + snap.count = first.size(); snap.stride = sizeof(sample_t); - snap.data2 = second.data(); + snap.data2 = second.data(); snap.count2 = 2; TEST_ASSERT(snap.count1() == 0, @@ -502,11 +502,11 @@ bool test_layout_cache_key_distinguishes_adjacent_int64_time_windows() // timestamps with single-nanosecond precision. plot::layout_cache_key_t base{}; - base.v0 = 0.0f; - base.v1 = 1.0f; - base.t0 = 1'700'000'000'000'000'000LL; // ~late 2023 in ns since epoch - base.t1 = base.t0 + 60LL * 1'000'000'000LL; // 60-second window - base.viewport_size = plot::Size_2i{1024, 768}; + base.v0 = 0.0f; + base.v1 = 1.0f; + base.t0 = 1'700'000'000'000'000'000LL; // ~late 2023 in ns since epoch + base.t1 = base.t0 + 60LL * 1'000'000'000LL; // 60-second window + base.viewport_size = plot::Size_2i{1024, 768}; base.adjusted_reserved_height = 24.0; base.adjusted_preview_height = 32.0; base.adjusted_font_size_in_pixels = 13.5; @@ -534,10 +534,10 @@ bool test_layout_cache_key_distinguishes_adjacent_int64_time_windows() // fields would lose precision entirely. plot::layout_cache_key_t high_a = base; plot::layout_cache_key_t high_b = base; - high_a.t0 = std::numeric_limits::max() - 1; - high_a.t1 = std::numeric_limits::max(); - high_b.t0 = std::numeric_limits::max() - 2; - high_b.t1 = std::numeric_limits::max() - 1; + high_a.t0 = std::numeric_limits::max() - 1; + high_a.t1 = std::numeric_limits::max(); + high_b.t0 = std::numeric_limits::max() - 2; + high_b.t1 = std::numeric_limits::max() - 1; TEST_ASSERT(!(high_a == high_b), "layout_cache_key_t must distinguish adjacent ns windows even " "near INT64_MAX where double fields would lose precision"); diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 93a455b6..7b1e41fa 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -113,11 +113,11 @@ plot::data_query_context_t make_query( std::int64_t t_max) { plot::data_query_context_t query; - query.access = &access; - query.semantics_key.value = k_query_semantics_key; - query.semantics_key.revision = 1; + query.access = &access; + query.semantics_key.value = k_query_semantics_key; + query.semantics_key.revision = 1; query.semantics_key.conservative = false; - query.time_window = {t_min, t_max}; + query.time_window = {t_min, t_max}; return query; } @@ -127,7 +127,7 @@ plot::data_query_context_t make_hold_query( std::int64_t t_max) { plot::data_query_context_t query = make_query(access, t_min, t_max); - query.interpolation = plot::Series_interpolation::STEP_AFTER; + query.interpolation = plot::Series_interpolation::STEP_AFTER; query.empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; return query; } @@ -138,7 +138,7 @@ plot::data_query_context_t make_draw_query( std::int64_t t_max) { plot::data_query_context_t query = make_query(access, t_min, t_max); - query.empty_window_behavior = plot::Empty_window_behavior::DRAW_NOTHING; + query.empty_window_behavior = plot::Empty_window_behavior::DRAW_NOTHING; return query; } diff --git a/tests/test_font_disk_cache.cpp b/tests/test_font_disk_cache.cpp index f578ca52..9aa5cf14 100644 --- a/tests/test_font_disk_cache.cpp +++ b/tests/test_font_disk_cache.cpp @@ -47,7 +47,7 @@ struct Scoped_temp_dir std::filesystem::remove_all(path, ec); } - Scoped_temp_dir(const Scoped_temp_dir&) = delete; + Scoped_temp_dir(const Scoped_temp_dir&) = delete; Scoped_temp_dir& operator=(const Scoped_temp_dir&) = delete; }; @@ -193,7 +193,7 @@ bool test_corrupt_glyph_count_is_rejected() Scoped_temp_dir tmp; const auto digest = make_digest(0x20u); cache_file_options_t options; - options.digest = digest; + options.digest = digest; options.glyph_count = std::numeric_limits::max(); const auto path = tmp.path / "corrupt_glyph_count.bin"; @@ -208,8 +208,8 @@ bool test_corrupt_kerning_count_is_rejected() Scoped_temp_dir tmp; const auto digest = make_digest(0x30u); cache_file_options_t options; - options.digest = digest; - options.glyph_count = 1u; + options.digest = digest; + options.glyph_count = 1u; options.kerning_count = 2u; const auto path = tmp.path / "corrupt_kerning_count.bin"; @@ -225,7 +225,7 @@ bool test_corrupt_atlas_size_and_bytes_are_rejected() const auto digest = make_digest(0x40u); cache_file_options_t bad_size; - bad_size.digest = digest; + bad_size.digest = digest; bad_size.atlas_size = k_atlas_texture_size / 2u; const auto bad_size_path = tmp.path / "corrupt_atlas_size.bin"; TEST_ASSERT(write_cache_file(bad_size_path, bad_size), @@ -234,7 +234,7 @@ bool test_corrupt_atlas_size_and_bytes_are_rejected() "atlas size different from the renderer texture size must be rejected"); cache_file_options_t bad_bytes; - bad_bytes.digest = digest; + bad_bytes.digest = digest; bad_bytes.atlas_bytes = k_expected_atlas_bytes - 4u; const auto bad_bytes_path = tmp.path / "corrupt_atlas_bytes.bin"; TEST_ASSERT(write_cache_file(bad_bytes_path, bad_bytes), @@ -252,7 +252,7 @@ bool test_same_height_changed_digest_does_not_reuse_old_cache() const auto changed_digest = make_digest(0x90u); cache_file_options_t options; - options.digest = old_digest; + options.digest = old_digest; options.write_atlas_payload = true; const auto path = tmp.path / "old_digest_same_height.bin"; @@ -270,8 +270,8 @@ bool test_previous_cache_version_is_rejected() const auto digest = make_digest(0x60u); cache_file_options_t options; - options.digest = digest; - options.cache_version = k_previous_cache_version; + options.digest = digest; + options.cache_version = k_previous_cache_version; options.write_atlas_payload = true; const auto path = tmp.path / "previous_cache_version.bin"; diff --git a/tests/test_layout_calculator.cpp b/tests/test_layout_calculator.cpp index e7be265e..fb88f2ad 100644 --- a/tests/test_layout_calculator.cpp +++ b/tests/test_layout_calculator.cpp @@ -37,22 +37,22 @@ plot::Layout_calculator::parameters_t make_minimal_params( std::vector& recorded_calls) { plot::Layout_calculator::parameters_t params; - params.v_min = 0.0f; - params.v_max = 1.0f; - params.t_min = t_min_ns; - params.t_max = t_max_ns; - params.usable_width = 800.0; - params.usable_height = 480.0; - params.vbar_width = 56.0; - params.label_visible_height = 480.0; - params.adjusted_font_size_in_pixels = 14.0; + params.v_min = 0.0f; + params.v_max = 1.0f; + params.t_min = t_min_ns; + params.t_max = t_max_ns; + params.usable_width = 800.0; + params.usable_height = 480.0; + params.vbar_width = 56.0; + params.label_visible_height = 480.0; + params.adjusted_font_size_in_pixels = 14.0; params.h_label_vertical_nudge_factor = 0.0f; - params.measure_text_cache_key = 0; + params.measure_text_cache_key = 0; // Emulate a monospace font so the calculator does not need a // measure_text callback to estimate label widths. params.monospace_char_advance_px = 8.0f; params.monospace_advance_is_reliable = true; - params.measure_text_func = [](const char* text) { + params.measure_text_func = [](const char* text) { return static_cast(std::strlen(text)) * 8.0f; }; params.get_required_fixed_digits_func = [](double) { return 2; }; @@ -253,10 +253,10 @@ bool test_vertical_labels_keep_dense_level_when_glyphs_fit() { std::vector recorded; auto params = make_minimal_params(0LL, 60LL * k_ns_per_second, recorded); - params.v_min = -5000.0f; - params.v_max = 45000.0f; - params.usable_height = 140.0; - params.label_visible_height = params.usable_height; + params.v_min = -5000.0f; + params.v_max = 45000.0f; + params.usable_height = 140.0; + params.label_visible_height = params.usable_height; params.adjusted_font_size_in_pixels = 10.0; plot::Layout_calculator calc; diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index b4c0e875..50bc7934 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -51,8 +51,8 @@ zoom_state_t advance_zoom(double initial_velocity, const std::vector& el { zoom_state_t state{1.0, initial_velocity}; for (double elapsed_step : elapsed_steps) { - state.scale *= plot::Plot_interaction_item::zoom_animation_scale_factor(state.velocity, elapsed_step); - state.velocity = plot::Plot_interaction_item::zoom_animation_velocity_after(state.velocity, elapsed_step); + state.scale *= plot::Plot_interaction_item::zoom_animation_scale_factor(state.velocity, elapsed_step); + state.velocity = plot::Plot_interaction_item::zoom_animation_velocity_after(state.velocity, elapsed_step); } return state; } @@ -74,11 +74,11 @@ std::shared_ptr make_sample_series( }; auto series = std::make_shared(); - series->series_label = "indicator"; - series->interpolation = interpolation; + series->series_label = "indicator"; + series->interpolation = interpolation; series->empty_window_behavior = empty_window_behavior; - series->data_source = source; - series->access = access.erase(); + series->data_source = source; + series->access = access.erase(); return series; } @@ -91,10 +91,10 @@ void configure_view( float vmax) { plot::Plot_view view; - view.t_range = std::pair{tmin_ns, tmax_ns}; + view.t_range = std::pair{tmin_ns, tmax_ns}; view.t_available_range = std::pair{tmin_ns, tmax_ns}; - view.v_range = std::pair{vmin, vmax}; - view.v_auto = false; + view.v_range = std::pair{vmin, vmax}; + view.v_auto = false; widget.set_view(view); } diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 37b8e15f..86e6d974 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -110,12 +110,12 @@ class Test_source final : public plot::Data_source ++m_sequence; } plot::data_snapshot_t snapshot; - snapshot.data = m_samples.data(); - snapshot.count = m_samples.size(); - snapshot.stride = sizeof(test_sample_t); + snapshot.data = m_samples.data(); + snapshot.count = m_samples.size(); + snapshot.stride = sizeof(test_sample_t); snapshot.sequence = m_sequence; - auto hold = std::make_shared(17); - m_last_hold = hold; + auto hold = std::make_shared(17); + m_last_hold = hold; snapshot.hold = hold; return { snapshot, @@ -266,26 +266,26 @@ class Recording_layer_state final : public plot::Qrhi_series_layer_state bool prepare(const plot::qrhi_series_prepare_context_t& ctx) override { layer_event_t event; - event.layer_id = m_layer_id; - event.action = "prepare"; - event.resources_changed = ctx.resources_changed; - event.snapshot_valid = static_cast(ctx.window.snapshot); - event.snapshot_count = ctx.window.snapshot.count; - event.snapshot_sequence = ctx.window.snapshot.sequence; - event.view_kind = ctx.window.view_kind; - event.source_first = ctx.window.source_first; - event.source_count = ctx.window.source_count; - event.synthetic_hold_count = ctx.window.synthetic_hold_count; - event.gpu_count = ctx.window.gpu_count; - event.drawable_spans = ctx.window.drawable_spans; - event.sample_sequence = ctx.window.sample_sequence; - event.t_min_ns = ctx.window.t_min_ns; - event.t_max_ns = ctx.window.t_max_ns; - event.t_origin_ns = ctx.window.t_origin_ns; - event.v_min = ctx.window.v_min; - event.v_max = ctx.window.v_max; - event.nonfinite_policy = ctx.window.nonfinite_policy; - event.sample_buffer = ctx.sample_buffer.buffer; + event.layer_id = m_layer_id; + event.action = "prepare"; + event.resources_changed = ctx.resources_changed; + event.snapshot_valid = static_cast(ctx.window.snapshot); + event.snapshot_count = ctx.window.snapshot.count; + event.snapshot_sequence = ctx.window.snapshot.sequence; + event.view_kind = ctx.window.view_kind; + event.source_first = ctx.window.source_first; + event.source_count = ctx.window.source_count; + event.synthetic_hold_count = ctx.window.synthetic_hold_count; + event.gpu_count = ctx.window.gpu_count; + event.drawable_spans = ctx.window.drawable_spans; + event.sample_sequence = ctx.window.sample_sequence; + event.t_min_ns = ctx.window.t_min_ns; + event.t_max_ns = ctx.window.t_max_ns; + event.t_origin_ns = ctx.window.t_origin_ns; + event.v_min = ctx.window.v_min; + event.v_max = ctx.window.v_max; + event.nonfinite_policy = ctx.window.nonfinite_policy; + event.sample_buffer = ctx.sample_buffer.buffer; event.sample_buffer_first_sample = ctx.sample_buffer.first_sample; event.sample_buffer_sample_count = ctx.sample_buffer.sample_count; event.sample_buffer_source_first = ctx.sample_buffer.source_first; @@ -293,10 +293,10 @@ class Recording_layer_state final : public plot::Qrhi_series_layer_state event.sample_buffer_synthetic_hold_count = ctx.sample_buffer.synthetic_hold_count; event.sample_buffer_t_origin_ns = ctx.sample_buffer.t_origin_ns; - event.sample_buffer_t_min_ns = ctx.sample_buffer.t_min_ns; - event.sample_buffer_t_max_ns = ctx.sample_buffer.t_max_ns; - event.sample_buffer_v_min = ctx.sample_buffer.v_min; - event.sample_buffer_v_max = ctx.sample_buffer.v_max; + event.sample_buffer_t_min_ns = ctx.sample_buffer.t_min_ns; + event.sample_buffer_t_max_ns = ctx.sample_buffer.t_max_ns; + event.sample_buffer_v_min = ctx.sample_buffer.v_min; + event.sample_buffer_v_max = ctx.sample_buffer.v_max; event.sample_buffer_stride_bytes = ctx.sample_buffer.layout.stride_bytes; event.sample_buffer_t_rel_seconds_offset = @@ -314,22 +314,22 @@ class Recording_layer_state final : public plot::Qrhi_series_layer_state void record(const plot::qrhi_series_record_context_t& ctx) override { layer_event_t event; - event.layer_id = m_layer_id; - event.action = "record"; - event.snapshot_valid = static_cast(ctx.window.snapshot); - event.snapshot_count = ctx.window.snapshot.count; - event.snapshot_sequence = ctx.window.snapshot.sequence; - event.view_kind = ctx.window.view_kind; - event.source_first = ctx.window.source_first; - event.source_count = ctx.window.source_count; + event.layer_id = m_layer_id; + event.action = "record"; + event.snapshot_valid = static_cast(ctx.window.snapshot); + event.snapshot_count = ctx.window.snapshot.count; + event.snapshot_sequence = ctx.window.snapshot.sequence; + event.view_kind = ctx.window.view_kind; + event.source_first = ctx.window.source_first; + event.source_count = ctx.window.source_count; event.synthetic_hold_count = ctx.window.synthetic_hold_count; - event.gpu_count = ctx.window.gpu_count; - event.drawable_spans = ctx.window.drawable_spans; - event.sample_sequence = ctx.window.sample_sequence; - event.t_min_ns = ctx.window.t_min_ns; - event.t_max_ns = ctx.window.t_max_ns; - event.t_origin_ns = ctx.window.t_origin_ns; - event.nonfinite_policy = ctx.window.nonfinite_policy; + event.gpu_count = ctx.window.gpu_count; + event.drawable_spans = ctx.window.drawable_spans; + event.sample_sequence = ctx.window.sample_sequence; + event.t_min_ns = ctx.window.t_min_ns; + event.t_max_ns = ctx.window.t_max_ns; + event.t_origin_ns = ctx.window.t_origin_ns; + event.nonfinite_policy = ctx.window.nonfinite_policy; m_events.push_back(event); } @@ -441,10 +441,10 @@ class Offscreen_rhi_fixture } QRhiResourceUpdateBatch* updates = m_rhi->nextResourceUpdateBatch(); - ctx.rhi = m_rhi.get(); - ctx.cb = command_buffer; + ctx.rhi = m_rhi.get(); + ctx.cb = command_buffer; ctx.render_target = m_render_target.get(); - ctx.rhi_updates = updates; + ctx.rhi_updates = updates; renderer.prepare(ctx, series_map); events.push_back({"frame", "begin_pass"}); @@ -469,7 +469,7 @@ class Offscreen_rhi_fixture plot::frame_layout_result_t make_layout() { plot::frame_layout_result_t layout; - layout.usable_width = 240.0; + layout.usable_width = 240.0; layout.usable_height = 120.0; return layout; } @@ -479,15 +479,15 @@ plot::frame_context_t make_context( const plot::Plot_config& config) { plot::frame_context_t ctx{layout}; - ctx.t0 = 0; - ctx.t1 = 3'000'000'000LL; + ctx.t0 = 0; + ctx.t1 = 3'000'000'000LL; ctx.t_available_min = 0; ctx.t_available_max = 7'000'000'000LL; - ctx.v0 = 0.0f; - ctx.v1 = 10.0f; - ctx.win_w = 320; - ctx.win_h = 180; - ctx.config = &config; + ctx.v0 = 0.0f; + ctx.v1 = 10.0f; + ctx.win_w = 320; + ctx.win_h = 180; + ctx.config = &config; return ctx; } @@ -495,10 +495,10 @@ std::shared_ptr make_layer_only_series( std::shared_ptr source, std::vector> layers) { - auto series = std::make_shared(); - series->style = plot::Display_style::NONE; + auto series = std::make_shared(); + series->style = plot::Display_style::NONE; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); series->qrhi_layers = std::move(layers); return series; } @@ -508,10 +508,10 @@ std::shared_ptr make_builtin_plus_layer_series( plot::Display_style style, std::vector> layers) { - auto series = std::make_shared(); - series->style = style; + auto series = std::make_shared(); + series->style = style; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); series->qrhi_layers = std::move(layers); return series; } @@ -717,9 +717,9 @@ bool test_style_none_without_layers_does_not_upload_samples() std::vector events; auto source = std::make_shared(); auto series = std::make_shared(); - series->style = plot::Display_style::NONE; + series->style = plot::Display_style::NONE; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); std::map> series_map; const int series_id = 8; @@ -780,9 +780,9 @@ bool test_custom_sample_buffer_not_reused_when_current_access_cannot_stage() TEST_ASSERT(first_prepare && first_prepare->sample_buffer, "initial custom-only prepare should expose a compact sample buffer"); - auto value_only_series = make_layer_only_series(source, {layer}); + auto value_only_series = make_layer_only_series(source, {layer}); value_only_series->access = make_value_only_access_policy(); - series_map[series_id] = value_only_series; + series_map[series_id] = value_only_series; events.clear(); TEST_ASSERT( @@ -848,10 +848,10 @@ bool test_builtin_upload_stages_visible_window_only() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40LL * k_second_ns; - ctx.t1 = 42LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 40LL * k_second_ns; + ctx.t1 = 42LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -918,10 +918,10 @@ bool test_builtin_upload_reuses_vbo_capacity_headroom() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40LL * k_second_ns; - ctx.t1 = 41LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 40LL * k_second_ns; + ctx.t1 = 41LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -943,7 +943,7 @@ bool test_builtin_upload_reuses_vbo_capacity_headroom() "first capacity test frame should allocate enough VBO bytes"); events.clear(); - ctx.t1 = 42LL * k_second_ns; + ctx.t1 = 42LL * k_second_ns; ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1004,10 +1004,10 @@ bool test_combined_builtin_uploads_samples_once_per_view() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40LL * k_second_ns; - ctx.t1 = 42LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 40LL * k_second_ns; + ctx.t1 = 42LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1079,14 +1079,14 @@ bool test_direct_member_policy_uses_member_dispatch_in_renderer_staging() return source; }; - auto direct_series = std::make_shared(); - direct_series->style = plot::Display_style::DOTS; + auto direct_series = std::make_shared(); + direct_series->style = plot::Display_style::DOTS; direct_series->data_source = make_source(); - direct_series->access = make_direct_member_access_policy(); + direct_series->access = make_direct_member_access_policy(); access_call_counts_t fallback_calls; - auto fallback_series = std::make_shared(); - fallback_series->style = plot::Display_style::DOTS; + auto fallback_series = std::make_shared(); + fallback_series->style = plot::Display_style::DOTS; fallback_series->data_source = make_source(); fallback_series->access = make_fallback_access_policy_with_counted_public_accessors(fallback_calls); @@ -1109,10 +1109,10 @@ bool test_direct_member_policy_uses_member_dispatch_in_renderer_staging() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 5LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 5LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1165,10 +1165,10 @@ bool test_access_policy_change_reuploads_builtin_samples() } source->set_samples(std::move(samples)); - auto series = std::make_shared(); - series->style = plot::Display_style::DOTS; + auto series = std::make_shared(); + series->style = plot::Display_style::DOTS; series->data_source = source; - series->access = make_direct_member_access_policy(); + series->access = make_direct_member_access_policy(); std::map> series_map; const int series_id = 53; @@ -1186,10 +1186,10 @@ bool test_access_policy_change_reuploads_builtin_samples() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 5LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 5LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1235,10 +1235,10 @@ bool test_builtin_staging_normalizes_finite_reversed_ranges() { 3LL * k_second_ns, 4.0f, 6.0f, 4.0f} }); - auto series = std::make_shared(); - series->style = plot::Display_style::DOTS; + auto series = std::make_shared(); + series->style = plot::Display_style::DOTS; series->data_source = source; - series->access = make_direct_member_access_policy(); + series->access = make_direct_member_access_policy(); std::map> series_map; const int series_id = 54; @@ -1256,10 +1256,10 @@ bool test_builtin_staging_normalizes_finite_reversed_ranges() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 3LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 3LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1341,10 +1341,10 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 4LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 4LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -1456,10 +1456,10 @@ bool test_nonfinite_replace_with_zero_keeps_contiguous_span() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 4LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 4LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -1538,10 +1538,10 @@ bool test_nonfinite_reject_window_suppresses_drawable_upload() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 3LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 3LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -1576,10 +1576,10 @@ bool test_nonfinite_reject_window_invalidates_prior_upload_before_busy() }); auto series = std::make_shared(); - series->style = plot::Display_style::DOTS; + series->style = plot::Display_style::DOTS; series->nonfinite_policy = plot::Nonfinite_sample_policy::REJECT_WINDOW; - series->data_source = source; - series->access = make_access_policy(); + series->data_source = source; + series->access = make_access_policy(); std::map> series_map; const int series_id = 104; @@ -1597,10 +1597,10 @@ bool test_nonfinite_reject_window_invalidates_prior_upload_before_busy() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 2LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 2LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1682,10 +1682,10 @@ bool test_custom_layer_zero_gpu_window_invalidates_prior_upload_before_busy() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 2LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 2LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1742,10 +1742,10 @@ bool test_non_drawable_window_invalidates_prior_upload_before_fast_path() { 10LL * k_second_ns, 10.0f} }); - auto series = std::make_shared(); - series->style = plot::Display_style::DOTS; + auto series = std::make_shared(); + series->style = plot::Display_style::DOTS; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); std::map> series_map; const int series_id = 105; @@ -1763,10 +1763,10 @@ bool test_non_drawable_window_invalidates_prior_upload_before_fast_path() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 1LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 1LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1781,9 +1781,9 @@ bool test_non_drawable_window_invalidates_prior_upload_before_fast_path() source->set_samples({ {10LL * k_second_ns, 10.0f} }); - series->style = plot::Display_style::LINE; - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 11LL * k_second_ns; + series->style = plot::Display_style::LINE; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 11LL * k_second_ns; ctx.t_available_min = ctx.t0; ctx.t_available_max = ctx.t1; events.clear(); @@ -1822,10 +1822,10 @@ bool test_non_rhi_prepare_invalidates_prior_upload_before_fast_path() { 10LL * k_second_ns, 10.0f} }); - auto series = std::make_shared(); - series->style = plot::Display_style::DOTS; + auto series = std::make_shared(); + series->style = plot::Display_style::DOTS; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); std::map> series_map; const int series_id = 110; @@ -1843,10 +1843,10 @@ bool test_non_rhi_prepare_invalidates_prior_upload_before_fast_path() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 1LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 1LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -1859,8 +1859,8 @@ bool test_non_rhi_prepare_invalidates_prior_upload_before_fast_path() "initial QRhi frame should upload multiple samples"); plot::frame_context_t non_rhi_ctx = make_context(layout, config); - non_rhi_ctx.t0 = 10LL * k_second_ns; - non_rhi_ctx.t1 = 11LL * k_second_ns; + non_rhi_ctx.t0 = 10LL * k_second_ns; + non_rhi_ctx.t1 = 11LL * k_second_ns; non_rhi_ctx.t_available_min = non_rhi_ctx.t0; non_rhi_ctx.t_available_max = non_rhi_ctx.t1; renderer.prepare(non_rhi_ctx, series_map); @@ -1942,10 +1942,10 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 3LL * k_second_ns; - ctx.t1 = 4LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 3LL * k_second_ns; + ctx.t1 = 4LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -2037,10 +2037,10 @@ bool test_nonfinite_skip_hold_forward_preserves_earlier_held_sample_with_visible plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 3LL * k_second_ns; - ctx.t1 = 6LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 3LL * k_second_ns; + ctx.t1 = 6LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -2128,10 +2128,10 @@ bool test_nonfinite_skip_hold_forward_ignores_future_padding_without_visible_dat plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 3LL * k_second_ns; - ctx.t1 = 4LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 3LL * k_second_ns; + ctx.t1 = 4LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -2218,10 +2218,10 @@ bool test_global_draw_order_sorts_builtins_across_series_and_custom_layers() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -2311,10 +2311,10 @@ bool test_builtin_draw_commands_sort_relative_to_custom_layers() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -2387,10 +2387,10 @@ bool test_builtins_do_not_use_qrhi_layer_cache() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -2471,10 +2471,10 @@ bool test_builtin_upload_stages_visible_windows_for_dots_and_area() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40LL * k_second_ns; - ctx.t1 = 42LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 40LL * k_second_ns; + ctx.t1 = 42LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -2524,12 +2524,12 @@ bool test_builtin_upload_stages_single_synthetic_hold_sample() }); auto series = std::make_shared(); - series->style = plot::Display_style::LINE; - series->interpolation = plot::Series_interpolation::STEP_AFTER; + series->style = plot::Display_style::LINE; + series->interpolation = plot::Series_interpolation::STEP_AFTER; series->empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; - series->data_source = source; - series->access = make_access_policy(); - series->qrhi_layers = {layer}; + series->data_source = source; + series->access = make_access_policy(); + series->qrhi_layers = {layer}; std::map> series_map; const int series_id = 32; @@ -2546,10 +2546,10 @@ bool test_builtin_upload_stages_single_synthetic_hold_sample() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -2607,12 +2607,12 @@ bool test_builtin_upload_stages_hold_windows_for_dots_and_area() }); auto series = std::make_shared(); - series->style = test_case.style; + series->style = test_case.style; series->interpolation = plot::Series_interpolation::STEP_AFTER; series->empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); series->qrhi_layers = {layer}; std::map> series_map; @@ -2629,10 +2629,10 @@ bool test_builtin_upload_stages_hold_windows_for_dots_and_area() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame( @@ -2756,12 +2756,12 @@ bool test_resources_changed_tracks_hold_timestamp_changes() }); auto series = std::make_shared(); - series->style = plot::Display_style::LINE; + series->style = plot::Display_style::LINE; series->interpolation = plot::Series_interpolation::STEP_AFTER; series->empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); series->qrhi_layers = {layer}; std::map> series_map; @@ -2778,10 +2778,10 @@ bool test_resources_changed_tracks_hold_timestamp_changes() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -2799,7 +2799,7 @@ bool test_resources_changed_tracks_hold_timestamp_changes() const std::int64_t first_origin = first.t_origin_ns; events.clear(); - ctx.t1 = 13LL * k_second_ns; + ctx.t1 = 13LL * k_second_ns; ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -2903,11 +2903,11 @@ bool test_busy_stale_fallback_rejects_changed_request_shape() }); auto series = std::make_shared(); - series->style = plot::Display_style::LINE; - series->interpolation = test_case.interpolation; + series->style = plot::Display_style::LINE; + series->interpolation = test_case.interpolation; series->empty_window_behavior = test_case.empty_behavior; - series->data_source = source; - series->access = make_access_policy(); + series->data_source = source; + series->access = make_access_policy(); std::map> series_map; series_map[series_id] = series; @@ -2924,8 +2924,8 @@ bool test_busy_stale_fallback_rejects_changed_request_shape() plot::frame_layout_result_t layout = make_layout(); layout.usable_width = test_case.initial_width; plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = test_case.initial_t0; - ctx.t1 = test_case.initial_t1; + ctx.t0 = test_case.initial_t0; + ctx.t1 = test_case.initial_t1; ctx.t_available_min = ctx.t0; ctx.t_available_max = ctx.t1; @@ -2954,8 +2954,8 @@ bool test_busy_stale_fallback_rejects_changed_request_shape() plot::frame_layout_result_t busy_layout = make_layout(); busy_layout.usable_width = test_case.busy_width; plot::frame_context_t busy_ctx = make_context(busy_layout, config); - busy_ctx.t0 = test_case.busy_t0; - busy_ctx.t1 = test_case.busy_t1; + busy_ctx.t0 = test_case.busy_t0; + busy_ctx.t1 = test_case.busy_t1; busy_ctx.t_available_min = busy_ctx.t0; busy_ctx.t_available_max = busy_ctx.t1; TEST_ASSERT( @@ -2992,12 +2992,12 @@ bool test_busy_hold_forward_does_not_prepare_stale_tmax() }); auto series = std::make_shared(); - series->style = plot::Display_style::LINE; + series->style = plot::Display_style::LINE; series->interpolation = plot::Series_interpolation::STEP_AFTER; series->empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); std::map> series_map; const int series_id = 39; @@ -3014,10 +3014,10 @@ bool test_busy_hold_forward_does_not_prepare_stale_tmax() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10LL * k_second_ns; - ctx.t1 = 12LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 10LL * k_second_ns; + ctx.t1 = 12LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -3034,7 +3034,7 @@ bool test_busy_hold_forward_does_not_prepare_stale_tmax() const std::int64_t prepared_t_max = initial_view_state.last_prepared_t_max_ns; const std::size_t vbo_generation = initial_view_state.last_vbo_generation; source->return_busy_once(); - ctx.t1 = 13LL * k_second_ns; + ctx.t1 = 13LL * k_second_ns; ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -3062,12 +3062,12 @@ bool test_busy_hold_forward_does_not_reuse_non_hold_window() }); auto series = std::make_shared(); - series->style = plot::Display_style::LINE; + series->style = plot::Display_style::LINE; series->interpolation = plot::Series_interpolation::STEP_AFTER; series->empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; series->data_source = source; - series->access = make_access_policy(); + series->access = make_access_policy(); std::map> series_map; const int series_id = 40; @@ -3084,10 +3084,10 @@ bool test_busy_hold_forward_does_not_reuse_non_hold_window() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 2LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 2LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -3106,7 +3106,7 @@ bool test_busy_hold_forward_does_not_reuse_non_hold_window() const std::size_t vbo_generation = initial_view_state.last_vbo_generation; source->return_busy_once(); - ctx.t1 = 3LL * k_second_ns; + ctx.t1 = 3LL * k_second_ns; ctx.t_available_max = ctx.t1; TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), @@ -3397,10 +3397,10 @@ bool test_range_only_access_skips_builtin_value_styles() plot::Plot_config config; const plot::frame_layout_result_t layout = make_layout(); plot::frame_context_t ctx = make_context(layout, config); - ctx.t0 = 0; - ctx.t1 = 3LL * k_second_ns; - ctx.t_available_min = ctx.t0; - ctx.t_available_max = ctx.t1; + ctx.t0 = 0; + ctx.t1 = 3LL * k_second_ns; + ctx.t_available_min = ctx.t0; + ctx.t_available_max = ctx.t1; std::vector events; TEST_ASSERT( diff --git a/tests/test_qrhi_public_api.cpp b/tests/test_qrhi_public_api.cpp index 3e6c1ef5..01fd64e5 100644 --- a/tests/test_qrhi_public_api.cpp +++ b/tests/test_qrhi_public_api.cpp @@ -351,8 +351,8 @@ bool test_core_plan_types_are_usable() { plot::value_range_plan_t range; TEST_ASSERT(!range.valid, "value_range_plan_t should default to invalid"); - range.min = -4.0f; - range.max = 11.0f; + range.min = -4.0f; + range.max = 11.0f; range.valid = true; plot::Planned_snapshot planned_snapshot; @@ -362,39 +362,39 @@ bool test_core_plan_types_are_usable() plot::drawable_sample_span_t span; span.source_first = 2; span.source_count = 5; - span.gpu_first = 0; - span.gpu_count = span.source_count; + span.gpu_first = 0; + span.gpu_count = span.source_count; plot::Series_view_plan view_plan; - view_plan.series_id = 9; - view_plan.view_kind = plot::Series_view_kind::PREVIEW; - view_plan.lod_level = 2; - view_plan.lod_scale = 4; - view_plan.snapshot = planned_snapshot; - view_plan.source_first = span.source_first; - view_plan.source_count = span.source_count; + view_plan.series_id = 9; + view_plan.view_kind = plot::Series_view_kind::PREVIEW; + view_plan.lod_level = 2; + view_plan.lod_scale = 4; + view_plan.snapshot = planned_snapshot; + view_plan.source_first = span.source_first; + view_plan.source_count = span.source_count; view_plan.synthetic_hold_count = 1; view_plan.gpu_count = view_plan.source_count + view_plan.synthetic_hold_count; view_plan.drawable_spans.push_back(span); - view_plan.t_min_ns = 1'000; - view_plan.t_max_ns = 5'000; - view_plan.t_origin_ns = 1'000; - view_plan.hold_last_forward = true; - view_plan.hold_timestamp_ns = view_plan.t_max_ns; - view_plan.interpolation = plot::Series_interpolation::STEP_AFTER; + view_plan.t_min_ns = 1'000; + view_plan.t_max_ns = 5'000; + view_plan.t_origin_ns = 1'000; + view_plan.hold_last_forward = true; + view_plan.hold_timestamp_ns = view_plan.t_max_ns; + view_plan.interpolation = plot::Series_interpolation::STEP_AFTER; view_plan.empty_window_behavior = plot::Empty_window_behavior::HOLD_LAST_FORWARD; - view_plan.style = plot::Display_style::LINE; - view_plan.v_min = range.min; - view_plan.v_max = range.max; - view_plan.width_px = 320.0f; - view_plan.height_px = 64.0f; - view_plan.y_offset_px = 12.0f; - view_plan.window_alpha = 0.75f; - view_plan.pixels_per_sample = 2.5; + view_plan.style = plot::Display_style::LINE; + view_plan.v_min = range.min; + view_plan.v_max = range.max; + view_plan.width_px = 320.0f; + view_plan.height_px = 64.0f; + view_plan.y_offset_px = 12.0f; + view_plan.window_alpha = 0.75f; + view_plan.pixels_per_sample = 2.5; plot::Frame_range_plan frame_plan; - frame_plan.main_v_range = range; + frame_plan.main_v_range = range; frame_plan.preview_v_range = range; TEST_ASSERT(frame_plan.main_v_range.valid, "main range validity mismatch"); @@ -433,14 +433,14 @@ bool test_make_series_view_uniform_values() series.color = glm::vec4(0.2f, 0.4f, 0.6f, 0.8f); plot::sample_window_t window; - window.t_origin_ns = 1'000'000'000LL; - window.t_min_ns = 2'500'000'000LL; - window.t_max_ns = 5'000'000'000LL; - window.v_min = -3.0f; - window.v_max = 9.0f; - window.width_px = 640.0f; - window.height_px = 120.0f; - window.y_offset_px = 24.0f; + window.t_origin_ns = 1'000'000'000LL; + window.t_min_ns = 2'500'000'000LL; + window.t_max_ns = 5'000'000'000LL; + window.v_min = -3.0f; + window.v_max = 9.0f; + window.width_px = 640.0f; + window.height_px = 120.0f; + window.y_offset_px = 24.0f; window.window_alpha = 0.5f; const plot::series_view_uniform_std140_t uniform = diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 1797b5c4..d927e761 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -194,9 +194,9 @@ class Direct_window_source final : public Data_source last_query_semantics_key = query.semantics_key; plot::data_query_result_t result; - result.status = query_status; + result.status = query_status; result.sequence = query_sequence; - result.value = query_window; + result.value = query_window; return result; } }; @@ -250,14 +250,14 @@ frame_context_t make_context(const frame_layout_result_t& layout, Plot_config& c { frame_context_t ctx{layout}; // Timestamps are int64 ns. Tests use small ordinal indices for clarity. - ctx.t0 = 0; - ctx.t1 = 10; + ctx.t0 = 0; + ctx.t1 = 10; ctx.t_available_min = 0; ctx.t_available_max = 10; - ctx.win_w = 200; - ctx.win_h = 120; - ctx.dark_mode = config.dark_mode; - ctx.config = &config; + ctx.win_w = 200; + ctx.win_h = 120; + ctx.dark_mode = config.dark_mode; + ctx.config = &config; return ctx; } @@ -286,17 +286,17 @@ plot::Series_view_plan plan_two_level_lod_width( double width_px) { plot::detail::series_window_plan_request_t request; - request.planner_state = &state; + request.planner_state = &state; request.snapshot_cache = &cache; - request.frame_id = frame_id; - request.data_source = &source; - request.access = &access; - request.scales = &scales; - request.t_min_ns = 0; - request.t_max_ns = 99; - request.t_origin_ns = 0; - request.width_px = width_px; - request.style = Display_style::LINE; + request.frame_id = frame_id; + request.data_source = &source; + request.access = &access; + request.scales = &scales; + request.t_min_ns = 0; + request.t_max_ns = 99; + request.t_origin_ns = 0; + request.width_px = width_px; + request.style = Display_style::LINE; return plot::detail::plan_series_window(request); } @@ -304,7 +304,7 @@ std::shared_ptr make_single_level_source( std::vector timestamps, plot::Time_order order) { - auto source = std::make_shared(); + auto source = std::make_shared(); source->order = order; source->samples.resize(timestamps.size()); for (std::size_t i = 0; i < timestamps.size(); ++i) { @@ -345,27 +345,27 @@ std::shared_ptr make_direct_window_source() std::shared_ptr make_direct_window_series( const std::shared_ptr& source) { - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = source; - series->access = make_policy(); + series->access = make_policy(); return series; } bool test_direct_time_window_query_drives_renderer_window() { auto source = make_direct_window_source(); - source->query_window = {40, 3}; + source->query_window = {40, 3}; source->query_sequence = source->sequence; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40; - ctx.t1 = 42; + ctx.t0 = 40; + ctx.t1 = 42; ctx.t_available_min = 0; ctx.t_available_max = 127; @@ -401,22 +401,22 @@ bool test_direct_time_window_query_drives_renderer_window() bool test_direct_time_window_query_receives_access_semantics() { auto source = make_direct_window_source(); - source->query_window = {40, 3}; + source->query_window = {40, 3}; source->query_sequence = source->sequence; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40; - ctx.t1 = 42; + ctx.t0 = 40; + ctx.t1 = 42; ctx.t_available_min = 0; ctx.t_available_max = 127; { - auto series = make_direct_window_series(source); + auto series = make_direct_window_series(source); series->access = make_direct_member_policy(); const plot::sample_semantics_key_t expected_key = plot::detail::make_sample_semantics_key(&series->access); @@ -470,21 +470,21 @@ bool test_direct_time_window_query_receives_access_semantics() bool test_direct_time_window_empty_falls_back_to_renderer_padding() { auto source = std::make_shared(); - source->samples = { + source->samples = { { 0, 1.0f }, { 10, 2.0f }, }; - source->query_status = plot::Data_query_status::EMPTY; + source->query_status = plot::Data_query_status::EMPTY; source->query_sequence = source->sequence; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 5; - ctx.t1 = 6; + ctx.t0 = 5; + ctx.t1 = 6; ctx.t_available_min = 0; ctx.t_available_max = 127; @@ -513,21 +513,21 @@ bool test_direct_time_window_empty_falls_back_to_renderer_padding() bool test_direct_time_window_single_match_expands_for_linear_segments() { auto source = std::make_shared(); - source->samples = { + source->samples = { { 0, 1.0f }, { 10, 2.0f }, }; - source->query_window = {1, 1}; + source->query_window = {1, 1}; source->query_sequence = source->sequence; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 5; - ctx.t1 = 15; + ctx.t0 = 5; + ctx.t1 = 15; ctx.t_available_min = 0; ctx.t_available_max = 10; @@ -556,21 +556,21 @@ bool test_direct_time_window_single_match_expands_for_linear_segments() bool test_direct_time_window_hold_forward_synthesizes_terminal_sample() { auto source = make_direct_window_source(); - source->query_window = {2, 1}; + source->query_window = {2, 1}; source->query_sequence = source->sequence; auto series = make_direct_window_series(source); - series->interpolation = plot::Series_interpolation::STEP_AFTER; + series->interpolation = plot::Series_interpolation::STEP_AFTER; series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10; - ctx.t1 = 12; + ctx.t0 = 10; + ctx.t1 = 12; ctx.t_available_min = 0; ctx.t_available_max = 127; @@ -605,17 +605,17 @@ bool test_direct_time_window_hold_forward_synthesizes_terminal_sample() bool test_direct_time_window_sequence_mismatch_falls_back_to_snapshot_scan() { auto source = make_direct_window_source(); - source->query_window = {20, 5}; + source->query_window = {20, 5}; source->query_sequence = source->sequence + 1; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40; - ctx.t1 = 42; + ctx.t0 = 40; + ctx.t1 = 42; ctx.t_available_min = 0; ctx.t_available_max = 127; @@ -648,18 +648,18 @@ bool test_direct_time_window_sequence_mismatch_falls_back_to_snapshot_scan() bool test_direct_time_window_failed_status_suppresses_snapshot_fallback() { auto source = make_direct_window_source(); - source->query_window = {20, 5}; - source->query_status = plot::Data_query_status::FAILED; + source->query_window = {20, 5}; + source->query_status = plot::Data_query_status::FAILED; source->query_sequence = source->sequence; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40; - ctx.t1 = 42; + ctx.t0 = 40; + ctx.t1 = 42; ctx.t_available_min = 0; ctx.t_available_max = 127; @@ -690,18 +690,18 @@ bool test_direct_time_window_failed_status_suppresses_snapshot_fallback() bool test_direct_time_window_unsupported_falls_back_to_snapshot_scan() { auto source = make_direct_window_source(); - source->query_window = {20, 5}; - source->query_status = plot::Data_query_status::UNSUPPORTED; + source->query_window = {20, 5}; + source->query_status = plot::Data_query_status::UNSUPPORTED; source->query_sequence = source->sequence; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 40; - ctx.t1 = 42; + ctx.t0 = 40; + ctx.t1 = 42; ctx.t_available_min = 0; ctx.t_available_max = 127; @@ -737,13 +737,13 @@ bool test_ascending_time_order_skips_monotonicity_scan() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, plot::Time_order::ASCENDING); - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -779,13 +779,13 @@ bool run_defensive_time_order_scan_case( { auto data_source = make_single_level_source(timestamps, order); - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -838,13 +838,13 @@ bool test_descending_time_order_uses_linear_window_search() { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, plot::Time_order::DESCENDING); - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -878,19 +878,19 @@ bool test_descending_time_order_does_not_hold_oldest_sample() plot::Time_order::DESCENDING); auto series = std::make_shared(); - series->style = Display_style::LINE; - series->data_source = data_source; - series->access = make_policy(); + series->style = Display_style::LINE; + series->data_source = data_source; + series->access = make_policy(); series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - ctx.t0 = 10; - ctx.t1 = 12; + ctx.t0 = 10; + ctx.t1 = 12; ctx.t_available_min = ctx.t0; ctx.t_available_max = ctx.t1; @@ -918,13 +918,13 @@ bool test_renderer_uses_lod_scales_metadata() plot::Time_order::ASCENDING); data_source->scale_values = {0}; - auto series = std::make_shared(); - series->style = Display_style::LINE; + auto series = std::make_shared(); + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -962,16 +962,16 @@ bool test_direct_member_policy_uses_member_dispatch_in_planner() }; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; frame_context_t ctx = make_context(layout, config); - auto direct_series = std::make_shared(); - direct_series->style = Display_style::LINE; + auto direct_series = std::make_shared(); + direct_series->style = Display_style::LINE; direct_series->data_source = make_source(); - direct_series->access = make_direct_member_policy(); + direct_series->access = make_direct_member_policy(); Series_renderer direct_renderer; Asset_loader direct_asset_loader; @@ -989,8 +989,8 @@ bool test_direct_member_policy_uses_member_dispatch_in_planner() "direct member-pointer planner path should use member-pointer dispatch"); Access_call_counts fallback_calls; - auto fallback_series = std::make_shared(); - fallback_series->style = Display_style::LINE; + auto fallback_series = std::make_shared(); + fallback_series->style = Display_style::LINE; fallback_series->data_source = make_source(); fallback_series->access = make_fallback_policy_with_counted_public_accessors(fallback_calls); @@ -1026,12 +1026,12 @@ bool test_access_policy_change_invalidates_planner_fast_path_cache() const int series_id = 63; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_direct_member_policy(); + series->access = make_direct_member_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -1084,18 +1084,18 @@ bool test_frame_scoped_cache_reuse() const int series_id = 7; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; config.preview_visibility = 1.0; - frame_context_t ctx = make_context(layout, config); + frame_context_t ctx = make_context(layout, config); ctx.adjusted_preview_height = 20.0; Series_renderer renderer; @@ -1123,31 +1123,31 @@ bool test_preview_uses_distinct_source_snapshot() main_source->samples.resize(8, Test_sample{}); preview_source->samples.resize(8, Test_sample{}); for (size_t i = 0; i < main_source->samples.size(); ++i) { - main_source->samples[i].t = static_cast(i); - main_source->samples[i].v = 1.0f + static_cast(i); + main_source->samples[i].t = static_cast(i); + main_source->samples[i].v = 1.0f + static_cast(i); preview_source->samples[i].t = static_cast(i); preview_source->samples[i].v = 2.0f + static_cast(i); } const int series_id = 14; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = main_source; - series->access = make_policy(); + series->access = make_policy(); preview_config_t preview_cfg; preview_cfg.data_source = preview_source; - preview_cfg.access = make_policy(); - series->preview_config = preview_cfg; + preview_cfg.access = make_policy(); + series->preview_config = preview_cfg; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; config.preview_visibility = 1.0; - frame_context_t ctx = make_context(layout, config); + frame_context_t ctx = make_context(layout, config); ctx.adjusted_preview_height = 20.0; Series_renderer renderer; @@ -1176,23 +1176,23 @@ bool test_preview_disabled_skips_preview_snapshot() const int series_id = 15; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = main_source; - series->access = make_policy(); + series->access = make_policy(); preview_config_t preview_cfg; preview_cfg.data_source = preview_source; - preview_cfg.access = make_policy(); - series->preview_config = preview_cfg; + preview_cfg.access = make_policy(); + series->preview_config = preview_cfg; frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; config.preview_visibility = 1.0; - frame_context_t ctx = make_context(layout, config); + frame_context_t ctx = make_context(layout, config); ctx.adjusted_preview_height = 0.0; Series_renderer renderer; @@ -1223,12 +1223,12 @@ bool test_frame_change_invalidates_snapshot_cache() const int series_id = 8; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 140.0; + layout.usable_width = 140.0; layout.usable_height = 80.0; Plot_config config; @@ -1262,13 +1262,13 @@ bool test_empty_window_behavior_invalidates_fast_path_cache() const int series_id = 18; auto series = std::make_shared(); - series->style = Display_style::LINE; - series->data_source = data_source; - series->access = make_policy(); + series->style = Display_style::LINE; + series->data_source = data_source; + series->access = make_policy(); series->empty_window_behavior = Empty_window_behavior::DRAW_NOTHING; frame_layout_result_t layout; - layout.usable_width = 180.0; + layout.usable_width = 180.0; layout.usable_height = 80.0; Plot_config config; @@ -1314,21 +1314,21 @@ bool test_preview_honors_hold_last_forward() const int series_id = 19; auto series = std::make_shared(); - series->style = Display_style::LINE; - series->data_source = data_source; - series->access = make_policy(); + series->style = Display_style::LINE; + series->data_source = data_source; + series->access = make_policy(); series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; frame_layout_result_t layout; - layout.usable_width = 160.0; + layout.usable_width = 160.0; layout.usable_height = 80.0; Plot_config config; config.preview_visibility = 1.0; - frame_context_t ctx = make_context(layout, config); + frame_context_t ctx = make_context(layout, config); ctx.adjusted_preview_height = 24.0; - ctx.t_available_max = 40.0; + ctx.t_available_max = 40.0; Series_renderer renderer; Asset_loader asset_loader; @@ -1356,9 +1356,9 @@ bool test_lod_level_separation() const int series_id = 9; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); Plot_config config; @@ -1370,11 +1370,11 @@ bool test_lod_level_separation() series_map[series_id] = series; frame_layout_result_t layout_wide; - layout_wide.usable_width = 100.0; + layout_wide.usable_width = 100.0; layout_wide.usable_height = 80.0; frame_context_t ctx_wide = make_context(layout_wide, config); - ctx_wide.t0 = 0.0; - ctx_wide.t1 = 99.0; + ctx_wide.t0 = 0.0; + ctx_wide.t1 = 99.0; ctx_wide.win_w = 100; renderer.render(ctx_wide, series_map); @@ -1385,11 +1385,11 @@ bool test_lod_level_separation() "did not expect LOD1 snapshot at wide width"); frame_layout_result_t layout_narrow; - layout_narrow.usable_width = 20.0; + layout_narrow.usable_width = 20.0; layout_narrow.usable_height = 80.0; frame_context_t ctx_narrow = make_context(layout_narrow, config); - ctx_narrow.t0 = 0.0; - ctx_narrow.t1 = 99.0; + ctx_narrow.t0 = 0.0; + ctx_narrow.t1 = 99.0; ctx_narrow.win_w = 20; renderer.render(ctx_narrow, series_map); @@ -1454,12 +1454,12 @@ bool test_snapshot_released_after_render() const int series_id = 3; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 160.0; + layout.usable_width = 160.0; layout.usable_height = 80.0; Plot_config config; @@ -1499,12 +1499,12 @@ bool test_upload_origin_records_per_view_origin() const int series_id = 41; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -1513,8 +1513,8 @@ bool test_upload_origin_records_per_view_origin() // Span = 1 ms + 1 ns is strictly greater than k_ns_per_ms, so // choose_snap_ns falls into the next bucket and returns 1 us. t0 is // an exact multiple of 1 us, so the snap-aligned origin equals t0. - ctx.t0 = 5'000'000LL; - ctx.t1 = 5'000'001LL + 1'000'000LL; // 1 ms + 1 ns + ctx.t0 = 5'000'000LL; + ctx.t1 = 5'000'001LL + 1'000'000LL; // 1 ms + 1 ns ctx.t_available_min = ctx.t0; ctx.t_available_max = ctx.t1; @@ -1566,12 +1566,12 @@ bool test_upload_invalidates_when_origin_changes_across_snap_bucket() const int series_id = 42; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -1590,8 +1590,8 @@ bool test_upload_invalidates_when_origin_changes_across_snap_bucket() // origin change is part of the upload-invalidation key. auto run_frame = [&](std::int64_t t_min_ns, std::int64_t span_ns) { frame_context_t ctx = make_context(layout, config); - ctx.t0 = t_min_ns; - ctx.t1 = t_min_ns + span_ns; + ctx.t0 = t_min_ns; + ctx.t1 = t_min_ns + span_ns; ctx.t_available_min = ctx.t0; ctx.t_available_max = ctx.t1; renderer.render(ctx, series_map); @@ -1674,7 +1674,7 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() // renderer to find data within both windows without ballooning memory. constexpr std::int64_t k_ns_per_second = 1'000'000'000LL; constexpr std::int64_t k_ns_per_day = 86'400LL * k_ns_per_second; - constexpr std::int64_t k_ns_per_hour = 3'600LL * k_ns_per_second; + constexpr std::int64_t k_ns_per_hour = 3'600LL * k_ns_per_second; constexpr int k_num_samples = 365 * 10; data_source->samples.resize(k_num_samples); for (int i = 0; i < k_num_samples; ++i) { @@ -1684,12 +1684,12 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() const int series_id = 43; auto series = std::make_shared(); - series->style = Display_style::LINE; + series->style = Display_style::LINE; series->data_source = data_source; - series->access = make_policy(); + series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 200.0; + layout.usable_width = 200.0; layout.usable_height = 80.0; Plot_config config; @@ -1703,8 +1703,8 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() ctx.t0 = main_t0; ctx.t1 = main_t0 + k_ns_per_hour; // Preview view: full 10-year range starting at 0. - ctx.t_available_min = 0LL; - ctx.t_available_max = 10LL * 365LL * k_ns_per_day; + ctx.t_available_min = 0LL; + ctx.t_available_max = 10LL * 365LL * k_ns_per_day; ctx.adjusted_preview_height = 20.0; Series_renderer renderer; @@ -1764,20 +1764,20 @@ bool test_render_skips_invalid_series() const int disabled_id = 12; auto disabled_series = std::make_shared(); - disabled_series->enabled = false; - disabled_series->style = Display_style::LINE; + disabled_series->enabled = false; + disabled_series->style = Display_style::LINE; disabled_series->data_source = data_source; - disabled_series->access = make_policy(); + disabled_series->access = make_policy(); const int null_source_id = 13; auto null_source_series = std::make_shared(); - null_source_series->enabled = true; - null_source_series->style = Display_style::LINE; + null_source_series->enabled = true; + null_source_series->style = Display_style::LINE; null_source_series->data_source.reset(); null_source_series->access = make_policy(); frame_layout_result_t layout; - layout.usable_width = 140.0; + layout.usable_width = 140.0; layout.usable_height = 80.0; Plot_config config; @@ -1789,9 +1789,9 @@ bool test_render_skips_invalid_series() renderer.initialize(asset_loader); std::map> series_map; - series_map[disabled_id] = disabled_series; + series_map[disabled_id] = disabled_series; series_map[null_source_id] = null_source_series; - series_map[99] = nullptr; + series_map[99] = nullptr; renderer.render(ctx, series_map); diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 05638522..0e0b1c3d 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -180,8 +180,8 @@ bool test_make_access_policy_and_erase() // single literal stands for what the previous double-keyed test wrote // as 12.5. constexpr std::int64_t k_test_ts_ns = 12'500'000'000; - s.t = k_test_ts_ns; - s.v = 3.5f; + s.t = k_test_ts_ns; + s.v = 3.5f; s.v_min = 1.0f; s.v_max = 6.0f; @@ -304,8 +304,8 @@ bool test_erased_access_view_uses_direct_member_accessors() sample_t s{}; constexpr std::int64_t k_sample_timestamp_ns = 15'000'000'000; - s.t = k_sample_timestamp_ns; - s.v = 3.5f; + s.t = k_sample_timestamp_ns; + s.v = 3.5f; s.v_min = 1.25f; s.v_max = 5.5f; @@ -391,7 +391,7 @@ bool test_erased_access_view_uses_direct_member_accessors() plot::Data_access_policy slot_assigned = erased; slot_assigned.get_timestamp = slot_source.get_timestamp; - slot_assigned.get_value = slot_source.get_value; + slot_assigned.get_value = slot_source.get_value; const auto slot_assigned_view = plot::detail::make_erased_access_policy_view(slot_assigned); TEST_ASSERT( @@ -481,7 +481,7 @@ bool test_erased_access_view_uses_direct_member_accessors() TEST_ASSERT(revision_key_before != revision_key_after, "access policy cache key should change after accessor mutation"); - auto semantic_mutated = policy; + auto semantic_mutated = policy; semantic_mutated.get_value = [](const sample_t&) { return 13.0f; }; @@ -521,7 +521,7 @@ bool test_typed_api_floating_point_timestamp_member() fp_sample_t s{}; s.t_seconds = 12.5; - s.v = 3.5f; + s.v = 3.5f; // Forward direction: seconds -> int64 ns. constexpr std::int64_t k_expected_ns = 12'500'000'000; @@ -544,9 +544,9 @@ bool test_series_builder_preview_config() auto policy = plot::make_access_policy(&sample_t::t, &sample_t::v, &sample_t::v_min, &sample_t::v_max); plot::preview_config_t preview_cfg; - preview_cfg.data_source = preview_source; - preview_cfg.access = policy.erase(); - preview_cfg.style = plot::Display_style::AREA; + preview_cfg.data_source = preview_source; + preview_cfg.access = policy.erase(); + preview_cfg.style = plot::Display_style::AREA; preview_cfg.interpolation = plot::Series_interpolation::LINEAR; auto series = plot::Series_builder() From 03b435a7a6db628e7e5311fbb2def0adaf714d84 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:57:45 +0200 Subject: [PATCH 15/80] style: align inline method tables --- src/qt/t_axis_adjust.h | 8 ++++---- tests/test_data_source_queries.cpp | 2 +- tests/test_qrhi_layer_lifecycle.cpp | 12 ++++++------ tests/test_qrhi_public_api.cpp | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index 1f02e160..c5ea8c57 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -209,13 +209,13 @@ class Time_axis_model true); } - qint64 t_min() const { return m_t_min; } - qint64 t_max() const { return m_t_max; } + qint64 t_min() const { return m_t_min; } + qint64 t_max() const { return m_t_max; } qint64 t_available_min() const { return m_t_available_min; } qint64 t_available_max() const { return m_t_available_max; } - bool t_min_initialized() const { return m_t_min_initialized; } - bool t_max_initialized() const { return m_t_max_initialized; } + bool t_min_initialized() const { return m_t_min_initialized; } + bool t_max_initialized() const { return m_t_max_initialized; } bool t_available_min_initialized() const { return m_t_available_min_initialized; } bool t_available_max_initialized() const { return m_t_available_max_initialized; } diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 7b1e41fa..905d4653 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -51,7 +51,7 @@ class Query_source final : public plot::Data_source } std::size_t sample_stride() const override { return sizeof(sample_t); } - std::size_t lod_levels() const override { return m_scales.size(); } + std::size_t lod_levels() const override { return m_scales.size(); } std::size_t lod_scale(std::size_t level) const override { return level < m_scales.size() ? m_scales[level] : 1; diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 86e6d974..02465c36 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -148,8 +148,8 @@ class Test_source final : public plot::Data_source ++m_sequence; } - int snapshot_calls() const { return m_snapshot_calls; } - std::weak_ptr last_hold() const { return m_last_hold; } + int snapshot_calls() const { return m_snapshot_calls; } + std::weak_ptr last_hold() const { return m_last_hold; } void return_busy_once() { m_busy_snapshots_remaining = 1; } void advance_during_next_snapshot() { m_advance_during_next_snapshot = true; } @@ -355,9 +355,9 @@ class Recording_layer final : public plot::Qrhi_series_layer m_create_count(create_count) {} - std::string_view id() const override { return m_id; } - std::uint64_t revision() const override { return m_revision; } - int z_order() const override { return m_z_order; } + std::string_view id() const override { return m_id; } + std::uint64_t revision() const override { return m_revision; } + int z_order() const override { return m_z_order; } bool draws_view(plot::Series_view_kind view_kind) const override { @@ -422,7 +422,7 @@ class Offscreen_rhi_fixture return true; } - QRhi* rhi() const { return m_rhi.get(); } + QRhi* rhi() const { return m_rhi.get(); } QRhiTextureRenderTarget* render_target() const { return m_render_target.get(); } bool render_layer_frame( diff --git a/tests/test_qrhi_public_api.cpp b/tests/test_qrhi_public_api.cpp index 01fd64e5..d64ca63b 100644 --- a/tests/test_qrhi_public_api.cpp +++ b/tests/test_qrhi_public_api.cpp @@ -203,9 +203,9 @@ class Test_layer final : public plot::Qrhi_series_layer m_z_order(z_order) {} - std::string_view id() const override { return m_id; } - std::uint64_t revision() const override { return m_revision; } - int z_order() const override { return m_z_order; } + std::string_view id() const override { return m_id; } + std::uint64_t revision() const override { return m_revision; } + int z_order() const override { return m_z_order; } bool draws_view(plot::Series_view_kind view_kind) const override { From ccb6cb8c3f2da35c6dbded8df5c8cdfa0a07f796 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:58:36 +0200 Subject: [PATCH 16/80] style: align call argument tables --- src/core/font_renderer.cpp | 20 +++++----- src/core/primitive_renderer.cpp | 2 +- tests/test_asset_loader.cpp | 4 +- tests/test_core_algo.cpp | 14 +++---- tests/test_font_disk_cache.cpp | 2 +- tests/test_label_pane_geometry.cpp | 6 +-- tests/test_plot_interaction_item.cpp | 4 +- tests/test_qrhi_layer_lifecycle.cpp | 24 +++++------ tests/test_qrhi_public_api.cpp | 60 ++++++++++++++-------------- tests/test_typed_api.cpp | 4 +- 10 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index aa615ad6..3760e984 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -802,17 +802,17 @@ struct Text_block_std140 float background_color[4] = {}; }; -static_assert(offsetof(Text_block_std140, pmv) == 0, "Text UBO pmv offset"); -static_assert(offsetof(Text_block_std140, color) == 64, "Text UBO color offset"); -static_assert(offsetof(Text_block_std140, shadow_color) == 80, "Text UBO shadow color offset"); -static_assert(offsetof(Text_block_std140, px_range) == 96, "Text UBO px_range offset"); -static_assert(offsetof(Text_block_std140, target_width) == 100, "Text UBO target width offset"); -static_assert(offsetof(Text_block_std140, target_height) == 104, "Text UBO target height offset"); -static_assert(offsetof(Text_block_std140, shadow_radius) == 108, "Text UBO shadow radius offset"); +static_assert(offsetof(Text_block_std140, pmv) == 0, "Text UBO pmv offset"); +static_assert(offsetof(Text_block_std140, color) == 64, "Text UBO color offset"); +static_assert(offsetof(Text_block_std140, shadow_color) == 80, "Text UBO shadow color offset"); +static_assert(offsetof(Text_block_std140, px_range) == 96, "Text UBO px_range offset"); +static_assert(offsetof(Text_block_std140, target_width) == 100, "Text UBO target width offset"); +static_assert(offsetof(Text_block_std140, target_height) == 104, "Text UBO target height offset"); +static_assert(offsetof(Text_block_std140, shadow_radius) == 108, "Text UBO shadow radius offset"); static_assert(offsetof(Text_block_std140, lcd_subpixel_order) == 112, "Text UBO LCD order offset"); -static_assert(offsetof(Text_block_std140, framebuffer_y_up) == 116, "Text UBO framebuffer y-up offset"); -static_assert(offsetof(Text_block_std140, background_color) == 128, "Text UBO background color offset"); -static_assert(sizeof(Text_block_std140) == 144, "Text UBO std140 size"); +static_assert(offsetof(Text_block_std140, framebuffer_y_up) == 116, "Text UBO framebuffer y-up offset"); +static_assert(offsetof(Text_block_std140, background_color) == 128, "Text UBO background color offset"); +static_assert(sizeof(Text_block_std140) == 144, "Text UBO std140 size"); constexpr std::uint32_t k_text_ubo_bytes = sizeof(Text_block_std140); diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index c2dff605..7f787ed4 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -596,7 +596,7 @@ void Primitive_renderer::draw_grid_shader( block.grid_color[1] = color.g; block.grid_color[2] = color.b; block.grid_color[3] = color.a; - block.v_count = std::min(vertical_levels.count, grid_layer_params_t::k_max_levels); + block.v_count = std::min(vertical_levels.count, grid_layer_params_t::k_max_levels); block.t_count = std::min(horizontal_levels.count, grid_layer_params_t::k_max_levels); block.framebuffer_y_up = rhi->isYUpInFramebuffer() ? 1 : 0; block.win_h = static_cast(ctx.win_h); diff --git a/tests/test_asset_loader.cpp b/tests/test_asset_loader.cpp index 62e16526..271d975a 100644 --- a/tests/test_asset_loader.cpp +++ b/tests/test_asset_loader.cpp @@ -50,7 +50,7 @@ bool test_missing_asset_logs_and_returns_nullopt() auto result = loader.load("does/not/exist.vert"); TEST_ASSERT(!result.has_value(), "missing asset should return nullopt"); - TEST_ASSERT(!messages.empty(), "missing asset should surface a log message"); + TEST_ASSERT(!messages.empty(), "missing asset should surface a log message"); TEST_ASSERT(messages.front().find("does/not/exist.vert") != std::string::npos, "log message should reference the missing asset name"); return true; @@ -93,7 +93,7 @@ bool test_override_directory_falls_back_to_embedded_when_missing() loader.set_override_directory(tmp.path.string()); auto result = loader.load("example.vert"); - TEST_ASSERT(result.has_value(), "should fall back to embedded when override file is missing"); + TEST_ASSERT(result.has_value(), "should fall back to embedded when override file is missing"); TEST_ASSERT(*result == "embedded-only", "embedded fallback bytes should be returned"); return true; } diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index 379c1630..aed106e2 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -114,9 +114,9 @@ bool test_compute_lod_scales_forces_minimum_of_one() Zero_scale_source src; auto scales = plot::detail::compute_lod_scales(src); TEST_ASSERT(scales.size() == 3, "lod_levels should give 3 entries"); - TEST_ASSERT(scales[0] == 1, "zero scale at level 0 should be clamped to 1"); - TEST_ASSERT(scales[1] == 1, "unit scale at level 1 should survive"); - TEST_ASSERT(scales[2] == 1, "zero scale at level 2 should be clamped to 1"); + TEST_ASSERT(scales[0] == 1, "zero scale at level 0 should be clamped to 1"); + TEST_ASSERT(scales[1] == 1, "unit scale at level 1 should survive"); + TEST_ASSERT(scales[2] == 1, "zero scale at level 2 should be clamped to 1"); return true; } @@ -456,7 +456,7 @@ bool test_snapshot_truthiness_requires_usable_stride() snap.count = samples.size(); snap.stride = 0; - TEST_ASSERT(!snap.is_valid(), "stride-zero snapshot should be invalid"); + TEST_ASSERT(!snap.is_valid(), "stride-zero snapshot should be invalid"); TEST_ASSERT(!static_cast(snap), "stride-zero snapshot should be falsey"); plot::snapshot_result_t result{ @@ -483,7 +483,7 @@ bool test_snapshot_count1_clamps_malformed_count2() TEST_ASSERT(snap.count1() == 0, "malformed count2 > count should clamp count1 to zero"); - TEST_ASSERT(!snap.is_valid(), "count2 > count should be invalid"); + TEST_ASSERT(!snap.is_valid(), "count2 > count should be invalid"); TEST_ASSERT(!static_cast(snap), "count2 > count should be falsey"); TEST_ASSERT(snap.at(0) == nullptr, "count2 > count should make sample access fail explicitly"); @@ -657,10 +657,10 @@ bool test_horizontal_label_fade_keys_preserve_int64_timestamps() constexpr std::int64_t k_max = std::numeric_limits::max(); plot::Text_renderer::horizontal_axis_fade_tracker_t tracker; - tracker.states.emplace(k_min, plot::Text_renderer::label_fade_state_t{}); + tracker.states.emplace(k_min, plot::Text_renderer::label_fade_state_t{}); tracker.states.emplace(k_min + 1, plot::Text_renderer::label_fade_state_t{}); tracker.states.emplace(k_max - 1, plot::Text_renderer::label_fade_state_t{}); - tracker.states.emplace(k_max, plot::Text_renderer::label_fade_state_t{}); + tracker.states.emplace(k_max, plot::Text_renderer::label_fade_state_t{}); TEST_ASSERT(tracker.states.size() == 4, "horizontal fade tracker should distinguish adjacent extreme int64 timestamps"); diff --git a/tests/test_font_disk_cache.cpp b/tests/test_font_disk_cache.cpp index 9aa5cf14..fd16e4a1 100644 --- a/tests/test_font_disk_cache.cpp +++ b/tests/test_font_disk_cache.cpp @@ -164,7 +164,7 @@ bool write_cache_file( const std::uint8_t zero_available = 1u; const std::uint8_t padding[3]{0u, 0u, 0u}; out.write(reinterpret_cast(&zero_available), sizeof(zero_available)); - out.write(reinterpret_cast(padding), sizeof(padding)); + out.write(reinterpret_cast(padding), sizeof(padding)); write_value(out, options.glyph_count); if (options.glyph_count == 1u) { diff --git a/tests/test_label_pane_geometry.cpp b/tests/test_label_pane_geometry.cpp index 2b8caf08..7776f923 100644 --- a/tests/test_label_pane_geometry.cpp +++ b/tests/test_label_pane_geometry.cpp @@ -204,9 +204,9 @@ bool test_fractional_rects_round_inward_without_exceeding_framebuffer() plot::text_scissor_t scissor; TEST_ASSERT(plot::detail::framebuffer_scissor_from_top_left_rect(rect, width, height, scissor), "fractional rect with interior pixels must produce a scissor"); - TEST_ASSERT(scissor.x == 1, "fractional left edge must ceil inward"); - TEST_ASSERT(scissor.y == 20, "fractional bottom edge must floor before QRhi y conversion"); - TEST_ASSERT(scissor.width == 98, "fractional width must be rounded inward"); + TEST_ASSERT(scissor.x == 1, "fractional left edge must ceil inward"); + TEST_ASSERT(scissor.y == 20, "fractional bottom edge must floor before QRhi y conversion"); + TEST_ASSERT(scissor.width == 98, "fractional width must be rounded inward"); TEST_ASSERT(scissor.height == 39, "fractional height must be rounded inward"); TEST_ASSERT(scissor_inside_frame(scissor, width, height), "fractional scissor must stay inside the framebuffer"); diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index 50bc7934..90384a70 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -148,7 +148,7 @@ bool test_zoom_math_stays_composable_across_small_velocity_decay() 0.01, {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}); - TEST_ASSERT(nearly_equal(single_gap.scale, fine_steps.scale), "small-velocity scale should stay composable"); + TEST_ASSERT(nearly_equal(single_gap.scale, fine_steps.scale), "small-velocity scale should stay composable"); TEST_ASSERT(nearly_equal(single_gap.velocity, fine_steps.velocity), "small-velocity decay should stay composable"); return true; @@ -174,7 +174,7 @@ bool test_zoom_math_handles_zero_velocity() { const zoom_state_t state = advance_zoom(0.0, {0.3, 0.7, 1.5, 2.5, 5.0}); - TEST_ASSERT(nearly_equal(state.scale, 1.0), "zero velocity should keep identity scale"); + TEST_ASSERT(nearly_equal(state.scale, 1.0), "zero velocity should keep identity scale"); TEST_ASSERT(nearly_equal(state.velocity, 0.0), "zero velocity should stay zero"); return true; diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 02465c36..7553dfeb 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -663,23 +663,23 @@ bool test_layer_only_zero_style_prepare_record_order() rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), error_message); - TEST_ASSERT(low_create_count == 1, "low z-order layer state should be created once"); + TEST_ASSERT(low_create_count == 1, "low z-order layer state should be created once"); TEST_ASSERT(high_create_count == 1, "high z-order layer state should be created once"); - const std::size_t low_prepare = find_event_index(events, "low", "prepare"); - const std::size_t high_prepare = find_event_index(events, "high", "prepare"); + const std::size_t low_prepare = find_event_index(events, "low", "prepare"); + const std::size_t high_prepare = find_event_index(events, "high", "prepare"); const std::size_t begin_pass = find_event_index(events, "frame", "begin_pass"); - const std::size_t low_record = find_event_index(events, "low", "record"); - const std::size_t high_record = find_event_index(events, "high", "record"); + const std::size_t low_record = find_event_index(events, "low", "record"); + const std::size_t high_record = find_event_index(events, "high", "record"); - TEST_ASSERT(low_prepare < events.size(), "expected low layer prepare event"); + TEST_ASSERT(low_prepare < events.size(), "expected low layer prepare event"); TEST_ASSERT(high_prepare < events.size(), "expected high layer prepare event"); - TEST_ASSERT(begin_pass < events.size(), "expected beginPass event"); - TEST_ASSERT(low_record < events.size(), "expected low layer record event"); - TEST_ASSERT(high_record < events.size(), "expected high layer record event"); - TEST_ASSERT(low_prepare < high_prepare, "lower z-order layer must prepare first"); + TEST_ASSERT(begin_pass < events.size(), "expected beginPass event"); + TEST_ASSERT(low_record < events.size(), "expected low layer record event"); + TEST_ASSERT(high_record < events.size(), "expected high layer record event"); + TEST_ASSERT(low_prepare < high_prepare, "lower z-order layer must prepare first"); TEST_ASSERT(high_prepare < begin_pass, "prepare must finish before beginPass"); - TEST_ASSERT(begin_pass < low_record, "record must happen after beginPass"); - TEST_ASSERT(low_record < high_record, "lower z-order layer must record first"); + TEST_ASSERT(begin_pass < low_record, "record must happen after beginPass"); + TEST_ASSERT(low_record < high_record, "lower z-order layer must record first"); TEST_ASSERT(events[low_prepare].gpu_count > 0 && events[high_prepare].gpu_count > 0, "layer-only series with zero Display_style must not be skipped"); TEST_ASSERT(events[low_prepare].snapshot_valid && events[high_prepare].snapshot_valid, diff --git a/tests/test_qrhi_public_api.cpp b/tests/test_qrhi_public_api.cpp index d64ca63b..67672352 100644 --- a/tests/test_qrhi_public_api.cpp +++ b/tests/test_qrhi_public_api.cpp @@ -144,22 +144,22 @@ static_assert(std::is_same_v< decltype(std::declval().build_value()), plot::rhi_series_data_t>); -static_assert(static_cast(plot::Display_style::NONE) == 0x0); -static_assert(static_cast(plot::Display_style::DOTS) == 0x1); -static_assert(static_cast(plot::Display_style::LINE) == 0x2); -static_assert(static_cast(plot::Display_style::AREA) == 0x4); +static_assert(static_cast(plot::Display_style::NONE) == 0x0); +static_assert(static_cast(plot::Display_style::DOTS) == 0x1); +static_assert(static_cast(plot::Display_style::LINE) == 0x2); +static_assert(static_cast(plot::Display_style::AREA) == 0x4); static_assert(static_cast(plot::Display_style::DOTS_LINE_AREA) == 0x7); -static_assert(offsetof(plot::series_view_uniform_std140_t, pmv) == 0); -static_assert(offsetof(plot::series_view_uniform_std140_t, color) == 64); -static_assert(offsetof(plot::series_view_uniform_std140_t, t_min) == 80); -static_assert(offsetof(plot::series_view_uniform_std140_t, t_max) == 84); -static_assert(offsetof(plot::series_view_uniform_std140_t, v_min) == 88); -static_assert(offsetof(plot::series_view_uniform_std140_t, v_max) == 92); -static_assert(offsetof(plot::series_view_uniform_std140_t, width) == 96); -static_assert(offsetof(plot::series_view_uniform_std140_t, height) == 100); -static_assert(offsetof(plot::series_view_uniform_std140_t, y_offset) == 104); -static_assert(offsetof(plot::series_view_uniform_std140_t, win_h) == 108); +static_assert(offsetof(plot::series_view_uniform_std140_t, pmv) == 0); +static_assert(offsetof(plot::series_view_uniform_std140_t, color) == 64); +static_assert(offsetof(plot::series_view_uniform_std140_t, t_min) == 80); +static_assert(offsetof(plot::series_view_uniform_std140_t, t_max) == 84); +static_assert(offsetof(plot::series_view_uniform_std140_t, v_min) == 88); +static_assert(offsetof(plot::series_view_uniform_std140_t, v_max) == 92); +static_assert(offsetof(plot::series_view_uniform_std140_t, width) == 96); +static_assert(offsetof(plot::series_view_uniform_std140_t, height) == 100); +static_assert(offsetof(plot::series_view_uniform_std140_t, y_offset) == 104); +static_assert(offsetof(plot::series_view_uniform_std140_t, win_h) == 108); static_assert(offsetof(plot::series_view_uniform_std140_t, framebuffer_y_up) == 112); static_assert(sizeof(plot::series_view_uniform_std140_t) == 128); @@ -252,7 +252,7 @@ bool test_series_builder_qrhi_layers_append_replace_clear() "Rhi_series_builder series_label mismatch"); TEST_ASSERT(series.nonfinite_policy == plot::Nonfinite_sample_policy::SKIP, "Rhi_series_builder nonfinite_policy mismatch"); - TEST_ASSERT(series.qrhi_layers.size() == 2, "qrhi_layer() must append"); + TEST_ASSERT(series.qrhi_layers.size() == 2, "qrhi_layer() must append"); TEST_ASSERT(series.qrhi_layers[0] == layer_a, "first appended layer pointer mismatch"); TEST_ASSERT(series.qrhi_layers[1] == layer_b, "second appended layer pointer mismatch"); @@ -260,7 +260,7 @@ bool test_series_builder_qrhi_layers_append_replace_clear() .qrhi_layers({layer_c}) .build_value(); - TEST_ASSERT(series.qrhi_layers.size() == 1, "qrhi_layers() must replace existing layers"); + TEST_ASSERT(series.qrhi_layers.size() == 1, "qrhi_layers() must replace existing layers"); TEST_ASSERT(series.qrhi_layers[0] == layer_c, "replacement layer pointer mismatch"); series = builder @@ -308,8 +308,8 @@ bool test_qrhi_layer_api_surface_can_be_implemented() const Test_layer layer("api-layer", 23, -5); TEST_ASSERT(layer.id() == "api-layer", "layer id accessor mismatch"); - TEST_ASSERT(layer.revision() == 23, "layer revision accessor mismatch"); - TEST_ASSERT(layer.z_order() == -5, "layer z_order accessor mismatch"); + TEST_ASSERT(layer.revision() == 23, "layer revision accessor mismatch"); + TEST_ASSERT(layer.z_order() == -5, "layer z_order accessor mismatch"); TEST_ASSERT(layer.draws_view(plot::Series_view_kind::MAIN), "test layer should draw the main view"); TEST_ASSERT(!layer.draws_view(plot::Series_view_kind::PREVIEW), @@ -323,7 +323,7 @@ bool test_qrhi_layer_api_surface_can_be_implemented() TEST_ASSERT(prepare_context.updates == nullptr, "prepare context update batch default mismatch"); TEST_ASSERT(prepare_context.asset_loader == nullptr, "prepare context asset loader default mismatch"); - TEST_ASSERT(prepare_context.frame == nullptr, "prepare context frame default mismatch"); + TEST_ASSERT(prepare_context.frame == nullptr, "prepare context frame default mismatch"); TEST_ASSERT(prepare_context.series == nullptr, "prepare context series default mismatch"); TEST_ASSERT(prepare_context.view_uniform == nullptr, "prepare context view uniform default mismatch"); @@ -340,8 +340,8 @@ bool test_qrhi_layer_api_surface_can_be_implemented() TEST_ASSERT(record_context.cb == nullptr, "record context command buffer default mismatch"); TEST_ASSERT(record_context.render_target == nullptr, "record context render target default mismatch"); - TEST_ASSERT(record_context.frame == nullptr, "record context frame default mismatch"); - TEST_ASSERT(record_context.series == nullptr, "record context series default mismatch"); + TEST_ASSERT(record_context.frame == nullptr, "record context frame default mismatch"); + TEST_ASSERT(record_context.series == nullptr, "record context series default mismatch"); TEST_ASSERT(record_context.view_ubo == nullptr, "record context UBO default mismatch"); return true; @@ -446,8 +446,8 @@ bool test_make_series_view_uniform_values() const plot::series_view_uniform_std140_t uniform = plot::make_series_view_uniform(frame, series, window); - TEST_ASSERT(nearly_equal(uniform.pmv[0], 1.0f), "uniform pmv[0] mismatch"); - TEST_ASSERT(nearly_equal(uniform.pmv[5], 6.0f), "uniform pmv[5] mismatch"); + TEST_ASSERT(nearly_equal(uniform.pmv[0], 1.0f), "uniform pmv[0] mismatch"); + TEST_ASSERT(nearly_equal(uniform.pmv[5], 6.0f), "uniform pmv[5] mismatch"); TEST_ASSERT(nearly_equal(uniform.pmv[15], 16.0f), "uniform pmv[15] mismatch"); TEST_ASSERT(nearly_equal(uniform.color[0], 0.2f), "uniform color red mismatch"); @@ -456,14 +456,14 @@ bool test_make_series_view_uniform_values() TEST_ASSERT(nearly_equal(uniform.color[3], 0.4f), "uniform color alpha must include window alpha"); - TEST_ASSERT(nearly_equal(uniform.t_min, 1.5f), "uniform t_min relative seconds mismatch"); - TEST_ASSERT(nearly_equal(uniform.t_max, 4.0f), "uniform t_max relative seconds mismatch"); - TEST_ASSERT(nearly_equal(uniform.v_min, -3.0f), "uniform v_min mismatch"); - TEST_ASSERT(nearly_equal(uniform.v_max, 9.0f), "uniform v_max mismatch"); - TEST_ASSERT(nearly_equal(uniform.width, 640.0f), "uniform width mismatch"); - TEST_ASSERT(nearly_equal(uniform.height, 120.0f), "uniform height mismatch"); + TEST_ASSERT(nearly_equal(uniform.t_min, 1.5f), "uniform t_min relative seconds mismatch"); + TEST_ASSERT(nearly_equal(uniform.t_max, 4.0f), "uniform t_max relative seconds mismatch"); + TEST_ASSERT(nearly_equal(uniform.v_min, -3.0f), "uniform v_min mismatch"); + TEST_ASSERT(nearly_equal(uniform.v_max, 9.0f), "uniform v_max mismatch"); + TEST_ASSERT(nearly_equal(uniform.width, 640.0f), "uniform width mismatch"); + TEST_ASSERT(nearly_equal(uniform.height, 120.0f), "uniform height mismatch"); TEST_ASSERT(nearly_equal(uniform.y_offset, 24.0f), "uniform y_offset mismatch"); - TEST_ASSERT(nearly_equal(uniform.win_h, 300.0f), "uniform win_h mismatch"); + TEST_ASSERT(nearly_equal(uniform.win_h, 300.0f), "uniform win_h mismatch"); TEST_ASSERT(uniform.framebuffer_y_up == 0, "null frame.rhi must produce framebuffer_y_up == 0"); diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 0e0b1c3d..485f4e22 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -186,7 +186,7 @@ bool test_make_access_policy_and_erase() s.v_max = 6.0f; TEST_ASSERT(policy.get_timestamp(s) == k_test_ts_ns, "timestamp accessor mismatch"); - TEST_ASSERT(policy.get_value(s) == 3.5f, "value accessor mismatch"); + TEST_ASSERT(policy.get_value(s) == 3.5f, "value accessor mismatch"); const auto range = policy.get_range(s); TEST_ASSERT(range.first == 1.0f && range.second == 6.0f, "range accessor mismatch"); @@ -197,7 +197,7 @@ bool test_make_access_policy_and_erase() TEST_ASSERT(erased.layout_key == policy.layout_key, "erase() should propagate layout_key"); TEST_ASSERT(erased.get_timestamp(&s) == k_test_ts_ns, "erased timestamp accessor mismatch"); - TEST_ASSERT(erased.get_value(&s) == 3.5f, "erased value accessor mismatch"); + TEST_ASSERT(erased.get_value(&s) == 3.5f, "erased value accessor mismatch"); const auto erased_range = erased.get_range(&s); TEST_ASSERT(erased_range.first == 1.0f && erased_range.second == 6.0f, "erased range accessor mismatch"); From 2ac6723300d5884740551f9bff50682ed0ae0d54 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 14:59:29 +0200 Subject: [PATCH 17/80] style: wrap long calls --- src/core/chrome_renderer.cpp | 3 +- src/core/font_renderer.cpp | 9 +++-- src/core/layout_calculator.cpp | 3 +- src/core/series_renderer.cpp | 18 +++++----- src/core/series_window_planner.cpp | 52 +++++++++++++--------------- tests/test_plot_interaction_item.cpp | 9 +++-- tests/test_qrhi_layer_lifecycle.cpp | 5 ++- tests/test_snapshot_caching.cpp | 7 ++-- tests/test_typed_api.cpp | 14 ++++---- 9 files changed, 57 insertions(+), 63 deletions(-) diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index d839832f..13e63467 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -341,7 +341,8 @@ void Chrome_renderer::render_preview_overlay( else { const double xx = 0.5 * (k_preview_min_window_px - dd); prims.batch_rect(cover_color, {float(0 - xx), float(ptop + pband_h), float(x0 - xx), float(pbtm - pband_h)}); - prims.batch_rect(cover_color, {float(x1 + xx), float(ptop + pband_h), float(win_w + xx), float(pbtm - pband_h)}); + prims.batch_rect( + cover_color, {float(x1 + xx), float(ptop + pband_h), float(win_w + xx), float(pbtm - pband_h)}); prims.batch_rect(cover_color2, {float(x0 - xx), float(ptop + pband_h), float(x0), float(pbtm - pband_h)}); prims.batch_rect(cover_color2, {float(x1), float(ptop + pband_h), float(x1 + xx), float(pbtm - pband_h)}); } diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 3760e984..fe0730df 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -1014,11 +1014,10 @@ bool Font_renderer::text_visual_bounds_px( return false; } - const vnm::msdf_text::text_bounds_t measured = - vnm::msdf_text::measure_text_bounds_px( - *atlas, - m_impl->current_draw_pixel_height(), - text); + const vnm::msdf_text::text_bounds_t measured = vnm::msdf_text::measure_text_bounds_px( + *atlas, + m_impl->current_draw_pixel_height(), + text); if (!measured.has_visible_glyphs) { return false; } diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 9040a2db..8fcaeaeb 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -825,7 +825,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par params.horizontal_seed_index < static_cast(steps.size())) { const double seeded_step = steps[params.horizontal_seed_index]; - const double ref = std::max(1e-6, std::max(std::abs(seeded_step), std::abs(params.horizontal_seed_step))); + const double ref = std::max(1e-6, std::max(std::abs(seeded_step), + std::abs(params.horizontal_seed_step))); if (std::abs(seeded_step - params.horizontal_seed_step) <= ref * 1e-6) { si = params.horizontal_seed_index; } diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index fa4ca017..17cae7fe 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -1276,10 +1276,9 @@ void Series_renderer::prepare( plan.access ? detail::make_erased_access_policy_view(*plan.access) : detail::erased_access_policy_t{}; - const detail::access_policy_cache_key_t layer_access_key = - detail::make_access_policy_cache_key( - plan.access, - layer_access_view); + const detail::access_policy_cache_key_t layer_access_key = detail::make_access_policy_cache_key( + plan.access, + layer_access_view); rhi_state_t::qrhi_layer_program_key_t program_key; program_key.series_id = draw_state.id; @@ -1721,12 +1720,11 @@ bool Series_renderer::rhi_prepare_series_view_samples( const auto stage_one_sample = [&](gpu_sample_t& dst, const void* src, std::int64_t ts_ns) { detail::sample_draw_value_t draw_value; - const detail::sample_draw_status_t status = - detail::read_sample_draw_value( - access_view, - src, - window.nonfinite_policy, - draw_value); + const detail::sample_draw_status_t status = detail::read_sample_draw_value( + access_view, + src, + window.nonfinite_policy, + draw_value); if (status != detail::sample_draw_status_t::DRAWABLE) { return false; } diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index 18f82c93..cec04911 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -662,13 +662,12 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) VNM_PLOT_PROFILE_SCOPE( request.profiler, "process_view.linear_fallback"); - const visible_sample_window_t window = - select_visible_sample_window( - snapshot, - get_timestamp, - request.t_min_ns, - request.t_max_ns, - false); + const visible_sample_window_t window = select_visible_sample_window( + snapshot, + get_timestamp, + request.t_min_ns, + request.t_max_ns, + false); first_idx = window.first; last_idx = window.last_exclusive; } @@ -678,13 +677,12 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) VNM_PLOT_PROFILE_SCOPE( request.profiler, "process_view.binary_search"); - const visible_sample_window_t window = - select_visible_sample_window( - snapshot, - get_timestamp, - request.t_min_ns, - request.t_max_ns, - true); + const visible_sample_window_t window = select_visible_sample_window( + snapshot, + get_timestamp, + request.t_min_ns, + request.t_max_ns, + true); first_idx = window.first; last_idx = window.last_exclusive; } @@ -760,12 +758,11 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) const std::int64_t ts_ns = get_timestamp(sample); if (ts_ns >= request.t_min_ns && ts_ns <= request.t_max_ns) { sample_draw_value_t ignored; - const sample_draw_status_t status = - read_sample_draw_value( - access_view, - sample, - request.nonfinite_policy, - ignored); + const sample_draw_status_t status = read_sample_draw_value( + access_view, + sample, + request.nonfinite_policy, + ignored); if (status == sample_draw_status_t::FAILED) { failed_sample_in_requested_window = true; break; @@ -813,14 +810,13 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) } } - drawable_window_result_t drawable_window = - build_drawable_window( - snapshot, - access_view, - request.nonfinite_policy, - first_idx, - last_idx, - hold_last_forward); + drawable_window_result_t drawable_window = build_drawable_window( + snapshot, + access_view, + request.nonfinite_policy, + first_idx, + last_idx, + hold_last_forward); if (drawable_window.valid && drawable_window.gpu_count == 0 && hold_last_forward && diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index 90384a70..9b2f00ad 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -136,7 +136,8 @@ bool test_zoom_math_is_invariant_to_timer_cadence() TEST_ASSERT(nearly_equal(single_gap.scale, split_gap.scale), "scale should match for split elapsed time"); TEST_ASSERT(nearly_equal(single_gap.velocity, split_gap.velocity), "velocity should match for split elapsed time"); TEST_ASSERT(nearly_equal(single_gap.scale, fine_steps.scale), "scale should match for fine-grained elapsed time"); - TEST_ASSERT(nearly_equal(single_gap.velocity, fine_steps.velocity), "velocity should match for fine-grained elapsed time"); + TEST_ASSERT( + nearly_equal(single_gap.velocity, fine_steps.velocity), "velocity should match for fine-grained elapsed time"); return true; } @@ -163,8 +164,10 @@ bool test_zoom_math_handles_negative_velocity() {0.3, 0.7, 1.5, 2.5, 5.0}); TEST_ASSERT(nearly_equal(single_gap.scale, split_gap.scale), "negative scale should match for split elapsed time"); - TEST_ASSERT(nearly_equal(single_gap.velocity, split_gap.velocity), "negative velocity should match for split elapsed time"); - TEST_ASSERT(nearly_equal(single_gap.scale, fractional_steps.scale), "negative scale should match for fractional steps"); + TEST_ASSERT( + nearly_equal(single_gap.velocity, split_gap.velocity), "negative velocity should match for split elapsed time"); + TEST_ASSERT( + nearly_equal(single_gap.scale, fractional_steps.scale), "negative scale should match for fractional steps"); TEST_ASSERT(nearly_equal(single_gap.velocity, fractional_steps.velocity), "negative velocity should match for fractional steps"); return true; diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 7553dfeb..10f0e72d 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -2703,9 +2703,8 @@ bool test_resources_changed_tracks_data_and_window_changes() "unchanged data and window must not report resources_changed"); access_call_counts_t changed_access_calls; - series->access = - make_fallback_access_policy_with_counted_public_accessors( - changed_access_calls); + series->access = make_fallback_access_policy_with_counted_public_accessors( + changed_access_calls); events.clear(); TEST_ASSERT( rhi_fixture.render_layer_frame(renderer, ctx, series_map, events, error_message), diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index d927e761..555cd42e 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -1731,10 +1731,9 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() const std::int64_t expected_main_span = plot::detail::positive_span_ns_for_signed_api(ctx.t0, ctx.t1); - const std::int64_t expected_preview_span = - plot::detail::positive_span_ns_for_signed_api( - ctx.t_available_min, - ctx.t_available_max); + const std::int64_t expected_preview_span = plot::detail::positive_span_ns_for_signed_api( + ctx.t_available_min, + ctx.t_available_max); const std::int64_t expected_main_origin = plot::detail::choose_origin_ns(ctx.t0, expected_main_span); const std::int64_t expected_preview_origin = diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 485f4e22..9168cfba 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -465,19 +465,17 @@ bool test_erased_access_view_uses_direct_member_accessors() plot::Data_access_policy revision_policy = erased; const auto revision_view_before = plot::detail::make_erased_access_policy_view(revision_policy); - const auto revision_key_before = - plot::detail::make_access_policy_cache_key( - &revision_policy, - revision_view_before); + const auto revision_key_before = plot::detail::make_access_policy_cache_key( + &revision_policy, + revision_view_before); revision_policy.get_value = [](const void*) { return 11.0f; }; const auto revision_view_after = plot::detail::make_erased_access_policy_view(revision_policy); - const auto revision_key_after = - plot::detail::make_access_policy_cache_key( - &revision_policy, - revision_view_after); + const auto revision_key_after = plot::detail::make_access_policy_cache_key( + &revision_policy, + revision_view_after); TEST_ASSERT(revision_key_before != revision_key_after, "access policy cache key should change after accessor mutation"); From b5d9213441acb8d99771c1f1203dd433fe42bb98 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:00:58 +0200 Subject: [PATCH 18/80] style: wrap long conditions --- include/vnm_plot/core/algo.h | 4 +- include/vnm_plot/core/time_units.h | 16 +-- include/vnm_plot/core/types.h | 30 ++--- src/core/auto_range_resolver.cpp | 16 +-- src/core/font_renderer.cpp | 64 +++++----- src/core/label_pane_geometry.h | 10 +- src/core/layout_calculator.cpp | 22 ++-- src/core/platform_paths.cpp | 3 +- src/core/primitive_renderer.cpp | 27 ++--- src/core/rhi_helpers.h | 5 +- src/core/series_renderer.cpp | 175 +++++++++------------------- src/core/series_window_planner.cpp | 118 ++++++++----------- src/core/text_renderer.cpp | 13 +-- src/core/time_grid.cpp | 2 +- src/core/types.cpp | 23 +--- src/qt/plot_interaction_item.cpp | 9 +- src/qt/plot_time_axis.cpp | 12 +- src/qt/plot_widget.cpp | 4 +- src/qt/t_axis_adjust.h | 12 +- src/qt/text_lcd_resolver.cpp | 2 +- tests/test_concurrent_series.cpp | 22 ++-- tests/test_qrhi_layer_lifecycle.cpp | 56 ++------- 22 files changed, 242 insertions(+), 403 deletions(-) diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 4d4f90ea..5b936cc2 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -571,13 +571,13 @@ visible_sample_aggregate_t aggregate_visible_sample_range( } const std::int64_t ts_ns = get_timestamp(sample); if (interpolation == Series_interpolation::STEP_AFTER && - ts_ns < window_tmin_ns) + ts_ns < window_tmin_ns) { held_sample = sample; continue; } if (interpolation == Series_interpolation::STEP_AFTER && - ts_ns >= window_tmin_ns) + ts_ns >= window_tmin_ns) { have_sample_at_or_after_window_start = true; } diff --git a/include/vnm_plot/core/time_units.h b/include/vnm_plot/core/time_units.h index 6731c74e..88e59f9f 100644 --- a/include/vnm_plot/core/time_units.h +++ b/include/vnm_plot/core/time_units.h @@ -29,13 +29,13 @@ inline std::optional checked_add_ns( std::int64_t value_ns, std::int64_t delta_ns) noexcept { - if (delta_ns > 0 - && value_ns > std::numeric_limits::max() - delta_ns) + if (delta_ns > 0 && + value_ns > std::numeric_limits::max() - delta_ns) { return std::nullopt; } - if (delta_ns < 0 - && value_ns < std::numeric_limits::min() - delta_ns) + if (delta_ns < 0 && + value_ns < std::numeric_limits::min() - delta_ns) { return std::nullopt; } @@ -46,13 +46,13 @@ inline std::optional checked_sub_ns( std::int64_t value_ns, std::int64_t delta_ns) noexcept { - if (delta_ns > 0 - && value_ns < std::numeric_limits::min() + delta_ns) + if (delta_ns > 0 && + value_ns < std::numeric_limits::min() + delta_ns) { return std::nullopt; } - if (delta_ns < 0 - && value_ns > std::numeric_limits::max() + delta_ns) + if (delta_ns < 0 && + value_ns > std::numeric_limits::max() + delta_ns) { return std::nullopt; } diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 60cc2ab3..426450a3 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -113,12 +113,12 @@ struct access_policy_cache_key_t const access_policy_cache_key_t& other) const noexcept { return identity == other.identity && - layout_key == other.layout_key && - revision == other.revision && + layout_key == other.layout_key && + revision == other.revision && dispatch_kind == other.dispatch_kind && has_timestamp == other.has_timestamp && - has_value == other.has_value && - has_range == other.has_range; + has_value == other.has_value && + has_range == other.has_range; } [[nodiscard]] bool operator!=( @@ -1175,18 +1175,18 @@ struct layout_cache_key_t [[nodiscard]] bool operator==(const layout_cache_key_t& other) const noexcept { return v0 == other.v0 && - v1 == other.v1 && - t0 == other.t0 && - t1 == other.t1 && - viewport_size == other.viewport_size && - adjusted_reserved_height == other.adjusted_reserved_height && - adjusted_preview_height == other.adjusted_preview_height && + v1 == other.v1 && + t0 == other.t0 && + t1 == other.t1 && + viewport_size == other.viewport_size && + adjusted_reserved_height == other.adjusted_reserved_height && + adjusted_preview_height == other.adjusted_preview_height && adjusted_font_size_in_pixels == other.adjusted_font_size_in_pixels && - vbar_width_pixels == other.vbar_width_pixels && - font_metrics_key == other.font_metrics_key && - config_revision == other.config_revision && - format_timestamp_revision == other.format_timestamp_revision && - format_value_revision == other.format_value_revision; + vbar_width_pixels == other.vbar_width_pixels && + font_metrics_key == other.font_metrics_key && + config_revision == other.config_revision && + format_timestamp_revision == other.format_timestamp_revision && + format_value_revision == other.format_value_revision; } }; diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index b4ffd2b6..e2520561 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -508,13 +508,7 @@ std::pair resolve_main_v_range( float v_min = std::numeric_limits::max(); float v_max = std::numeric_limits::lowest(); if (!resolve_series_collection_range( - series, - data_cfg, - config, - false, - cache, - v_min, - v_max)) + series, data_cfg, config, false, cache, v_min, v_max)) { return fallback_range(data_cfg); } @@ -532,13 +526,7 @@ std::pair resolve_preview_v_range( float v_min = std::numeric_limits::max(); float v_max = std::numeric_limits::lowest(); if (!resolve_series_collection_range( - series, - data_cfg, - config, - true, - cache, - v_min, - v_max)) + series, data_cfg, config, true, cache, v_min, v_max)) { return fallback_range(data_cfg); } diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index fe0730df..76d5a4f4 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -254,7 +254,7 @@ bool validate_cached_glyph(const msdf_glyph_t& g) uv_in_range(g.uv_left) && uv_in_range(g.uv_bottom) && uv_in_range(g.uv_right) && - uv_in_range(g.uv_top) && + uv_in_range(g.uv_top) && g.uv_right >= g.uv_left && g.uv_bottom >= g.uv_top; } @@ -345,17 +345,14 @@ void add_text_to_vectors( std::size_t new_vertex_count = 0; quint32 checked_qrhi_value = 0; if (!detail::checked_size_product( - vertices.size(), k_text_vertex_float_count, added_float_count) || - !detail::checked_size_add(vertex_data.size(), added_float_count, new_float_count) || - !detail::checked_size_add(index_data.size(), indices.size(), new_index_count) || + vertices.size(), k_text_vertex_float_count, added_float_count) || + !detail::checked_size_add(vertex_data.size(), added_float_count, new_float_count) || + !detail::checked_size_add(index_data.size(), indices.size(), new_index_count) || !detail::checked_size_add( - vertex_data.size() / k_text_vertex_float_count, - vertices.size(), - new_vertex_count) || - !detail::to_qrhi_count(new_vertex_count, checked_qrhi_value) || - !detail::qrhi_byte_size(new_float_count, sizeof(float), checked_qrhi_value) || - !detail::qrhi_byte_size( - new_index_count, sizeof(std::uint32_t), checked_qrhi_value)) + vertex_data.size() / k_text_vertex_float_count, vertices.size(), new_vertex_count) || + !detail::to_qrhi_count(new_vertex_count, checked_qrhi_value) || + !detail::qrhi_byte_size(new_float_count, sizeof(float), checked_qrhi_value) || + !detail::qrhi_byte_size( new_index_count, sizeof(std::uint32_t), checked_qrhi_value)) { return; } @@ -1156,7 +1153,7 @@ void Font_renderer::rhi_queue_draw( const std::size_t vertex_start_float_count = m_impl->m_rhi_frame_vertex_data.size(); - if (vertex_start_float_count % k_text_vertex_float_count != 0u || + if (vertex_start_float_count % k_text_vertex_float_count != 0u || m_impl->m_rhi_vertex_data.size() % k_text_vertex_float_count != 0u) { m_impl->m_rhi_vertex_data.clear(); @@ -1167,10 +1164,9 @@ void Font_renderer::rhi_queue_draw( quint32 index_start = 0; quint32 base_vertex = 0; quint32 index_count = 0; - if (!detail::to_qrhi_count( - m_impl->m_rhi_frame_index_data.size(), index_start) || + if (!detail::to_qrhi_count( m_impl->m_rhi_frame_index_data.size(), index_start) || !detail::to_qrhi_count( - vertex_start_float_count / k_text_vertex_float_count, base_vertex) || + vertex_start_float_count / k_text_vertex_float_count, base_vertex) || !detail::to_qrhi_count(m_impl->m_rhi_index_data.size(), index_count)) { m_impl->m_rhi_vertex_data.clear(); @@ -1184,21 +1180,16 @@ void Font_renderer::rhi_queue_draw( quint32 checked_qrhi_bytes = 0; if (!detail::checked_size_add( m_impl->m_rhi_frame_vertex_data.size(), - m_impl->m_rhi_vertex_data.size(), - new_vertex_float_count) || + m_impl->m_rhi_vertex_data.size(), new_vertex_float_count) || !detail::checked_size_add( m_impl->m_rhi_frame_index_data.size(), - m_impl->m_rhi_index_data.size(), - new_index_count) || + m_impl->m_rhi_index_data.size(), new_index_count) || !detail::checked_size_add( vertex_start_float_count / k_text_vertex_float_count, - m_impl->m_rhi_vertex_data.size() / k_text_vertex_float_count, - queued_vertex_count) || - !detail::to_qrhi_count(queued_vertex_count, checked_qrhi_bytes) || - !detail::qrhi_byte_size( - new_vertex_float_count, sizeof(float), checked_qrhi_bytes) || - !detail::qrhi_byte_size( - new_index_count, sizeof(std::uint32_t), checked_qrhi_bytes)) + m_impl->m_rhi_vertex_data.size() / k_text_vertex_float_count, queued_vertex_count) || + !detail::to_qrhi_count(queued_vertex_count, checked_qrhi_bytes) || + !detail::qrhi_byte_size( new_vertex_float_count, sizeof(float), checked_qrhi_bytes) || + !detail::qrhi_byte_size( new_index_count, sizeof(std::uint32_t), checked_qrhi_bytes)) { m_impl->m_rhi_vertex_data.clear(); m_impl->m_rhi_index_data.clear(); @@ -1232,7 +1223,7 @@ void Font_renderer::rhi_queue_draw( const auto& cached = *m_impl->m_font_cache; if (!rhi_state.atlas_texture || - rhi_state.atlas_size != cached.atlas.atlas_size || + rhi_state.atlas_size != cached.atlas.atlas_size || rhi_state.uploaded_cache_epoch != cached.cache_epoch) { rhi_state.atlas_texture.reset(rhi->newTexture( @@ -1294,7 +1285,7 @@ void Font_renderer::rhi_queue_draw( } if (!call.srb || - call.srb_last_ubo != call.ubo.get() || + call.srb_last_ubo != call.ubo.get() || call.srb_last_texture != rhi_state.atlas_texture.get() || call.srb_last_sampler != rhi_state.sampler.get()) { @@ -1493,9 +1484,8 @@ void Font_renderer::rhi_queue_draw( void Font_renderer::rhi_finalize_frame(const frame_context_t& ctx) { auto& rhi_state = m_impl->m_rhi; - if (!ctx.rhi || !ctx.rhi_updates || - m_impl->m_rhi_frame_vertex_data.empty() || - m_impl->m_rhi_frame_index_data.empty()) + if (!ctx.rhi || !ctx.rhi_updates || + m_impl->m_rhi_frame_vertex_data.empty() || m_impl->m_rhi_frame_index_data.empty()) { return; } @@ -1508,11 +1498,11 @@ void Font_renderer::rhi_finalize_frame(const frame_context_t& ctx) quint32 qrhi_vertex_bytes = 0; quint32 qrhi_index_bytes = 0; if (!detail::qrhi_byte_size( - m_impl->m_rhi_frame_vertex_data.size(), sizeof(float), - vertex_bytes, qrhi_vertex_bytes) || + m_impl->m_rhi_frame_vertex_data.size(), + sizeof(float), vertex_bytes, qrhi_vertex_bytes) || !detail::qrhi_byte_size( - m_impl->m_rhi_frame_index_data.size(), sizeof(std::uint32_t), - index_bytes, qrhi_index_bytes)) + m_impl->m_rhi_frame_index_data.size(), + sizeof(std::uint32_t), index_bytes, qrhi_index_bytes)) { rhi_reset_frame(); return; @@ -1582,8 +1572,8 @@ void Font_renderer::rhi_record_frame(const frame_context_t& ctx) QRhiCommandBuffer::VertexInput vertex_input{rhi_state.vbo.get(), 0u}; const auto record_pass = [&](rhi_text_pass_t pass) { for (const auto& op : rhi_state.ops) { - if (op.pass != pass || - op.call_index >= rhi_state.calls.size() || + if (op.pass != pass || + op.call_index >= rhi_state.calls.size() || op.index_count == 0) { continue; diff --git a/src/core/label_pane_geometry.h b/src/core/label_pane_geometry.h index c151ec47..7cfbbb4e 100644 --- a/src/core/label_pane_geometry.h +++ b/src/core/label_pane_geometry.h @@ -139,11 +139,11 @@ namespace vnm::plot::detail { scissor.height = bottom - top; const bool contained = - scissor.x >= 0 && - scissor.y >= 0 && - scissor.width > 0 && - scissor.height > 0 && - scissor.x + scissor.width <= window_width && + scissor.x >= 0 && + scissor.y >= 0 && + scissor.width > 0 && + scissor.height > 0 && + scissor.x + scissor.width <= window_width && scissor.y + scissor.height <= window_height; if (!contained) { scissor = {}; diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 8fcaeaeb..8160b00f 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -191,12 +191,12 @@ class Timestamp_label_cache friend bool operator==(const Context_key& lhs, const Context_key& rhs) noexcept { return lhs.step_bits == rhs.step_bits && - lhs.range_bits == rhs.range_bits && - lhs.monospace_bits == rhs.monospace_bits && + lhs.range_bits == rhs.range_bits && + lhs.monospace_bits == rhs.monospace_bits && lhs.monospace_reliable == rhs.monospace_reliable && - lhs.measure_key == rhs.measure_key && - lhs.font_size_bits == rhs.font_size_bits && - lhs.format_signature == rhs.format_signature; + lhs.measure_key == rhs.measure_key && + lhs.font_size_bits == rhs.font_size_bits && + lhs.format_signature == rhs.format_signature; } }; @@ -298,10 +298,10 @@ class Format_signature_cache friend bool operator==(const Key& lhs, const Key& rhs) noexcept { return lhs.step_bits == rhs.step_bits && - lhs.coverage_bucket == rhs.coverage_bucket && - lhs.formatter_identity == rhs.formatter_identity && + lhs.coverage_bucket == rhs.coverage_bucket && + lhs.formatter_identity == rhs.formatter_identity && lhs.formatter_type_hash == rhs.formatter_type_hash && - lhs.formatter_revision == rhs.formatter_revision; + lhs.formatter_revision == rhs.formatter_revision; } }; @@ -447,12 +447,12 @@ bool Layout_calculator::fits_with_gap( while (j < accepted.size() && accepted[j].second + min_gap <= iv.first) { ++j; } - if (j < accepted.size() && + if (j < accepted.size() && std::max(iv.first, accepted[j].first) - std::min(iv.second, accepted[j].second) < min_gap) { return false; } - if (j > 0 && + if (j > 0 && std::max(iv.first, accepted[j - 1].first) - std::min(iv.second, accepted[j - 1].second) < min_gap) { return false; @@ -822,7 +822,7 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.setup"); if (params.has_horizontal_seed && params.horizontal_seed_index >= 0 && - params.horizontal_seed_index < static_cast(steps.size())) + params.horizontal_seed_index < static_cast(steps.size())) { const double seeded_step = steps[params.horizontal_seed_index]; const double ref = std::max(1e-6, std::max(std::abs(seeded_step), diff --git a/src/core/platform_paths.cpp b/src/core/platform_paths.cpp index 0ad37e52..5d053096 100644 --- a/src/core/platform_paths.cpp +++ b/src/core/platform_paths.cpp @@ -20,7 +20,8 @@ std::filesystem::path get_known_folder(int folder_id) wchar_t* path = nullptr; if (SUCCEEDED(SHGetKnownFolderPath( folder_id == CSIDL_LOCAL_APPDATA ? FOLDERID_LocalAppData : FOLDERID_RoamingAppData, - 0, nullptr, &path))) { + 0, nullptr, &path))) + { std::filesystem::path result(path); CoTaskMemFree(path); return result; diff --git a/src/core/primitive_renderer.cpp b/src/core/primitive_renderer.cpp index 7f787ed4..2fbc65ef 100644 --- a/src/core/primitive_renderer.cpp +++ b/src/core/primitive_renderer.cpp @@ -234,9 +234,7 @@ bool Primitive_renderer::rhi_ensure_rect_pipeline( QRhiRenderPassDescriptor* rpd = rt->renderPassDescriptor(); const int samples = rt->sampleCount(); - if (rhi_state.rect_pipeline - && (rhi_state.rect_pipeline_rpd != rpd - || rhi_state.rect_pipeline_samples != samples)) + if (rhi_state.rect_pipeline && (rhi_state.rect_pipeline_rpd != rpd || rhi_state.rect_pipeline_samples != samples)) { rhi_state.rect_pipeline.reset(); } @@ -281,9 +279,7 @@ bool Primitive_renderer::rhi_ensure_grid_pipeline( QRhiRenderPassDescriptor* rpd = rt->renderPassDescriptor(); const int samples = rt->sampleCount(); - if (rhi_state.grid_pipeline - && (rhi_state.grid_pipeline_rpd != rpd - || rhi_state.grid_pipeline_samples != samples)) + if (rhi_state.grid_pipeline && (rhi_state.grid_pipeline_rpd != rpd || rhi_state.grid_pipeline_samples != samples)) { rhi_state.grid_pipeline.reset(); } @@ -408,8 +404,7 @@ void Primitive_renderer::flush_rects(const frame_context_t& ctx, const glm::mat4 quint32 upload_bytes = 0; quint32 instance_count = 0; if (!detail::qrhi_byte_size( - m_cpu_buffer.size(), sizeof(rect_vertex_t), - bytes_needed, upload_bytes) || + m_cpu_buffer.size(), sizeof(rect_vertex_t), bytes_needed, upload_bytes) || !detail::to_qrhi_count(m_cpu_buffer.size(), instance_count)) { m_cpu_buffer.clear(); @@ -462,9 +457,7 @@ void Primitive_renderer::flush_rects(const frame_context_t& ctx, const glm::mat4 } if (!call.srb || call.srb_last_ubo != call.ubo.get()) { if (!detail::rebuild_single_ubo_srb( - rhi, call.srb, call.ubo.get(), - k_rect_ubo_bytes, - QRhiShaderResourceBinding::VertexStage)) + rhi, call.srb, call.ubo.get(), k_rect_ubo_bytes, QRhiShaderResourceBinding::VertexStage)) { m_cpu_buffer.clear(); m_rhi_state->rect_used--; @@ -546,10 +539,10 @@ void Primitive_renderer::draw_grid_shader( int y = 0; int w = 0; int h = 0; - if (!to_int_rounded(origin.x, x) || - !to_int_rounded(origin.y, y) || - !to_positive_int(size.x, w) || - !to_positive_int(size.y, h)) + if (!to_int_rounded(origin.x, x) || + !to_int_rounded(origin.y, y) || + !to_positive_int(size.x, w) || + !to_positive_int(size.y, h)) { return; } @@ -576,9 +569,7 @@ void Primitive_renderer::draw_grid_shader( } if (!call.srb || call.srb_last_ubo != call.ubo.get()) { if (!detail::rebuild_single_ubo_srb( - rhi, call.srb, call.ubo.get(), - k_grid_ubo_bytes, - QRhiShaderResourceBinding::FragmentStage)) + rhi, call.srb, call.ubo.get(), k_grid_ubo_bytes, QRhiShaderResourceBinding::FragmentStage)) { m_rhi_state->grid_used--; return; diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index bf6f2f0e..2da0d74d 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -46,7 +46,7 @@ inline bool to_positive_int(double value, int& out) const double rounded = std::round(value); if (rounded <= 0.0 || - rounded > static_cast(std::numeric_limits::max())) + rounded > static_cast(std::numeric_limits::max())) { return false; } @@ -243,8 +243,7 @@ inline std::unique_ptr build_alpha_blended_pipeline( std::unique_ptr layout_srb; if (!rebuild_single_ubo_srb( - rhi, layout_srb, layout_ubo.get(), - desc.ubo_bytes, desc.ubo_stages)) + rhi, layout_srb, layout_ubo.get(), desc.ubo_bytes, desc.ubo_stages)) { return nullptr; } diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index 17cae7fe..6f8ac2e4 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -900,7 +900,7 @@ void Series_renderer::prepare( main_plan.y_offset_px = 0.0f; main_plan.window_alpha = 1.0f; if (ctx.config && ctx.config->log_debug && - main_plan.gpu_count > 0 && + main_plan.gpu_count > 0 && main_plan.lod_level != prev_lod_level) { std::string message = "LOD selection: series=" + std::to_string(id) @@ -1229,24 +1229,15 @@ void Series_renderer::prepare( for (const auto& planned_draw : planned_draws) { if (planned_draw.is_builtin) { if (!samples_ready || - !is_builtin_primitive_drawable( - planned_draw.primitive_style, - window)) + !is_builtin_primitive_drawable( planned_draw.primitive_style, window)) { continue; } std::vector prepared_segment_spans; if (rhi_prepare_series_primitive( - ctx, - draw_state.series.get(), - planned_draw.primitive_style, - view_state, - window, - line_width_px, - point_diameter_px, - area_fill_alpha, - &prepared_segment_spans)) + ctx, draw_state.series.get(), planned_draw.primitive_style, view_state, window, + line_width_px, point_diameter_px, area_fill_alpha, &prepared_segment_spans)) { rhi_state_t::prepared_draw_command_t command; command.kind = @@ -1292,13 +1283,13 @@ void Series_renderer::prepare( if (!window.snapshot) { for (auto& [cached_key, cache_entry] : m_rhi_state->qrhi_layer_cache) { - if (cached_key.series_id == program_key.series_id && - cached_key.view_kind == program_key.view_kind && - cached_key.layer_id == program_key.layer_id && + if (cached_key.series_id == program_key.series_id && + cached_key.view_kind == program_key.view_kind && + cached_key.layer_id == program_key.layer_id && cached_key.layer_revision == program_key.layer_revision && - cached_key.layout_key == program_key.layout_key && - cached_key.access_key == program_key.access_key && - cached_key.rhi == program_key.rhi) + cached_key.layout_key == program_key.layout_key && + cached_key.access_key == program_key.access_key && + cached_key.rhi == program_key.rhi) { cache_entry.last_frame_used = m_frame_id; } @@ -1455,8 +1446,8 @@ void Series_renderer::prepare( } if (!source || !access || key.data_identity != source->identity() || - key.layout_key != access->layout_key || - key.rhi != rhi) + key.layout_key != access->layout_key || + key.rhi != rhi) { return false; } @@ -1474,14 +1465,14 @@ void Series_renderer::prepare( qrhi_layers.end(), [&](const auto& layer) { return layer && - layer->draws_view(key.view_kind) && - layer->id() == key.layer_id && + layer->draws_view(key.view_kind) && + layer->id() == key.layer_id && layer->revision() == key.layer_revision; }); }; for (auto it = m_rhi_state->qrhi_layer_cache.begin(); - it != m_rhi_state->qrhi_layer_cache.end(); ) + it != m_rhi_state->qrhi_layer_cache.end();) { if (it->second.last_frame_used == m_frame_id || qrhi_layer_still_configured(it->first)) @@ -1497,7 +1488,7 @@ void Series_renderer::prepare( m_last_qrhi_layer_cache_size = m_rhi_state->qrhi_layer_cache.size(); for (auto it = m_rhi_state->view_ubos.begin(); - it != m_rhi_state->view_ubos.end(); ) + it != m_rhi_state->view_ubos.end();) { if (it->second.last_frame_used == m_frame_id) { ++it; @@ -1641,10 +1632,10 @@ bool Series_renderer::rhi_prepare_series_view_samples( return false; } - if (window.synthetic_hold_count > 1 || - window.drawable_spans.empty() || - window.source_first > snapshot.count || - window.source_count > snapshot.count - window.source_first) + if (window.synthetic_hold_count > 1 || + window.drawable_spans.empty() || + window.source_first > snapshot.count || + window.source_count > snapshot.count - window.source_first) { invalidate_uploaded_vbo(); return false; @@ -1660,22 +1651,18 @@ bool Series_renderer::rhi_prepare_series_view_samples( window.drawable_spans[span_index]; const bool final_span = span_index + 1u == window.drawable_spans.size(); - if (span.source_count == 0 || - span.gpu_count < span.source_count || - span.gpu_first != expected_gpu_count || - span.source_first < window.source_first || - span.source_first > snapshot.count || - span.source_count > snapshot.count - span.source_first || - span.source_first + span.source_count > - window.source_first + window.source_count) + if (span.source_count == 0 || span.gpu_count < span.source_count || + span.gpu_first != expected_gpu_count || span.source_first < window.source_first || + span.source_first > snapshot.count || span.source_count > snapshot.count - span.source_first || + span.source_first + span.source_count > window.source_first + window.source_count) { invalidate_uploaded_vbo(); return false; } const bool has_synthetic_hold = - final_span && - window.synthetic_hold_count == 1 && + final_span && + window.synthetic_hold_count == 1 && span.gpu_count == span.source_count + 1u; if (has_synthetic_hold) { synthetic_hold_seen = true; @@ -1687,15 +1674,13 @@ bool Series_renderer::rhi_prepare_series_view_samples( } if (!detail::checked_size_add( - expected_gpu_count, - span.gpu_count, - expected_gpu_count)) + expected_gpu_count, span.gpu_count, expected_gpu_count)) { invalidate_uploaded_vbo(); return false; } } - if (expected_gpu_count != window.gpu_count || + if (expected_gpu_count != window.gpu_count || synthetic_hold_seen != (window.synthetic_hold_count == 1)) { invalidate_uploaded_vbo(); @@ -1707,8 +1692,7 @@ bool Series_renderer::rhi_prepare_series_view_samples( quint32 upload_bytes = 0; if (!detail::checked_size_add(window.gpu_count, 0u, needed_elements) || !detail::qrhi_byte_size( - needed_elements, sizeof(gpu_sample_t), - needed_bytes, upload_bytes)) + needed_elements, sizeof(gpu_sample_t), needed_bytes, upload_bytes)) { invalidate_uploaded_vbo(); return false; @@ -1741,9 +1725,7 @@ bool Series_renderer::rhi_prepare_series_view_samples( const void* src = snapshot.at(source_index); if (!src || !stage_one_sample( - staging[span.gpu_first + i], - src, - access_view.timestamp(src))) + staging[span.gpu_first + i], src, access_view.timestamp(src))) { invalidate_uploaded_vbo(); return false; @@ -1756,8 +1738,7 @@ bool Series_renderer::rhi_prepare_series_view_samples( if (!source_sample || !stage_one_sample( staging[span.gpu_first + span.gpu_count - 1u], - source_sample, - window.hold_timestamp_ns)) + source_sample, window.hold_timestamp_ns)) { invalidate_uploaded_vbo(); return false; @@ -1922,25 +1903,16 @@ bool Series_renderer::rhi_prepare_series_primitive( for (const builtin_segment_span_t& span : segment_spans) { std::size_t span_window_count = 0; if (!line_window_sample_count( - span.gpu_count, - window.interpolation, - span_window_count)) + span.gpu_count, window.interpolation, span_window_count)) { return false; } std::size_t span_padded_count = 0; - if (!detail::checked_size_add( - span_window_count, - 2u, - span_padded_count) || + if (!detail::checked_size_add( span_window_count, 2u, span_padded_count) || !detail::checked_size_add( - total_window_count, - span_window_count, - total_window_count) || + total_window_count, span_window_count, total_window_count) || !detail::checked_size_add( - total_padded_count, - span_padded_count, - total_padded_count)) + total_padded_count, span_padded_count, total_padded_count)) { return false; } @@ -1952,8 +1924,7 @@ bool Series_renderer::rhi_prepare_series_primitive( std::size_t needed_bytes = 0; quint32 upload_bytes = 0; if (!detail::qrhi_byte_size( - total_padded_count, sizeof(gpu_sample_t), - needed_bytes, upload_bytes)) + total_padded_count, sizeof(gpu_sample_t), needed_bytes, upload_bytes)) { return false; } @@ -1964,14 +1935,13 @@ bool Series_renderer::rhi_prepare_series_primitive( { return false; } - if (!view_state.rhi->line_window_vbo - || view_state.rhi_line_window_vbo_capacity_bytes < needed_bytes) + if (!view_state.rhi->line_window_vbo || + view_state.rhi_line_window_vbo_capacity_bytes < needed_bytes) { view_state.rhi->line_window_vbo.reset(rhi->newBuffer( QRhiBuffer::Static, QRhiBuffer::VertexBuffer, qrhi_alloc_bytes)); - if (view_state.rhi->line_window_vbo - && view_state.rhi->line_window_vbo->create()) + if (view_state.rhi->line_window_vbo && view_state.rhi->line_window_vbo->create()) { view_state.rhi_line_window_vbo_capacity_bytes = alloc_bytes; } @@ -1998,17 +1968,12 @@ bool Series_renderer::rhi_prepare_series_primitive( std::size_t span_window_count = 0; if (!line_window_sample_count( - span.gpu_count, - window.interpolation, - span_window_count)) + span.gpu_count, window.interpolation, span_window_count)) { return false; } std::size_t span_padded_count = 0; - if (!detail::checked_size_add( - span_window_count, - 2u, - span_padded_count) || + if (!detail::checked_size_add( span_window_count, 2u, span_padded_count) || span_padded_count > total_padded_count - write_idx) { return false; @@ -2080,9 +2045,7 @@ bool Series_renderer::rhi_prepare_series_primitive( // or sample count moves. QRhiRenderPassDescriptor* current_rpd = rt->renderPassDescriptor(); const int current_samples = rt->sampleCount(); - if (cached.pipeline - && (cached.last_rpd != current_rpd - || cached.last_sample_count != current_samples)) + if (cached.pipeline && (cached.last_rpd != current_rpd || cached.last_sample_count != current_samples)) { cached.pipeline.reset(); } @@ -2188,8 +2151,8 @@ bool Series_renderer::rhi_prepare_series_primitive( if (!detail::rebuild_single_ubo_srb( rhi, entry.srb, current_ubo, k_series_ubo_bytes, - QRhiShaderResourceBinding::VertexStage - | QRhiShaderResourceBinding::FragmentStage)) { + QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage)) + { // A failed create() leaves a non-null but unusable SRB; clear it so // the null guard in rhi_record_series_primitive skips this draw and // a later frame retries the rebuild instead of binding a bad object. @@ -2352,15 +2315,10 @@ void Series_renderer::rhi_record_series_primitive( quint32 instance_count = 0; quint32 first_offset = 0; quint32 next_offset = 0; - if (!detail::to_qrhi_count(span.gpu_count - 1u, instance_count) || - !detail::qrhi_buffer_offset( - span.gpu_first, - sizeof(gpu_sample_t), - first_offset) || + if (!detail::to_qrhi_count(span.gpu_count - 1u, instance_count) || + !detail::qrhi_buffer_offset( span.gpu_first, sizeof(gpu_sample_t), first_offset) || !detail::qrhi_buffer_offset( - span.gpu_first + 1u, - sizeof(gpu_sample_t), - next_offset)) + span.gpu_first + 1u, sizeof(gpu_sample_t), next_offset)) { return; } @@ -2398,37 +2356,14 @@ void Series_renderer::rhi_record_series_primitive( quint32 qrhi_offset2 = 0; quint32 qrhi_offset3 = 0; quint32 instance_count = 0; - if (!detail::checked_size_add( - line_span.line_first, - 1u, - offset1) || - !detail::checked_size_add( - line_span.line_first, - 2u, - offset2) || - !detail::checked_size_add( - line_span.line_first, - 3u, - offset3) || - !detail::qrhi_buffer_offset( - offset0, - sizeof(gpu_sample_t), - qrhi_offset0) || - !detail::qrhi_buffer_offset( - offset1, - sizeof(gpu_sample_t), - qrhi_offset1) || - !detail::qrhi_buffer_offset( - offset2, - sizeof(gpu_sample_t), - qrhi_offset2) || - !detail::qrhi_buffer_offset( - offset3, - sizeof(gpu_sample_t), - qrhi_offset3) || - !detail::to_qrhi_count( - line_span.line_count - 1u, - instance_count)) + if (!detail::checked_size_add( line_span.line_first, 1u, offset1) || + !detail::checked_size_add( line_span.line_first, 2u, offset2) || + !detail::checked_size_add( line_span.line_first, 3u, offset3) || + !detail::qrhi_buffer_offset( offset0, sizeof(gpu_sample_t), qrhi_offset0) || + !detail::qrhi_buffer_offset( offset1, sizeof(gpu_sample_t), qrhi_offset1) || + !detail::qrhi_buffer_offset( offset2, sizeof(gpu_sample_t), qrhi_offset2) || + !detail::qrhi_buffer_offset( offset3, sizeof(gpu_sample_t), qrhi_offset3) || + !detail::to_qrhi_count( line_span.line_count - 1u, instance_count)) { return; } diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index cec04911..15f24205 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -248,8 +248,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) VNM_PLOT_PROFILE_SCOPE(request.profiler, "process_view.try_snapshot"); snapshot_result_t snapshot_result; if (snapshot_cache.cached_snapshot_frame_id == request.frame_id && - snapshot_cache.cached_snapshot_level == level && - snapshot_cache.cached_snapshot_source == &data_source && + snapshot_cache.cached_snapshot_level == level && + snapshot_cache.cached_snapshot_source == &data_source && snapshot_cache.cached_snapshot) { snapshot_result.snapshot = snapshot_cache.cached_snapshot; @@ -329,19 +329,19 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) // reusing it under a moved origin would draw at the wrong x positions // because set_common_uniforms feeds the new view_origin_ns regardless. const bool identity_ok = - (state.cached_data_identity != nullptr) && - (state.cached_data_identity == current_identity) && - request.has_uploaded_vbo && - (state.last_count > 0) && - state.has_last_lod_level && - (state.last_lod_level == level) && - (state.last_access_key == access_key) && - (state.last_t_min == request.t_min_ns) && - (state.last_t_max == request.t_max_ns) && - (state.last_width_px == request.width_px) && + (state.cached_data_identity != nullptr) && + (state.cached_data_identity == current_identity) && + request.has_uploaded_vbo && + (state.last_count > 0) && + state.has_last_lod_level && + (state.last_lod_level == level) && + (state.last_access_key == access_key) && + (state.last_t_min == request.t_min_ns) && + (state.last_t_max == request.t_max_ns) && + (state.last_width_px == request.width_px) && (state.last_empty_window_behavior == request.empty_window_behavior) && - (state.last_nonfinite_policy == request.nonfinite_policy) && - (state.last_interpolation == request.interpolation) && + (state.last_nonfinite_policy == request.nonfinite_policy) && + (state.last_interpolation == request.interpolation) && (state.uploaded_t_origin_ns == request.t_origin_ns); if (!identity_ok) { return false; @@ -363,20 +363,20 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) bool hold_last_forward = false; const std::uint64_t current_seq = data_source.current_sequence(applied_level); - if (current_seq != 0 && - current_seq == state.last_sequence && - applied_level == state.last_lod_level && - request.has_uploaded_vbo && - state.last_count > 0 && - state.cached_data_identity == data_source.identity() && - state.last_access_key == access_key && - state.last_t_min == request.t_min_ns && - state.last_t_max == request.t_max_ns && - state.last_width_px == request.width_px && + if (current_seq != 0 && + current_seq == state.last_sequence && + applied_level == state.last_lod_level && + request.has_uploaded_vbo && + state.last_count > 0 && + state.cached_data_identity == data_source.identity() && + state.last_access_key == access_key && + state.last_t_min == request.t_min_ns && + state.last_t_max == request.t_max_ns && + state.last_width_px == request.width_px && state.last_empty_window_behavior == request.empty_window_behavior && - state.last_nonfinite_policy == request.nonfinite_policy && - state.last_interpolation == request.interpolation && - state.uploaded_t_origin_ns == request.t_origin_ns) + state.last_nonfinite_policy == request.nonfinite_policy && + state.last_interpolation == request.interpolation && + state.uploaded_t_origin_ns == request.t_origin_ns) { if (request.snapshot_requirement == Snapshot_requirement::Frame_snapshot_required) @@ -447,7 +447,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) direct_time_window_empty = true; } else - if (first < snapshot.count && + if (first < snapshot.count && checked_size_add(first, count, last_exclusive) && last_exclusive <= snapshot.count) { @@ -488,16 +488,14 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) else { const std::int64_t first_ts_ns = get_timestamp(first_sample); - if (first_ts_ns >= request.t_min_ns && - direct_first_idx > 0) + if (first_ts_ns >= request.t_min_ns && + direct_first_idx > 0) { --direct_first_idx; } std::size_t padded_last = direct_last_idx; if (checked_size_add( - direct_last_idx, - 2u, - padded_last)) + direct_last_idx, 2u, padded_last)) { direct_last_idx = std::min(padded_last, snapshot.count); @@ -589,10 +587,10 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) } else { const bool need_monotonicity_scan = - state.last_timestamp_order_sequence != snapshot.sequence || - state.last_timestamp_order_identity != current_identity || - state.last_timestamp_order_access_key != access_key || - state.last_timestamp_source_order != source_order; + state.last_timestamp_order_sequence != snapshot.sequence || + state.last_timestamp_order_identity != current_identity || + state.last_timestamp_order_access_key != access_key || + state.last_timestamp_source_order != source_order; if (need_monotonicity_scan) { bool is_monotonic = true; state.last_timestamp_order_scan_performed = true; @@ -701,12 +699,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) std::size_t hold_source_index = 0; bool hold_failed = false; if (select_hold_source_index( - snapshot, - access_view, - request.nonfinite_policy, - snapshot.count - 1u, - hold_source_index, - hold_failed)) + snapshot, access_view, request.nonfinite_policy, + snapshot.count - 1u, hold_source_index, hold_failed)) { first_idx = hold_source_index; last_idx = hold_source_index + 1u; @@ -739,13 +733,13 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) hold_last_forward = true; } - if (request.interpolation == Series_interpolation::STEP_AFTER && + if (request.interpolation == Series_interpolation::STEP_AFTER && request.empty_window_behavior == - Empty_window_behavior::HOLD_LAST_FORWARD && - request.nonfinite_policy == Nonfinite_sample_policy::SKIP && - !have_direct_time_window && - timestamps_monotonic && - first_idx < last_idx) + Empty_window_behavior::HOLD_LAST_FORWARD && + request.nonfinite_policy == Nonfinite_sample_policy::SKIP && + !have_direct_time_window && + timestamps_monotonic && + first_idx < last_idx) { bool has_drawable_sample_in_requested_window = false; bool failed_sample_in_requested_window = false; @@ -783,12 +777,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) std::size_t hold_source_index = 0; bool hold_failed = false; if (select_hold_source_index( - snapshot, - access_view, - request.nonfinite_policy, - first_idx, - hold_source_index, - hold_failed)) + snapshot, access_view, request.nonfinite_policy, first_idx, hold_source_index, hold_failed)) { if (has_drawable_sample_in_requested_window) { first_idx = std::min(first_idx, hold_source_index); @@ -819,19 +808,14 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) hold_last_forward); if (drawable_window.valid && drawable_window.gpu_count == 0 && - hold_last_forward && - request.nonfinite_policy == Nonfinite_sample_policy::SKIP && - last_idx > 0) + hold_last_forward && + request.nonfinite_policy == Nonfinite_sample_policy::SKIP && + last_idx > 0) { std::size_t hold_source_index = 0; bool hold_failed = false; if (select_hold_source_index( - snapshot, - access_view, - request.nonfinite_policy, - last_idx - 1u, - hold_source_index, - hold_failed)) + snapshot, access_view, request.nonfinite_policy, last_idx - 1u, hold_source_index, hold_failed)) { first_idx = hold_source_index; last_idx = hold_source_index + 1u; @@ -855,9 +839,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) const std::size_t source_count = last_idx - first_idx; std::size_t count_for_lod = 0; if (!checked_size_add( - source_count, - hold_last_forward ? 1u : 0u, - count_for_lod)) + source_count, hold_last_forward ? 1u : 0u, count_for_lod)) { break; } @@ -879,7 +861,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) } const bool lod_switched = - state.has_last_lod_level && + state.has_last_lod_level && state.cached_data_identity == data_source.identity() && state.last_lod_level != applied_level; diff --git a/src/core/text_renderer.cpp b/src/core/text_renderer.cpp index 86ea2c0d..c9fad55b 100644 --- a/src/core/text_renderer.cpp +++ b/src/core/text_renderer.cpp @@ -334,8 +334,8 @@ bool Text_renderer::render_axis_labels( m_fonts->batch_text(snapped_x, snapped_y, state.text.c_str()); if (ctx.rhi) { const bool label_lcd_eligible = - label_lcd_possible && - label_scissor.enabled && + label_lcd_possible && + label_scissor.enabled && state.alpha >= detail::k_text_lcd_opaque_alpha_cutoff && text_fits_label_backing; const text_lcd_t label_lcd = @@ -438,8 +438,8 @@ bool Text_renderer::render_info_overlay( m_fonts->batch_text(pen_x, pen_y, state.text.c_str()); if (ctx.rhi) { const bool label_lcd_eligible = - label_lcd_possible && - label_scissor.enabled && + label_lcd_possible && + label_scissor.enabled && state.alpha >= detail::k_text_lcd_opaque_alpha_cutoff && text_fits_label_backing; const text_lcd_t label_lcd = @@ -533,9 +533,8 @@ bool Text_renderer::render_info_overlay( const bool timestamp_formatter_changed = timestamp_revision != m_last_timestamp_revision; - if (timestamp_style_changed || timestamp_values_changed - || timestamp_formatter_changed || m_cached_from_ts.empty() - || m_cached_to_ts.empty()) + if (timestamp_style_changed || timestamp_values_changed || timestamp_formatter_changed || + m_cached_from_ts.empty() || m_cached_to_ts.empty()) { const auto format_ts = (ctx.config && ctx.config->format_timestamp) ? ctx.config->format_timestamp diff --git a/src/core/time_grid.cpp b/src/core/time_grid.cpp index 3e8fe4aa..fc3329ed 100644 --- a/src/core/time_grid.cpp +++ b/src/core/time_grid.cpp @@ -72,7 +72,7 @@ grid_layer_params_t build_time_grid_layers( const double px_per_unit = width_px / range; const auto steps = detail::build_time_steps_covering(range); int idx = std::max(0, detail::find_time_step_start_index(steps, range)); - while (idx + 1 < static_cast(steps.size()) && + while (idx + 1 < static_cast(steps.size()) && steps[idx] * px_per_unit < cell_span_min) { ++idx; diff --git a/src/core/types.cpp b/src/core/types.cpp index 81b904ea..b24c9ce4 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -625,12 +625,9 @@ validated_time_window_t validated_time_window( const bool has_match = candidates.match_first < candidates.match_last_exclusive; - if (has_match && !validate_match_range( - snapshot, - access, - query, - candidates.match_first, - candidates.match_last_exclusive)) + if (has_match && + !validate_match_range( + snapshot, access, query, candidates.match_first, candidates.match_last_exclusive)) { out.valid = false; return out; @@ -739,7 +736,7 @@ sample_draw_status_t read_sample_draw_value( if (access.has_range()) { std::tie(low, high) = access.range(sample); } - if (!normalize_draw_component(low, policy) || + if (!normalize_draw_component(low, policy) || !normalize_draw_component(high, policy)) { return status_for_nonfinite(policy); @@ -875,11 +872,7 @@ data_query_result_t Data_source::query_v_range( const Time_order order = time_order(lod); if (order == Time_order::UNKNOWN || order == Time_order::UNORDERED) { if (!scan_value_range( - snapshot_result.snapshot, - *query.access, - query, - range, - has_value)) + snapshot_result.snapshot, *query.access, query, range, has_value)) { result.status = Data_query_status::FAILED; return result; @@ -927,11 +920,7 @@ data_query_result_t Data_source::query_v_range( } if (!include_sample_range( - range, - has_value, - *query.access, - sample, - query.nonfinite_policy)) + range, has_value, *query.access, sample, query.nonfinite_policy)) { result.status = Data_query_status::FAILED; return result; diff --git a/src/qt/plot_interaction_item.cpp b/src/qt/plot_interaction_item.cpp index 8e45d636..094fccba 100644 --- a/src/qt/plot_interaction_item.cpp +++ b/src/qt/plot_interaction_item.cpp @@ -367,13 +367,8 @@ void Plot_interaction_item::wheelEvent(QWheelEvent* event) const QPoint angle_delta = event->angleDelta(); const QPoint pixel_delta = event->pixelDelta(); if (!handle_wheel( - event->position().x(), - event->position().y(), - angle_delta.x(), - angle_delta.y(), - pixel_delta.x(), - pixel_delta.y(), - event->modifiers().toInt())) + event->position().x(), event->position().y(), angle_delta.x(), + angle_delta.y(), pixel_delta.x(), pixel_delta.y(), event->modifiers().toInt())) { event->ignore(); return; diff --git a/src/qt/plot_time_axis.cpp b/src/qt/plot_time_axis.cpp index 72700856..5fef54ed 100644 --- a/src/qt/plot_time_axis.cpp +++ b/src/qt/plot_time_axis.cpp @@ -560,12 +560,12 @@ bool Plot_time_axis::apply_time_axis_limits_if_changed( bool t_available_max_initialized) { const bool changed = - m_t_min != t_min_ns || - m_t_max != t_max_ns || - m_t_available_min != t_available_min_ns || - m_t_available_max != t_available_max_ns || - m_t_min_initialized != t_min_initialized || - m_t_max_initialized != t_max_initialized || + m_t_min != t_min_ns || + m_t_max != t_max_ns || + m_t_available_min != t_available_min_ns || + m_t_available_max != t_available_max_ns || + m_t_min_initialized != t_min_initialized || + m_t_max_initialized != t_max_initialized || m_t_available_min_initialized != t_available_min_initialized || m_t_available_max_initialized != t_available_max_initialized; diff --git a/src/qt/plot_widget.cpp b/src/qt/plot_widget.cpp index 61500eb8..55b0cc4d 100644 --- a/src/qt/plot_widget.cpp +++ b/src/qt/plot_widget.cpp @@ -560,8 +560,8 @@ void Plot_widget::set_time_axis(Plot_time_axis* axis) if (!m_time_axis->any_view_bound_initialized() && cfg.t_max > cfg.t_min) { m_time_axis->set_t_range(cfg.t_min, cfg.t_max); } - if (!m_time_axis->any_available_bound_initialized() - && cfg.t_available_max > cfg.t_available_min) + if (!m_time_axis->any_available_bound_initialized() && + cfg.t_available_max > cfg.t_available_min) { m_time_axis->set_available_t_range( cfg.t_available_min, cfg.t_available_max); diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index c5ea8c57..00bba96f 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -560,12 +560,12 @@ class Time_axis_model bool t_available_max_initialized) { const bool changed = - m_t_min != t_min_ns || - m_t_max != t_max_ns || - m_t_available_min != t_available_min_ns || - m_t_available_max != t_available_max_ns || - m_t_min_initialized != t_min_initialized || - m_t_max_initialized != t_max_initialized || + m_t_min != t_min_ns || + m_t_max != t_max_ns || + m_t_available_min != t_available_min_ns || + m_t_available_max != t_available_max_ns || + m_t_min_initialized != t_min_initialized || + m_t_max_initialized != t_max_initialized || m_t_available_min_initialized != t_available_min_initialized || m_t_available_max_initialized != t_available_max_initialized; diff --git a/src/qt/text_lcd_resolver.cpp b/src/qt/text_lcd_resolver.cpp index dd939ca0..e54b4b8d 100644 --- a/src/qt/text_lcd_resolver.cpp +++ b/src/qt/text_lcd_resolver.cpp @@ -50,7 +50,7 @@ text_lcd_resolved_subpixel_order_t text_lcd_subpixel_order_from_windows() k_win_spi_get_font_smoothing, 0U, &font_smoothing_enabled, - 0U) == 0 || + 0U) == 0 || font_smoothing_enabled == 0) { return text_lcd_resolved_subpixel_order_t::NONE; diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index 42d6e415..73f556af 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -212,9 +212,10 @@ bool test_vector_source_snapshots_are_consistent_under_concurrent_set_data() const float generation = first->v; for (std::size_t i = 0; i < result.snapshot.count; ++i) { const auto* current = sample_at(result.snapshot, i); - if (!current - || current->t != static_cast(i) - || current->v != generation) { + if (!current || + current->t != static_cast(i) || + current->v != generation) + { reader_errors.fetch_add(1, std::memory_order_relaxed); break; } @@ -230,7 +231,8 @@ bool test_vector_source_snapshots_are_consistent_under_concurrent_set_data() && !observed_max_sequence.compare_exchange_weak( observed, result.snapshot.sequence, - std::memory_order_relaxed)) { + std::memory_order_relaxed)) + { } }; @@ -304,9 +306,10 @@ bool test_vector_source_snapshots_progress_while_set_data_is_active() const float generation = first->v; for (std::size_t i = 0; i < result.snapshot.count; ++i) { const auto* current = blocking_sample_at(result.snapshot, i); - if (!current - || current->t != static_cast(i) - || current->v != generation) { + if (!current || + current->t != static_cast(i) || + current->v != generation) + { reader_errors.fetch_add(1, std::memory_order_relaxed); break; } @@ -336,7 +339,7 @@ bool test_vector_source_snapshots_progress_while_set_data_is_active() const auto read_deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(2000); while (active_reads.load(std::memory_order_acquire) < required_active_reads && - std::chrono::steady_clock::now() < read_deadline) + std::chrono::steady_clock::now() < read_deadline) { std::this_thread::yield(); } @@ -430,7 +433,8 @@ bool test_ring_source_snapshots_are_consistent_under_concurrent_writes() std::uint64_t current = observed_max_sequence.load(std::memory_order_relaxed); while (snap.sequence > current && !observed_max_sequence.compare_exchange_weak(current, snap.sequence, - std::memory_order_relaxed)) { + std::memory_order_relaxed)) + { } } }; diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 10f0e72d..90199a18 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -694,11 +694,7 @@ bool test_layer_only_zero_style_prepare_record_order() TEST_ASSERT(view_state.last_primitive_prepare_count == 0, "custom-only drawable layers must not prepare built-in primitives"); if (!assert_compact_upload_state( - renderer, - 7, - events[low_prepare], - 0, - "custom-only low layer")) + renderer, 7, events[low_prepare], 0, "custom-only low layer")) { return false; } @@ -870,11 +866,7 @@ bool test_builtin_upload_stages_visible_window_only() "linear visible upload should stage one GPU sample per source sample"); if (!assert_compact_upload_state( - renderer, - series_id, - *prepare, - prepare->gpu_count, - "linear line")) + renderer, series_id, *prepare, prepare->gpu_count, "linear line")) { return false; } @@ -1364,10 +1356,8 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() "gap window should compact only drawable samples"); TEST_ASSERT(prepare->drawable_spans.size() == 2, "gap window should split drawable samples into two spans"); - if (!assert_drawable_span( - prepare->drawable_spans, 0, 0, 2, 0, 2, test_case.layer_id) || - !assert_drawable_span( - prepare->drawable_spans, 1, 3, 2, 2, 2, test_case.layer_id)) + if (!assert_drawable_span(prepare->drawable_spans, 0, 0, 2, 0, 2, test_case.layer_id) || + !assert_drawable_span(prepare->drawable_spans, 1, 3, 2, 2, 2, test_case.layer_id)) { return false; } @@ -1403,11 +1393,7 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() "LINE padded windows should be built per drawable span"); if (!assert_compact_upload_state( - renderer, - test_case.series_id, - *prepare, - 4, - test_case.layer_id)) + renderer, test_case.series_id, *prepare, 4, test_case.layer_id)) { return false; } @@ -1972,13 +1958,7 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() TEST_ASSERT(prepare->drawable_spans.size() == 1, "drawable held sample should have one drawable span"); if (!assert_drawable_span( - prepare->drawable_spans, - 0, - test_case.expected_source_first, - 1, - 0, - 2, - test_case.layer_id)) + prepare->drawable_spans, 0, test_case.expected_source_first, 1, 0, 2, test_case.layer_id)) { return false; } @@ -2058,10 +2038,8 @@ bool test_nonfinite_skip_hold_forward_preserves_earlier_held_sample_with_visible "SKIP held window should stage held, visible, and synthetic hold samples"); TEST_ASSERT(prepare->drawable_spans.size() == 2, "SKIP held window should keep the skipped sample as a drawable gap"); - if (!assert_drawable_span( - prepare->drawable_spans, 0, 0, 1, 0, 1, "hold-skip-visible") || - !assert_drawable_span( - prepare->drawable_spans, 1, 2, 1, 1, 2, "hold-skip-visible")) + if (!assert_drawable_span(prepare->drawable_spans, 0, 0, 1, 0, 1, "hold-skip-visible") || + !assert_drawable_span(prepare->drawable_spans, 1, 2, 1, 1, 2, "hold-skip-visible")) { return false; } @@ -2495,11 +2473,7 @@ bool test_builtin_upload_stages_visible_windows_for_dots_and_area() "visible dots/area upload should stage one GPU sample per source sample"); if (!assert_compact_upload_state( - renderer, - test_case.series_id, - *prepare, - 0, - test_case.layer_id)) + renderer, test_case.series_id, *prepare, 0, test_case.layer_id)) { return false; } @@ -2566,11 +2540,7 @@ bool test_builtin_upload_stages_single_synthetic_hold_sample() "hold-forward upload should stage one real and one synthetic GPU sample"); if (!assert_compact_upload_state( - renderer, - series_id, - *prepare, - 3, - "hold-forward line")) + renderer, series_id, *prepare, 3, "hold-forward line")) { return false; } @@ -2651,11 +2621,7 @@ bool test_builtin_upload_stages_hold_windows_for_dots_and_area() "hold-forward dots/area upload should stage real and synthetic samples"); if (!assert_compact_upload_state( - renderer, - test_case.series_id, - *prepare, - 0, - test_case.layer_id)) + renderer, test_case.series_id, *prepare, 0, test_case.layer_id)) { return false; } From 3bc7cb15b0f5e1920ad56622506dcd3227321828 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:02:13 +0200 Subject: [PATCH 19/80] style: normalize ternary continuations --- include/vnm_plot/core/types.h | 5 +++-- src/core/series_renderer.cpp | 24 ++++++++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 426450a3..37013d6d 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -94,8 +94,9 @@ struct erased_access_policy_t std::pair range(const void* sample) const { - return get_range ? get_range(*this, sample) - : std::make_pair(0.0f, 0.0f); + return get_range + ? get_range(*this, sample) + : std::make_pair(0.0f, 0.0f); } }; diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index 6f8ac2e4..f60c86a2 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -1203,8 +1203,9 @@ void Series_renderer::prepare( view_state, window); const qrhi_series_sample_buffer_t sample_buffer = - samples_ready ? make_sample_buffer(view_state, window) - : qrhi_series_sample_buffer_t{}; + samples_ready + ? make_sample_buffer(view_state, window) + : qrhi_series_sample_buffer_t{}; const bool needs_view_ubo = has_custom_layer; series_view_uniform_std140_t uniform{}; const series_view_uniform_std140_t* view_uniform = nullptr; @@ -1544,8 +1545,8 @@ void Series_renderer::render( m_last_recorded_draw_styles.push_back( command.kind == rhi_state_t::prepared_draw_command_t::kind_t::BUILTIN - ? command.primitive_style - : Display_style::NONE); + ? command.primitive_style + : Display_style::NONE); m_last_recorded_draw_series_ids.push_back(command.series_id); m_last_recorded_draw_view_kinds.push_back(command.view_kind); @@ -1817,8 +1818,9 @@ bool Series_renderer::rhi_prepare_series_primitive( return false; } const std::vector segment_spans = - is_dots ? std::vector{} - : builtin_segment_spans(window); + is_dots + ? std::vector{} + : builtin_segment_spans(window); const bool has_segment_span = !segment_spans.empty(); if (!is_dots && !has_segment_span) { return false; @@ -2033,8 +2035,9 @@ bool Series_renderer::rhi_prepare_series_primitive( rhi_state_t::pipeline_key_t key{ is_dots ? rhi_state_t::pipeline_kind_t::DOTS - : (is_area ? rhi_state_t::pipeline_kind_t::AREA - : rhi_state_t::pipeline_kind_t::LINE) + : (is_area + ? rhi_state_t::pipeline_kind_t::AREA + : rhi_state_t::pipeline_kind_t::LINE) }; auto& cached = m_rhi_state->pipelines[key]; @@ -2269,8 +2272,9 @@ void Series_renderer::rhi_record_series_primitive( rhi_state_t::pipeline_key_t key{ is_dots ? rhi_state_t::pipeline_kind_t::DOTS - : (is_area ? rhi_state_t::pipeline_kind_t::AREA - : rhi_state_t::pipeline_kind_t::LINE) + : (is_area + ? rhi_state_t::pipeline_kind_t::AREA + : rhi_state_t::pipeline_kind_t::LINE) }; auto pipe_it = m_rhi_state->pipelines.find(key); if (pipe_it == m_rhi_state->pipelines.end() || !pipe_it->second.pipeline) { From e275e2c1d8518f54111c51c7e0e97650e5116371 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:05:01 +0200 Subject: [PATCH 20/80] docs: close baseline dependency gate --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index eb0df424..7738d4da 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -24,16 +24,21 @@ Claude was unavailable for the stated 85-minute review window. Three Codex worke The architecture review records **19 failed or terminated executions** in [Observed failures and current gate status](VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md#observed-failures-and-current-gate-status). Plan authoring added one failed `apply_patch` verification: a combined patch expected text that no longer exactly matched the staged draft. Codex `/root` owned the authoring error and recovered by rereading the file and applying smaller exact hunks, bringing the total to **20** before implementation began. -Batch 1B then added two failed style executions, bringing the running total to **22**: +Batch 1B then added seven failed or terminated style executions, bringing the running total to **27**: 1. The aggregate `style_pipeline.py --write` invocation against the three originally named files advanced beyond the 14 switch fixes and attempted 737 insertions/826 deletions. Review caught `fix_hanging_indent.py` deleting a ternary expression's `?`, true arm, and `:` in `sample_statement_for_offset()` before commit. Codex `/root` owned the unsafe invocation, rejected the output, and restored all generated changes through `apply_patch`; no corrupting change was retained. 2. After applying only the authorized 14 switch fixes, the canonical no-write pipeline passed its first stage and failed at stage two on four previously hidden `else if` layout violations. A read-only audit then showed 22 of 27 rule groups red; those counts are diagnostic/provisional because earlier ordered fixes can affect later checks. +3. A worker's isolated formatter replay used the live repository as its effective working directory and reapplied scratch output there. The worker and Codex `/root` owned the scope error, compared the tree to the intended checkpoint, and restored the exact intended state before further work. +4. The prototype-block formatter's first retry terminated with `PermissionError` while an unrelated concurrent build held source files open. No formatter output was retained; Codex `/root` waited for the build to release the files and reran the same bounded checkpoint successfully. +5. One initialized build/test wrapper exited before execution because its PowerShell quoting was malformed. Codex `/root` corrected the invocation and retained the successful initialized Release build and CTest result rather than suppressing the failed command. +6. One read-only aggregate-inventory wrapper exited because its diagnostic parser expected the wrong message shape. No source was changed; Codex `/root` corrected the parser and retained the resulting all-rule inventory. +7. One canonical no-write pipeline invocation exceeded a 30-second wrapper timeout and ended with a downstream broken-pipe error. No source was changed; subsequent canonical runs use a recorded timeout long enough for the complete pipeline. Preserve all ledgers rather than replacing them with later green results. | Current state | Owning batch | |---|---| -| Dependency Windows workflow failed before creating jobs | Startup failure recovered by `vnm_msdf_text@b9c216a`; real Windows jobs were created. At the 2026-07-10 execution-record update, Linux/macOS/FreeBSD and the normal Windows job were green while Windows full export was still running in [run 29090524058](https://github.com/imakris/vnm_msdf_text/actions/runs/29090524058). Retain the original failure and close Batch 1A only after the terminal four-platform result is recorded. | +| Dependency Windows workflow failed before creating jobs | Recovered and closed by `vnm_msdf_text@b9c216a`: Linux, macOS, FreeBSD, normal Windows, and Windows full export all passed in [run 29090524058](https://github.com/imakris/vnm_msdf_text/actions/runs/29090524058). Dependent `vnm_plot@2d94f01` text-OFF/text-ON CI also passed on all four platforms. Retain the original startup failure as closed evidence. | | Style baseline | The original 14 switch violations are recovered in local checkpoint `3fe78e6`. The short-circuiting pipeline exposed broader pre-existing governed debt and an unsafe `fix_hanging_indent.py` rewrite; expanded Batch 1B remains open. | | Benchmark cold dynamic timeout unresolved | Codex `/root` performance-harness owner; Batch 2 instruments it and the ledger stays open after Batch 2 if cause remains unresolved | | `vnm_plot` eight first-attempt CI failures | Recovered on attempt 2; retain as closed evidence | @@ -114,7 +119,7 @@ Execution status recorded 2026-07-10: - the smallest workflow-only fix landed on dependency `master` as `vnm_msdf_text@b9c216a`; - the invalid job-level `runner.temp` use was replaced by step-level `RUNNER_TEMP` initialization exported through `GITHUB_ENV`; -- dependency Linux, macOS, and FreeBSD passed at `b9c216a`; Windows created both real jobs and its normal job passed, while its full-export job remained in progress in run `29090524058` at the time of this record; +- dependency Linux, macOS, FreeBSD, normal Windows, and Windows full export passed at `b9c216a` in run `29090524058`; - all eight dependent `vnm_plot@2d94f01` text-OFF/text-ON jobs passed on attempt 2; - `actionlint` is not installed locally; retain its versioned bootstrap/validation as environment evidence rather than treating it as a missing project definition. @@ -170,7 +175,7 @@ Process exactly one canonical style rule at a time in pipeline order: 1. retain the no-write checker's enumerated findings and external standards identity; 2. run only that rule's fixer against its enumerated files, never the aggregate pipeline `--write`; -3. require a lexical C/C++ token-equivalence check for every formatting rewrite before build/test; any intended token change requires an explicit plan amendment and leaves this batch; +3. require a lexical C/C++ token-equivalence check for every formatting rewrite before build/test; any intended token change requires an explicit plan amendment and leaves this batch for the named Batch 1C checkpoint; 4. inspect and retain the complete diff, then rerun all preceding rules plus the active rule; 5. run `git diff --check`, the initialized Release build, and CTest 21/21; 6. obtain the iterative three-worker and Claude Fable review required for the batch, feeding findings into the next remediation/review round; @@ -189,11 +194,23 @@ Record standards repository base `f5edc8b` and `style_pipeline.py` SHA-256 `8715 Gate: -- governed style pipeline passes from its first stage; +- every token-preserving rule checker passes individually; only the explicitly routed Batch 1C naming findings may remain before that checkpoint; - initialized Release build passes; - CTest passes 21/21. -Parallel rule: Batch 1A remains a final-merge gate, but it does not block local Batch 1B/2 work while dependent `vnm_plot` CI and local product gates are green. Batch 1B must pass before semantic `vnm_plot` changes are pushed for review. +Batch 1A is closed and no longer blocks local or merge work. The combined Batch 1B/1C canonical pipeline gate must pass before semantic `vnm_plot` changes are pushed for review. + +### Batch 1C — Explicit non-behavioral style-gate token repairs + +Batch 1B remains formatting-only. If the ordered no-write checks still report governed naming findings that cannot be satisfied without changing tokens, isolate only the checker-enumerated private identifiers here. The initially known scope is the `_pad0`, `_pad1`, and `_pad2` members in `src/core/series_renderer.cpp`; rename them to the checker-approved private names without changing declaration order, field types, initialization values, buffer packing, public headers, or exported symbols. Do not use this checkpoint for unrelated cleanup. + +Gate: + +- retain the exact naming-checker findings before the change and prove that no old identifier use remains; +- inspect the complete token-changing diff and preserve the existing uniform-layout `static_assert` coverage; +- initialized Release build and CTest pass 21/21; +- complete canonical style pipeline passes without `--write`; +- the same iterative three-worker and Claude Fable review covers Batch 1B and 1C before either is merged. ## Stage 2 — Establish evidence, then remove unchanged-frame work @@ -573,4 +590,4 @@ Before the feature merge/release is considered complete: ## Recommended immediate next action -The Batch 1A startup repair has landed; monitor its remaining Windows full-export job and record the terminal four-platform result. Locally, start with Batch 1B, then Batch 2; do not touch product stack code before the evidence and contract stages pass. Review branches may be pushed, but no batch is merged while Batch 1A remains red or incomplete. This is the shortest path that produces trustworthy evidence without idling local work. +Batch 1A is closed with all dependency and dependent-consumer jobs green. Complete the ordered Batch 1B formatting checkpoints and the narrowly scoped Batch 1C naming repair, then run their joint canonical style/build/test/review gate before starting Batch 2. This is the shortest path that produces trustworthy evidence without idling local work. From f90dee1e9d029333266e13fd62a72a5162125241 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:06:06 +0200 Subject: [PATCH 21/80] docs: isolate style token repairs --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index 7738d4da..0cfdc602 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -202,11 +202,16 @@ Batch 1A is closed and no longer blocks local or merge work. The combined Batch ### Batch 1C — Explicit non-behavioral style-gate token repairs -Batch 1B remains formatting-only. If the ordered no-write checks still report governed naming findings that cannot be satisfied without changing tokens, isolate only the checker-enumerated private identifiers here. The initially known scope is the `_pad0`, `_pad1`, and `_pad2` members in `src/core/series_renderer.cpp`; rename them to the checker-approved private names without changing declaration order, field types, initialization values, buffer packing, public headers, or exported symbols. Do not use this checkpoint for unrelated cleanup. +Batch 1B remains formatting-only. Isolate here only the two checker-enumerated cases that cannot be made green safely without changing tokens: + +1. Rewrite `tests/test_msdf_lcd_shader_reference.cpp::sample_statement_for_offset()` from its ternary return to an equivalent empty-expression early return followed by the existing non-empty string construction. This avoids the proven `std::string`/ternary parser collision without changing generated shader text; retain the focused LCD shader-reference assertions. +2. If the ordered naming check still reports them, rename only the private `_pad0`, `_pad1`, and `_pad2` members in `src/core/series_renderer.cpp` to checker-approved names without changing declaration order, field types, initialization values, buffer packing, public headers, or exported symbols. + +Do not use this checkpoint for unrelated cleanup. Gate: -- retain the exact naming-checker findings before the change and prove that no old identifier use remains; +- retain the exact checker findings before each change and prove that no old padding identifier use remains; - inspect the complete token-changing diff and preserve the existing uniform-layout `static_assert` coverage; - initialized Release build and CTest pass 21/21; - complete canonical style pipeline passes without `--write`; From 69c94af1111a97eeb7b8399c1c0841883abe019e Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:07:15 +0200 Subject: [PATCH 22/80] style: avoid ambiguous shader helper ternary --- tests/test_msdf_lcd_shader_reference.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 10436a88..60f8d91d 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -230,10 +230,12 @@ std::string sample_statement_for_offset(float offset) { const std::string sample_name = sample_name_for_offset(offset); const std::string expression = sample_expression_for_offset(offset); - return expression.empty() - ? std::string{} - : "float " + sample_name + " = glyph_alpha_at_ratio(" + - expression + ", uv_min, uv_max);"; + if (expression.empty()) { + return {}; + } + + return "float " + sample_name + " = glyph_alpha_at_ratio(" + + expression + ", uv_min, uv_max);"; } std::string filter_weight_statement(std::string_view name, std::string_view literal) From df10722421f897d59fe0bbbf55aaf3fad33745aa Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:09:38 +0200 Subject: [PATCH 23/80] style: normalize hanging indent --- include/vnm_plot/core/types.h | 64 +++++---- src/core/auto_range_resolver.cpp | 38 ++--- src/core/chrome_renderer.cpp | 15 +- src/core/font_renderer.cpp | 28 ++-- src/core/layout_calculator.cpp | 26 ++-- src/core/series_renderer.cpp | 80 ++++++----- src/core/series_window_planner.cpp | 60 ++++---- src/core/time_grid.cpp | 2 +- src/core/types.cpp | 16 ++- tests/test_cache_invalidation.cpp | 174 +++++++++++------------ tests/test_concurrent_series.cpp | 10 +- tests/test_core_algo.cpp | 60 ++++---- tests/test_data_source_queries.cpp | 168 ++++++++++++---------- tests/test_font_renderer_bounds.cpp | 2 +- tests/test_function_sample_source.cpp | 2 +- tests/test_label_pane_geometry.cpp | 28 ++-- tests/test_layout_calculator.cpp | 4 +- tests/test_msdf_lcd_shader_reference.cpp | 63 ++++---- tests/test_qrhi_layer_lifecycle.cpp | 106 +++++++------- tests/test_rhi_helpers.cpp | 8 +- tests/test_snapshot_caching.cpp | 70 ++++----- tests/test_time_grid.cpp | 10 +- tests/test_typed_api.cpp | 12 +- 23 files changed, 549 insertions(+), 497 deletions(-) diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 37013d6d..8cf7a5d5 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -113,7 +113,8 @@ struct access_policy_cache_key_t [[nodiscard]] bool operator==( const access_policy_cache_key_t& other) const noexcept { - return identity == other.identity && + return + identity == other.identity && layout_key == other.layout_key && revision == other.revision && dispatch_kind == other.dispatch_kind && @@ -324,11 +325,12 @@ struct data_snapshot_t bool is_valid() const noexcept { - return data != nullptr - && count > 0 - && stride > 0 - && count2 <= count - && (count2 == 0 || data2 != nullptr); + return + data != nullptr && + count > 0 && + stride > 0 && + count2 <= count && + (count2 == 0 || data2 != nullptr); } const void* at(size_t index) const @@ -513,9 +515,11 @@ inline std::int64_t std_function_access_timestamp( const void* sample) { const auto* policy = static_cast(view.ctx); - return policy && policy->get_timestamp - ? policy->get_timestamp(sample) - : std::int64_t{0}; + return + policy && + policy->get_timestamp + ? policy->get_timestamp(sample) + : std::int64_t{0}; } inline float std_function_access_value( @@ -531,9 +535,11 @@ inline std::pair std_function_access_range( const void* sample) { const auto* policy = static_cast(view.ctx); - return policy && policy->get_range - ? policy->get_range(sample) - : std::make_pair(0.0f, 0.0f); + return + policy && + policy->get_range + ? policy->get_range(sample) + : std::make_pair(0.0f, 0.0f); } inline erased_access_policy_t make_erased_access_policy_view( @@ -1097,9 +1103,10 @@ struct series_data_t if (!data_source || !prev || data_source.get() != prev) { return false; } - return preview_access().layout_key == access.layout_key - && effective_preview_style() == style - && effective_preview_interpolation() == interpolation; + return + preview_access().layout_key == access.layout_key && + effective_preview_style() == style && + effective_preview_interpolation() == interpolation; } }; @@ -1175,19 +1182,20 @@ struct layout_cache_key_t [[nodiscard]] bool operator==(const layout_cache_key_t& other) const noexcept { - return v0 == other.v0 && - v1 == other.v1 && - t0 == other.t0 && - t1 == other.t1 && - viewport_size == other.viewport_size && - adjusted_reserved_height == other.adjusted_reserved_height && - adjusted_preview_height == other.adjusted_preview_height && - adjusted_font_size_in_pixels == other.adjusted_font_size_in_pixels && - vbar_width_pixels == other.vbar_width_pixels && - font_metrics_key == other.font_metrics_key && - config_revision == other.config_revision && - format_timestamp_revision == other.format_timestamp_revision && - format_value_revision == other.format_value_revision; + return + v0 == other.v0 && + v1 == other.v1 && + t0 == other.t0 && + t1 == other.t1 && + viewport_size == other.viewport_size && + adjusted_reserved_height == other.adjusted_reserved_height && + adjusted_preview_height == other.adjusted_preview_height && + adjusted_font_size_in_pixels == other.adjusted_font_size_in_pixels && + vbar_width_pixels == other.vbar_width_pixels && + font_metrics_key == other.font_metrics_key && + config_revision == other.config_revision && + format_timestamp_revision == other.format_timestamp_revision && + format_value_revision == other.format_value_revision; } }; diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index e2520561..351defa0 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -209,21 +209,22 @@ bool same_cache_shape( make_erased_access_policy_view(access); const access_policy_cache_key_t access_key = make_access_policy_cache_key(&access, access_view); - return entry.valid - && entry.source_identity == source.identity() - && entry.access_identity == &access - && entry.access_key == access_key - && entry.layout_key == access.layout_key - && entry.semantics_value == query.semantics_key.value - && entry.semantics_revision == query.semantics_key.revision - && entry.semantics_conservative == query.semantics_key.conservative - && entry.lod_level == lod_level - && entry.t_min_ns == query.time_window.min_ns - && entry.t_max_ns == query.time_window.max_ns - && entry.interpolation == query.interpolation - && entry.empty_window_behavior == query.empty_window_behavior - && entry.nonfinite_policy == query.nonfinite_policy - && entry.sequence == sequence; + return + entry.valid && + entry.source_identity == source.identity() && + entry.access_identity == &access && + entry.access_key == access_key && + entry.layout_key == access.layout_key && + entry.semantics_value == query.semantics_key.value && + entry.semantics_revision == query.semantics_key.revision && + entry.semantics_conservative == query.semantics_key.conservative && + entry.lod_level == lod_level && + entry.t_min_ns == query.time_window.min_ns && + entry.t_max_ns == query.time_window.max_ns && + entry.interpolation == query.interpolation && + entry.empty_window_behavior == query.empty_window_behavior && + entry.nonfinite_policy == query.nonfinite_policy && + entry.sequence == sequence; } auto_range_cache_entry_t make_cache_entry( @@ -291,9 +292,10 @@ void prune_cache_entries( bool valid_query_range(value_range_t range) { - return std::isfinite(range.min) - && std::isfinite(range.max) - && range.min <= range.max; + return + std::isfinite(range.min) && + std::isfinite(range.max) && + range.min <= range.max; } bool query_or_scan_series_range( diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index 13e63467..c0f4e6fd 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -143,10 +143,10 @@ void Chrome_renderer::render_grid_and_backgrounds( } prims.batch_rect(separator_color, glm::vec4(0.f, float(ctx.win_h) - float(ctx.adjusted_reserved_height), - float(ctx.win_w), float(ctx.win_h - ctx.adjusted_reserved_height + 1.0))); + float(ctx.win_w), float(ctx.win_h - ctx.adjusted_reserved_height + 1.0))); prims.batch_rect(separator_color, glm::vec4(0.f, float(ctx.win_h) - float(ctx.adjusted_preview_height + 1.0), - float(ctx.win_w), float(ctx.win_h) - float(ctx.adjusted_preview_height))); + float(ctx.win_w), float(ctx.win_h) - float(ctx.adjusted_preview_height))); prims.flush_rects(ctx, ctx.pmv); @@ -181,7 +181,10 @@ void Chrome_renderer::render_grid_and_backgrounds( prims.draw_grid_shader(ctx, main_origin, main_size, grid_rgb, vertical_levels_gl, horizontal_levels); } - const auto match_level_properties = [](float pos, const grid_layer_params_t& levels) -> std::pair { + const auto match_level_properties = []( + float pos, + const grid_layer_params_t& levels) -> std::pair + { float alpha = k_grid_line_alpha_base; float thick = 0.8f; for (int i = 0; i < levels.count; ++i) { @@ -203,7 +206,11 @@ void Chrome_renderer::render_grid_and_backgrounds( return {alpha, thick}; }; - const auto build_tick_levels = [&](auto&& get_pos, const auto& labels, const grid_layer_params_t& main_levels) { + const auto build_tick_levels = [&]( + auto&& get_pos, + const auto& labels, + const grid_layer_params_t& main_levels) + { grid_layer_params_t ticks; for (const auto& label : labels) { if (ticks.count >= grid_layer_params_t::k_max_levels) { diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 76d5a4f4..ea1e8b87 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -244,18 +244,18 @@ bool validate_cached_glyph(const msdf_glyph_t& g) // rectangles are derived per draw size via scaled_glyph(). Invisible // advance-only glyphs (e.g. U+0020) carry zero bounds, so equality is valid. return - std::isfinite(g.advance_units) && - std::isfinite(g.bounds_left_units) && - std::isfinite(g.bounds_bottom_units) && - std::isfinite(g.bounds_right_units) && - std::isfinite(g.bounds_top_units) && + std::isfinite(g.advance_units) && + std::isfinite(g.bounds_left_units) && + std::isfinite(g.bounds_bottom_units) && + std::isfinite(g.bounds_right_units) && + std::isfinite(g.bounds_top_units) && g.bounds_right_units >= g.bounds_left_units && g.bounds_top_units >= g.bounds_bottom_units && - uv_in_range(g.uv_left) && - uv_in_range(g.uv_bottom) && - uv_in_range(g.uv_right) && - uv_in_range(g.uv_top) && - g.uv_right >= g.uv_left && + uv_in_range(g.uv_left) && + uv_in_range(g.uv_bottom) && + uv_in_range(g.uv_right) && + uv_in_range(g.uv_top) && + g.uv_right >= g.uv_left && g.uv_bottom >= g.uv_top; } @@ -1029,7 +1029,7 @@ bool Font_renderer::text_visual_bounds_px( std::isfinite(bounds.y) && std::isfinite(bounds.z) && std::isfinite(bounds.w) && - bounds.z > bounds.x && + bounds.z > bounds.x && bounds.w > bounds.y; } @@ -1422,9 +1422,9 @@ void Font_renderer::rhi_queue_draw( } const auto queue_text_pass = [&](std::size_t call_index, - const glm::vec4& draw_color, - const text_shadow_t& draw_shadow, - rhi_text_pass_t pass) { + const glm::vec4& draw_color, + const text_shadow_t& draw_shadow, + rhi_text_pass_t pass) { auto& call = rhi_state.calls[call_index]; Text_block_std140 block{}; diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 8160b00f..7ef6177e 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -190,13 +190,14 @@ class Timestamp_label_cache friend bool operator==(const Context_key& lhs, const Context_key& rhs) noexcept { - return lhs.step_bits == rhs.step_bits && - lhs.range_bits == rhs.range_bits && - lhs.monospace_bits == rhs.monospace_bits && - lhs.monospace_reliable == rhs.monospace_reliable && - lhs.measure_key == rhs.measure_key && - lhs.font_size_bits == rhs.font_size_bits && - lhs.format_signature == rhs.format_signature; + return + lhs.step_bits == rhs.step_bits && + lhs.range_bits == rhs.range_bits && + lhs.monospace_bits == rhs.monospace_bits && + lhs.monospace_reliable == rhs.monospace_reliable && + lhs.measure_key == rhs.measure_key && + lhs.font_size_bits == rhs.font_size_bits && + lhs.format_signature == rhs.format_signature; } }; @@ -297,11 +298,12 @@ class Format_signature_cache friend bool operator==(const Key& lhs, const Key& rhs) noexcept { - return lhs.step_bits == rhs.step_bits && - lhs.coverage_bucket == rhs.coverage_bucket && - lhs.formatter_identity == rhs.formatter_identity && - lhs.formatter_type_hash == rhs.formatter_type_hash && - lhs.formatter_revision == rhs.formatter_revision; + return + lhs.step_bits == rhs.step_bits && + lhs.coverage_bucket == rhs.coverage_bucket && + lhs.formatter_identity == rhs.formatter_identity && + lhs.formatter_type_hash == rhs.formatter_type_hash && + lhs.formatter_revision == rhs.formatter_revision; } }; diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index f60c86a2..ca8eac3d 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -374,14 +374,15 @@ struct Series_renderer::rhi_state_t bool operator==(const qrhi_layer_program_key_t& o) const noexcept { - return series_id == o.series_id - && view_kind == o.view_kind - && layer_id == o.layer_id - && layer_revision == o.layer_revision - && data_identity == o.data_identity - && layout_key == o.layout_key - && access_key == o.access_key - && rhi == o.rhi; + return + series_id == o.series_id && + view_kind == o.view_kind && + layer_id == o.layer_id && + layer_revision == o.layer_revision && + data_identity == o.data_identity && + layout_key == o.layout_key && + access_key == o.access_key && + rhi == o.rhi; } }; @@ -422,20 +423,21 @@ struct Series_renderer::rhi_state_t bool operator==(const qrhi_layer_data_key_t& o) const noexcept { - return lod_level == o.lod_level - && sample_sequence == o.sample_sequence - && t_origin_ns == o.t_origin_ns - && source_first == o.source_first - && source_count == o.source_count - && synthetic_hold_count == o.synthetic_hold_count - && gpu_count == o.gpu_count - && hold_last_forward == o.hold_last_forward - && hold_timestamp_ns == o.hold_timestamp_ns - && interpolation == o.interpolation - && nonfinite_policy == o.nonfinite_policy - && drawable_span_count == o.drawable_span_count - && drawable_spans_hash == o.drawable_spans_hash - && access_key == o.access_key; + return + lod_level == o.lod_level && + sample_sequence == o.sample_sequence && + t_origin_ns == o.t_origin_ns && + source_first == o.source_first && + source_count == o.source_count && + synthetic_hold_count == o.synthetic_hold_count && + gpu_count == o.gpu_count && + hold_last_forward == o.hold_last_forward && + hold_timestamp_ns == o.hold_timestamp_ns && + interpolation == o.interpolation && + nonfinite_policy == o.nonfinite_policy && + drawable_span_count == o.drawable_span_count && + drawable_spans_hash == o.drawable_spans_hash && + access_key == o.access_key; } }; @@ -748,7 +750,7 @@ void Series_renderer::prepare( }; const auto log_error_once = [&](Error_cat cat, int series_id, - const std::string& message) { + const std::string& message) { if (!ctx.config || !ctx.config->log_error) { return; } @@ -903,9 +905,9 @@ void Series_renderer::prepare( main_plan.gpu_count > 0 && main_plan.lod_level != prev_lod_level) { - std::string message = "LOD selection: series=" + std::to_string(id) - + " level=" + std::to_string(main_plan.lod_level) - + " pps=" + std::to_string(main_plan.pixels_per_sample); + std::string message = "LOD selection: series=" + std::to_string(id) + + " level=" + std::to_string(main_plan.lod_level) + + " pps=" + std::to_string(main_plan.pixels_per_sample); ctx.config->log_debug(message); } @@ -1180,10 +1182,9 @@ void Series_renderer::prepare( planned_draws.begin(), planned_draws.end(), [&](const planned_draw_t& draw) { - return draw.is_builtin && - is_builtin_primitive_drawable( - draw.primitive_style, - window); + return + draw.is_builtin && + is_builtin_primitive_drawable(draw.primitive_style, window); }); const bool has_custom_layer = std::any_of( planned_draws.begin(), @@ -1465,15 +1466,16 @@ void Series_renderer::prepare( qrhi_layers.begin(), qrhi_layers.end(), [&](const auto& layer) { - return layer && - layer->draws_view(key.view_kind) && - layer->id() == key.layer_id && + return + layer && + layer->draws_view(key.view_kind) && + layer->id() == key.layer_id && layer->revision() == key.layer_revision; }); }; for (auto it = m_rhi_state->qrhi_layer_cache.begin(); - it != m_rhi_state->qrhi_layer_cache.end();) + it != m_rhi_state->qrhi_layer_cache.end();) { if (it->second.last_frame_used == m_frame_id || qrhi_layer_still_configured(it->first)) @@ -1489,7 +1491,7 @@ void Series_renderer::prepare( m_last_qrhi_layer_cache_size = m_rhi_state->qrhi_layer_cache.size(); for (auto it = m_rhi_state->view_ubos.begin(); - it != m_rhi_state->view_ubos.end();) + it != m_rhi_state->view_ubos.end();) { if (it->second.last_frame_used == m_frame_id) { ++it; @@ -1645,8 +1647,8 @@ bool Series_renderer::rhi_prepare_series_view_samples( std::size_t expected_gpu_count = 0; bool synthetic_hold_seen = false; for (std::size_t span_index = 0; - span_index < window.drawable_spans.size(); - ++span_index) + span_index < window.drawable_spans.size(); + ++span_index) { const drawable_sample_span_t& span = window.drawable_spans[span_index]; @@ -2146,8 +2148,8 @@ bool Series_renderer::rhi_prepare_series_primitive( // use-after-free. auto ensure_srb = [&](vbo_view_state_t::rhi_buffers_t::srb_entry_t& entry) -> bool { QRhiBuffer* current_ubo = entry.ubo.get(); - const bool srb_handles_match = entry.srb - && entry.last_ubo == current_ubo; + const bool srb_handles_match = entry.srb && + entry.last_ubo == current_ubo; if (srb_handles_match) { return true; } diff --git a/src/core/series_window_planner.cpp b/src/core/series_window_planner.cpp index 15f24205..66a064ae 100644 --- a/src/core/series_window_planner.cpp +++ b/src/core/series_window_planner.cpp @@ -324,31 +324,31 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) const auto try_stale_fallback = [&](Series_view_plan& p, std::size_t level) -> bool { - const void* current_identity = data_source.identity(); - // The cached VBO holds samples rebased against uploaded_t_origin_ns; - // reusing it under a moved origin would draw at the wrong x positions - // because set_common_uniforms feeds the new view_origin_ns regardless. - const bool identity_ok = - (state.cached_data_identity != nullptr) && - (state.cached_data_identity == current_identity) && - request.has_uploaded_vbo && - (state.last_count > 0) && - state.has_last_lod_level && - (state.last_lod_level == level) && - (state.last_access_key == access_key) && - (state.last_t_min == request.t_min_ns) && - (state.last_t_max == request.t_max_ns) && - (state.last_width_px == request.width_px) && - (state.last_empty_window_behavior == request.empty_window_behavior) && - (state.last_nonfinite_policy == request.nonfinite_policy) && - (state.last_interpolation == request.interpolation) && - (state.uploaded_t_origin_ns == request.t_origin_ns); - if (!identity_ok) { - return false; - } - load_cached_plan(p, state.last_lod_level); - return true; - }; + const void* current_identity = data_source.identity(); + // The cached VBO holds samples rebased against uploaded_t_origin_ns; + // reusing it under a moved origin would draw at the wrong x positions + // because set_common_uniforms feeds the new view_origin_ns regardless. + const bool identity_ok = + (state.cached_data_identity != nullptr) && + (state.cached_data_identity == current_identity) && + request.has_uploaded_vbo && + (state.last_count > 0) && + state.has_last_lod_level && + (state.last_lod_level == level) && + (state.last_access_key == access_key) && + (state.last_t_min == request.t_min_ns) && + (state.last_t_max == request.t_max_ns) && + (state.last_width_px == request.width_px) && + (state.last_empty_window_behavior == request.empty_window_behavior) && + (state.last_nonfinite_policy == request.nonfinite_policy) && + (state.last_interpolation == request.interpolation) && + (state.uploaded_t_origin_ns == request.t_origin_ns); + if (!identity_ok) { + return false; + } + load_cached_plan(p, state.last_lod_level); + return true; + }; const int max_attempts = static_cast(level_count) + 2; @@ -458,8 +458,8 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) bool has_match_in_requested_window = false; bool direct_window_valid = true; for (std::size_t index = first; - index < last_exclusive; - ++index) + index < last_exclusive; + ++index) { const void* sample = snapshot.at(index); if (!sample) { @@ -504,7 +504,7 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) direct_last_idx = snapshot.count; } if (request.empty_window_behavior == - Empty_window_behavior::HOLD_LAST_FORWARD && + Empty_window_behavior::HOLD_LAST_FORWARD && direct_last_idx == snapshot.count) { const void* last_window_sample = @@ -524,9 +524,9 @@ Series_view_plan plan_series_window(const series_window_plan_request_t& request) } else if (request.interpolation == - Series_interpolation::STEP_AFTER && + Series_interpolation::STEP_AFTER && request.empty_window_behavior == - Empty_window_behavior::HOLD_LAST_FORWARD) + Empty_window_behavior::HOLD_LAST_FORWARD) { const void* last_window_sample = snapshot.at(last_exclusive - 1u); diff --git a/src/core/time_grid.cpp b/src/core/time_grid.cpp index fc3329ed..b9e203a5 100644 --- a/src/core/time_grid.cpp +++ b/src/core/time_grid.cpp @@ -73,7 +73,7 @@ grid_layer_params_t build_time_grid_layers( const auto steps = detail::build_time_steps_covering(range); int idx = std::max(0, detail::find_time_step_start_index(steps, range)); while (idx + 1 < static_cast(steps.size()) && - steps[idx] * px_per_unit < cell_span_min) + steps[idx] * px_per_unit < cell_span_min) { ++idx; } diff --git a/src/core/types.cpp b/src/core/types.cpp index b24c9ce4..e29f7744 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -61,15 +61,17 @@ Data_query_status invalid_ready_snapshot_status(const data_snapshot_t& snapshot) bool time_window_contains(time_range_t window, std::int64_t timestamp_ns) { - return window.min_ns <= window.max_ns - && timestamp_ns >= window.min_ns - && timestamp_ns <= window.max_ns; + return + window.min_ns <= window.max_ns && + timestamp_ns >= window.min_ns && + timestamp_ns <= window.max_ns; } bool wants_hold_forward(const data_query_context_t& query) { - return query.interpolation == Series_interpolation::STEP_AFTER - && query.empty_window_behavior == Empty_window_behavior::HOLD_LAST_FORWARD; + return + query.interpolation == Series_interpolation::STEP_AFTER && + query.empty_window_behavior == Empty_window_behavior::HOLD_LAST_FORWARD; } bool timestamp_at( @@ -680,8 +682,8 @@ validated_time_window_t validated_time_window( bool selected_by_time_window(const validated_time_window_t& window, std::size_t index) { return (window.has_match && - index >= window.match_first && - index < window.match_last_exclusive) || + index >= window.match_first && + index < window.match_last_exclusive) || (window.has_held && index == window.held_index); } diff --git a/tests/test_cache_invalidation.cpp b/tests/test_cache_invalidation.cpp index faace568..790a5a19 100644 --- a/tests/test_cache_invalidation.cpp +++ b/tests/test_cache_invalidation.cpp @@ -266,27 +266,27 @@ bool test_visible_auto_range_uses_source_query_without_snapshot_fallback() true); TEST_ASSERT(range.first == 2.0f && range.second == 5.0f, - "visible auto-range should use the source query result"); + "visible auto-range should use the source query result"); TEST_ASSERT(source->query_calls == 1, - "visible auto-range should call query_v_range once"); + "visible auto-range should call query_v_range once"); TEST_ASSERT(source->snapshot_calls == 0, - "READY query result should avoid snapshot fallback"); + "READY query result should avoid snapshot fallback"); TEST_ASSERT(source->last_query_lod == 0, - "VISIBLE mode should query LOD 0"); + "VISIBLE mode should query LOD 0"); TEST_ASSERT(source->last_query.time_window.min_ns == 10 && - source->last_query.time_window.max_ns == 20, + source->last_query.time_window.max_ns == 20, "visible query should use the configured time window"); TEST_ASSERT(source->last_query.interpolation == Series_interpolation::STEP_AFTER, - "query should carry series interpolation"); + "query should carry series interpolation"); TEST_ASSERT(source->last_query.empty_window_behavior == - Empty_window_behavior::HOLD_LAST_FORWARD, + Empty_window_behavior::HOLD_LAST_FORWARD, "query should carry series empty-window behavior"); TEST_ASSERT(source->last_query.semantics_key.value == 0, - "default access semantics key should not reuse layout identity"); + "default access semantics key should not reuse layout identity"); TEST_ASSERT(source->last_query.semantics_key.conservative, - "default access semantics key should be conservative"); + "default access semantics key should be conservative"); TEST_ASSERT(source->last_query.semantics_key.revision != 0, - "conservative access semantics should carry accessor revision"); + "conservative access semantics should carry accessor revision"); return true; } @@ -310,15 +310,15 @@ bool test_member_pointer_query_uses_stable_semantics_key() true); TEST_ASSERT(range.first == 2.0f && range.second == 5.0f, - "member-pointer query should use the source query result"); + "member-pointer query should use the source query result"); TEST_ASSERT(!source->last_query.semantics_key.conservative, - "member-pointer query should expose stable semantics"); + "member-pointer query should expose stable semantics"); TEST_ASSERT(source->last_query.semantics_key.value != 0, - "member-pointer query semantics key should be non-zero"); + "member-pointer query semantics key should be non-zero"); TEST_ASSERT(source->last_query.semantics_key.value != series->access.layout_key, - "query semantics key should not reuse layout identity"); + "query semantics key should not reuse layout identity"); TEST_ASSERT(source->last_query.semantics_key.revision == 0, - "member-pointer query semantics should not consume accessor revision"); + "member-pointer query semantics should not consume accessor revision"); return true; } @@ -340,11 +340,11 @@ bool test_global_lod_auto_range_uses_query_when_no_legacy_range_exists() true); TEST_ASSERT(range.first == -4.0f && range.second == 9.0f, - "GLOBAL_LOD auto-range should use query_v_range when no legacy O(1) range exists"); + "GLOBAL_LOD auto-range should use query_v_range when no legacy O(1) range exists"); TEST_ASSERT(source->last_query_lod == 1, - "GLOBAL_LOD should query the last LOD level"); + "GLOBAL_LOD should query the last LOD level"); TEST_ASSERT(source->snapshot_calls == 0, - "READY global query result should avoid snapshot fallback"); + "READY global query result should avoid snapshot fallback"); return true; } @@ -369,11 +369,11 @@ bool test_unsupported_query_falls_back_to_snapshot_scan() true); TEST_ASSERT(range.first == 6.0f && range.second == 12.0f, - "unsupported query should fall back to snapshot scan"); + "unsupported query should fall back to snapshot scan"); TEST_ASSERT(source->query_calls == 1, - "resolver should try query_v_range before fallback"); + "resolver should try query_v_range before fallback"); TEST_ASSERT(source->snapshot_calls == 1, - "unsupported query should take one fallback snapshot"); + "unsupported query should take one fallback snapshot"); return true; } @@ -396,13 +396,13 @@ bool test_ready_query_profiler_counts_query_without_scan() true); TEST_ASSERT(range.first == 2.0f && range.second == 5.0f, - "READY query should resolve the auto-range"); + "READY query should resolve the auto-range"); TEST_ASSERT(profiler->total("renderer.auto_range.query_count") == 1.0, - "READY query should increment the auto-range query counter"); + "READY query should increment the auto-range query counter"); TEST_ASSERT(profiler->total("renderer.auto_range.range_scan_count") == 0.0, - "READY query should not be counted as a range scan"); + "READY query should not be counted as a range scan"); TEST_ASSERT(source->snapshot_calls == 0, - "READY query should avoid snapshot work"); + "READY query should avoid snapshot work"); return true; } @@ -428,13 +428,13 @@ bool test_default_query_profiler_counts_snapshot_scan() true); TEST_ASSERT(range.first == 6.0f && range.second == 12.0f, - "default query should resolve the auto-range through its snapshot scan"); + "default query should resolve the auto-range through its snapshot scan"); TEST_ASSERT(profiler->total("renderer.auto_range.query_count") == 1.0, - "default query should increment the auto-range query counter"); + "default query should increment the auto-range query counter"); TEST_ASSERT(profiler->total("renderer.auto_range.range_scan_count") == 1.0, - "default query snapshot scan should increment the range scan counter"); + "default query snapshot scan should increment the range scan counter"); TEST_ASSERT(source->snapshot_calls == 1, - "default query should take one snapshot"); + "default query should take one snapshot"); return true; } @@ -455,9 +455,9 @@ bool test_positive_auto_range_excludes_zero_by_default() true); TEST_ASSERT(range.first == 2.0f && range.second == 8.0f, - "positive-only auto-range should preserve the positive data range by default"); + "positive-only auto-range should preserve the positive data range by default"); TEST_ASSERT(range.first > 0.0f && range.second > 0.0f, - "positive-only auto-range should not force zero into the default range"); + "positive-only auto-range should not force zero into the default range"); return true; } @@ -478,9 +478,9 @@ bool test_negative_auto_range_excludes_zero_by_default() true); TEST_ASSERT(range.first == -8.0f && range.second == -2.0f, - "negative-only auto-range should preserve the negative data range by default"); + "negative-only auto-range should preserve the negative data range by default"); TEST_ASSERT(range.first < 0.0f && range.second < 0.0f, - "negative-only auto-range should not force zero into the default range"); + "negative-only auto-range should not force zero into the default range"); return true; } @@ -503,7 +503,7 @@ bool test_nonnegative_auto_range_floor_policy_includes_zero() true); TEST_ASSERT(range.first == 0.0f && range.second == 5.0f, - "nonnegative auto-range floor policy should clamp padded lower bound to zero"); + "nonnegative auto-range floor policy should clamp padded lower bound to zero"); return true; } @@ -532,11 +532,11 @@ bool test_visible_step_after_hold_forward_contributes_held_sample() true); TEST_ASSERT(range.first == -4.0f && range.second == 6.0f, - "visible STEP_AFTER auto-range should include the held sample entering the window"); + "visible STEP_AFTER auto-range should include the held sample entering the window"); TEST_ASSERT(source->query_calls == 1, - "visible STEP_AFTER auto-range should try query_v_range before fallback"); + "visible STEP_AFTER auto-range should try query_v_range before fallback"); TEST_ASSERT(source->snapshot_calls == 1, - "unsupported STEP_AFTER query should fall back to one snapshot scan"); + "unsupported STEP_AFTER query should fall back to one snapshot scan"); return true; } @@ -568,11 +568,11 @@ bool test_visible_step_after_skip_fallback_keeps_earlier_drawable_held_sample() true); TEST_ASSERT(range.first == -4.0f && range.second == 6.0f, - "SKIP fallback auto-range should keep the earlier drawable held sample"); + "SKIP fallback auto-range should keep the earlier drawable held sample"); TEST_ASSERT(source->query_calls == 1, - "SKIP fallback auto-range should try query_v_range before fallback"); + "SKIP fallback auto-range should try query_v_range before fallback"); TEST_ASSERT(source->snapshot_calls == 1, - "SKIP fallback auto-range should take one snapshot scan"); + "SKIP fallback auto-range should take one snapshot scan"); return true; } @@ -600,11 +600,11 @@ bool test_global_value_only_access_falls_back_to_snapshot_scan() true); TEST_ASSERT(range.first == -3.0f && range.second == 8.0f, - "global value-only access should use snapshot scan fallback"); + "global value-only access should use snapshot scan fallback"); TEST_ASSERT(source->query_calls == 1, - "value-only fallback should still try the source query first"); + "value-only fallback should still try the source query first"); TEST_ASSERT(source->snapshot_calls == 1, - "value-only fallback should take one snapshot"); + "value-only fallback should take one snapshot"); return true; } @@ -629,11 +629,11 @@ bool test_failed_query_does_not_fall_back_to_stale_scan() true); TEST_ASSERT(range.first == cfg.v_min && range.second == cfg.v_max, - "FAILED query should be authoritative and leave configured fallback range"); + "FAILED query should be authoritative and leave configured fallback range"); TEST_ASSERT(source->query_calls == 1, - "FAILED source should still be queried once"); + "FAILED source should still be queried once"); TEST_ASSERT(source->snapshot_calls == 0, - "FAILED query must not be silently downgraded to snapshot fallback"); + "FAILED query must not be silently downgraded to snapshot fallback"); return true; } @@ -666,11 +666,11 @@ bool test_ready_query_result_is_cached_by_current_sequence() &cache); TEST_ASSERT(first.first == 1.0f && first.second == 4.0f, - "first range should come from query"); + "first range should come from query"); TEST_ASSERT(second.first == 1.0f && second.second == 4.0f, - "second range should come from cache"); + "second range should come from cache"); TEST_ASSERT(source->query_calls == 1, - "matching sequence and query shape should reuse cached range"); + "matching sequence and query shape should reuse cached range"); return true; } @@ -703,9 +703,9 @@ bool test_conservative_query_result_is_not_cached() &cache); TEST_ASSERT(source->query_calls == 2, - "conservative callable semantics should not reuse cached query results"); + "conservative callable semantics should not reuse cached query results"); TEST_ASSERT(cache.main_entries.empty(), - "conservative callable semantics should not populate resolver cache"); + "conservative callable semantics should not populate resolver cache"); return true; } @@ -738,11 +738,11 @@ bool test_empty_query_result_is_cached_by_current_sequence() &cache); TEST_ASSERT(first.first == cfg.v_min && first.second == cfg.v_max, - "empty query should use configured fallback range"); + "empty query should use configured fallback range"); TEST_ASSERT(second.first == cfg.v_min && second.second == cfg.v_max, - "cached empty query should keep configured fallback range"); + "cached empty query should keep configured fallback range"); TEST_ASSERT(source->query_calls == 1, - "matching empty query should be cached by sequence"); + "matching empty query should be cached by sequence"); return true; } @@ -779,9 +779,9 @@ bool test_sequence_change_invalidates_auto_range_cache() &cache); TEST_ASSERT(range.first == -3.0f && range.second == 9.0f, - "sequence change should force a fresh query result"); + "sequence change should force a fresh query result"); TEST_ASSERT(source->query_calls == 2, - "sequence change should invalidate the cached range"); + "sequence change should invalidate the cached range"); return true; } @@ -819,9 +819,9 @@ bool test_visible_window_change_invalidates_auto_range_cache() &cache); TEST_ASSERT(range.first == -6.0f && range.second == -2.0f, - "visible window change should force a fresh query result"); + "visible window change should force a fresh query result"); TEST_ASSERT(source->query_calls == 2, - "visible window should be part of the cache key"); + "visible window should be part of the cache key"); return true; } @@ -857,9 +857,9 @@ bool test_access_policy_change_invalidates_auto_range_cache() &cache); TEST_ASSERT(range.first == 10.0f && range.second == 12.0f, - "access-policy identity change should not reuse an old range"); + "access-policy identity change should not reuse an old range"); TEST_ASSERT(source->query_calls == 2, - "cache key should include access-policy identity"); + "cache key should include access-policy identity"); return true; } @@ -894,9 +894,9 @@ bool test_semantics_revision_change_invalidates_auto_range_cache() &cache); TEST_ASSERT(range.first == 8.0f && range.second == 10.0f, - "semantics revision change should force a fresh query result"); + "semantics revision change should force a fresh query result"); TEST_ASSERT(source->query_calls == 2, - "cache key should include explicit semantics revision"); + "cache key should include explicit semantics revision"); return true; } @@ -921,7 +921,7 @@ bool test_removed_series_prunes_auto_range_cache() true, &cache); TEST_ASSERT(cache.main_entries.size() == 1, - "first query should populate one cache entry"); + "first query should populate one cache entry"); std::map> empty_series; (void)plot::detail::resolve_main_v_range( @@ -931,7 +931,7 @@ bool test_removed_series_prunes_auto_range_cache() true, &cache); TEST_ASSERT(cache.main_entries.empty(), - "removed series should be pruned from auto-range cache"); + "removed series should be pruned from auto-range cache"); return true; } @@ -959,13 +959,13 @@ bool test_preview_auto_range_uses_preview_query_source() config); TEST_ASSERT(range.first == -2.0f && range.second == 11.0f, - "preview auto-range should use the preview source query"); + "preview auto-range should use the preview source query"); TEST_ASSERT(main_source->query_calls == 0, - "preview resolver should not query the main source when a preview source is set"); + "preview resolver should not query the main source when a preview source is set"); TEST_ASSERT(preview_source->query_calls == 1, - "preview resolver should query preview source"); + "preview resolver should query preview source"); TEST_ASSERT(preview_source->snapshot_calls == 0, - "READY preview query should avoid snapshot fallback"); + "READY preview query should avoid snapshot fallback"); return true; } @@ -1010,19 +1010,19 @@ bool test_frame_range_planner_populates_ranges_and_reuses_cache() true); TEST_ASSERT(first.main_v_range.valid && first.main_v_range.min == 2.0f && - first.main_v_range.max == 5.0f, + first.main_v_range.max == 5.0f, "frame planner should populate the main range plan"); TEST_ASSERT(first.preview_v_range.valid && first.preview_v_range.min == -2.0f && - first.preview_v_range.max == 11.0f, + first.preview_v_range.max == 11.0f, "frame planner should populate the preview range plan"); TEST_ASSERT(second.main_v_range.min == 2.0f && second.main_v_range.max == 5.0f, - "frame planner should reuse cached main range values"); + "frame planner should reuse cached main range values"); TEST_ASSERT(second.preview_v_range.min == -2.0f && second.preview_v_range.max == 11.0f, - "frame planner should reuse cached preview range values"); + "frame planner should reuse cached preview range values"); TEST_ASSERT(main_source->query_calls == 1, - "frame planner should preserve main range cache reuse"); + "frame planner should preserve main range cache reuse"); TEST_ASSERT(preview_source->query_calls == 1, - "frame planner should preserve preview range cache reuse"); + "frame planner should preserve preview range cache reuse"); main_source->query_range = {-4.0f, 12.0f}; main_source->query_sequence = 10; @@ -1035,12 +1035,12 @@ bool test_frame_range_planner_populates_ranges_and_reuses_cache() true); TEST_ASSERT(after_sequence_change.main_v_range.min == -4.0f && - after_sequence_change.main_v_range.max == 12.0f, + after_sequence_change.main_v_range.max == 12.0f, "frame planner should preserve sequence-based main cache invalidation"); TEST_ASSERT(main_source->query_calls == 2, - "main sequence change should force a fresh planner query"); + "main sequence change should force a fresh planner query"); TEST_ASSERT(preview_source->query_calls == 1, - "unchanged preview range should remain cached"); + "unchanged preview range should remain cached"); return true; } @@ -1071,13 +1071,13 @@ bool test_frame_range_planner_skips_preview_when_disabled() false); TEST_ASSERT(plan.main_v_range.min == 1.0f && plan.main_v_range.max == 4.0f, - "disabled-preview planner should still compute the main range"); + "disabled-preview planner should still compute the main range"); TEST_ASSERT(plan.preview_v_range.min == 1.0f && plan.preview_v_range.max == 4.0f, - "disabled-preview planner should mirror the main range"); + "disabled-preview planner should mirror the main range"); TEST_ASSERT(main_source->query_calls == 1, - "disabled-preview planner should query the main source"); + "disabled-preview planner should query the main source"); TEST_ASSERT(preview_source->query_calls == 0, - "disabled-preview planner should not query preview sources"); + "disabled-preview planner should not query preview sources"); return true; } @@ -1108,11 +1108,11 @@ bool test_frame_range_planner_preserves_step_after_visible_scan() false); TEST_ASSERT(plan.main_v_range.min == -3.0f && plan.main_v_range.max == 8.0f, - "frame planner should preserve visible STEP_AFTER held-sample scan behavior"); + "frame planner should preserve visible STEP_AFTER held-sample scan behavior"); TEST_ASSERT(source->query_calls == 1, - "frame planner should try query_v_range before step-after scan fallback"); + "frame planner should try query_v_range before step-after scan fallback"); TEST_ASSERT(source->snapshot_calls == 1, - "unsupported step-after query should fall back to one snapshot scan"); + "unsupported step-after query should fall back to one snapshot scan"); return true; } @@ -1133,11 +1133,11 @@ bool test_manual_range_skips_queries() false); TEST_ASSERT(range.first == cfg.v_manual_min && range.second == cfg.v_manual_max, - "manual v-range should return manual config values"); + "manual v-range should return manual config values"); TEST_ASSERT(source->query_calls == 0, - "manual v-range should not query sources"); + "manual v-range should not query sources"); TEST_ASSERT(source->snapshot_calls == 0, - "manual v-range should not snapshot sources"); + "manual v-range should not snapshot sources"); return true; } diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index 73f556af..eae362e4 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -285,7 +285,7 @@ bool test_vector_source_snapshots_progress_while_set_data_is_active() auto reader_fn = [&] { while (!readers_started.load(std::memory_order_acquire) && - !readers_stop.load(std::memory_order_acquire)) + !readers_stop.load(std::memory_order_acquire)) { std::this_thread::yield(); } @@ -328,7 +328,7 @@ bool test_vector_source_snapshots_progress_while_set_data_is_active() const auto destroy_deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(2000); while (!probe->destroy_entered.load(std::memory_order_acquire) && - std::chrono::steady_clock::now() < destroy_deadline) + std::chrono::steady_clock::now() < destroy_deadline) { std::this_thread::yield(); } @@ -339,7 +339,7 @@ bool test_vector_source_snapshots_progress_while_set_data_is_active() const auto read_deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(2000); while (active_reads.load(std::memory_order_acquire) < required_active_reads && - std::chrono::steady_clock::now() < read_deadline) + std::chrono::steady_clock::now() < read_deadline) { std::this_thread::yield(); } @@ -432,8 +432,8 @@ bool test_ring_source_snapshots_are_consistent_under_concurrent_writes() } std::uint64_t current = observed_max_sequence.load(std::memory_order_relaxed); while (snap.sequence > current && - !observed_max_sequence.compare_exchange_weak(current, snap.sequence, - std::memory_order_relaxed)) + !observed_max_sequence.compare_exchange_weak(current, snap.sequence, + std::memory_order_relaxed)) { } } diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index aed106e2..d6066f91 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -157,8 +157,8 @@ bool test_decimal_precision_helpers_reject_invalid_scaled_values() TEST_ASSERT(!plot::detail::any_fractional_at_precision({nan}, 1), "NaN values should be rejected cleanly"); TEST_ASSERT(!plot::detail::any_fractional_at_precision( - { std::numeric_limits::max() }, - 1), + { std::numeric_limits::max() }, + 1), "values whose scaled form exceeds the safe integer range should be rejected"); TEST_ASSERT(!plot::detail::any_fractional_at_precision({1.25}, 400), "overflowing precision scale should be rejected cleanly"); @@ -240,18 +240,18 @@ bool test_raw_timestamp_search_rejects_zero_stride() }; TEST_ASSERT(plot::detail::lower_bound_timestamp( - samples.data(), - samples.size(), - 0, - get_ts, - std::int64_t{1}) == 0, + samples.data(), + samples.size(), + 0, + get_ts, + std::int64_t{1}) == 0, "raw lower_bound should reject stride-zero input"); TEST_ASSERT(plot::detail::upper_bound_timestamp( - samples.data(), - samples.size(), - 0, - get_ts, - std::int64_t{1}) == 0, + samples.data(), + samples.size(), + 0, + get_ts, + std::int64_t{1}) == 0, "raw upper_bound should reject stride-zero input"); TEST_ASSERT(get_timestamp_calls == 0, "stride-zero search should not call the timestamp accessor"); @@ -616,32 +616,32 @@ bool test_time_unit_helpers_handle_edges() plot::time_range_t{k_max - 20, k_max - 10}, 50); TEST_ASSERT(shifted_right - && shifted_right->min_ns == k_max - 10 - && shifted_right->max_ns == k_max, + && shifted_right->min_ns == k_max - 10 && + shifted_right->max_ns == k_max, "positive translation at INT64_MAX should clamp while preserving span"); const auto shifted_left = plot::translate_time_range_ns( plot::time_range_t{k_min + 10, k_min + 20}, -50); TEST_ASSERT(shifted_left - && shifted_left->min_ns == k_min - && shifted_left->max_ns == k_min + 10, + && shifted_left->min_ns == k_min && + shifted_left->max_ns == k_min + 10, "negative translation at INT64_MIN should clamp while preserving span"); const auto clamped_to_edge = plot::clamp_time_range_to_available_ns( plot::time_range_t{k_max - 12, k_max - 2}, plot::time_range_t{k_min + 4, k_max - 5}); TEST_ASSERT(clamped_to_edge - && clamped_to_edge->min_ns == k_max - 15 - && clamped_to_edge->max_ns == k_max - 5, + && clamped_to_edge->min_ns == k_max - 15 && + clamped_to_edge->max_ns == k_max - 5, "availability clamp should preserve target span near INT64_MAX"); const auto clamped_full_target = plot::clamp_time_range_to_available_ns( plot::time_range_t{k_min, k_max}, plot::time_range_t{-500, 500}); TEST_ASSERT(clamped_full_target - && clamped_full_target->min_ns == -500 - && clamped_full_target->max_ns == 500, + && clamped_full_target->min_ns == -500 && + clamped_full_target->max_ns == 500, "target wider than availability should adopt the available range"); const std::string formatted = plot::default_format_timestamp(k_min, plot::k_ns_per_second); @@ -723,10 +723,10 @@ bool test_text_lcd_policy_helpers() TEST_ASSERT(plot::detail::text_lcd_effective_order(auto_request, order) == order, "AUTO should resolve to every display-specific detected order"); TEST_ASSERT(plot::detail::text_lcd_draw_is_eligible( - surface_t::VERTICAL_AXIS_LABEL, order, 1.0f, true), + surface_t::VERTICAL_AXIS_LABEL, order, 1.0f, true), "vertical axis labels may be LCD-eligible for every display-specific order"); TEST_ASSERT(plot::detail::text_lcd_draw_is_eligible( - surface_t::HORIZONTAL_AXIS_LABEL, order, 1.0f, true), + surface_t::HORIZONTAL_AXIS_LABEL, order, 1.0f, true), "horizontal axis labels may be LCD-eligible for every display-specific order"); } @@ -787,26 +787,26 @@ bool test_text_lcd_policy_helpers() "manual frame order should still work without config"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - surface_t::HORIZONTAL_AXIS_LABEL, resolved_t::RGB, 1.0f, false), + surface_t::HORIZONTAL_AXIS_LABEL, resolved_t::RGB, 1.0f, false), "horizontal axis labels should not be LCD-eligible without backing"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - surface_t::VERTICAL_AXIS_LABEL, resolved_t::RGB, 1.0f, false), + surface_t::VERTICAL_AXIS_LABEL, resolved_t::RGB, 1.0f, false), "vertical axis labels should not be LCD-eligible without backing"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - surface_t::VERTICAL_AXIS_LABEL, resolved_t::NONE, 1.0f, true), + surface_t::VERTICAL_AXIS_LABEL, resolved_t::NONE, 1.0f, true), "axis labels should not be LCD-eligible for NONE frame order"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - surface_t::HORIZONTAL_AXIS_LABEL, resolved_t::NONE, 1.0f, true), + surface_t::HORIZONTAL_AXIS_LABEL, resolved_t::NONE, 1.0f, true), "axis labels should not be LCD-eligible for NONE frame order"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - surface_t::VERTICAL_AXIS_LABEL, resolved_t::RGB, 0.998f, true), + surface_t::VERTICAL_AXIS_LABEL, resolved_t::RGB, 0.998f, true), "axis labels should not be LCD-eligible with translucent backing"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - surface_t::VERTICAL_AXIS_LABEL, resolved_t::RGB, - std::numeric_limits::quiet_NaN(), true), + surface_t::VERTICAL_AXIS_LABEL, resolved_t::RGB, + std::numeric_limits::quiet_NaN(), true), "axis labels should not be LCD-eligible with unknown backing alpha"); TEST_ASSERT(!plot::detail::text_lcd_draw_is_eligible( - static_cast(255), resolved_t::RGB, 1.0f, true), + static_cast(255), resolved_t::RGB, 1.0f, true), "invalid draw surfaces should fail closed"); return true; diff --git a/tests/test_data_source_queries.cpp b/tests/test_data_source_queries.cpp index 905d4653..00a6782f 100644 --- a/tests/test_data_source_queries.cpp +++ b/tests/test_data_source_queries.cpp @@ -157,11 +157,12 @@ bool test_query_v_range_without_access_is_unsupported() bool test_ready_value_range_scan_populates_sequence() { - Query_source source({ - { 0, 3.0f }, - { 1, -2.0f }, - { 2, 5.0f }, - }); + Query_source source( + { + { 0, 3.0f }, + { 1, -2.0f }, + { 2, 5.0f }, + }); source.set_sequence(123); const plot::Data_access_policy access = make_value_access(); @@ -243,11 +244,12 @@ bool test_ascending_skip_hold_value_range_scans_bounded_prefix() bool test_unordered_value_range_aggregates_discontiguous_matches() { - Query_source source({ - { 0, 1.0f }, - { 100, 100.0f }, - { 5, 2.0f }, - }); + Query_source source( + { + { 0, 1.0f }, + { 100, 100.0f }, + { 5, 2.0f }, + }); source.set_time_order(plot::Time_order::UNORDERED); const plot::Data_access_policy access = make_value_access(); @@ -319,12 +321,13 @@ bool test_nonfinite_values_are_skipped_or_zeroed_by_policy() const plot::Data_access_policy access = make_value_access(); - Query_source mixed_source({ - { 0, 5.0f }, - { 1, nan }, - { 2, -2.0f }, - { 3, inf }, - }); + Query_source mixed_source( + { + { 0, 5.0f }, + { 1, nan }, + { 2, -2.0f }, + { 3, inf }, + }); const auto default_query = make_query(access, 0, 3); TEST_ASSERT(default_query.nonfinite_policy == plot::Nonfinite_sample_policy::BREAK_SEGMENT, "query default nonfinite policy should be BREAK_SEGMENT"); @@ -336,10 +339,11 @@ bool test_nonfinite_values_are_skipped_or_zeroed_by_policy() TEST_ASSERT(default_result.value.min == -2.0f && default_result.value.max == 5.0f, "nonfinite values should not contribute to the default aggregate range"); - Query_source nonfinite_source({ - { 0, nan }, - { 1, inf }, - }); + Query_source nonfinite_source( + { + { 0, nan }, + { 1, inf }, + }); auto replace_query = make_query(access, 0, 1); replace_query.nonfinite_policy = plot::Nonfinite_sample_policy::REPLACE_WITH_ZERO; const auto replace_result = nonfinite_source.query_v_range(0, replace_query); @@ -385,13 +389,14 @@ bool test_query_time_window_returns_simple_ascending_window() bool test_query_time_window_handles_descending_inclusive_bounds() { - Query_source source({ - { 9, 9.0f }, - { 7, 7.0f }, - { 5, 5.0f }, - { 3, 3.0f }, - { 1, 1.0f }, - }); + Query_source source( + { + { 9, 9.0f }, + { 7, 7.0f }, + { 5, 5.0f }, + { 3, 3.0f }, + { 1, 1.0f }, + }); source.set_time_order(plot::Time_order::DESCENDING); const plot::Data_access_policy access = make_timestamp_access(); @@ -406,12 +411,13 @@ bool test_query_time_window_handles_descending_inclusive_bounds() bool test_query_time_window_hold_forward_includes_held_sample() { - Query_source source({ - { 0, 0.0f }, - { 10, 10.0f }, - { 20, 20.0f }, - { 30, 30.0f }, - }); + Query_source source( + { + { 0, 0.0f }, + { 10, 10.0f }, + { 20, 20.0f }, + { 30, 30.0f }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_timestamp_access(); @@ -427,11 +433,12 @@ bool test_query_time_window_hold_forward_includes_held_sample() bool test_query_time_window_keeps_break_segment_gaps_in_window() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 1.0f }, - { 1, nan }, - { 2, 2.0f }, - }); + Query_source source( + { + { 0, 1.0f }, + { 1, nan }, + { 2, 2.0f }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -447,11 +454,12 @@ bool test_query_time_window_keeps_break_segment_gaps_in_window() bool test_query_time_window_reject_window_fails_on_nonfinite_in_window_sample() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 1.0f }, - { 1, nan }, - { 2, 2.0f }, - }); + Query_source source( + { + { 0, 1.0f }, + { 1, nan }, + { 2, 2.0f }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -467,10 +475,11 @@ bool test_query_time_window_reject_window_fails_on_nonfinite_in_window_sample() bool test_query_time_window_does_not_hold_nonfinite_break_segment_sample() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 7.0f }, - { 2, nan }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, nan }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -484,10 +493,11 @@ bool test_query_time_window_does_not_hold_nonfinite_break_segment_sample() bool test_query_time_window_skip_holds_latest_drawable_sample() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 7.0f }, - { 2, nan }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, nan }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -505,10 +515,11 @@ bool test_query_time_window_skip_holds_latest_drawable_sample() bool test_query_time_window_reject_window_fails_on_nonfinite_held_sample() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 7.0f }, - { 2, nan }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, nan }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -523,11 +534,12 @@ bool test_query_time_window_reject_window_fails_on_nonfinite_held_sample() bool test_hold_forward_value_range_includes_pre_window_sample() { - Query_source source({ - { 0, 10.0f }, - { 5, 1.0f }, - { 6, 2.0f }, - }); + Query_source source( + { + { 0, 10.0f }, + { 5, 1.0f }, + { 6, 2.0f }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -542,10 +554,11 @@ bool test_hold_forward_value_range_includes_pre_window_sample() bool test_hold_forward_value_range_ready_from_held_sample_only() { - Query_source source({ - { 0, 7.0f }, - { 2, 9.0f }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, 9.0f }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -561,10 +574,11 @@ bool test_hold_forward_value_range_ready_from_held_sample_only() bool test_hold_forward_does_not_use_nonfinite_break_segment_sample() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 7.0f }, - { 2, nan }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, nan }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -578,10 +592,11 @@ bool test_hold_forward_does_not_use_nonfinite_break_segment_sample() bool test_hold_forward_skip_uses_latest_drawable_pre_window_sample() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 7.0f }, - { 2, nan }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, nan }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); @@ -599,10 +614,11 @@ bool test_hold_forward_skip_uses_latest_drawable_pre_window_sample() bool test_hold_forward_reject_window_fails_on_nonfinite_held_candidate() { const float nan = std::numeric_limits::quiet_NaN(); - Query_source source({ - { 0, 7.0f }, - { 2, nan }, - }); + Query_source source( + { + { 0, 7.0f }, + { 2, nan }, + }); source.set_time_order(plot::Time_order::ASCENDING); const plot::Data_access_policy access = make_value_access(); diff --git a/tests/test_font_renderer_bounds.cpp b/tests/test_font_renderer_bounds.cpp index 504be4c8..f3508c6d 100644 --- a/tests/test_font_renderer_bounds.cpp +++ b/tests/test_font_renderer_bounds.cpp @@ -25,7 +25,7 @@ bool finite_ordered(const glm::vec4& bounds) std::isfinite(bounds.y) && std::isfinite(bounds.z) && std::isfinite(bounds.w) && - bounds.z > bounds.x && + bounds.z > bounds.x && bounds.w > bounds.y; } diff --git a/tests/test_function_sample_source.cpp b/tests/test_function_sample_source.cpp index 7817bac1..9cd70df6 100644 --- a/tests/test_function_sample_source.cpp +++ b/tests/test_function_sample_source.cpp @@ -113,7 +113,7 @@ bool test_function_sample_policy_uses_callable_manual_keys() TEST_ASSERT(erased.layout_key == policy.layout_key, "erased function sample policy should preserve layout key"); TEST_ASSERT(!erased_key.conservative && - erased_key.value == policy.semantics_key.value, + erased_key.value == policy.semantics_key.value, "erased function sample policy should preserve explicit semantics key"); TEST_ASSERT(erased.get_timestamp(&sample) == k_expected_timestamp_ns, "erased function sample timestamp accessor mismatch"); diff --git a/tests/test_label_pane_geometry.cpp b/tests/test_label_pane_geometry.cpp index 7776f923..5358bb53 100644 --- a/tests/test_label_pane_geometry.cpp +++ b/tests/test_label_pane_geometry.cpp @@ -33,11 +33,11 @@ bool rect_equal(const glm::vec4& lhs, const glm::vec4& rhs) bool scissor_inside_frame(const plot::text_scissor_t& scissor, int width, int height) { return - scissor.enabled && - scissor.x >= 0 && - scissor.y >= 0 && - scissor.width > 0 && - scissor.height > 0 && + scissor.enabled && + scissor.x >= 0 && + scissor.y >= 0 && + scissor.width > 0 && + scissor.height > 0 && scissor.x + scissor.width <= width && scissor.y + scissor.height <= height; } @@ -88,7 +88,7 @@ bool test_no_preview_horizontal_pane_scissor_reaches_frame_bottom() plot::text_scissor_t scissor; TEST_ASSERT(plot::detail::framebuffer_scissor_from_top_left_rect( - horizontal, ctx.win_w, ctx.win_h, scissor), + horizontal, ctx.win_w, ctx.win_h, scissor), "horizontal axis label pane must convert to an in-frame scissor"); TEST_ASSERT(scissor.x == 0 && scissor.y == 0 && scissor.width == 900 && scissor.height == 34, "frame-bottom horizontal pane must map to QRhi y=0 scissor"); @@ -121,7 +121,7 @@ bool test_partial_overflow_horizontal_pane_clamps_to_frame_bottom() plot::text_scissor_t scissor; TEST_ASSERT(plot::detail::framebuffer_scissor_from_top_left_rect( - horizontal, ctx.win_w, ctx.win_h, scissor), + horizontal, ctx.win_w, ctx.win_h, scissor), "partial-overflow horizontal pane must convert to an in-frame scissor"); TEST_ASSERT(scissor.x == 0 && scissor.y == 0 && scissor.width == ctx.win_w, "partial-overflow horizontal pane scissor must span the frame bottom edge"); @@ -155,10 +155,10 @@ bool test_partial_overflow_vertical_pane_clamps_to_frame_right() plot::text_scissor_t scissor; TEST_ASSERT(plot::detail::framebuffer_scissor_from_top_left_rect( - vertical, ctx.win_w, ctx.win_h, scissor), + vertical, ctx.win_w, ctx.win_h, scissor), "partial-overflow vertical pane must convert to an in-frame scissor"); TEST_ASSERT(scissor.x == static_cast(layout.usable_width) && - scissor.y == ctx.win_h - static_cast(layout.usable_height), + scissor.y == ctx.win_h - static_cast(layout.usable_height), "partial-overflow vertical pane scissor must keep the expected QRhi origin"); TEST_ASSERT(scissor.width > 0 && scissor.width < layout.v_bar_width, "partial-overflow vertical pane scissor must be smaller than the full label lane"); @@ -186,7 +186,7 @@ bool test_standard_vertical_pane_scissor_maps_to_qrhi_coordinates() plot::text_scissor_t scissor; TEST_ASSERT(plot::detail::framebuffer_scissor_from_top_left_rect( - vertical, ctx.win_w, ctx.win_h, scissor), + vertical, ctx.win_w, ctx.win_h, scissor), "standard vertical axis label pane must convert to an in-frame scissor"); TEST_ASSERT(scissor.y == 120 && scissor.height == 360, "standard vertical pane must map to the expected QRhi y and height"); @@ -221,21 +221,21 @@ bool test_invalid_inputs_fail_closed() plot::text_scissor_t scissor; scissor.enabled = true; TEST_ASSERT(!plot::detail::framebuffer_scissor_from_top_left_rect( - glm::vec4(0.0f, nan, 40.0f, 60.0f), 100, 80, scissor), + glm::vec4(0.0f, nan, 40.0f, 60.0f), 100, 80, scissor), "NaN rect must fail closed"); TEST_ASSERT(!scissor.enabled, "NaN rect failure must disable the scissor"); scissor.enabled = true; TEST_ASSERT(!plot::detail::framebuffer_scissor_from_top_left_rect( - glm::vec4(0.0f, 10.0f, infinity, 60.0f), 100, 80, scissor), + glm::vec4(0.0f, 10.0f, infinity, 60.0f), 100, 80, scissor), "infinite rect must fail closed"); TEST_ASSERT(!scissor.enabled, "infinite rect failure must disable the scissor"); scissor.enabled = true; TEST_ASSERT(!plot::detail::framebuffer_scissor_from_top_left_rect( - glm::vec4(0.0f, 10.0f, 40.0f, 60.0f), 0, 0, scissor), + glm::vec4(0.0f, 10.0f, 40.0f, 60.0f), 0, 0, scissor), "zero-size window must fail closed"); TEST_ASSERT(!scissor.enabled, "zero-size window failure must disable the scissor"); @@ -259,7 +259,7 @@ bool test_degenerate_and_offscreen_panes_fail_closed() { plot::text_scissor_t scissor; TEST_ASSERT(!plot::detail::framebuffer_scissor_from_top_left_rect( - glm::vec4(10.2f, 10.0f, 10.8f, 30.0f), 100, 80, scissor), + glm::vec4(10.2f, 10.0f, 10.8f, 30.0f), 100, 80, scissor), "subpixel-width rect with no covered integer pixels must fail closed"); TEST_ASSERT(!scissor.enabled, "failed degenerate scissor must be disabled"); diff --git a/tests/test_layout_calculator.cpp b/tests/test_layout_calculator.cpp index fb88f2ad..d04b8169 100644 --- a/tests/test_layout_calculator.cpp +++ b/tests/test_layout_calculator.cpp @@ -131,7 +131,7 @@ bool test_format_timestamp_receives_nanosecond_units() } TEST_ASSERT(saw_label_in_window, std::string("expected at least one formatter call with a timestamp " - "inside the visible window [") + + "inside the visible window [") + std::to_string(k_t_min_ns) + " .. " + std::to_string(k_t_max_ns) + "]; if the calculator passed t_seconds instead of t_ns, the " "values would land near 1.7e9 instead of 1.7e18"); @@ -143,7 +143,7 @@ bool test_format_timestamp_receives_nanosecond_units() constexpr std::int64_t k_sentinel_hi = std::numeric_limits::max(); for (const auto& call : recorded) { TEST_ASSERT(call.timestamp_ns != k_sentinel_lo && - call.timestamp_ns != k_sentinel_hi, + call.timestamp_ns != k_sentinel_hi, "no formatter call should receive an INT64 sentinel timestamp"); TEST_ASSERT(call.step_ns > 0, "formatter step must be positive (the calculator should never " diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 60f8d91d..42f6e63a 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -48,12 +48,18 @@ bool is_glsl_identifier_char(unsigned char ch) bool is_glsl_two_char_operator(std::string_view text) { return - text == "&&" || text == "||" || - text == "<=" || text == ">=" || - text == "==" || text == "!=" || - text == "++" || text == "--" || - text == "+=" || text == "-=" || - text == "*=" || text == "/="; + text == "&&" || + text == "||" || + text == "<=" || + text == ">=" || + text == "==" || + text == "!=" || + text == "++" || + text == "--" || + text == "+=" || + text == "-=" || + text == "*=" || + text == "/="; } glsl_token_list_t tokenize_glsl(std::string_view text) @@ -89,7 +95,7 @@ glsl_token_list_t tokenize_glsl(std::string_view text) if (is_glsl_identifier_start(ch)) { const std::size_t start = pos++; while (pos < text.size() && - is_glsl_identifier_char(static_cast(text[pos]))) + is_glsl_identifier_char(static_cast(text[pos]))) { ++pos; } @@ -219,9 +225,11 @@ std::string decode_threshold_statement(const ref::decode_threshold_t& threshold) } return - "bool " + bool_name + " = u.lcd_subpixel_order " + - condition.substr(0, separator_pos) + - " && u.lcd_subpixel_order " + + "bool " + + bool_name + + " = u.lcd_subpixel_order " + + condition.substr(0, separator_pos) + + " && u.lcd_subpixel_order " + condition.substr(separator_pos + separator.size()) + ";"; } @@ -234,8 +242,12 @@ std::string sample_statement_for_offset(float offset) return {}; } - return "float " + sample_name + " = glyph_alpha_at_ratio(" + - expression + ", uv_min, uv_max);"; + return + "float " + + sample_name + + " = glyph_alpha_at_ratio(" + + expression + + ", uv_min, uv_max);"; } std::string filter_weight_statement(std::string_view name, std::string_view literal) @@ -276,20 +288,21 @@ std::string lcd_vertical_group_statement() std::string subpixel_step_statement() { return - "vec2 subpixel_step = lcd_horizontal\n" - " ? vec2(" + std::string(ref::k_lcd_horizontal_step_glsl) + ", 0.0)\n" - " : vec2(0.0, " + std::string(ref::k_lcd_vertical_step_glsl) + ");"; + "vec2 subpixel_step = lcd_horizontal\n" " ? vec2(" + + std::string(ref::k_lcd_horizontal_step_glsl) + + ", 0.0)\n" " : vec2(0.0, " + + std::string(ref::k_lcd_vertical_step_glsl) + + ");"; } std::string lcd_enabled_statement() { return - "bool lcd_enabled =\n" - " (lcd_horizontal || lcd_vertical) &&\n" - " u.shadow_radius <= 0.0 &&\n" - " u.color.a >= " + std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + " &&\n" - " u.background_color.a >= " + - std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + ";"; + "bool lcd_enabled =\n" " (lcd_horizontal || lcd_vertical) &&\n" " u.shadow_radius <= 0.0 &&\n" " u.color.a >= " + + std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + + " &&\n" " u.background_color.a >= " + + std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + + ";"; } std::string forward_order_statement() @@ -351,13 +364,13 @@ bool test_plot_shader_binds_lcd_reference_literals() } TEST_ASSERT(contains_glsl_token_sequence( - shader_tokens, filter_weight_statement("filter_edge", ref::k_lcd_filter_edge_glsl)), + shader_tokens, filter_weight_statement("filter_edge", ref::k_lcd_filter_edge_glsl)), "plot shader LCD edge filter literal must match shared reference"); TEST_ASSERT(contains_glsl_token_sequence( - shader_tokens, filter_weight_statement("filter_side", ref::k_lcd_filter_side_glsl)), + shader_tokens, filter_weight_statement("filter_side", ref::k_lcd_filter_side_glsl)), "plot shader LCD side filter literal must match shared reference"); TEST_ASSERT(contains_glsl_token_sequence( - shader_tokens, filter_weight_statement("filter_center", ref::k_lcd_filter_center_glsl)), + shader_tokens, filter_weight_statement("filter_center", ref::k_lcd_filter_center_glsl)), "plot shader LCD center filter literal must match shared reference"); for (const ref::filter_window_t& window : ref::k_lcd_filter_windows) { @@ -389,7 +402,7 @@ bool test_plot_shader_binds_lcd_reference_literals() TEST_ASSERT(contains_glsl_token_sequence(shader_tokens, lcd_enabled_statement()), "plot shader opacity cutoff expression must match shared reference"); TEST_ASSERT(plot::detail::k_text_lcd_opaque_alpha_cutoff == - ref::k_lcd_opaque_alpha_cutoff, + ref::k_lcd_opaque_alpha_cutoff, "plot CPU opacity cutoff must match shared shader reference"); return true; diff --git a/tests/test_qrhi_layer_lifecycle.cpp b/tests/test_qrhi_layer_lifecycle.cpp index 90199a18..cc93985f 100644 --- a/tests/test_qrhi_layer_lifecycle.cpp +++ b/tests/test_qrhi_layer_lifecycle.cpp @@ -569,10 +569,10 @@ bool assert_compact_upload_state( std::to_string(view_state.last_staged_sample_count) + ", expected " + std::to_string(prepare.gpu_count)); TEST_ASSERT(view_state.last_sample_upload_bytes == - prepare.gpu_count * k_gpu_sample_bytes, + prepare.gpu_count * k_gpu_sample_bytes, std::string(label) + " upload bytes must match compact GPU sample count"); TEST_ASSERT(view_state.last_sample_upload_bytes < - prepare.snapshot_count * k_gpu_sample_bytes, + prepare.snapshot_count * k_gpu_sample_bytes, std::string(label) + " upload bytes must not scale with full snapshot count"); TEST_ASSERT( view_state.last_line_window_sample_count == @@ -587,23 +587,23 @@ bool assert_compact_upload_state( TEST_ASSERT(prepare.sample_buffer_sample_count == prepare.gpu_count, std::string(label) + " sample buffer count mismatch"); TEST_ASSERT(prepare.sample_buffer_source_first == prepare.source_first && - prepare.sample_buffer_source_count == prepare.source_count && - prepare.sample_buffer_synthetic_hold_count == - prepare.synthetic_hold_count, + prepare.sample_buffer_source_count == prepare.source_count && + prepare.sample_buffer_synthetic_hold_count == + prepare.synthetic_hold_count, std::string(label) + " sample buffer window metadata mismatch"); TEST_ASSERT(prepare.sample_buffer_t_origin_ns == prepare.t_origin_ns && - prepare.sample_buffer_t_min_ns == prepare.t_min_ns && - prepare.sample_buffer_t_max_ns == prepare.t_max_ns, + prepare.sample_buffer_t_min_ns == prepare.t_min_ns && + prepare.sample_buffer_t_max_ns == prepare.t_max_ns, std::string(label) + " sample buffer time metadata mismatch"); TEST_ASSERT(prepare.sample_buffer_v_min == prepare.v_min && - prepare.sample_buffer_v_max == prepare.v_max, + prepare.sample_buffer_v_max == prepare.v_max, std::string(label) + " sample buffer value range mismatch"); TEST_ASSERT(prepare.sample_buffer_stride_bytes == k_gpu_sample_bytes, std::string(label) + " sample buffer stride mismatch"); TEST_ASSERT(prepare.sample_buffer_t_rel_seconds_offset == 0u && - prepare.sample_buffer_value_offset == sizeof(float) && - prepare.sample_buffer_range_min_offset == sizeof(float) * 2u && - prepare.sample_buffer_range_max_offset == sizeof(float) * 3u, + prepare.sample_buffer_value_offset == sizeof(float) && + prepare.sample_buffer_range_min_offset == sizeof(float) * 2u && + prepare.sample_buffer_range_max_offset == sizeof(float) * 3u, std::string(label) + " sample buffer lane offsets mismatch"); return true; @@ -1020,7 +1020,7 @@ bool test_combined_builtin_uploads_samples_once_per_view() TEST_ASSERT(view_state.last_staged_sample_count == prepare->gpu_count, "combined style upload must stage the shared compact GPU window"); TEST_ASSERT(view_state.last_sample_upload_bytes == - prepare->gpu_count * k_gpu_sample_bytes, + prepare->gpu_count * k_gpu_sample_bytes, "combined style upload bytes must match one compact GPU window"); TEST_ASSERT(view_state.last_line_window_sample_count == prepare->gpu_count, "combined style LINE primitive should still prepare its padded window"); @@ -1132,8 +1132,8 @@ bool test_direct_member_policy_uses_member_dispatch_in_renderer_staging() plot::detail::access_dispatch_kind_t::STD_FUNCTION, "capturing renderer fallback should use std::function dispatch"); TEST_ASSERT(fallback_calls.timestamp > 0 && - fallback_calls.value > 0 && - fallback_calls.range > 0, + fallback_calls.value > 0 && + fallback_calls.range > 0, "capturing renderer fallback should call public std::function accessors"); return true; @@ -1208,8 +1208,8 @@ bool test_access_policy_change_reuploads_builtin_samples() plot::detail::access_dispatch_kind_t::STD_FUNCTION, "changed policy should stage with std::function dispatch"); TEST_ASSERT(changed_calls.timestamp > 0 && - changed_calls.value > 0 && - changed_calls.range > 0, + changed_calls.value > 0 && + changed_calls.range > 0, "changed policy should invoke replacement public accessors"); return true; @@ -1369,23 +1369,23 @@ bool test_nonfinite_break_and_skip_split_drawable_spans() TEST_ASSERT(view_state.last_staged_sample_count == 4, "gap staging should upload four compact samples"); TEST_ASSERT(view_state.staging[0].y == 1.0f && - view_state.staging[1].y == 2.0f && - view_state.staging[2].y == 4.0f && - view_state.staging[3].y == 5.0f, + view_state.staging[1].y == 2.0f && + view_state.staging[2].y == 4.0f && + view_state.staging[3].y == 5.0f, "gap staging should omit the nonfinite sample without reordering valid samples"); const std::size_t expected_builtin_span_count = test_case.policy == plot::Nonfinite_sample_policy::SKIP ? 1u : 2u; const std::size_t expected_builtin_segment_count = test_case.policy == plot::Nonfinite_sample_policy::SKIP ? 3u : 2u; TEST_ASSERT(view_state.last_recorded_line_span_count == - expected_builtin_span_count && + expected_builtin_span_count && view_state.last_recorded_line_segment_count == - expected_builtin_segment_count, + expected_builtin_segment_count, "LINE rendering should break only for BREAK_SEGMENT and compact SKIP gaps"); TEST_ASSERT(view_state.last_recorded_area_span_count == - expected_builtin_span_count && + expected_builtin_span_count && view_state.last_recorded_area_segment_count == - expected_builtin_segment_count, + expected_builtin_segment_count, "AREA rendering should break only for BREAK_SEGMENT and compact SKIP gaps"); TEST_ASSERT(view_state.last_recorded_dot_sample_count == 4, "DOTS rendering should draw only compact valid samples"); @@ -1471,14 +1471,14 @@ bool test_nonfinite_replace_with_zero_keeps_contiguous_span() TEST_ASSERT(view_state.last_staged_sample_count == 5, "REPLACE_WITH_ZERO should stage all five samples"); TEST_ASSERT(view_state.staging[2].y == 0.0f && - view_state.staging[2].y_min == 0.0f && - view_state.staging[2].y_max == 0.0f, + view_state.staging[2].y_min == 0.0f && + view_state.staging[2].y_max == 0.0f, "REPLACE_WITH_ZERO should stage zero for nonfinite value/range lanes"); TEST_ASSERT(view_state.last_recorded_line_span_count == 1 && - view_state.last_recorded_line_segment_count == 4, + view_state.last_recorded_line_segment_count == 4, "REPLACE_WITH_ZERO line rendering should remain contiguous"); TEST_ASSERT(view_state.last_recorded_area_span_count == 1 && - view_state.last_recorded_area_segment_count == 4, + view_state.last_recorded_area_segment_count == 4, "REPLACE_WITH_ZERO area rendering should remain contiguous"); TEST_ASSERT(view_state.last_recorded_dot_sample_count == 5, "REPLACE_WITH_ZERO dots should draw every compact sample"); @@ -1543,7 +1543,7 @@ bool test_nonfinite_reject_window_suppresses_drawable_upload() "expected renderer VBO state for reject-window test"); const auto& view_state = state_it->second.main_view; TEST_ASSERT(view_state.last_sample_upload_count == 0 && - view_state.last_staged_sample_count == 0, + view_state.last_staged_sample_count == 0, "REJECT_WINDOW should not upload compact sample data"); return true; @@ -1761,7 +1761,7 @@ bool test_non_drawable_window_invalidates_prior_upload_before_fast_path() TEST_ASSERT(state_it != renderer.m_vbo_states.end(), "expected renderer VBO state for non-drawable fast-path test"); TEST_ASSERT(state_it->second.main_view.has_uploaded_vbo && - state_it->second.main_view.last_staged_sample_count > 1, + state_it->second.main_view.last_staged_sample_count > 1, "initial DOTS frame should upload multiple samples"); source->set_samples({ @@ -1789,7 +1789,7 @@ bool test_non_drawable_window_invalidates_prior_upload_before_fast_path() TEST_ASSERT(state_it->second.main_view.has_uploaded_vbo, "DOTS frame after non-drawable singleton should upload its own VBO"); TEST_ASSERT(state_it->second.main_view.last_sample_upload_count == 1 && - state_it->second.main_view.last_staged_sample_count == 1, + state_it->second.main_view.last_staged_sample_count == 1, "DOTS frame after non-drawable singleton must not reuse the old two-sample upload"); TEST_ASSERT(state_it->second.main_view.staging[0].y == 10.0f, "DOTS frame after non-drawable singleton should stage the singleton sample"); @@ -1841,7 +1841,7 @@ bool test_non_rhi_prepare_invalidates_prior_upload_before_fast_path() TEST_ASSERT(state_it != renderer.m_vbo_states.end(), "expected renderer VBO state for non-RHI prepare test"); TEST_ASSERT(state_it->second.main_view.has_uploaded_vbo && - state_it->second.main_view.last_staged_sample_count > 1, + state_it->second.main_view.last_staged_sample_count > 1, "initial QRhi frame should upload multiple samples"); plot::frame_context_t non_rhi_ctx = make_context(layout, config); @@ -1865,7 +1865,7 @@ bool test_non_rhi_prepare_invalidates_prior_upload_before_fast_path() TEST_ASSERT(state_it->second.main_view.last_staged_sample_count == 2, "QRhi frame after non-RHI prepare should stage the new expanded window"); TEST_ASSERT(state_it->second.main_view.staging[0].y == 2.0f && - state_it->second.main_view.staging[1].y == 10.0f, + state_it->second.main_view.staging[1].y == 10.0f, "QRhi frame after non-RHI prepare should stage samples from the new window"); return true; @@ -1950,10 +1950,10 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() TEST_ASSERT(prepare, "REPLACE_WITH_ZERO held sample should prepare"); TEST_ASSERT(prepare->source_first == test_case.expected_source_first && - prepare->source_count == 1, + prepare->source_count == 1, "drawable held sample should use the expected source sample"); TEST_ASSERT(prepare->synthetic_hold_count == 1 && - prepare->gpu_count == 2, + prepare->gpu_count == 2, "drawable hold should stage source plus synthetic hold samples"); TEST_ASSERT(prepare->drawable_spans.size() == 1, "drawable held sample should have one drawable span"); @@ -1970,7 +1970,7 @@ bool test_nonfinite_hold_forward_policy_controls_held_sample() TEST_ASSERT(view_state.last_staged_sample_count == 2, "drawable held sample should stage two GPU samples"); TEST_ASSERT(view_state.staging[0].y == test_case.expected_value && - view_state.staging[1].y == test_case.expected_value, + view_state.staging[1].y == test_case.expected_value, "held source and synthetic samples should stage the expected value"); } @@ -2034,7 +2034,7 @@ bool test_nonfinite_skip_hold_forward_preserves_earlier_held_sample_with_visible TEST_ASSERT(prepare->source_first == 0 && prepare->source_count == 3, "SKIP held sample should widen the containing source window backward"); TEST_ASSERT(prepare->synthetic_hold_count == 1 && - prepare->gpu_count == 3, + prepare->gpu_count == 3, "SKIP held window should stage held, visible, and synthetic hold samples"); TEST_ASSERT(prepare->drawable_spans.size() == 2, "SKIP held window should keep the skipped sample as a drawable gap"); @@ -2051,14 +2051,14 @@ bool test_nonfinite_skip_hold_forward_preserves_earlier_held_sample_with_visible TEST_ASSERT(view_state.last_staged_sample_count == 3, "SKIP held visible window should stage three compact GPU samples"); TEST_ASSERT(view_state.staging[0].y == 7.0f && - view_state.staging[1].y == 9.0f && - view_state.staging[2].y == 9.0f, + view_state.staging[1].y == 9.0f && + view_state.staging[2].y == 9.0f, "SKIP held visible staging should preserve held, visible, and hold values"); TEST_ASSERT(view_state.last_recorded_line_span_count == 1 && - view_state.last_recorded_line_segment_count == 4, + view_state.last_recorded_line_segment_count == 4, "SKIP held visible LINE rendering should connect the compact held and visible samples"); TEST_ASSERT(view_state.last_recorded_area_span_count == 1 && - view_state.last_recorded_area_segment_count == 2, + view_state.last_recorded_area_segment_count == 2, "SKIP held visible AREA rendering should connect the compact held and visible samples"); TEST_ASSERT(view_state.last_recorded_dot_sample_count == 3, "DOTS should draw the compact held and visible samples"); @@ -2123,7 +2123,7 @@ bool test_nonfinite_skip_hold_forward_ignores_future_padding_without_visible_dat TEST_ASSERT(prepare->source_first == 0 && prepare->source_count == 1, "SKIP held-only window should collapse to the earlier drawable held sample"); TEST_ASSERT(prepare->synthetic_hold_count == 1 && - prepare->gpu_count == 2, + prepare->gpu_count == 2, "SKIP held-only window should stage source plus synthetic hold samples"); TEST_ASSERT(prepare->drawable_spans.size() == 1, "SKIP held-only window should have one drawable span"); @@ -2140,7 +2140,7 @@ bool test_nonfinite_skip_hold_forward_ignores_future_padding_without_visible_dat TEST_ASSERT(view_state.last_staged_sample_count == 2, "SKIP held-only window should stage two compact GPU samples"); TEST_ASSERT(view_state.staging[0].y == 7.0f && - view_state.staging[1].y == 7.0f, + view_state.staging[1].y == 7.0f, "SKIP held-only staging should ignore skipped pre-window and future padding samples"); return true; @@ -2314,8 +2314,8 @@ bool test_builtin_draw_commands_sort_relative_to_custom_layers() TEST_ASSERT(renderer.m_last_qrhi_layer_cache_size == 3, "custom layer cache should contain only the three custom states"); TEST_ASSERT(under_create_count == 1 && - middle_create_count == 1 && - top_create_count == 1, + middle_create_count == 1 && + top_create_count == 1, "custom layer states should each be created once"); const std::size_t under_record = @@ -2755,9 +2755,9 @@ bool test_resources_changed_tracks_hold_timestamp_changes() TEST_ASSERT(first_prepare && first_prepare->resources_changed, "first hold-forward prepare must report resources_changed"); TEST_ASSERT(first_prepare->source_first == 2 && - first_prepare->source_count == 1 && - first_prepare->synthetic_hold_count == 1 && - first_prepare->gpu_count == 2, + first_prepare->source_count == 1 && + first_prepare->synthetic_hold_count == 1 && + first_prepare->gpu_count == 2, "first hold-forward prepare should draw one real and one synthetic sample"); const layer_event_t first = *first_prepare; @@ -2775,10 +2775,10 @@ bool test_resources_changed_tracks_hold_timestamp_changes() TEST_ASSERT(second_prepare->t_origin_ns == first_origin, "hold timestamp test requires both frames to stay in the same origin bucket"); TEST_ASSERT(second_prepare->source_first == first.source_first && - second_prepare->source_count == first.source_count && - second_prepare->synthetic_hold_count == - first.synthetic_hold_count && - second_prepare->gpu_count == first.gpu_count, + second_prepare->source_count == first.source_count && + second_prepare->synthetic_hold_count == + first.synthetic_hold_count && + second_prepare->gpu_count == first.gpu_count, "hold timestamp test requires unchanged source/gpu window metadata"); TEST_ASSERT(second_prepare->resources_changed, "changed hold-forward timestamp must invalidate external layer data key"); @@ -3398,10 +3398,10 @@ bool test_range_only_access_skips_builtin_value_styles() TEST_ASSERT(range_view.last_primitive_prepare_count == 0, "range-only access must not prepare any built-in value primitive"); TEST_ASSERT(range_view.last_recorded_line_segment_count == 0 && - range_view.last_recorded_line_span_count == 0, + range_view.last_recorded_line_span_count == 0, "range-only access must record no line geometry"); TEST_ASSERT(range_view.last_recorded_area_segment_count == 0 && - range_view.last_recorded_area_span_count == 0, + range_view.last_recorded_area_span_count == 0, "range-only access must record no area geometry"); TEST_ASSERT(range_view.last_recorded_dot_sample_count == 0, "range-only access must record no dots"); diff --git a/tests/test_rhi_helpers.cpp b/tests/test_rhi_helpers.cpp index 76168a35..be6f49cf 100644 --- a/tests/test_rhi_helpers.cpp +++ b/tests/test_rhi_helpers.cpp @@ -65,21 +65,21 @@ bool test_qrhi_grown_capacity_bytes_checks_headroom_overflow() static_cast(std::numeric_limits::max()); TEST_ASSERT(plot::detail::qrhi_grown_capacity_bytes( - 80u, capacity, qrhi_capacity), + 80u, capacity, qrhi_capacity), "QRhi grown-capacity helper must accept ordinary byte counts"); TEST_ASSERT(capacity == 100u && qrhi_capacity == 100u, "QRhi grown-capacity helper must add 25 percent headroom"); TEST_ASSERT(plot::detail::qrhi_grown_capacity_bytes( - max_qrhi, capacity, qrhi_capacity), + max_qrhi, capacity, qrhi_capacity), "QRhi grown-capacity helper must accept a representable full-size buffer"); TEST_ASSERT(capacity == max_qrhi && - qrhi_capacity == std::numeric_limits::max(), + qrhi_capacity == std::numeric_limits::max(), "QRhi grown-capacity helper must cap headroom at quint32 max"); if (std::numeric_limits::max() > max_qrhi) { TEST_ASSERT(!plot::detail::qrhi_grown_capacity_bytes( - max_qrhi + 1u, capacity, qrhi_capacity), + max_qrhi + 1u, capacity, qrhi_capacity), "QRhi grown-capacity helper must reject byte counts above quint32 max"); } return true; diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 555cd42e..8e664b1c 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -385,10 +385,10 @@ bool test_direct_time_window_query_drives_renderer_window() TEST_ASSERT(source->snapshot_calls == 1, "direct time-window planning should still acquire one paired frame snapshot"); TEST_ASSERT(source->last_query_time_window.min_ns == ctx.t0 && - source->last_query_time_window.max_ns == ctx.t1, + source->last_query_time_window.max_ns == ctx.t1, "direct time-window query should receive the renderer view range"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::QUERY, + plot::detail::Timestamp_window_search::QUERY, "direct time-window query should bypass local timestamp search"); TEST_ASSERT(state->last_first == 39, "renderer planner should expand direct query with a predecessor sample"); @@ -433,8 +433,8 @@ bool test_direct_time_window_query_receives_access_semantics() TEST_ASSERT(state, "expected planner state for member semantics query test"); TEST_ASSERT(!source->last_query_semantics_key.conservative && - source->last_query_semantics_key.value == expected_key.value && - source->last_query_semantics_key.revision == expected_key.revision, + source->last_query_semantics_key.value == expected_key.value && + source->last_query_semantics_key.revision == expected_key.revision, "direct time-window query should receive member-pointer semantics"); } @@ -459,8 +459,8 @@ bool test_direct_time_window_query_receives_access_semantics() TEST_ASSERT(source->query_calls == 1, "explicit semantics direct-window source should be queried once"); TEST_ASSERT(!source->last_query_semantics_key.conservative && - source->last_query_semantics_key.value == expected_key.value && - source->last_query_semantics_key.revision == 9, + source->last_query_semantics_key.value == expected_key.value && + source->last_query_semantics_key.revision == 9, "direct time-window query should receive explicit semantics revision"); } @@ -502,7 +502,7 @@ bool test_direct_time_window_empty_falls_back_to_renderer_padding() TEST_ASSERT(source->query_calls == 1, "direct empty query should be attempted once"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::BINARY, + plot::detail::Timestamp_window_search::BINARY, "direct empty query should fall back to local renderer padding"); TEST_ASSERT(state->last_first == 0 && state->last_source_count == 2, "direct empty query fallback should keep adjacent renderer samples"); @@ -543,7 +543,7 @@ bool test_direct_time_window_single_match_expands_for_linear_segments() TEST_ASSERT(state, "expected planner state for direct single-match query test"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::QUERY, + plot::detail::Timestamp_window_search::QUERY, "direct single-match query should still drive renderer planning"); TEST_ASSERT(state->last_first == 0 && state->last_source_count == 2, "direct single-match query should expand to draw the visible segment"); @@ -588,15 +588,15 @@ bool test_direct_time_window_hold_forward_synthesizes_terminal_sample() TEST_ASSERT(source->query_calls == 1, "direct hold-forward source should be queried by renderer planning"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::QUERY, + plot::detail::Timestamp_window_search::QUERY, "direct hold-forward query should drive renderer planning"); TEST_ASSERT(state->last_first == source->query_window.first, "direct hold-forward query should keep the queried source sample"); TEST_ASSERT(state->last_source_count == 1, "direct hold-forward query should keep one real source sample"); TEST_ASSERT(state->last_synthetic_hold_count == 1 && - state->last_count == 2 && - state->last_hold_last_forward, + state->last_count == 2 && + state->last_hold_last_forward, "direct hold-forward query should synthesize the terminal GPU sample"); return true; @@ -635,7 +635,7 @@ bool test_direct_time_window_sequence_mismatch_falls_back_to_snapshot_scan() TEST_ASSERT(source->snapshot_calls == 1, "sequence mismatch fallback should reuse the acquired frame snapshot"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::BINARY, + plot::detail::Timestamp_window_search::BINARY, "sequence mismatch should fall back to local snapshot search"); TEST_ASSERT(state->last_first == 39, "sequence mismatch must not pair stale query metadata with the snapshot"); @@ -679,7 +679,7 @@ bool test_direct_time_window_failed_status_suppresses_snapshot_fallback() TEST_ASSERT(source->snapshot_calls == 1, "failed direct query still needs the paired snapshot sequence check"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::QUERY, + plot::detail::Timestamp_window_search::QUERY, "failed direct query should remain authoritative for the matched sequence"); TEST_ASSERT(state->last_count == 0, "failed direct query must not fall back and draw local snapshot samples"); @@ -721,7 +721,7 @@ bool test_direct_time_window_unsupported_falls_back_to_snapshot_scan() TEST_ASSERT(source->snapshot_calls == 1, "unsupported direct query fallback should take the normal snapshot"); TEST_ASSERT(state->last_timestamp_window_search == - plot::detail::Timestamp_window_search::BINARY, + plot::detail::Timestamp_window_search::BINARY, "unsupported direct query should fall back to local snapshot search"); TEST_ASSERT(state->last_first == 39, "unsupported direct query must not drive the renderer window"); @@ -1108,10 +1108,10 @@ bool test_frame_scoped_cache_reuse() renderer.render(ctx, series_map); TEST_ASSERT(data_source->snapshot_calls == 1, - std::string("expected shared snapshot between main and preview views, got ") + - std::to_string(data_source->snapshot_calls)); + std::string("expected shared snapshot between main and preview views, got ") + + std::to_string(data_source->snapshot_calls)); TEST_ASSERT(data_source->last_hold.expired(), - "expected frame-scoped snapshot hold to release after render"); + "expected frame-scoped snapshot hold to release after render"); return true; } @@ -1160,9 +1160,9 @@ bool test_preview_uses_distinct_source_snapshot() renderer.render(ctx, series_map); TEST_ASSERT(main_source->snapshot_calls == 1, - "expected main source snapshot call"); + "expected main source snapshot call"); TEST_ASSERT(preview_source->snapshot_calls == 1, - "expected preview source snapshot call"); + "expected preview source snapshot call"); return true; } @@ -1205,9 +1205,9 @@ bool test_preview_disabled_skips_preview_snapshot() renderer.render(ctx, series_map); TEST_ASSERT(main_source->snapshot_calls == 1, - "expected main source snapshot call"); + "expected main source snapshot call"); TEST_ASSERT(preview_source->snapshot_calls == 0, - "expected preview source to be skipped when preview disabled"); + "expected preview source to be skipped when preview disabled"); return true; } @@ -1246,7 +1246,7 @@ bool test_frame_change_invalidates_snapshot_cache() renderer.render(ctx, series_map); TEST_ASSERT(data_source->snapshot_calls == 2, - "expected snapshot refresh on frame change"); + "expected snapshot refresh on frame change"); return true; } @@ -1284,21 +1284,21 @@ bool test_empty_window_behavior_invalidates_fast_path_cache() renderer.render(ctx, series_map); TEST_ASSERT(data_source->snapshot_calls == 1, - "expected first render to take one snapshot"); + "expected first render to take one snapshot"); auto state_it = renderer.m_vbo_states.find(series_id); TEST_ASSERT(state_it != renderer.m_vbo_states.end(), - "expected vbo state for test series"); + "expected vbo state for test series"); // QRhi-less tests seed upload state to exercise the CPU fast-path conditions in plan_view(). state_it->second.main_view.has_uploaded_vbo = true; renderer.render(ctx, series_map); TEST_ASSERT(data_source->snapshot_calls == 1, - "expected fast-path cache hit to skip snapshot"); + "expected fast-path cache hit to skip snapshot"); series->empty_window_behavior = Empty_window_behavior::HOLD_LAST_FORWARD; renderer.render(ctx, series_map); TEST_ASSERT(data_source->snapshot_calls == 2, - "expected empty_window_behavior change to invalidate fast-path cache"); + "expected empty_window_behavior change to invalidate fast-path cache"); return true; } @@ -1340,11 +1340,11 @@ bool test_preview_honors_hold_last_forward() renderer.render(ctx, series_map); auto state_it = renderer.m_vbo_states.find(series_id); TEST_ASSERT(state_it != renderer.m_vbo_states.end(), - "expected vbo state for preview hold-forward test"); + "expected vbo state for preview hold-forward test"); TEST_ASSERT(state_it->second.preview_view.planner, - "expected preview planner state for preview hold-forward test"); + "expected preview planner state for preview hold-forward test"); TEST_ASSERT(planner_state(state_it->second.preview_view).last_hold_last_forward, - "preview should honor HOLD_LAST_FORWARD behavior"); + "preview should honor HOLD_LAST_FORWARD behavior"); return true; } @@ -1380,9 +1380,9 @@ bool test_lod_level_separation() renderer.render(ctx_wide, series_map); TEST_ASSERT(data_source->snapshot_calls[0] >= 1, - "expected LOD0 snapshot at wide width"); + "expected LOD0 snapshot at wide width"); TEST_ASSERT(data_source->snapshot_calls[1] == 0, - "did not expect LOD1 snapshot at wide width"); + "did not expect LOD1 snapshot at wide width"); frame_layout_result_t layout_narrow; layout_narrow.usable_width = 20.0; @@ -1395,7 +1395,7 @@ bool test_lod_level_separation() renderer.render(ctx_narrow, series_map); TEST_ASSERT(data_source->snapshot_calls[1] >= 1, - "expected LOD1 snapshot at narrow width"); + "expected LOD1 snapshot at narrow width"); return true; } @@ -1641,7 +1641,7 @@ bool test_upload_invalidates_when_origin_changes_across_snap_bucket() planner_state(state_it->second.main_view).uploaded_t_origin_ns; TEST_ASSERT(origin_after_frame3 == k_one_second_ns, std::string("expected origin to advance to 1 s bucket after t_min " - "crosses snap boundary, got ") + + "crosses snap boundary, got ") + std::to_string(origin_after_frame3)); TEST_ASSERT(origin_after_frame3 != origin_after_frame1, "origin must change when t_min crosses a snap-step boundary"); @@ -1749,7 +1749,7 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() std::to_string(expected_preview_origin)); TEST_ASSERT(main_origin != preview_origin, std::string("main and preview must record different origins when " - "their spans land in different snap buckets; got main=") + + "their spans land in different snap buckets; got main=") + std::to_string(main_origin) + ", preview=" + std::to_string(preview_origin)); @@ -1795,7 +1795,7 @@ bool test_render_skips_invalid_series() renderer.render(ctx, series_map); TEST_ASSERT(data_source->snapshot_calls == 0, - "expected disabled series to skip snapshots"); + "expected disabled series to skip snapshots"); return true; } diff --git a/tests/test_time_grid.cpp b/tests/test_time_grid.cpp index 8d47a2da..91b6bdb9 100644 --- a/tests/test_time_grid.cpp +++ b/tests/test_time_grid.cpp @@ -91,11 +91,11 @@ bool test_time_grid_layers_reject_degenerate_ranges() { bool dropped_non_multiple_step = true; TEST_ASSERT(plot::build_time_grid_layers( - 5.0, - 5.0, - 600.0, - 10.0, - &dropped_non_multiple_step).count == 0, + 5.0, + 5.0, + 600.0, + 10.0, + &dropped_non_multiple_step).count == 0, "zero-width time range should produce no grid levels"); TEST_ASSERT(!dropped_non_multiple_step, "degenerate ranges should clear the non-multiple diagnostic flag"); diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 9168cfba..68d2b5f5 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -282,7 +282,7 @@ bool test_explicit_semantics_key_helpers() const plot::sample_semantics_key_t typed_key = plot::detail::make_sample_semantics_key(&erased); TEST_ASSERT(!typed_key.conservative && typed_key.value != 0 && - typed_key.revision == 5, + typed_key.revision == 5, "typed policy explicit semantics should survive erase()"); typed.get_value = [](const sample_t&) { @@ -373,8 +373,8 @@ bool test_erased_access_view_uses_direct_member_accessors() TEST_ASSERT(mutated_range.first == 7.0f && mutated_range.second == 8.0f, "mutated erased range accessor should use the replacement callable"); TEST_ASSERT(mutated_timestamp_calls == 1 && - mutated_value_calls == 1 && - mutated_range_calls == 1, + mutated_value_calls == 1 && + mutated_range_calls == 1, "mutated erased policy should invoke each replacement callable once"); TEST_ASSERT(mutated.semantics_key.conservative, "mutating an erased direct policy should clear member-pointer semantics"); @@ -416,7 +416,7 @@ bool test_erased_access_view_uses_direct_member_accessors() plot::detail::access_dispatch_kind_t::MEMBER_POINTER, "mutating a detached accessor copy must not clear the source policy"); TEST_ASSERT(after_detached_slot_mutation_view.timestamp(&s) == - k_sample_timestamp_ns, + k_sample_timestamp_ns, "detached accessor mutation must not affect source policy semantics"); plot::Data_access_policy move_source = erased; @@ -439,7 +439,7 @@ bool test_erased_access_view_uses_direct_member_accessors() plot::detail::access_dispatch_kind_t::MEMBER_POINTER, "moving a whole policy should preserve destination member-pointer dispatch"); TEST_ASSERT(after_whole_policy_move_view.timestamp(&s) == - k_sample_timestamp_ns, + k_sample_timestamp_ns, "whole-policy move should preserve direct timestamp semantics"); auto typed_mutated = policy; @@ -493,7 +493,7 @@ bool test_erased_access_view_uses_direct_member_accessors() "erasing a mutated typed policy should expose conservative semantics"); return true; -} + } bool test_typed_api_floating_point_timestamp_member() { From 06d49df2cfaf04ce9751d4077a793c0527c72476 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:11:08 +0200 Subject: [PATCH 24/80] style: wrap expression right-hand sides --- include/vnm_plot/core/access_policy.h | 9 +- include/vnm_plot/core/color_palette.h | 11 +- src/core/auto_range_resolver.cpp | 25 ++-- src/core/chrome_renderer.cpp | 12 +- src/core/font_renderer.cpp | 8 +- src/core/layout_calculator.cpp | 5 +- src/core/rhi_helpers.h | 4 +- src/core/series_renderer.cpp | 5 +- src/qt/plot_renderer.cpp | 17 +-- src/qt/t_axis_adjust.h | 171 ++++++++++++++------------ tests/test_core_algo.cpp | 5 +- tests/test_snapshot_caching.cpp | 5 +- tests/test_typed_api.cpp | 14 ++- 13 files changed, 159 insertions(+), 132 deletions(-) diff --git a/include/vnm_plot/core/access_policy.h b/include/vnm_plot/core/access_policy.h index 86be8454..d6791d7c 100644 --- a/include/vnm_plot/core/access_policy.h +++ b/include/vnm_plot/core/access_policy.h @@ -113,11 +113,10 @@ std::pair member_range_access( { using range_min_t = std::decay_t; using range_max_t = std::decay_t; - return std::make_pair( - static_cast( - member_at_offset(sample, access.range_min_offset)), - static_cast( - member_at_offset(sample, access.range_max_offset))); + return + std::make_pair( + static_cast(member_at_offset(sample, access.range_min_offset)), + static_cast(member_at_offset(sample, access.range_max_offset))); } // Produces a stable cache key from the byte-level identity of a Sample type's diff --git a/include/vnm_plot/core/color_palette.h b/include/vnm_plot/core/color_palette.h index 4a537cf0..bb3f3d6a 100644 --- a/include/vnm_plot/core/color_palette.h +++ b/include/vnm_plot/core/color_palette.h @@ -35,11 +35,12 @@ constexpr glm::vec4 hex_to_vec4(const char* str) inline glm::vec4 rgba_u8(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = 255) { constexpr float k_inv_255 = 1.0f / 255.0f; - return glm::vec4( - static_cast(r) * k_inv_255, - static_cast(g) * k_inv_255, - static_cast(b) * k_inv_255, - static_cast(a) * k_inv_255); + return + glm::vec4( + static_cast(r) * k_inv_255, + static_cast(g) * k_inv_255, + static_cast(b) * k_inv_255, + static_cast(a) * k_inv_255); } // ----------------------------------------------------------------------------- diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index 351defa0..83483fae 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -385,18 +385,19 @@ bool query_or_scan_series_range( if (profiler) { profiler->record_counter("renderer.auto_range.range_scan_count"); } - return scan_series_range( - source, - access, - level, - interpolation, - empty_window_behavior, - nonfinite_policy, - visible_only, - time_window.min_ns, - time_window.max_ns, - out_min, - out_max); + return + scan_series_range( + source, + access, + level, + interpolation, + empty_window_behavior, + nonfinite_policy, + visible_only, + time_window.min_ns, + time_window.max_ns, + out_min, + out_max); } return false; diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index c0f4e6fd..6e1b3677 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -156,7 +156,10 @@ void Chrome_renderer::render_grid_and_backgrounds( const glm::vec2 main_origin = to_gl_origin(ctx, main_top_left, main_size); const grid_layer_params_t vertical_levels = calculate_grid_params( - double(ctx.v0), double(ctx.v1), pl.usable_height, ctx.adjusted_font_px); + double(ctx.v0), + double(ctx.v1), + pl.usable_height, + ctx.adjusted_font_px); // Grid spacing math runs in fp64 seconds; the shift origin is the // (rebased) seconds-domain t_min that the axis uniforms already use. constexpr double k_seconds_per_ns = 1.0e-9; @@ -320,10 +323,11 @@ void Chrome_renderer::render_preview_overlay( // CPU calculations const double x0 = static_cast( - static_cast(ctx.win_w) * - span_ns_as_long_double(ctx.t_available_min, ctx.t0) / t_avail_span); + static_cast(ctx.win_w) * + span_ns_as_long_double(ctx.t_available_min, ctx.t0) / + t_avail_span ); const double x1 = static_cast( - static_cast(ctx.win_w) * + static_cast(ctx.win_w) * (1.0L - span_ns_as_long_double(ctx.t1, ctx.t_available_max) / t_avail_span)); const double dd = x1 - x0; diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index ea1e8b87..8e19679c 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -426,9 +426,11 @@ std::array compute_font_digest() std::string digest_to_hex(const std::array& digest) { - return QByteArray( - reinterpret_cast(digest.data()), - static_cast(digest.size())).toHex().toStdString(); + return + QByteArray( + reinterpret_cast(digest.data()), + static_cast(digest.size()) + ).toHex().toStdString(); } std::filesystem::path cache_file_path( diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index 7ef6177e..ee1ad437 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -827,8 +827,9 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par params.horizontal_seed_index < static_cast(steps.size())) { const double seeded_step = steps[params.horizontal_seed_index]; - const double ref = std::max(1e-6, std::max(std::abs(seeded_step), - std::abs(params.horizontal_seed_step))); + const double ref = std::max( + 1e-6, + std::max(std::abs(seeded_step), std::abs(params.horizontal_seed_step))); if (std::abs(seeded_step - params.horizontal_seed_step) <= ref * 1e-6) { si = params.horizontal_seed_index; } diff --git a/src/core/rhi_helpers.h b/src/core/rhi_helpers.h index 2da0d74d..12b5870f 100644 --- a/src/core/rhi_helpers.h +++ b/src/core/rhi_helpers.h @@ -235,8 +235,8 @@ inline std::unique_ptr build_alpha_blended_pipeline( return nullptr; } - auto layout_ubo = std::unique_ptr(rhi->newBuffer( - QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, desc.ubo_bytes)); + auto layout_ubo = std::unique_ptr( + rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, desc.ubo_bytes)); if (!layout_ubo || !layout_ubo->create()) { return nullptr; } diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index ca8eac3d..41b97d5d 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -1455,8 +1455,9 @@ void Series_renderer::prepare( } const detail::erased_access_policy_t access_view = detail::make_erased_access_policy_view(*access); - const detail::access_policy_cache_key_t access_key = - detail::make_access_policy_cache_key(access, access_view); + const detail::access_policy_cache_key_t access_key = detail::make_access_policy_cache_key( + access, + access_view); if (key.access_key != access_key) { return false; } diff --git a/src/qt/plot_renderer.cpp b/src/qt/plot_renderer.cpp index 48c4b8dd..c94d93a5 100644 --- a/src/qt/plot_renderer.cpp +++ b/src/qt/plot_renderer.cpp @@ -42,11 +42,12 @@ glm::mat4 to_glm_mat4(const QMatrix4x4& matrix) glm::vec4 qcolor_to_vec4(const QColor& color) { - return glm::vec4( - static_cast(color.redF()), - static_cast(color.greenF()), - static_cast(color.blueF()), - static_cast(color.alphaF())); + return + glm::vec4( + static_cast(color.redF()), + static_cast(color.greenF()), + static_cast(color.blueF()), + static_cast(color.alphaF())); } struct label_pane_opacity_t @@ -250,9 +251,9 @@ void Plot_renderer::render(QRhiCommandBuffer* cb) vnm::plot::Profiler* profiler = config.profiler.get(); const auto callback_now = std::chrono::steady_clock::now(); if (profiler && m_impl->last_render_callback.time_since_epoch().count() != 0) { - const double elapsed_ms = - std::chrono::duration( - callback_now - m_impl->last_render_callback).count(); + const double elapsed_ms = std::chrono::duration( + callback_now - m_impl->last_render_callback + ).count(); profiler->record_observation("qrhi.renderer.callback_interval", elapsed_ms); } m_impl->last_render_callback = callback_now; diff --git a/src/qt/t_axis_adjust.h b/src/qt/t_axis_adjust.h index 00bba96f..7e5c496d 100644 --- a/src/qt/t_axis_adjust.h +++ b/src/qt/t_axis_adjust.h @@ -250,15 +250,16 @@ class Time_axis_model if (m_t_max_initialized && !(v < m_t_max)) { return {}; } - return set_limits_if_changed( - v, - m_t_max, - m_t_available_min, - m_t_available_max, - true, - m_t_max_initialized, - m_t_available_min_initialized, - m_t_available_max_initialized); + return + set_limits_if_changed( + v, + m_t_max, + m_t_available_min, + m_t_available_max, + true, + m_t_max_initialized, + m_t_available_min_initialized, + m_t_available_max_initialized); } qint64 new_min = v; @@ -274,15 +275,16 @@ class Time_axis_model } } - return set_limits_if_changed( - new_min, - new_max, - m_t_available_min, - m_t_available_max, - true, - true, - m_t_available_min_initialized, - m_t_available_max_initialized); + return + set_limits_if_changed( + new_min, + new_max, + m_t_available_min, + m_t_available_max, + true, + true, + m_t_available_min_initialized, + m_t_available_max_initialized); } time_axis_update_result_t set_t_max(qint64 v) @@ -296,15 +298,16 @@ class Time_axis_model if (m_t_min_initialized && !(v > m_t_min)) { return {}; } - return set_limits_if_changed( - m_t_min, - v, - m_t_available_min, - m_t_available_max, - m_t_min_initialized, - true, - m_t_available_min_initialized, - m_t_available_max_initialized); + return + set_limits_if_changed( + m_t_min, + v, + m_t_available_min, + m_t_available_max, + m_t_min_initialized, + true, + m_t_available_min_initialized, + m_t_available_max_initialized); } qint64 new_min = m_t_min; @@ -320,15 +323,16 @@ class Time_axis_model } } - return set_limits_if_changed( - new_min, - new_max, - m_t_available_min, - m_t_available_max, - true, - true, - m_t_available_min_initialized, - m_t_available_max_initialized); + return + set_limits_if_changed( + new_min, + new_max, + m_t_available_min, + m_t_available_max, + true, + true, + m_t_available_min_initialized, + m_t_available_max_initialized); } time_axis_update_result_t set_t_range(qint64 t_min_ns, qint64 t_max_ns) @@ -337,15 +341,16 @@ class Time_axis_model return {}; } - return set_limits_if_changed( - t_min_ns, - t_max_ns, - m_t_available_min, - m_t_available_max, - true, - true, - m_t_available_min_initialized, - m_t_available_max_initialized); + return + set_limits_if_changed( + t_min_ns, + t_max_ns, + m_t_available_min, + m_t_available_max, + true, + true, + m_t_available_min_initialized, + m_t_available_max_initialized); } time_axis_update_result_t set_t_available_min(qint64 v) @@ -354,15 +359,16 @@ class Time_axis_model if (m_t_available_min_initialized && v == m_t_available_min) { return {true, false}; } - return set_limits_if_changed( - m_t_min, - m_t_max, - v, - m_t_available_max, - m_t_min_initialized, - m_t_max_initialized, - true, - false); + return + set_limits_if_changed( + m_t_min, + m_t_max, + v, + m_t_available_max, + m_t_min_initialized, + m_t_max_initialized, + true, + false); } return set_available_t_range(v, m_t_available_max); @@ -374,15 +380,16 @@ class Time_axis_model if (m_t_available_max_initialized && v == m_t_available_max) { return {true, false}; } - return set_limits_if_changed( - m_t_min, - m_t_max, - m_t_available_min, - v, - m_t_min_initialized, - m_t_max_initialized, - false, - true); + return + set_limits_if_changed( + m_t_min, + m_t_max, + m_t_available_min, + v, + m_t_min_initialized, + m_t_max_initialized, + false, + true); } return set_available_t_range(m_t_available_min, v); @@ -426,15 +433,16 @@ class Time_axis_model } } - return set_limits_if_changed( - new_t_min, - new_t_max, - t_available_min_ns, - t_available_max_ns, - new_t_min_initialized, - new_t_max_initialized, - true, - true); + return + set_limits_if_changed( + new_t_min, + new_t_max, + t_available_min_ns, + t_available_max_ns, + new_t_min_initialized, + new_t_max_initialized, + true, + true); } time_axis_update_result_t adjust_t_to_target( @@ -456,15 +464,16 @@ class Time_axis_model target = *clamped; } - return set_limits_if_changed( - target.min_ns, - target.max_ns, - m_t_available_min, - m_t_available_max, - true, - true, - m_t_available_min_initialized, - m_t_available_max_initialized); + return + set_limits_if_changed( + target.min_ns, + target.max_ns, + m_t_available_min, + m_t_available_max, + true, + true, + m_t_available_min_initialized, + m_t_available_max_initialized); } time_axis_update_result_t adjust_t_from_mouse_diff( diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index d6066f91..1d920477 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -593,8 +593,9 @@ bool test_time_unit_helpers_handle_edges() TEST_ASSERT(plot::midpoint_ns(k_min, k_max) == -1, "midpoint should avoid overflow for full int64 range"); - const plot::time_range_t full_centered = - plot::centered_time_range_ns(-1, std::numeric_limits::max()); + const plot::time_range_t full_centered = plot::centered_time_range_ns( + -1, + std::numeric_limits::max()); TEST_ASSERT(full_centered.min_ns == k_min && full_centered.max_ns == k_max, "centered full-range construction should preserve both int64 endpoints"); diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index 8e664b1c..f5aa8821 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -1736,8 +1736,9 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() ctx.t_available_max); const std::int64_t expected_main_origin = plot::detail::choose_origin_ns(ctx.t0, expected_main_span); - const std::int64_t expected_preview_origin = - plot::detail::choose_origin_ns(ctx.t_available_min, expected_preview_span); + const std::int64_t expected_preview_origin = plot::detail::choose_origin_ns( + ctx.t_available_min, + expected_preview_span); TEST_ASSERT(main_origin == expected_main_origin, std::string("main view must record its own per-view origin; got ") + diff --git a/tests/test_typed_api.cpp b/tests/test_typed_api.cpp index 68d2b5f5..7e17710f 100644 --- a/tests/test_typed_api.cpp +++ b/tests/test_typed_api.cpp @@ -99,7 +99,10 @@ bool test_layout_key_distinguishes_sample_types() }; const auto policy_a = plot::make_access_policy( - &sample_t::t, &sample_t::v, &sample_t::v_min, &sample_t::v_max); + &sample_t::t, + &sample_t::v, + &sample_t::v_min, + &sample_t::v_max); const auto policy_b = plot::make_access_policy( &other_sample_t::t, &other_sample_t::v); @@ -109,7 +112,10 @@ bool test_layout_key_distinguishes_sample_types() "layout_key should differ for differently shaped sample types"); const auto policy_a2 = plot::make_access_policy( - &sample_t::t, &sample_t::v, &sample_t::v_min, &sample_t::v_max); + &sample_t::t, + &sample_t::v, + &sample_t::v_min, + &sample_t::v_max); TEST_ASSERT(policy_a.layout_key == policy_a2.layout_key, "layout_key should be deterministic for the same sample shape"); @@ -487,8 +493,8 @@ bool test_erased_access_view_uses_direct_member_accessors() "mutating a typed member-pointer policy should clear stable semantics"); const plot::Data_access_policy erased_semantic_mutated = semantic_mutated.erase(); - const plot::sample_semantics_key_t semantic_mutated_key = - plot::detail::make_sample_semantics_key(&erased_semantic_mutated); + const plot::sample_semantics_key_t semantic_mutated_key = plot::detail::make_sample_semantics_key( + &erased_semantic_mutated); TEST_ASSERT(semantic_mutated_key.conservative, "erasing a mutated typed policy should expose conservative semantics"); From d84151a29fdd5d521b7392d4ac194473fe43e17e Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:11:52 +0200 Subject: [PATCH 25/80] docs: extend style execution ledger --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index 0cfdc602..1dd1a20d 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -24,7 +24,7 @@ Claude was unavailable for the stated 85-minute review window. Three Codex worke The architecture review records **19 failed or terminated executions** in [Observed failures and current gate status](VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md#observed-failures-and-current-gate-status). Plan authoring added one failed `apply_patch` verification: a combined patch expected text that no longer exactly matched the staged draft. Codex `/root` owned the authoring error and recovered by rereading the file and applying smaller exact hunks, bringing the total to **20** before implementation began. -Batch 1B then added seven failed or terminated style executions, bringing the running total to **27**: +Batch 1B then added eleven failed or terminated style executions, bringing the running total to **31**: 1. The aggregate `style_pipeline.py --write` invocation against the three originally named files advanced beyond the 14 switch fixes and attempted 737 insertions/826 deletions. Review caught `fix_hanging_indent.py` deleting a ternary expression's `?`, true arm, and `:` in `sample_statement_for_offset()` before commit. Codex `/root` owned the unsafe invocation, rejected the output, and restored all generated changes through `apply_patch`; no corrupting change was retained. 2. After applying only the authorized 14 switch fixes, the canonical no-write pipeline passed its first stage and failed at stage two on four previously hidden `else if` layout violations. A read-only audit then showed 22 of 27 rule groups red; those counts are diagnostic/provisional because earlier ordered fixes can affect later checks. @@ -33,6 +33,10 @@ Batch 1B then added seven failed or terminated style executions, bringing the ru 5. One initialized build/test wrapper exited before execution because its PowerShell quoting was malformed. Codex `/root` corrected the invocation and retained the successful initialized Release build and CTest result rather than suppressing the failed command. 6. One read-only aggregate-inventory wrapper exited because its diagnostic parser expected the wrong message shape. No source was changed; Codex `/root` corrected the parser and retained the resulting all-rule inventory. 7. One canonical no-write pipeline invocation exceeded a 30-second wrapper timeout and ended with a downstream broken-pipe error. No source was changed; subsequent canonical runs use a recorded timeout long enough for the complete pipeline. +8. One filtered hanging-indent check incorrectly passed `--root` to a positional-only individual checker; the Python error was hidden by the filtering pipeline while the build/test portion continued. No source was changed by the invalid check; Codex `/root` later detected the missing diagnostic and reran the checker through its actual interface. +9. A direct fixer capability probe incorrectly passed unsupported `--help` to the positional-only hanging-indent fixer, which treated it as a filename and exited. No source was changed. +10. A second direct hanging-indent check repeated the unsupported `--root` assumption in the same diagnostic command. No source was changed. Codex `/root` read both scripts' `main()` functions and switched all individual-rule invocations to positional files or their default repository scan. +11. After the hanging-indent fixer reported all 23 enumerated files token-equivalent, its own no-write checker retained one `operator return block should be normalized` finding in `include/vnm_plot/core/types.h`. The fixer's repeated-pass normalization did not converge on the renderer's required one-column mixed-parenthesis alignment. Codex `/root` applied that exact whitespace-only alignment manually, reran the token comparison, and obtained a green hanging-indent/build/CTest checkpoint. Preserve all ledgers rather than replacing them with later green results. @@ -206,6 +210,7 @@ Batch 1B remains formatting-only. Isolate here only the two checker-enumerated c 1. Rewrite `tests/test_msdf_lcd_shader_reference.cpp::sample_statement_for_offset()` from its ternary return to an equivalent empty-expression early return followed by the existing non-empty string construction. This avoids the proven `std::string`/ternary parser collision without changing generated shader text; retain the focused LCD shader-reference assertions. 2. If the ordered naming check still reports them, rename only the private `_pad0`, `_pad1`, and `_pad2` members in `src/core/series_renderer.cpp` to checker-approved names without changing declaration order, field types, initialization values, buffer packing, public headers, or exported symbols. +3. Permit only checker-enumerated adjacent C++ string-literal splits that the long-string rule cannot express without introducing an additional literal token. Require a focused diff proving that concatenated bytes, prefixes, and suffixes are unchanged; the initially known scope is one test message in `tests/test_plot_interaction_item.cpp`. Do not use this checkpoint for unrelated cleanup. From b2a5979d9190318c866c80b9fe18ab18ef8a006a Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:12:53 +0200 Subject: [PATCH 26/80] style: split long test message --- tests/test_plot_interaction_item.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_plot_interaction_item.cpp b/tests/test_plot_interaction_item.cpp index 9b2f00ad..ea48ae4e 100644 --- a/tests/test_plot_interaction_item.cpp +++ b/tests/test_plot_interaction_item.cpp @@ -168,7 +168,8 @@ bool test_zoom_math_handles_negative_velocity() nearly_equal(single_gap.velocity, split_gap.velocity), "negative velocity should match for split elapsed time"); TEST_ASSERT( nearly_equal(single_gap.scale, fractional_steps.scale), "negative scale should match for fractional steps"); - TEST_ASSERT(nearly_equal(single_gap.velocity, fractional_steps.velocity), "negative velocity should match for fractional steps"); + TEST_ASSERT(nearly_equal(single_gap.velocity, fractional_steps.velocity), "negative velocity should " + "match for fractional steps"); return true; } From c625698ec4fcea33bfd303e33c4eeb295f7b81ea Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:13:43 +0200 Subject: [PATCH 27/80] style: rename private uniform padding fields --- src/core/series_renderer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index 41b97d5d..45f2f63d 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -557,8 +557,8 @@ struct Line_block_std140 view; // offset 0 float line_px; // offset 128 int snap_to_pixels; // offset 132 - float _pad0; // offset 136 - float _pad1; // offset 140 + float pad0; // offset 136 + float pad1; // offset 140 }; static_assert(sizeof(Line_block_std140) == 144, "Line_block_std140 must be a multiple of 16"); static_assert(offsetof(Line_block_std140, line_px) == 128, "Line_block line_px offset"); @@ -571,9 +571,9 @@ struct Dot_block_std140 series_view_uniform_std140_t view; // offset 0 float point_diameter_px; // offset 128 - float _pad0; // offset 132 - float _pad1; // offset 136 - float _pad2; // offset 140 + float pad0; // offset 132 + float pad1; // offset 136 + float pad2; // offset 140 }; static_assert(sizeof(Dot_block_std140) == 144, "Dot_block_std140 must be a multiple of 16"); static_assert(offsetof(Dot_block_std140, point_diameter_px) == 128, "Dot_block point_diameter_px offset"); @@ -585,9 +585,9 @@ struct Area_block_std140 series_view_uniform_std140_t view; // offset 0 int interpolation; // offset 128 - int _pad0; // offset 132 - int _pad1; // offset 136 - int _pad2; // offset 140 + int pad0; // offset 132 + int pad1; // offset 136 + int pad2; // offset 140 }; static_assert(sizeof(Area_block_std140) == 144, "Area_block_std140 must be a multiple of 16"); static_assert(offsetof(Area_block_std140, interpolation) == 128, "Area_block interpolation offset"); From 60ddf4f9fe519c352707c578ff2868554dfc67e2 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:19:13 +0200 Subject: [PATCH 28/80] style: reduce hard-limit source lines --- include/vnm_plot/core/algo.h | 6 ++--- include/vnm_plot/core/plot_config.h | 4 +-- include/vnm_plot/qt/plot_interaction_item.h | 18 ++++++++++--- include/vnm_plot/qt/plot_time_axis.h | 12 +++++++-- include/vnm_plot/qt/plot_widget.h | 6 ++++- src/core/layout_calculator.cpp | 30 ++++++++++++++------- tests/test_core_algo.cpp | 15 +++++++---- tests/test_snapshot_caching.cpp | 4 +-- 8 files changed, 67 insertions(+), 28 deletions(-) diff --git a/include/vnm_plot/core/algo.h b/include/vnm_plot/core/algo.h index 5b936cc2..e7d3dd49 100644 --- a/include/vnm_plot/core/algo.h +++ b/include/vnm_plot/core/algo.h @@ -708,9 +708,9 @@ inline std::int64_t choose_snap_ns(std::int64_t span_ns) constexpr std::int64_t k_ns_per_us = 1000LL; constexpr std::int64_t k_ns_per_ms = 1000000LL; constexpr std::int64_t k_ns_per_second = 1000000000LL; - constexpr std::int64_t k_ns_per_hour = 3600LL * k_ns_per_second; - constexpr std::int64_t k_ns_per_day = 86400LL * k_ns_per_second; - constexpr std::int64_t k_ns_per_year = 365LL * k_ns_per_day; + constexpr std::int64_t k_ns_per_hour = k_ns_per_second * 3600LL; + constexpr std::int64_t k_ns_per_day = k_ns_per_second * 86400LL; + constexpr std::int64_t k_ns_per_year = k_ns_per_day * 365LL; if (span_ns <= k_ns_per_ms) { return 1LL; } if (span_ns <= k_ns_per_second) { return k_ns_per_us; } diff --git a/include/vnm_plot/core/plot_config.h b/include/vnm_plot/core/plot_config.h index 174dd564..86cc854a 100644 --- a/include/vnm_plot/core/plot_config.h +++ b/include/vnm_plot/core/plot_config.h @@ -107,8 +107,8 @@ struct Plot_config // --- Theme --- bool dark_mode = false; bool show_text = true; - double grid_visibility = 1.0; // 0..1 alpha; 0 = hidden (skipped), 1 = fully visible - double preview_visibility = 1.0; // 0..1 alpha; 0 = hidden (skipped), 1 = fully visible + double grid_visibility = 1.0; // [0, 1] alpha; zero skips rendering + double preview_visibility = 1.0; // [0, 1] alpha; zero skips rendering Color_palette dark_color_palette = Color_palette::dark(); Color_palette light_color_palette = Color_palette::light(); diff --git a/include/vnm_plot/qt/plot_interaction_item.h b/include/vnm_plot/qt/plot_interaction_item.h index 2c0fd140..f13113f1 100644 --- a/include/vnm_plot/qt/plot_interaction_item.h +++ b/include/vnm_plot/qt/plot_interaction_item.h @@ -13,9 +13,21 @@ class Plot_interaction_item : public QQuickItem { Q_OBJECT Q_PROPERTY(Plot_widget* plot_widget READ plot_widget WRITE set_plot_widget NOTIFY plot_widget_changed REQUIRED) - Q_PROPERTY(Plot_widget* time_plot_widget READ time_plot_widget WRITE set_time_plot_widget NOTIFY time_plot_widget_changed) - Q_PROPERTY(bool pin_time_pivot_to_right READ pin_time_pivot_to_right WRITE set_pin_time_pivot_to_right NOTIFY pin_time_pivot_to_right_changed) - Q_PROPERTY(bool interaction_enabled READ is_interaction_enabled WRITE set_interaction_enabled NOTIFY interaction_enabled_changed) + Q_PROPERTY( + Plot_widget* time_plot_widget + READ time_plot_widget + WRITE set_time_plot_widget + NOTIFY time_plot_widget_changed) + Q_PROPERTY( + bool pin_time_pivot_to_right + READ pin_time_pivot_to_right + WRITE set_pin_time_pivot_to_right + NOTIFY pin_time_pivot_to_right_changed) + Q_PROPERTY( + bool interaction_enabled + READ is_interaction_enabled + WRITE set_interaction_enabled + NOTIFY interaction_enabled_changed) public: explicit Plot_interaction_item(QQuickItem* parent = nullptr); diff --git a/include/vnm_plot/qt/plot_time_axis.h b/include/vnm_plot/qt/plot_time_axis.h index 9ac02dcd..a55a9d93 100644 --- a/include/vnm_plot/qt/plot_time_axis.h +++ b/include/vnm_plot/qt/plot_time_axis.h @@ -26,8 +26,16 @@ class Plot_time_axis : public QObject // names end in _qml_ms to keep the unit obvious at the boundary. Q_PROPERTY(qint64 t_min READ t_min_qml_ms WRITE set_t_min_qml_ms NOTIFY t_limits_changed) Q_PROPERTY(qint64 t_max READ t_max_qml_ms WRITE set_t_max_qml_ms NOTIFY t_limits_changed) - Q_PROPERTY(qint64 t_available_min READ t_available_min_qml_ms WRITE set_t_available_min_qml_ms NOTIFY t_limits_changed) - Q_PROPERTY(qint64 t_available_max READ t_available_max_qml_ms WRITE set_t_available_max_qml_ms NOTIFY t_limits_changed) + Q_PROPERTY( + qint64 t_available_min + READ t_available_min_qml_ms + WRITE set_t_available_min_qml_ms + NOTIFY t_limits_changed) + Q_PROPERTY( + qint64 t_available_max + READ t_available_max_qml_ms + WRITE set_t_available_max_qml_ms + NOTIFY t_limits_changed) Q_PROPERTY(bool sync_vbar_width READ sync_vbar_width WRITE set_sync_vbar_width NOTIFY sync_vbar_width_changed) Q_PROPERTY(bool indicator_active READ indicator_active NOTIFY indicator_state_changed) Q_PROPERTY(qint64 indicator_t READ indicator_t_qml_ms NOTIFY indicator_state_changed) diff --git a/include/vnm_plot/qt/plot_widget.h b/include/vnm_plot/qt/plot_widget.h index 22f6f465..2733d46b 100644 --- a/include/vnm_plot/qt/plot_widget.h +++ b/include/vnm_plot/qt/plot_widget.h @@ -87,7 +87,11 @@ class Plot_widget : public QQuickRhiItem Q_PROPERTY(double scaling_factor READ scaling_factor NOTIFY scaling_factor_changed) Q_PROPERTY(bool dark_mode READ dark_mode WRITE set_dark_mode NOTIFY dark_mode_changed) Q_PROPERTY(double grid_visibility READ grid_visibility WRITE set_grid_visibility NOTIFY grid_visibility_changed) - Q_PROPERTY(double preview_visibility READ preview_visibility WRITE set_preview_visibility NOTIFY preview_visibility_changed) + Q_PROPERTY( + double preview_visibility + READ preview_visibility + WRITE set_preview_visibility + NOTIFY preview_visibility_changed) Q_PROPERTY(double line_width_px READ line_width_px WRITE set_line_width_px NOTIFY line_width_px_changed) Q_PROPERTY(double vbar_width_px READ vbar_width_pixels NOTIFY vbar_width_changed) Q_PROPERTY(double vbar_width_qml READ vbar_width_qml NOTIFY vbar_width_changed) diff --git a/src/core/layout_calculator.cpp b/src/core/layout_calculator.cpp index ee1ad437..723be985 100644 --- a/src/core/layout_calculator.cpp +++ b/src/core/layout_calculator.cpp @@ -908,7 +908,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.signature_build"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.signature_build"); format_signature = format_signature_cache().get_or_compute(step, t_range, params); } @@ -941,7 +942,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par while (t <= t_max_seconds + step) { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.candidate_loop"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.candidate_loop"); const float x = x_of_t(t); if (x >= right_vis) { break; @@ -964,7 +966,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.anchor_check"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.anchor_check"); anchor_taken = has_anchor_within(accepted, x, k_coincide); } @@ -988,24 +991,29 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par if (cache_hit) { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.cache_hit_lookup"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.cache_hit_lookup"); VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.cache_hit_count"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.cache_hit_count"); w = cached->width; } else { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.cache_miss_lookup"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.cache_miss_lookup"); VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.cache_miss_count"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.cache_miss_count"); std::string label; { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.format_timestamp"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.format_timestamp"); label = label_text(t, step); } @@ -1016,7 +1024,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par if (params.measure_text_func) { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.format_labels.measure_text"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "format_labels.measure_text"); w = params.measure_text_func(label.c_str()); if (w <= 0.f && advance > 0.f) { w = advance * float(label.size()); @@ -1083,7 +1092,8 @@ Layout_calculator::result_t Layout_calculator::calculate(const parameters_t& par { VNM_PLOT_PROFILE_SCOPE( profiler, - "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis.arrange_labels.anchor_filter"); + "renderer.frame.calculate_layout.impl.cache_miss.pass1.horizontal_axis." + "arrange_labels.anchor_filter"); auto write_it = candidates.begin(); for (auto it = candidates.begin(); it != candidates.end(); ++it) { const bool anchor_taken = has_anchor_within(accepted, it->x_anchor, k_coincide); diff --git a/tests/test_core_algo.cpp b/tests/test_core_algo.cpp index 1d920477..02ccda4b 100644 --- a/tests/test_core_algo.cpp +++ b/tests/test_core_algo.cpp @@ -182,16 +182,20 @@ bool test_lower_and_upper_bound_on_contiguous_buffer() // The original "3.5" probe has no integer-only equivalent; use 4 as the // first timestamp >= 3.5, which is what lower_bound is meant to find. TEST_ASSERT( - plot::detail::lower_bound_timestamp(samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{4}) == 4, + plot::detail::lower_bound_timestamp( + samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{4}) == 4, "lower_bound(4) should land on index 4"); TEST_ASSERT( - plot::detail::lower_bound_timestamp(samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{3}) == 3, + plot::detail::lower_bound_timestamp( + samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{3}) == 3, "lower_bound(3) should land on index 3"); TEST_ASSERT( - plot::detail::upper_bound_timestamp(samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{3}) == 4, + plot::detail::upper_bound_timestamp( + samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{3}) == 4, "upper_bound(3) should land on index 4"); TEST_ASSERT( - plot::detail::lower_bound_timestamp(samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{-5}) == 0, + plot::detail::lower_bound_timestamp( + samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{-5}) == 0, "lower_bound below range should be 0"); TEST_ASSERT( plot::detail::lower_bound_timestamp(samples.data(), samples.size(), sizeof(sample_t), get_ts, std::int64_t{100}) @@ -735,7 +739,8 @@ bool test_text_lcd_policy_helpers() "Qt LCD detection should win over OS detection"); TEST_ASSERT(plot::detail::text_lcd_auto_order_from_detections(resolved_t::NONE, resolved_t::BGR) == resolved_t::BGR, "OS LCD detection should be used when Qt has no order"); - TEST_ASSERT(plot::detail::text_lcd_auto_order_from_detections(resolved_t::NONE, resolved_t::NONE) == resolved_t::NONE, + TEST_ASSERT(plot::detail::text_lcd_auto_order_from_detections( + resolved_t::NONE, resolved_t::NONE) == resolved_t::NONE, "AUTO detection should fail closed when no source has an order"); TEST_ASSERT(plot::detail::text_lcd_effective_order(auto_request, resolved_t::RGB) == resolved_t::RGB, diff --git a/tests/test_snapshot_caching.cpp b/tests/test_snapshot_caching.cpp index f5aa8821..aad48813 100644 --- a/tests/test_snapshot_caching.cpp +++ b/tests/test_snapshot_caching.cpp @@ -1673,8 +1673,8 @@ bool test_renderer_assigns_distinct_origins_to_main_and_preview() // Sparse 10-year coverage: one sample per day is enough for the // renderer to find data within both windows without ballooning memory. constexpr std::int64_t k_ns_per_second = 1'000'000'000LL; - constexpr std::int64_t k_ns_per_day = 86'400LL * k_ns_per_second; - constexpr std::int64_t k_ns_per_hour = 3'600LL * k_ns_per_second; + constexpr std::int64_t k_ns_per_day = k_ns_per_second * 86'400LL; + constexpr std::int64_t k_ns_per_hour = k_ns_per_second * 3'600LL; constexpr int k_num_samples = 365 * 10; data_source->samples.resize(k_num_samples); for (int i = 0; i < k_num_samples; ++i) { From d0b7adf567a45e3a3ca4ff2536d944070ee5d9bb Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:19:39 +0200 Subject: [PATCH 29/80] docs: govern formatter conflict workarounds --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index 1dd1a20d..03ad5edc 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -24,7 +24,7 @@ Claude was unavailable for the stated 85-minute review window. Three Codex worke The architecture review records **19 failed or terminated executions** in [Observed failures and current gate status](VNM_PLOT_ARCHITECTURE_AND_STACKING_REVIEW.md#observed-failures-and-current-gate-status). Plan authoring added one failed `apply_patch` verification: a combined patch expected text that no longer exactly matched the staged draft. Codex `/root` owned the authoring error and recovered by rereading the file and applying smaller exact hunks, bringing the total to **20** before implementation began. -Batch 1B then added eleven failed or terminated style executions, bringing the running total to **31**: +Batch 1B then added fourteen failed or terminated style executions, bringing the running total to **34**: 1. The aggregate `style_pipeline.py --write` invocation against the three originally named files advanced beyond the 14 switch fixes and attempted 737 insertions/826 deletions. Review caught `fix_hanging_indent.py` deleting a ternary expression's `?`, true arm, and `:` in `sample_statement_for_offset()` before commit. Codex `/root` owned the unsafe invocation, rejected the output, and restored all generated changes through `apply_patch`; no corrupting change was retained. 2. After applying only the authorized 14 switch fixes, the canonical no-write pipeline passed its first stage and failed at stage two on four previously hidden `else if` layout violations. A read-only audit then showed 22 of 27 rule groups red; those counts are diagnostic/provisional because earlier ordered fixes can affect later checks. @@ -37,6 +37,9 @@ Batch 1B then added eleven failed or terminated style executions, bringing the r 9. A direct fixer capability probe incorrectly passed unsupported `--help` to the positional-only hanging-indent fixer, which treated it as a filename and exited. No source was changed. 10. A second direct hanging-indent check repeated the unsupported `--root` assumption in the same diagnostic command. No source was changed. Codex `/root` read both scripts' `main()` functions and switched all individual-rule invocations to positional files or their default repository scan. 11. After the hanging-indent fixer reported all 23 enumerated files token-equivalent, its own no-write checker retained one `operator return block should be normalized` finding in `include/vnm_plot/core/types.h`. The fixer's repeated-pass normalization did not converge on the renderer's required one-column mixed-parenthesis alignment. Codex `/root` applied that exact whitespace-only alignment manually, reran the token comparison, and obtained a green hanging-indent/build/CTest checkpoint. +12. A complete canonical replay after the later expression/hard-limit work found two earlier local-declaration findings reintroduced by ordered downstream formatters in `include/vnm_plot/core/algo.h` and `tests/test_snapshot_caching.cpp`. No unsafe output was retained; the findings were isolated to initialized constant tables. +13. After the local-declaration formatter made those blocks green, the next canonical replay found the assignment-table checker required the opposite spacing on the same two initialized declarations. +14. A combined verification after applying the assignment formatter confirmed the oscillation: assignment layout was green while local-declaration layout was red again. Codex `/root` avoided modifying the dirty external standards checkout and instead reordered only the constant multiplication operands, preserving exact constant values while satisfying both canonical checkers. Preserve all ledgers rather than replacing them with later green results. @@ -211,6 +214,8 @@ Batch 1B remains formatting-only. Isolate here only the two checker-enumerated c 1. Rewrite `tests/test_msdf_lcd_shader_reference.cpp::sample_statement_for_offset()` from its ternary return to an equivalent empty-expression early return followed by the existing non-empty string construction. This avoids the proven `std::string`/ternary parser collision without changing generated shader text; retain the focused LCD shader-reference assertions. 2. If the ordered naming check still reports them, rename only the private `_pad0`, `_pad1`, and `_pad2` members in `src/core/series_renderer.cpp` to checker-approved names without changing declaration order, field types, initialization values, buffer packing, public headers, or exported symbols. 3. Permit only checker-enumerated adjacent C++ string-literal splits that the long-string rule cannot express without introducing an additional literal token. Require a focused diff proving that concatenated bytes, prefixes, and suffixes are unchanged; the initially known scope is one test message in `tests/test_plot_interaction_item.cpp`. +4. For the two initialized constant blocks where the ordered local-declaration and assignment-table formatters require opposite spacing, permit commutative constant-multiplication operand reordering so each derived expression begins with its already declared base unit. Preserve the exact compile-time values and retain the core/snapshot tests; the exact scope is `choose_snap_ns()` in `include/vnm_plot/core/algo.h` and the main/preview origin regression in `tests/test_snapshot_caching.cpp`. +5. In `tests/test_msdf_lcd_shader_reference.cpp::lcd_enabled_statement()`, permit decomposition of the same generated shader bytes into a `std::string` first clause and short `+`-joined literal clauses when required by the hard line-length gate. The focused shader-reference test must prove the complete generated statement remains byte-identical. Do not use this checkpoint for unrelated cleanup. From 2ec801395cfe47abb82c96e222331e354b893305 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:30:47 +0200 Subject: [PATCH 30/80] style: resolve formatter boundary cases --- include/vnm_plot/core/types.h | 13 ++++++++----- src/core/auto_range_resolver.cpp | 10 +++++----- src/core/chrome_renderer.cpp | 12 ++++++------ src/core/font_renderer.cpp | 4 ++-- src/core/series_renderer.cpp | 15 +++++++++------ src/core/time_grid.cpp | 2 +- src/core/types.cpp | 4 ++-- tests/test_concurrent_series.cpp | 2 +- tests/test_msdf_lcd_shader_reference.cpp | 12 ++++++++---- 9 files changed, 42 insertions(+), 32 deletions(-) diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 8cf7a5d5..4a572436 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -1182,7 +1182,7 @@ struct layout_cache_key_t [[nodiscard]] bool operator==(const layout_cache_key_t& other) const noexcept { - return + const bool layout_fields_match = v0 == other.v0 && v1 == other.v1 && t0 == other.t0 && @@ -1192,10 +1192,13 @@ struct layout_cache_key_t adjusted_preview_height == other.adjusted_preview_height && adjusted_font_size_in_pixels == other.adjusted_font_size_in_pixels && vbar_width_pixels == other.vbar_width_pixels && - font_metrics_key == other.font_metrics_key && - config_revision == other.config_revision && - format_timestamp_revision == other.format_timestamp_revision && - format_value_revision == other.format_value_revision; + font_metrics_key == other.font_metrics_key; + + return + layout_fields_match && + config_revision == other.config_revision && + format_timestamp_revision == other.format_timestamp_revision && + format_value_revision == other.format_value_revision; } }; diff --git a/src/core/auto_range_resolver.cpp b/src/core/auto_range_resolver.cpp index 83483fae..a3941c36 100644 --- a/src/core/auto_range_resolver.cpp +++ b/src/core/auto_range_resolver.cpp @@ -209,7 +209,7 @@ bool same_cache_shape( make_erased_access_policy_view(access); const access_policy_cache_key_t access_key = make_access_policy_cache_key(&access, access_view); - return + return ( entry.valid && entry.source_identity == source.identity() && entry.access_identity == &access && @@ -220,11 +220,11 @@ bool same_cache_shape( entry.semantics_conservative == query.semantics_key.conservative && entry.lod_level == lod_level && entry.t_min_ns == query.time_window.min_ns && - entry.t_max_ns == query.time_window.max_ns && - entry.interpolation == query.interpolation && + entry.t_max_ns == query.time_window.max_ns && + entry.interpolation == query.interpolation && entry.empty_window_behavior == query.empty_window_behavior && - entry.nonfinite_policy == query.nonfinite_policy && - entry.sequence == sequence; + entry.nonfinite_policy == query.nonfinite_policy && + entry.sequence == sequence); } auto_range_cache_entry_t make_cache_entry( diff --git a/src/core/chrome_renderer.cpp b/src/core/chrome_renderer.cpp index 6e1b3677..e3830a2f 100644 --- a/src/core/chrome_renderer.cpp +++ b/src/core/chrome_renderer.cpp @@ -322,13 +322,13 @@ void Chrome_renderer::render_preview_overlay( const glm::vec4 separator_color = palette.separator; // CPU calculations - const double x0 = static_cast( - static_cast(ctx.win_w) * - span_ns_as_long_double(ctx.t_available_min, ctx.t0) / - t_avail_span ); + const long double scaled_left_span = + static_cast(ctx.win_w) * + span_ns_as_long_double(ctx.t_available_min, ctx.t0); + const double x0 = static_cast(scaled_left_span / t_avail_span); const double x1 = static_cast( - static_cast(ctx.win_w) * - (1.0L - span_ns_as_long_double(ctx.t1, ctx.t_available_max) / t_avail_span)); + (static_cast(ctx.win_w) * + (1.0L - span_ns_as_long_double(ctx.t1, ctx.t_available_max) / t_avail_span))); const double dd = x1 - x0; const double win_w = ctx.win_w; diff --git a/src/core/font_renderer.cpp b/src/core/font_renderer.cpp index 8e19679c..398cfe6a 100644 --- a/src/core/font_renderer.cpp +++ b/src/core/font_renderer.cpp @@ -243,7 +243,7 @@ bool validate_cached_glyph(const msdf_glyph_t& g) // Geometry is stored in scale-independent font units (Y-up bounds); plane // rectangles are derived per draw size via scaled_glyph(). Invisible // advance-only glyphs (e.g. U+0020) carry zero bounds, so equality is valid. - return + return ( std::isfinite(g.advance_units) && std::isfinite(g.bounds_left_units) && std::isfinite(g.bounds_bottom_units) && @@ -256,7 +256,7 @@ bool validate_cached_glyph(const msdf_glyph_t& g) uv_in_range(g.uv_right) && uv_in_range(g.uv_top) && g.uv_right >= g.uv_left && - g.uv_bottom >= g.uv_top; + g.uv_bottom >= g.uv_top); } // draw_scale matching the library's draw_scaling_for(): draw_pixel_height / diff --git a/src/core/series_renderer.cpp b/src/core/series_renderer.cpp index 45f2f63d..2161bc12 100644 --- a/src/core/series_renderer.cpp +++ b/src/core/series_renderer.cpp @@ -423,7 +423,7 @@ struct Series_renderer::rhi_state_t bool operator==(const qrhi_layer_data_key_t& o) const noexcept { - return + const bool frame_fields_match = lod_level == o.lod_level && sample_sequence == o.sample_sequence && t_origin_ns == o.t_origin_ns && @@ -433,11 +433,14 @@ struct Series_renderer::rhi_state_t gpu_count == o.gpu_count && hold_last_forward == o.hold_last_forward && hold_timestamp_ns == o.hold_timestamp_ns && - interpolation == o.interpolation && - nonfinite_policy == o.nonfinite_policy && - drawable_span_count == o.drawable_span_count && - drawable_spans_hash == o.drawable_spans_hash && - access_key == o.access_key; + interpolation == o.interpolation; + + return + frame_fields_match && + nonfinite_policy == o.nonfinite_policy && + drawable_span_count == o.drawable_span_count && + drawable_spans_hash == o.drawable_spans_hash && + access_key == o.access_key; } }; diff --git a/src/core/time_grid.cpp b/src/core/time_grid.cpp index b9e203a5..38a4b59c 100644 --- a/src/core/time_grid.cpp +++ b/src/core/time_grid.cpp @@ -72,7 +72,7 @@ grid_layer_params_t build_time_grid_layers( const double px_per_unit = width_px / range; const auto steps = detail::build_time_steps_covering(range); int idx = std::max(0, detail::find_time_step_start_index(steps, range)); - while (idx + 1 < static_cast(steps.size()) && + while (idx + 1 < static_cast(steps.size()) && steps[idx] * px_per_unit < cell_span_min) { ++idx; diff --git a/src/core/types.cpp b/src/core/types.cpp index e29f7744..3db01a45 100644 --- a/src/core/types.cpp +++ b/src/core/types.cpp @@ -682,8 +682,8 @@ validated_time_window_t validated_time_window( bool selected_by_time_window(const validated_time_window_t& window, std::size_t index) { return (window.has_match && - index >= window.match_first && - index < window.match_last_exclusive) || + index >= window.match_first && + index < window.match_last_exclusive) || (window.has_held && index == window.held_index); } diff --git a/tests/test_concurrent_series.cpp b/tests/test_concurrent_series.cpp index eae362e4..3fabd3c4 100644 --- a/tests/test_concurrent_series.cpp +++ b/tests/test_concurrent_series.cpp @@ -339,7 +339,7 @@ bool test_vector_source_snapshots_progress_while_set_data_is_active() const auto read_deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(2000); while (active_reads.load(std::memory_order_acquire) < required_active_reads && - std::chrono::steady_clock::now() < read_deadline) + std::chrono::steady_clock::now() < read_deadline) { std::this_thread::yield(); } diff --git a/tests/test_msdf_lcd_shader_reference.cpp b/tests/test_msdf_lcd_shader_reference.cpp index 42f6e63a..10af586f 100644 --- a/tests/test_msdf_lcd_shader_reference.cpp +++ b/tests/test_msdf_lcd_shader_reference.cpp @@ -298,10 +298,14 @@ std::string subpixel_step_statement() std::string lcd_enabled_statement() { return - "bool lcd_enabled =\n" " (lcd_horizontal || lcd_vertical) &&\n" " u.shadow_radius <= 0.0 &&\n" " u.color.a >= " + - std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + - " &&\n" " u.background_color.a >= " + - std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + + std::string("bool lcd_enabled =\n") + + " (lcd_horizontal || lcd_vertical) &&\n" + + " u.shadow_radius <= 0.0 &&\n" + + " u.color.a >= " + + std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + + " &&\n" + + " u.background_color.a >= " + + std::string(ref::k_lcd_opaque_alpha_cutoff_glsl) + ";"; } From cd59a8d827b5ee8706cbcc433663d682f6a31b43 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:31:45 +0200 Subject: [PATCH 31/80] docs: record final style remediation cycle --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index 03ad5edc..3f97db53 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -41,6 +41,15 @@ Batch 1B then added fourteen failed or terminated style executions, bringing the 13. After the local-declaration formatter made those blocks green, the next canonical replay found the assignment-table checker required the opposite spacing on the same two initialized declarations. 14. A combined verification after applying the assignment formatter confirmed the oscillation: assignment layout was green while local-declaration layout was red again. Codex `/root` avoided modifying the dirty external standards checkout and instead reordered only the constant multiplication operands, preserving exact constant values while satisfying both canonical checkers. +The final canonical replay/remediation cycle added sixteen failed executions, bringing the running total to **50**: + +15. Three ordered checks exposed downstream formatter interaction in sequence: eight long-condition findings, then four hanging-indent findings after those were wrapped, then the same four long-condition findings after hanging normalization. +16. Two focused parenthesized-return attempts still left two inline equality chains oscillating between the condition and hanging rules. +17. One context-light multi-file `apply_patch` placed opening parentheses in earlier `return` blocks while placing the closing parentheses in the intended blocks. Codex `/root` owned the targeting error, found it through the complete diff before build/commit, and restored every unintended edit with context-rich patches. +18. One focused check after splitting the equality chains still needed hanging normalization; the next two canonical replays exposed a single expression-RHS/condition oscillation in `chrome_renderer.cpp`. +19. Five focused `chrome_renderer.cpp` layout prototypes remained red under one side of that expression-RHS/condition pair. None was committed; each was inspected and replaced by the next narrower form. +20. Two exact-operation-grouping prototypes remained red before the accepted form materialized the existing long-double left product and parenthesized the unchanged right expression. The final canonical pipeline, initialized Release build, and CTest 21/21 then passed. + Preserve all ledgers rather than replacing them with later green results. | Current state | Owning batch | @@ -216,6 +225,9 @@ Batch 1B remains formatting-only. Isolate here only the two checker-enumerated c 3. Permit only checker-enumerated adjacent C++ string-literal splits that the long-string rule cannot express without introducing an additional literal token. Require a focused diff proving that concatenated bytes, prefixes, and suffixes are unchanged; the initially known scope is one test message in `tests/test_plot_interaction_item.cpp`. 4. For the two initialized constant blocks where the ordered local-declaration and assignment-table formatters require opposite spacing, permit commutative constant-multiplication operand reordering so each derived expression begins with its already declared base unit. Preserve the exact compile-time values and retain the core/snapshot tests; the exact scope is `choose_snap_ns()` in `include/vnm_plot/core/algo.h` and the main/preview origin regression in `tests/test_snapshot_caching.cpp`. 5. In `tests/test_msdf_lcd_shader_reference.cpp::lcd_enabled_statement()`, permit decomposition of the same generated shader bytes into a `std::string` first clause and short `+`-joined literal clauses when required by the hard line-length gate. The focused shader-reference test must prove the complete generated statement remains byte-identical. +6. Permit outer parentheses around the unchanged boolean return expressions in `same_cache_shape()` and `validate_cached_glyph()` when required to satisfy both the long-condition and hanging-indent checkers. +7. In `qrhi_layer_data_key_t::operator==` and `layout_cache_key_t::operator==`, permit a named prefix boolean followed by the remaining short-circuit chain. Preserve clause order so no field is evaluated earlier than in the original expression; retain cache-key equality and renderer cache tests. +8. In `Chrome_renderer::render_preview_overlay()`, permit materializing the existing long-double left product before its existing division and parenthesizing the unchanged right-side product. Preserve arithmetic operator order and retain renderer/preview geometry tests; benchmark numeric calibration must include this boundary in its proposed noise margins. Do not use this checkpoint for unrelated cleanup. From dd5a14de352214a1803b9e474a459447c471cbde Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 15:48:27 +0200 Subject: [PATCH 32/80] docs: repin repaired style pipeline --- VNM_PLOT_IMPLEMENTATION_PLAN.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/VNM_PLOT_IMPLEMENTATION_PLAN.md b/VNM_PLOT_IMPLEMENTATION_PLAN.md index 3f97db53..6cccb1f7 100644 --- a/VNM_PLOT_IMPLEMENTATION_PLAN.md +++ b/VNM_PLOT_IMPLEMENTATION_PLAN.md @@ -50,12 +50,19 @@ The final canonical replay/remediation cycle added sixteen failed executions, br 19. Five focused `chrome_renderer.cpp` layout prototypes remained red under one side of that expression-RHS/condition pair. None was committed; each was inspected and replaced by the next narrower form. 20. Two exact-operation-grouping prototypes remained red before the accepted form materialized the existing long-double left product and parenthesized the unchanged right expression. The final canonical pipeline, initialized Release build, and CTest 21/21 then passed. +The independent write-mode investigation added eight failed executions, bringing the running total to **58**: + +21. In an isolated candidate clone, the tool reviewer ran three successive aggregate `--write` passes. Each exited zero without producing a valid fixed point: the first changed six files and the next two continued or retained the cross-stage formatter conflict. The no-write verification after each pass failed, accounting for six executions. No token-changing or ternary corruption recurred. +22. Codex `/root` independently reproduced one false-green aggregate write and its immediately red no-write verification, accounting for two executions. The root cause was `style_pipeline.py` running every fixer unconditionally even when that rule's check was already green, then omitting a final all-rule verification. + +The repair is isolated in standards commit `ce01c3a` and [Varinomics/varinomics-standards PR #4](https://github.com/Varinomics/varinomics-standards/pull/4). Write mode now prechecks each fixable rule, skips fixers for green rules, verifies confirmed fixes, and performs one final read-only sweep after any fixer ran. It deliberately returns nonzero rather than auto-looping if a later fixer invalidates an earlier rule. Standards tests pass 576/576; on `vnm_plot@2ec8013`, repaired no-write is green and repaired `--write` exits green with zero file changes. The original dirty standards checkout was not modified. + Preserve all ledgers rather than replacing them with later green results. | Current state | Owning batch | |---|---| | Dependency Windows workflow failed before creating jobs | Recovered and closed by `vnm_msdf_text@b9c216a`: Linux, macOS, FreeBSD, normal Windows, and Windows full export all passed in [run 29090524058](https://github.com/imakris/vnm_msdf_text/actions/runs/29090524058). Dependent `vnm_plot@2d94f01` text-OFF/text-ON CI also passed on all four platforms. Retain the original startup failure as closed evidence. | -| Style baseline | The original 14 switch violations are recovered in local checkpoint `3fe78e6`. The short-circuiting pipeline exposed broader pre-existing governed debt and an unsafe `fix_hanging_indent.py` rewrite; expanded Batch 1B remains open. | +| Style baseline | Candidate `vnm_plot@2ec8013` passes the complete no-write pipeline, initialized Release build, CTest 21/21, and eight-platform PR CI. Repaired standards `--write` is a zero-change fixed point. Batch 1B/1C remains open only for final iterative-review closure and merge. | | Benchmark cold dynamic timeout unresolved | Codex `/root` performance-harness owner; Batch 2 instruments it and the ledger stays open after Batch 2 if cause remains unresolved | | `vnm_plot` eight first-attempt CI failures | Recovered on attempt 2; retain as closed evidence | | MSVC initialization, local Qt platform, report-validation, and plan-authoring command failures | Recovered/documented; keep in final handoff | @@ -204,7 +211,7 @@ The canonical check command is: --root C:\plms\bsd_licensed\vnm_plot ``` -Record standards repository base `f5edc8b` and `style_pipeline.py` SHA-256 `8715313C94D8DCC4257EB3792459BA8D7C759C9CEB6958958B64560FD65CB2F4` with the initial gate because the standards repository is external and moving. Repin both after any standards-tool repair. +Preserve the initial standards identity as historical evidence: repository base `f5edc8b` and `style_pipeline.py` SHA-256 `8715313C94D8DCC4257EB3792459BA8D7C759C9CEB6958958B64560FD65CB2F4`. The repaired review identity is commit `ce01c3a` from standards PR #4 and pipeline SHA-256 `38056A555CB3AC8CEE31B633A2F5C68CA6B823885C0EF6B15B95979989498CFC`; its tests pass 576/576, candidate no-write is green, and candidate `--write` is green with zero changes. Repin to the terminal merged standards commit if PR #4 is rebased or amended before merge. `fix_hanging_indent.py` is quarantined: an isolated replay proved that its operator-return renderer corrupts the `std::string{}` ternary in `tests/test_msdf_lcd_shader_reference.cpp::sample_statement_for_offset()`. Do not run that fixer again until the standards repository has a focused regression test and corrected implementation, or until the affected findings are satisfied by manually reviewed token-equivalent edits. A later green result does not erase the failed aggregate-write execution. @@ -237,6 +244,7 @@ Gate: - inspect the complete token-changing diff and preserve the existing uniform-layout `static_assert` coverage; - initialized Release build and CTest pass 21/21; - complete canonical style pipeline passes without `--write`; +- repaired canonical pipeline with `--write` passes without changing an already green candidate; - the same iterative three-worker and Claude Fable review covers Batch 1B and 1C before either is merged. ## Stage 2 — Establish evidence, then remove unchanged-frame work @@ -617,4 +625,4 @@ Before the feature merge/release is considered complete: ## Recommended immediate next action -Batch 1A is closed with all dependency and dependent-consumer jobs green. Complete the ordered Batch 1B formatting checkpoints and the narrowly scoped Batch 1C naming repair, then run their joint canonical style/build/test/review gate before starting Batch 2. This is the shortest path that produces trustworthy evidence without idling local work. +Batch 1A is closed. Batch 1B/1C candidate `2ec8013`, its eight-platform CI, and its local style/build/test gates are green; standards repair `ce01c3a` makes confirmed `--write` a zero-change fixed point. Close the final iterative review round and merge the reviewed standards repair before marking the style PR ready, then start Batch 2. This is the shortest path that produces trustworthy evidence without idling local work. From 6e470ed9de926e7c554eee687f5b889318aa63cc Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 16:01:12 +0200 Subject: [PATCH 33/80] benchmark: stabilize streaming revisions --- benchmark/CMakeLists.txt | 2 +- benchmark/include/benchmark_data_source.h | 36 +++- benchmark/include/ring_buffer.h | 201 +++++++++++-------- benchmark/src/benchmark_window.cpp | 4 + benchmark/src/test_benchmark_data_source.cpp | 41 ++-- benchmark/src/test_ring_buffer.cpp | 38 +++- include/vnm_plot/core/types.h | 9 +- include/vnm_plot/rhi/qrhi_series_layer.h | 3 + 8 files changed, 210 insertions(+), 124 deletions(-) diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index d611efb7..1b29cc15 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -21,7 +21,7 @@ if(NOT VNM_PLOT_ENABLE_TEXT) message(FATAL_ERROR "vnm_plot benchmark requires text rendering. Configure with -DVNM_PLOT_ENABLE_TEXT=ON or disable the benchmark.") endif() -option(VNM_PLOT_BUILD_BENCHMARK_TESTS "Build benchmark helper tests" OFF) +option(VNM_PLOT_BUILD_BENCHMARK_TESTS "Build benchmark helper tests" ON) # ----------------------------------------------------------------------------- # Benchmark executable diff --git a/benchmark/include/benchmark_data_source.h b/benchmark/include/benchmark_data_source.h index dc439ea7..c8b72d81 100644 --- a/benchmark/include/benchmark_data_source.h +++ b/benchmark/include/benchmark_data_source.h @@ -9,6 +9,8 @@ #include +#include +#include #include #include @@ -42,11 +44,18 @@ class Benchmark_data_source : public vnm::plot::Data_source { return {vnm::plot::data_snapshot_t{}, Status::FAILED}; } + const auto started = std::chrono::steady_clock::now(); auto view = m_buffer.view(); - m_snapshot_sequence = view.sequence; - - if (view.count == 0) { - return {vnm::plot::data_snapshot_t{}, Status::EMPTY}; + m_snapshot_sequence.store(view.sequence, std::memory_order_release); + + if (m_profiler) { + const double snapshot_ns = std::chrono::duration( + std::chrono::steady_clock::now() - started).count(); + m_profiler->record_observation("benchmark.snapshot.time_ns", snapshot_ns); + m_profiler->record_counter("benchmark.snapshot.count"); + m_profiler->record_observation( + "benchmark.snapshot.bytes", + static_cast(view.count * sizeof(T))); } vnm::plot::data_snapshot_t snapshot; @@ -56,6 +65,11 @@ class Benchmark_data_source : public vnm::plot::Data_source { snapshot.sequence = view.sequence; snapshot.data2 = view.data2; snapshot.count2 = view.count2; + + if (view.count == 0) { + return {snapshot, Status::EMPTY}; + } + snapshot.hold = view.lock; return { @@ -82,20 +96,22 @@ class Benchmark_data_source : public vnm::plot::Data_source { } uint64_t current_sequence(size_t lod_level = 0) const override { - (void)lod_level; - // Ring_buffer::clear() resets its sequence, so it cannot be exposed - // as the monotonic skip key required by Data_source::current_sequence. - return 0; + return lod_level == 0 ? m_buffer.sequence() : 0; } /// Get current sequence for change detection uint64_t sequence() const { - return m_snapshot_sequence; + return m_snapshot_sequence.load(std::memory_order_acquire); + } + + void set_profiler(vnm::plot::Profiler* profiler) noexcept { + m_profiler = profiler; } private: Ring_buffer& m_buffer; - uint64_t m_snapshot_sequence = 0; + std::atomic m_snapshot_sequence{0}; + vnm::plot::Profiler* m_profiler = nullptr; }; /// Create a Data_access_policy for Bar_sample. The renderer owns the GPU-side diff --git a/benchmark/include/ring_buffer.h b/benchmark/include/ring_buffer.h index 5d8e682c..07968811 100644 --- a/benchmark/include/ring_buffer.h +++ b/benchmark/include/ring_buffer.h @@ -8,8 +8,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -23,6 +25,14 @@ namespace vnm::benchmark { template class Ring_buffer { public: + struct Statistics { + std::size_t occupancy = 0; + std::size_t high_water_occupancy = 0; + std::uint64_t revision = 0; + std::uint64_t published_samples = 0; + std::uint64_t overwritten_samples = 0; + }; + /// Result of a copy operation struct Copy_result { std::size_t count; ///< Number of samples copied @@ -67,25 +77,34 @@ class Ring_buffer { /// Push a single sample. Overwrites oldest if full. void push(const T& sample) { + const auto wait_started = std::chrono::steady_clock::now(); std::unique_lock lock(m_mutex); + const double wait_ns = producer_wait_ns(wait_started); const std::size_t cap = m_buffer.size(); const std::size_t h = m_head.load(std::memory_order_relaxed); const std::size_t t = m_tail.load(std::memory_order_relaxed); - const uint64_t seq = m_sequence.load(std::memory_order_relaxed); + const std::size_t count = m_count.load(std::memory_order_relaxed); - // Check if buffer is currently full (head == tail && has data) - const bool was_full = (h == t) && (seq > 0); + const bool was_full = count == cap; m_buffer[h] = sample; m_head.store((h + 1) % cap, std::memory_order_relaxed); - // If buffer was full, advance tail to discard oldest if (was_full) { m_tail.store((t + 1) % cap, std::memory_order_relaxed); + m_overwritten_samples.fetch_add(1, std::memory_order_relaxed); + } + else { + const std::size_t new_count = count + 1; + m_count.store(new_count, std::memory_order_relaxed); + update_high_water(new_count); } - m_sequence.fetch_add(1, std::memory_order_release); + m_published_samples.fetch_add(1, std::memory_order_relaxed); + publish_next_revision(); + lock.unlock(); + record_producer_wait(wait_ns); } /// Push multiple samples. Overwrites oldest as needed. @@ -94,31 +113,41 @@ class Ring_buffer { return; } + const auto wait_started = std::chrono::steady_clock::now(); std::unique_lock lock(m_mutex); + const double wait_ns = producer_wait_ns(wait_started); const std::size_t cap = m_buffer.size(); + std::size_t occupancy = m_count.load(std::memory_order_relaxed); + std::size_t overwritten = 0; + std::uint64_t revision = m_revision.load(std::memory_order_relaxed); for (std::size_t i = 0; i < count; ++i) { const std::size_t h = m_head.load(std::memory_order_relaxed); const std::size_t t = m_tail.load(std::memory_order_relaxed); - const uint64_t seq = m_sequence.load(std::memory_order_relaxed); - - // Check if buffer is currently full (head == tail && has data) - const bool was_full = (h == t) && (seq > 0); + const bool was_full = occupancy == cap; m_buffer[h] = samples[i]; m_head.store((h + 1) % cap, std::memory_order_relaxed); - // If buffer was full, advance tail to discard oldest if (was_full) { m_tail.store((t + 1) % cap, std::memory_order_relaxed); + ++overwritten; + } + else { + ++occupancy; } - m_sequence.fetch_add(1, std::memory_order_relaxed); + revision = next_revision(revision); } - // Release fence for change-detection consistency - std::atomic_thread_fence(std::memory_order_release); + m_count.store(occupancy, std::memory_order_relaxed); + update_high_water(occupancy); + m_published_samples.fetch_add(count, std::memory_order_relaxed); + m_overwritten_samples.fetch_add(overwritten, std::memory_order_relaxed); + m_revision.store(revision, std::memory_order_release); + lock.unlock(); + record_producer_wait(wait_ns); } // ------------------------------------------------------------------------- @@ -131,39 +160,22 @@ class Ring_buffer { View_result view; view.lock = std::make_shared>(m_mutex); - const std::size_t h = m_head.load(std::memory_order_acquire); const std::size_t t = m_tail.load(std::memory_order_acquire); - const uint64_t seq = m_sequence.load(std::memory_order_acquire); - view.sequence = seq; + const std::size_t count = m_count.load(std::memory_order_acquire); + view.sequence = m_revision.load(std::memory_order_acquire); - if (h == t && seq == 0) { + if (count == 0) { return view; } const std::size_t cap = m_buffer.size(); - if (h == t) { - // Full buffer - view.data = m_buffer.data() + t; - view.count = cap; - if (t > 0) { - view.data2 = m_buffer.data(); - view.count2 = t; - } - return view; - } - - if (h > t) { - // Contiguous - view.data = m_buffer.data() + t; - view.count = h - t; - return view; - } - - // Wrapped view.data = m_buffer.data() + t; - view.data2 = m_buffer.data(); - view.count2 = h; - view.count = (cap - t) + h; + view.count = count; + const std::size_t first_count = std::min(count, cap - t); + if (first_count < count) { + view.data2 = m_buffer.data(); + view.count2 = count - first_count; + } return view; } @@ -175,51 +187,30 @@ class Ring_buffer { VNM_PLOT_PROFILE_SCOPE(m_profiler, "renderer.frame.data_copy"); std::shared_lock lock(m_mutex); - const std::size_t h = m_head.load(std::memory_order_acquire); const std::size_t t = m_tail.load(std::memory_order_acquire); - const uint64_t seq = m_sequence.load(std::memory_order_acquire); + const std::size_t count = m_count.load(std::memory_order_acquire); + const uint64_t revision = m_revision.load(std::memory_order_acquire); - if (h == t && seq == 0) { - // Empty buffer (never written to) + if (count == 0) { dest.clear(); - return {0, seq}; + return {0, revision}; } const std::size_t cap = m_buffer.size(); - std::size_t count; - - if (h > t) { - // Contiguous: [tail, head) - count = h - t; - dest.resize(count); - std::copy(m_buffer.begin() + t, m_buffer.begin() + h, dest.begin()); - } - else - if (h < t) { - // Wrapped: [tail, cap) + [0, head) - const std::size_t part1 = cap - t; - const std::size_t part2 = h; - count = part1 + part2; - dest.resize(count); - std::copy(m_buffer.begin() + t, m_buffer.end(), dest.begin()); - std::copy(m_buffer.begin(), m_buffer.begin() + h, dest.begin() + part1); - } - else { - // h == t && seq > 0: buffer is full (all N elements valid) - count = cap; - dest.resize(count); - // Copy from tail to end, then from beginning to tail - std::copy(m_buffer.begin() + t, m_buffer.end(), dest.begin()); - std::copy(m_buffer.begin(), m_buffer.begin() + t, dest.begin() + (cap - t)); + const std::size_t first_count = std::min(count, cap - t); + dest.resize(count); + std::copy_n(m_buffer.begin() + t, first_count, dest.begin()); + if (first_count < count) { + std::copy_n(m_buffer.begin(), count - first_count, dest.begin() + first_count); } - return {count, seq}; + return {count, revision}; } /// Query current sequence without copying (for change detection). /// Returns sequence number which increments on every push. uint64_t sequence() const { - return m_sequence.load(std::memory_order_acquire); + return m_revision.load(std::memory_order_acquire); } // ------------------------------------------------------------------------- @@ -234,38 +225,74 @@ class Ring_buffer { /// Return current number of valid samples. /// Note: This is a snapshot and may change immediately after return. std::size_t size() const { - std::shared_lock lock(m_mutex); - const std::size_t h = m_head.load(std::memory_order_acquire); - const std::size_t t = m_tail.load(std::memory_order_acquire); - const uint64_t seq = m_sequence.load(std::memory_order_acquire); - - if (h == t) { - return seq == 0 ? 0 : m_buffer.size(); // Empty or full - } - if (h > t) { - return h - t; - } - return m_buffer.size() - t + h; + return m_count.load(std::memory_order_acquire); } /// Check if buffer is empty. bool empty() const { - return m_sequence.load(std::memory_order_acquire) == 0; + return m_count.load(std::memory_order_acquire) == 0; } - /// Clear all data and reset sequence. + /// Clear all data while advancing the stable revision. void clear() { std::unique_lock lock(m_mutex); m_head.store(0, std::memory_order_relaxed); m_tail.store(0, std::memory_order_relaxed); - m_sequence.store(0, std::memory_order_release); + m_count.store(0, std::memory_order_relaxed); + publish_next_revision(); + } + + Statistics statistics() const { + Statistics stats; + stats.occupancy = m_count.load(std::memory_order_acquire); + stats.high_water_occupancy = m_high_water_occupancy.load(std::memory_order_acquire); + stats.revision = m_revision.load(std::memory_order_acquire); + stats.published_samples = m_published_samples.load(std::memory_order_acquire); + stats.overwritten_samples = m_overwritten_samples.load(std::memory_order_acquire); + return stats; } private: + static std::uint64_t next_revision(std::uint64_t revision) { + return revision == std::numeric_limits::max() + ? 1 + : revision + 1; + } + + void publish_next_revision() { + const std::uint64_t revision = m_revision.load(std::memory_order_relaxed); + m_revision.store(next_revision(revision), std::memory_order_release); + } + + void update_high_water(std::size_t occupancy) { + std::size_t previous = m_high_water_occupancy.load(std::memory_order_relaxed); + while (previous < occupancy && !m_high_water_occupancy.compare_exchange_weak( + previous, + occupancy, + std::memory_order_relaxed)) + {} + } + + static double producer_wait_ns(std::chrono::steady_clock::time_point wait_started) { + return std::chrono::duration( + std::chrono::steady_clock::now() - wait_started).count(); + } + + void record_producer_wait(double wait_ns) { + if (!m_profiler) { + return; + } + m_profiler->record_observation("benchmark.producer.lock_wait_ns", wait_ns); + } + std::vector m_buffer; std::atomic m_head{0}; ///< Write position (next slot to write) std::atomic m_tail{0}; ///< Start of valid data - std::atomic m_sequence{0}; ///< Increments on every push + std::atomic m_count{0}; + std::atomic m_high_water_occupancy{0}; + std::atomic m_revision{1}; + std::atomic m_published_samples{0}; + std::atomic m_overwritten_samples{0}; mutable std::shared_mutex m_mutex; ///< Protects m_buffer during copy vnm::plot::Profiler* m_profiler = nullptr; }; diff --git a/benchmark/src/benchmark_window.cpp b/benchmark/src/benchmark_window.cpp index ed12092b..f9c1886a 100644 --- a/benchmark/src/benchmark_window.cpp +++ b/benchmark/src/benchmark_window.cpp @@ -143,11 +143,13 @@ Benchmark_rhi_window::Benchmark_rhi_window(const Benchmark_config& config) m_trade_buffer = std::make_unique>(m_config.ring_capacity); m_trade_buffer->set_profiler(&m_profiler); m_trade_source = std::make_unique>(*m_trade_buffer); + m_trade_source->set_profiler(&m_profiler); } else { m_bar_buffer = std::make_unique>(m_config.ring_capacity); m_bar_buffer->set_profiler(&m_profiler); m_bar_source = std::make_unique>(*m_bar_buffer); + m_bar_source->set_profiler(&m_profiler); } m_render_config.dark_mode = true; @@ -390,11 +392,13 @@ void Benchmark_rhi_offscreen_runner::setup_data_source() m_trade_buffer = std::make_unique>(m_config.ring_capacity); m_trade_buffer->set_profiler(&m_profiler); m_trade_source = std::make_unique>(*m_trade_buffer); + m_trade_source->set_profiler(&m_profiler); } else { m_bar_buffer = std::make_unique>(m_config.ring_capacity); m_bar_buffer->set_profiler(&m_profiler); m_bar_source = std::make_unique>(*m_bar_buffer); + m_bar_source->set_profiler(&m_profiler); } } diff --git a/benchmark/src/test_benchmark_data_source.cpp b/benchmark/src/test_benchmark_data_source.cpp index ebf8d3e5..cf94d71d 100644 --- a/benchmark/src/test_benchmark_data_source.cpp +++ b/benchmark/src/test_benchmark_data_source.cpp @@ -204,13 +204,13 @@ bool test_sequence_tracking() { buffer.push(bar); source.try_snapshot(); - TEST_ASSERT(source.sequence() == 1, "sequence should be 1 after one push"); + TEST_ASSERT(source.sequence() == 2, "snapshot should expose revision 2 after one push"); buffer.push(bar); buffer.push(bar); source.try_snapshot(); - TEST_ASSERT(source.sequence() == 3, "sequence should be 3 after three pushes"); + TEST_ASSERT(source.sequence() == 4, "snapshot should expose revision 4 after three pushes"); return true; } @@ -262,44 +262,55 @@ bool test_query_metadata_single_lod_unknown_order() { return true; } -// Test: current_sequence remains unsupported because ring sequence can reset +// Test: current_sequence exposes the same stable nonzero ring revision bool test_current_sequence_metadata() { Ring_buffer buffer(4); Benchmark_data_source source(buffer); - TEST_ASSERT(source.current_sequence(0) == 0, - "initial LOD 0 current_sequence should be 0"); + TEST_ASSERT(source.current_sequence(0) == 1, + "initial LOD 0 current_sequence should expose stable revision 1"); TEST_ASSERT(source.current_sequence(1) == 0, "unsupported LOD current_sequence should be 0"); TEST_ASSERT(source.sequence() == 0, "last snapshot sequence should start at 0"); + auto empty_result = source.try_snapshot(); + TEST_ASSERT(empty_result.status == vnm::plot::snapshot_result_t::Snapshot_status::EMPTY, + "initial snapshot should be EMPTY"); + TEST_ASSERT(empty_result.snapshot.sequence == source.current_sequence(0), + "EMPTY snapshot and current_sequence should expose the same revision"); + Trade_sample trade{}; buffer.push(trade); buffer.push(trade); - TEST_ASSERT(source.current_sequence(0) == 0, - "current_sequence should stay unsupported before snapshot"); + TEST_ASSERT(source.current_sequence(0) == 3, + "current_sequence should advance independently of snapshots"); TEST_ASSERT(source.current_sequence(1) == 0, "unsupported LOD current_sequence should stay 0"); - TEST_ASSERT(source.sequence() == 0, - "last snapshot sequence should not update before try_snapshot"); + TEST_ASSERT(source.sequence() == 1, + "last snapshot sequence should retain the initial EMPTY revision"); auto result = source.try_snapshot(); TEST_ASSERT(result.status == vnm::plot::snapshot_result_t::Snapshot_status::READY, "snapshot should be READY after pushes"); - TEST_ASSERT(result.snapshot.sequence == 2, + TEST_ASSERT(result.snapshot.sequence == 3, "snapshot sequence should match ring sequence"); - TEST_ASSERT(source.sequence() == 2, + TEST_ASSERT(source.sequence() == 3, "last snapshot sequence should update after try_snapshot"); result = {}; buffer.clear(); - TEST_ASSERT(source.current_sequence(0) == 0, - "current_sequence should stay unsupported after clear"); + TEST_ASSERT(source.current_sequence(0) == 4, + "clear should advance current_sequence without resetting it"); + empty_result = source.try_snapshot(); + TEST_ASSERT(empty_result.status == vnm::plot::snapshot_result_t::Snapshot_status::EMPTY, + "snapshot after clear should be EMPTY"); + TEST_ASSERT(empty_result.snapshot.sequence == source.current_sequence(0), + "cleared snapshot and current_sequence should expose the same revision"); buffer.push(trade); - TEST_ASSERT(source.current_sequence(0) == 0, - "current_sequence should not expose reset ring sequence after clear and push"); + TEST_ASSERT(source.current_sequence(0) == 5, + "push after clear should continue the stable revision"); TEST_ASSERT(source.current_sequence(1) == 0, "unsupported LOD current_sequence should stay 0 after reset"); diff --git a/benchmark/src/test_ring_buffer.cpp b/benchmark/src/test_ring_buffer.cpp index bb2eb6c0..a2d3e155 100644 --- a/benchmark/src/test_ring_buffer.cpp +++ b/benchmark/src/test_ring_buffer.cpp @@ -39,12 +39,12 @@ bool test_empty_buffer() { TEST_ASSERT(buf.capacity() == 10, "capacity should be 10"); TEST_ASSERT(buf.size() == 0, "size should be 0"); TEST_ASSERT(buf.empty(), "should be empty"); - TEST_ASSERT(buf.sequence() == 0, "sequence should be 0"); + TEST_ASSERT(buf.sequence() == 1, "stable revision should start at 1"); std::vector dest; auto result = buf.copy_to(dest); TEST_ASSERT(result.count == 0, "copy count should be 0"); - TEST_ASSERT(result.sequence == 0, "copy sequence should be 0"); + TEST_ASSERT(result.sequence == 1, "empty copy should expose stable revision 1"); TEST_ASSERT(dest.empty(), "dest should be empty"); return true; @@ -57,7 +57,7 @@ bool test_basic_push() { buf.push(42); TEST_ASSERT(buf.size() == 1, "size should be 1 after push"); TEST_ASSERT(!buf.empty(), "should not be empty"); - TEST_ASSERT(buf.sequence() == 1, "sequence should be 1"); + TEST_ASSERT(buf.sequence() == 2, "revision should advance after one push"); std::vector dest; auto result = buf.copy_to(dest); @@ -77,7 +77,7 @@ bool test_multiple_pushes() { } TEST_ASSERT(buf.size() == 5, "size should be 5"); - TEST_ASSERT(buf.sequence() == 5, "sequence should be 5"); + TEST_ASSERT(buf.sequence() == 6, "revision should advance for every push"); std::vector dest; auto result = buf.copy_to(dest); @@ -99,7 +99,7 @@ bool test_batch_push() { buf.push_batch(data, 5); TEST_ASSERT(buf.size() == 5, "size should be 5"); - TEST_ASSERT(buf.sequence() == 5, "sequence should be 5"); + TEST_ASSERT(buf.sequence() == 6, "batch push should advance revision per sample"); std::vector dest; auto result = buf.copy_to(dest); @@ -122,14 +122,14 @@ bool test_overwrite() { } TEST_ASSERT(buf.size() == 5, "size should be 5 (full)"); - TEST_ASSERT(buf.sequence() == 5, "sequence should be 5"); + TEST_ASSERT(buf.sequence() == 6, "filled buffer revision should be 6"); // Push more, should overwrite oldest buf.push(100); buf.push(101); TEST_ASSERT(buf.size() == 5, "size should still be 5"); - TEST_ASSERT(buf.sequence() == 7, "sequence should be 7"); + TEST_ASSERT(buf.sequence() == 8, "overwrite pushes should advance revision"); std::vector dest; auto result = buf.copy_to(dest); @@ -142,6 +142,15 @@ bool test_overwrite() { TEST_ASSERT(dest[3] == 100, "dest[3] should be 100"); TEST_ASSERT(dest[4] == 101, "dest[4] should be 101"); + const auto stats = buf.statistics(); + TEST_ASSERT(stats.occupancy == 5, "statistics should report full occupancy"); + TEST_ASSERT(stats.high_water_occupancy == 5, + "statistics should retain full occupancy as the high-water mark"); + TEST_ASSERT(stats.published_samples == 7, + "statistics should report all published samples"); + TEST_ASSERT(stats.overwritten_samples == 2, + "statistics should report overwritten samples"); + return true; } @@ -182,7 +191,20 @@ bool test_clear() { TEST_ASSERT(buf.size() == 0, "size should be 0 after clear"); TEST_ASSERT(buf.empty(), "should be empty after clear"); - TEST_ASSERT(buf.sequence() == 0, "sequence should be 0 after clear"); + TEST_ASSERT(buf.sequence() == 7, "clear should advance rather than reset revision"); + + buf.push(17); + TEST_ASSERT(buf.size() == 1, "push after clear should restore one occupied slot"); + TEST_ASSERT(buf.sequence() == 8, "push after clear should keep revision monotonic"); + + const auto stats = buf.statistics(); + TEST_ASSERT(stats.occupancy == 1, "statistics should report current occupancy"); + TEST_ASSERT(stats.high_water_occupancy == 5, + "statistics should retain lifetime occupancy high-water"); + TEST_ASSERT(stats.published_samples == 6, + "statistics should retain lifetime published sample count"); + TEST_ASSERT(stats.overwritten_samples == 0, + "clear test should not report overwritten samples"); return true; } diff --git a/include/vnm_plot/core/types.h b/include/vnm_plot/core/types.h index 4a572436..c0d21e06 100644 --- a/include/vnm_plot/core/types.h +++ b/include/vnm_plot/core/types.h @@ -745,9 +745,12 @@ class Data_source virtual size_t sample_stride() const = 0; virtual const void* identity() const { return this; } - /// Returns current sequence for the given LOD level without taking a snapshot. - /// Useful for skip optimization when data hasn't changed. - /// Returns 0 if not supported or unknown. + /// Returns the current content revision for the given LOD level without + /// taking a snapshot. A supported revision must remain nonzero, change + /// whenever the logical snapshot content changes (including clear/reset), + /// and equal the sequence returned by try_snapshot() while that content is + /// current. Returning 0, or a revision that cannot satisfy this contract, + /// disables sequence-based reuse. virtual uint64_t current_sequence(size_t lod_level = 0) const { (void)lod_level; return 0; } virtual Time_order time_order(std::size_t lod) const; diff --git a/include/vnm_plot/rhi/qrhi_series_layer.h b/include/vnm_plot/rhi/qrhi_series_layer.h index 83642dd0..f732b9c9 100644 --- a/include/vnm_plot/rhi/qrhi_series_layer.h +++ b/include/vnm_plot/rhi/qrhi_series_layer.h @@ -108,6 +108,9 @@ class Qrhi_series_layer_state public: virtual ~Qrhi_series_layer_state() = default; virtual void cleanup_qrhi_resources(QRhi* rhi) { (void)rhi; } + // Called for every planned custom-layer draw, even when renderer-owned + // sample resources are reused. `resources_changed` only describes whether + // the renderer-visible layer inputs changed; it does not suppress prepare. virtual bool prepare(const qrhi_series_prepare_context_t& ctx) = 0; virtual void record(const qrhi_series_record_context_t& ctx) = 0; }; From f7bedb4c481ab45b813f96ecd3aff7f2528db6c3 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Fri, 10 Jul 2026 16:37:47 +0200 Subject: [PATCH 34/80] benchmark: retain hot-path baseline evidence --- .gitignore | 2 + benchmark/CMakeLists.txt | 83 +++ benchmark/README.md | 58 ++ .../include/benchmark_build_metadata.h.in | 12 + benchmark/include/benchmark_profiler.h | 204 ++++- benchmark/include/benchmark_window.h | 72 +- benchmark/src/benchmark_window.cpp | 703 ++++++++++++++---- benchmark/src/main.cpp | 193 ++++- benchmark/src/test_benchmark_data_source.cpp | 48 ++ benchmark/src/test_benchmark_profiler.cpp | 40 + benchmark/tools/calibrate.py | 343 +++++++++ include/vnm_plot/rhi/series_renderer.h | 4 + src/core/series_renderer.cpp | 105 ++- src/core/series_window_planner.cpp | 4 + 14 files changed, 1715 insertions(+), 156 deletions(-) create mode 100644 benchmark/README.md create mode 100644 benchmark/include/benchmark_build_metadata.h.in create mode 100644 benchmark/tools/calibrate.py diff --git a/.gitignore b/.gitignore index 01419c8d..4bce9cb7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ # Benchmark output files inspector_benchmark_*.txt +inspector_benchmark_*.json +benchmark_phase_trace.jsonl # QtCreator user settings /examples/**/.qtcreator/ diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 1b29cc15..38d1a0fe 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -23,6 +23,65 @@ endif() option(VNM_PLOT_BUILD_BENCHMARK_TESTS "Build benchmark helper tests" ON) +set(VNM_PLOT_BENCHMARK_SOURCE_COMMIT "unknown") +set(VNM_PLOT_BENCHMARK_SOURCE_TREE "unknown") +set(VNM_PLOT_BENCHMARK_SOURCE_DIFF_SHA256 "unknown") +set(VNM_PLOT_BENCHMARK_SOURCE_DIRTY "unknown") +set(VNM_PLOT_BENCHMARK_DEPENDENCY_COMMIT "unknown") + +find_package(Git QUIET) +if(Git_FOUND) + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE VNM_PLOT_BENCHMARK_SOURCE_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse "HEAD^{tree}" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE VNM_PLOT_BENCHMARK_SOURCE_TREE + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + execute_process( + COMMAND "${GIT_EXECUTABLE}" status --porcelain --untracked-files=no + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE _benchmark_git_status + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff --binary HEAD + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE _benchmark_git_diff + ERROR_QUIET + ) + string(SHA256 VNM_PLOT_BENCHMARK_SOURCE_DIFF_SHA256 "${_benchmark_git_diff}") + if(_benchmark_git_status STREQUAL "") + set(VNM_PLOT_BENCHMARK_SOURCE_DIRTY "false") + else() + set(VNM_PLOT_BENCHMARK_SOURCE_DIRTY "true") + endif() + + if(DEFINED vnm_msdf_text_SOURCE_DIR AND EXISTS "${vnm_msdf_text_SOURCE_DIR}/.git") + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD + WORKING_DIRECTORY "${vnm_msdf_text_SOURCE_DIR}" + OUTPUT_VARIABLE VNM_PLOT_BENCHMARK_DEPENDENCY_COMMIT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + endif() +endif() + +configure_file( + include/benchmark_build_metadata.h.in + generated/benchmark_build_metadata.h + @ONLY +) + # ----------------------------------------------------------------------------- # Benchmark executable # ----------------------------------------------------------------------------- @@ -54,10 +113,14 @@ set_target_properties(vnm_plot_benchmark PROPERTIES target_include_directories(vnm_plot_benchmark PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/generated ${PROJECT_SOURCE_DIR}/include ) target_compile_features(vnm_plot_benchmark PRIVATE cxx_std_20) +target_compile_definitions(vnm_plot_benchmark PRIVATE + VNM_PLOT_BENCHMARK_BUILD_TYPE="$" +) # Link dependencies target_link_libraries(vnm_plot_benchmark @@ -73,6 +136,7 @@ target_link_libraries(vnm_plot_benchmark # Platform-specific settings if(WIN32) target_compile_definitions(vnm_plot_benchmark PRIVATE NOMINMAX) + target_link_libraries(vnm_plot_benchmark PRIVATE psapi) # Console application for benchmark output set_target_properties(vnm_plot_benchmark PROPERTIES WIN32_EXECUTABLE FALSE @@ -244,4 +308,23 @@ endif() add_test(NAME benchmark_data_source_tests COMMAND test_benchmark_data_source) message(STATUS "vnm_plot: Building benchmark data source tests") + +add_test( + NAME benchmark_native_smoke + COMMAND vnm_plot_benchmark + --backend qrhi-offscreen + --graphics-backend native + --static + --data-type bars + --render-style line + --seed 12345 + --warmup-frames 2 + --frames 3 + --finish + --pixel-checksum + --quiet + --output-dir "${CMAKE_CURRENT_BINARY_DIR}/smoke-reports" + --scenario ci-native-smoke +) +set_tests_properties(benchmark_native_smoke PROPERTIES TIMEOUT 60) endif() diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 00000000..e39fe0e6 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,58 @@ +# vnm_plot benchmark evidence + +`vnm_plot_benchmark` has two separate backend controls: + +- `--backend qrhi|qrhi-offscreen` selects the presentation path. +- `--graphics-backend native|d3d11|metal|vulkan|opengl|null` selects the + graphics API. `native` never falls back to Null. Null is available only when + it is requested explicitly. + +For repeatable runs, prefer an exact frame count: + +```powershell +build-text\benchmark\vnm_plot_benchmark.exe ` + --backend qrhi-offscreen ` + --graphics-backend native ` + --static --data-type bars --render-style line ` + --series-count 8 --seed 42 ` + --warmup-frames 2 --frames 120 --finish ` + --scenario static-bars-line-8 ` + --output-dir benchmark-results +``` + +Each successful run writes a human-readable `.txt` report, a raw `.json` +artifact, and `benchmark_phase_trace.jsonl`. The raw artifact retains the +invocation, source commit/tree/diff identity, dependency commit, compiler build +type, Qt version, requested and actual QRhi backend/device, text/finish state, +dimensions, seed, scenario, frame output count, raw observations, and calculated +p50/p95/p99 values. High-rate metrics use deterministic reservoir sampling with +the retained limit recorded in the artifact; aggregate count/total/min/max are +not sampled. + +The phase trace is flushed at cold setup, backend creation, every warmup and +measured frame boundary, generator shutdown, and completion. If an external +timeout kills a run, its last complete phase remains available. + +## Calibration protocol + +`tools/calibrate.py` generates six scenarios: static Bars and live Trades, each +with 1, 8, and 64 ordinary LINE series. Every series owns an independent ring +and data source; the generator publishes the same deterministic sample to each +ring. This avoids nested direct-view locks while preserving per-series renderer +work and total publication counters. + +The default protocol performs two calibration sets of seven runs. Each run has +two untimed warmup frames followed by 120 measured, GPU-finished frames at +1200x720 with text enabled. It writes `scenario_manifest.json`, all raw run +artifacts and phase traces, and `proposed_noise_margins.json`: + +```powershell +python benchmark\tools\calibrate.py ` + --executable build-text\benchmark\vnm_plot_benchmark.exe ` + --output-dir benchmark-results\calibration +``` + +Generated manifests and margins are labeled +`proposed-owner-approval-required`; the runner does not promote its own +calibration into an acceptance threshold. Interrupted runs are resumable only +when the retained artifact has the requested measured-frame count. diff --git a/benchmark/include/benchmark_build_metadata.h.in b/benchmark/include/benchmark_build_metadata.h.in new file mode 100644 index 00000000..9f7a79e1 --- /dev/null +++ b/benchmark/include/benchmark_build_metadata.h.in @@ -0,0 +1,12 @@ +// Generated by benchmark/CMakeLists.txt. Do not edit. + +#ifndef VNM_PLOT_BENCHMARK_BUILD_METADATA_H +#define VNM_PLOT_BENCHMARK_BUILD_METADATA_H + +#define VNM_PLOT_BENCHMARK_SOURCE_COMMIT "@VNM_PLOT_BENCHMARK_SOURCE_COMMIT@" +#define VNM_PLOT_BENCHMARK_SOURCE_TREE "@VNM_PLOT_BENCHMARK_SOURCE_TREE@" +#define VNM_PLOT_BENCHMARK_SOURCE_DIFF_SHA256 "@VNM_PLOT_BENCHMARK_SOURCE_DIFF_SHA256@" +#define VNM_PLOT_BENCHMARK_SOURCE_DIRTY "@VNM_PLOT_BENCHMARK_SOURCE_DIRTY@" +#define VNM_PLOT_BENCHMARK_DEPENDENCY_COMMIT "@VNM_PLOT_BENCHMARK_DEPENDENCY_COMMIT@" + +#endif diff --git a/benchmark/include/benchmark_profiler.h b/benchmark/include/benchmark_profiler.h index 15bd8a5d..39a1a8e3 100644 --- a/benchmark/include/benchmark_profiler.h +++ b/benchmark/include/benchmark_profiler.h @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include namespace vnm::benchmark { @@ -42,6 +44,7 @@ struct Report_metadata { double volatility = 0.0; std::size_t ring_capacity = 0; std::size_t samples_generated = 0; + std::map reproduction; }; /// Profiler that builds hierarchical timing tree with scope aggregation. @@ -108,7 +111,7 @@ class Benchmark_profiler : public vnm::plot::Profiler { } std::lock_guard lock(m_mutex); - record_observation_locked(name, 1, value, value, value); + record_observation_locked(name, 1, value, value, value, true); } void record_observation_summary( @@ -125,16 +128,19 @@ class Benchmark_profiler : public vnm::plot::Profiler { } std::lock_guard lock(m_mutex); - record_observation_locked(name, call_count, total, min, max); + record_observation_locked(name, call_count, total, min, max, false); } private: + static constexpr std::size_t k_max_retained_samples = 8192; + void record_observation_locked( const char* name, uint64_t call_count, double total, double min, - double max) + double max, + bool retain_sample) { auto& stats = m_observations[name]; stats.name = name; @@ -142,6 +148,19 @@ class Benchmark_profiler : public vnm::plot::Profiler { stats.total += total; stats.min = std::min(stats.min, min); stats.max = std::max(stats.max, max); + if (retain_sample) { + if (stats.samples.size() < k_max_retained_samples) { + stats.samples.push_back(total); + } + else { + const std::uint64_t mixed = + stats.call_count * 11'400'714'819'323'198'485ull; + const std::uint64_t candidate = mixed % stats.call_count; + if (candidate < k_max_retained_samples) { + stats.samples[static_cast(candidate)] = total; + } + } + } } public: @@ -217,10 +236,90 @@ class Benchmark_profiler : public vnm::plot::Profiler { // Write report std::ofstream ofs(output_path); - if (ofs) { - ofs << generate_report(meta); + if (!ofs) { + throw std::runtime_error("cannot open benchmark report: " + output_path.string()); + } + ofs << generate_report(meta); + if (!ofs) { + throw std::runtime_error("cannot write benchmark report: " + output_path.string()); + } + + write_raw_report(meta); + + return output_path; + } + + std::filesystem::path raw_report_path(const Report_metadata& meta) const + { + return meta.output_directory / generate_raw_filename(meta); + } + + std::filesystem::path write_raw_report(const Report_metadata& meta) const + { + const std::filesystem::path output_path = raw_report_path(meta); + std::filesystem::create_directories(meta.output_directory); + + std::lock_guard lock(m_mutex); + std::ofstream ofs(output_path); + if (!ofs) { + throw std::runtime_error("cannot open raw benchmark report: " + output_path.string()); } + ofs << "{\n \"schema_version\": 1,\n"; + ofs << " \"retained_sample_limit_per_metric\": " + << k_max_retained_samples << ",\n"; + ofs << " \"metadata\": {\n"; + write_json_string_field(ofs, "session", meta.session, true, 4); + write_json_string_field(ofs, "stream", meta.stream, true, 4); + write_json_string_field(ofs, "data_type", meta.data_type, true, 4); + write_json_string_field(ofs, "backend", meta.backend, true, 4); + write_json_number_field(ofs, "target_duration_seconds", meta.target_duration, true, 4); + write_json_string_field(ofs, "started_at_utc", format_utc_time(meta.started_at), true, 4); + write_json_string_field(ofs, "generated_at_utc", format_utc_time(meta.generated_at), + !meta.reproduction.empty(), 4); + std::size_t reproduction_index = 0; + for (const auto& [name, value] : meta.reproduction) { + write_json_string_field( + ofs, + name, + value, + ++reproduction_index < meta.reproduction.size(), + 4); + } + ofs << " },\n \"observations\": {\n"; + + std::size_t observation_index = 0; + for (const auto& [name, stats] : m_observations) { + ofs << " \"" << json_escape(name) << "\": {\n"; + ofs << " \"count\": " << stats.call_count << ",\n"; + ofs << " \"retained_sample_count\": " << stats.samples.size() << ",\n"; + ofs << " \"total\": " << json_number(stats.total) << ",\n"; + const double mean = stats.call_count > 0 + ? stats.total / static_cast(stats.call_count) + : 0.0; + ofs << " \"mean\": " << json_number(mean) << ",\n"; + ofs << " \"min\": " << json_number(stats.min) << ",\n"; + ofs << " \"max\": " << json_number(stats.max) << ",\n"; + write_json_percentile(ofs, "p50", stats.samples, 0.50); + write_json_percentile(ofs, "p95", stats.samples, 0.95); + write_json_percentile(ofs, "p99", stats.samples, 0.99); + ofs << " \"samples\": ["; + for (std::size_t i = 0; i < stats.samples.size(); ++i) { + if (i > 0) { + ofs << ", "; + } + ofs << json_number(stats.samples[i]); + } + ofs << "]\n }"; + if (++observation_index < m_observations.size()) { + ofs << ","; + } + ofs << "\n"; + } + ofs << " }\n}\n"; + if (!ofs) { + throw std::runtime_error("cannot write raw benchmark report: " + output_path.string()); + } return output_path; } @@ -257,6 +356,7 @@ class Benchmark_profiler : public vnm::plot::Profiler { double total = 0.0; double min = std::numeric_limits::max(); double max = 0.0; + std::vector samples; }; struct Thread_context { @@ -342,6 +442,10 @@ class Benchmark_profiler : public vnm::plot::Profiler { if (meta.include_extended) { os << " - volatility: " << std::fixed << std::setprecision(4) << meta.volatility << "\n"; } + + for (const auto& [name, value] : meta.reproduction) { + os << " - " << name << ": " << value << "\n"; + } } void write_observations(std::ostream& os) const @@ -387,6 +491,96 @@ class Benchmark_profiler : public vnm::plot::Profiler { return oss.str(); } + static std::string generate_raw_filename(const Report_metadata& meta) + { + std::filesystem::path filename(generate_filename(meta)); + filename.replace_extension(".json"); + return filename.generic_string(); + } + + static std::string json_escape(const std::string& value) + { + std::ostringstream oss; + for (const unsigned char c : value) { + switch (c) { + case '\"': oss << "\\\""; break; + case '\\': oss << "\\\\"; break; + case '\b': oss << "\\b"; break; + case '\f': oss << "\\f"; break; + case '\n': oss << "\\n"; break; + case '\r': oss << "\\r"; break; + case '\t': oss << "\\t"; break; + default: + if (c < 0x20) { + oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') + << static_cast(c) << std::dec << std::setfill(' '); + } + else { + oss << static_cast(c); + } + break; + } + } + return oss.str(); + } + + static std::string json_number(double value) + { + if (!std::isfinite(value)) { + return "null"; + } + std::ostringstream oss; + oss << std::setprecision(17) << value; + return oss.str(); + } + + static double percentile(std::vector values, double fraction) + { + if (values.empty()) { + return std::numeric_limits::quiet_NaN(); + } + std::sort(values.begin(), values.end()); + const double index = fraction * static_cast(values.size() - 1); + const std::size_t lower = static_cast(std::floor(index)); + const std::size_t upper = static_cast(std::ceil(index)); + const double weight = index - static_cast(lower); + return values[lower] * (1.0 - weight) + values[upper] * weight; + } + + static void write_json_string_field( + std::ostream& os, + const std::string& name, + const std::string& value, + bool comma, + int indent) + { + os << std::string(static_cast(indent), ' ') + << "\"" << json_escape(name) << "\": \"" << json_escape(value) << "\"" + << (comma ? "," : "") << "\n"; + } + + static void write_json_number_field( + std::ostream& os, + const std::string& name, + double value, + bool comma, + int indent) + { + os << std::string(static_cast(indent), ' ') + << "\"" << json_escape(name) << "\": " << json_number(value) + << (comma ? "," : "") << "\n"; + } + + static void write_json_percentile( + std::ostream& os, + const char* name, + const std::vector& samples, + double fraction) + { + os << " \"" << name << "\": " + << json_number(percentile(samples, fraction)) << ",\n"; + } + // Extract short name from fully qualified scope name (e.g., "renderer.frame.foo" -> "foo") static std::string short_name(const std::string& full_name) { diff --git a/benchmark/include/benchmark_window.h b/benchmark/include/benchmark_window.h index 13ca2fed..d81328af 100644 --- a/benchmark/include/benchmark_window.h +++ b/benchmark/include/benchmark_window.h @@ -31,14 +31,18 @@ #include #include #include +#include #include #include +#include class QRhi; class QRhiRenderBuffer; class QRhiRenderPassDescriptor; class QRhiTextureRenderTarget; +class QRhiTexture; class QOffscreenSurface; +class QVulkanInstance; namespace vnm::benchmark { @@ -56,11 +60,23 @@ struct Benchmark_config { double volatility = 0.02; double rate = 1000.0; // samples per second std::size_t ring_capacity = 100000; + std::size_t series_count = 1; bool extended_metadata = false; bool quiet = false; // Suppress console output during benchmark bool show_text = true; // Text/font rendering (default: on) std::string backend = "qrhi-offscreen"; // "qrhi" or "qrhi-offscreen" + // Requested graphics API. "native" selects the platform's normal QRhi + // backend; Null is used only when explicitly requested. + std::string graphics_backend = "native"; bool finish = false; // Wait for GPU completion after offscreen frames + int framebuffer_width = 1200; + int framebuffer_height = 720; + std::size_t warmup_frames = 2; + // Zero keeps duration-based execution. Nonzero runs exactly this many + // measured frames after warmup and is preferred for calibration/CI. + std::size_t measured_frames = 0; + std::string scenario = "ad-hoc"; + bool capture_pixel_checksum = false; // Visual-diff mode: pre-fill 5 fixed samples (4-segment zig-zag) and // skip the generator. Useful for side-by-side rendering comparisons. bool static_data = false; @@ -73,6 +89,14 @@ struct Benchmark_config { double point_diameter_px = 1.0; }; +struct Graphics_device_info { + std::string backend = "uninitialized"; + std::string device_name = "unknown"; + std::string device_type = "unknown"; + std::uint64_t device_id = 0; + std::uint64_t vendor_id = 0; +}; + /// QRhi benchmark window using the public QQuickRhiItem Plot_widget path. class Benchmark_rhi_window : public QQuickWindow { Q_OBJECT @@ -86,6 +110,9 @@ class Benchmark_rhi_window : public QQuickWindow { const Benchmark_config& config() const { return m_config; } std::size_t samples_generated() const { return m_samples_generated.load(); } std::chrono::system_clock::time_point started_at() const { return m_started_at; } + Graphics_device_info graphics_device_info() const; + std::size_t measured_frame_count() const { return m_measured_frame_count; } + std::uint64_t pixel_checksum() const { return 0; } signals: void benchmark_finished(); @@ -100,21 +127,22 @@ private slots: void stop_generator_thread(); void fill_static_data(); void update_plot_view(); + void record_final_statistics(); Benchmark_config m_config; Benchmark_profiler m_profiler; - std::unique_ptr> m_bar_buffer; - std::unique_ptr> m_trade_buffer; - std::unique_ptr> m_bar_source; - std::unique_ptr> m_trade_source; + std::vector>> m_bar_buffers; + std::vector>> m_trade_buffers; + std::vector>> m_bar_sources; + std::vector>> m_trade_sources; Brownian_generator m_generator; std::thread m_generator_thread; std::atomic m_stop_generator{false}; vnm::plot::Plot_widget* m_plot = nullptr; - std::shared_ptr m_series; + std::vector> m_series; vnm::plot::Plot_config m_render_config; @@ -133,6 +161,11 @@ private slots: double m_timer_interval_max_ms = 0.0; std::chrono::system_clock::time_point m_started_at; std::atomic m_samples_generated{0}; + mutable std::mutex m_graphics_info_mutex; + Graphics_device_info m_graphics_info; + std::size_t m_measured_frame_count = 0; + std::size_t m_warmup_frames_remaining = 0; + bool m_measurement_finished = false; }; /// Direct QRhi benchmark that renders into an offscreen target without Qt Quick. @@ -147,6 +180,9 @@ class Benchmark_rhi_offscreen_runner const Benchmark_config& config() const { return m_config; } std::size_t samples_generated() const { return m_samples_generated.load(); } std::chrono::system_clock::time_point started_at() const { return m_started_at; } + Graphics_device_info graphics_device_info() const { return m_graphics_info; } + std::size_t measured_frame_count() const { return m_measured_frame_count; } + std::uint64_t pixel_checksum() const { return m_pixel_checksum; } bool run(std::string& error_message); @@ -158,23 +194,29 @@ class Benchmark_rhi_offscreen_runner void stop_generator_thread(); void fill_static_data(); bool initialize_rhi(std::string& error_message); - bool render_frame(std::string& error_message); + bool render_frame(std::string& error_message, bool measured); + void record_final_statistics(double measured_seconds); + void record_phase(const char* phase, std::size_t frame = 0) const; Benchmark_config m_config; Benchmark_profiler m_profiler; - std::unique_ptr> m_bar_buffer; - std::unique_ptr> m_trade_buffer; - std::unique_ptr> m_bar_source; - std::unique_ptr> m_trade_source; + std::vector>> m_bar_buffers; + std::vector>> m_trade_buffers; + std::vector>> m_bar_sources; + std::vector>> m_trade_sources; Brownian_generator m_generator; std::thread m_generator_thread; std::atomic m_stop_generator{false}; std::unique_ptr m_fallback_surface; +#if QT_CONFIG(vulkan) && __has_include() + std::unique_ptr m_vulkan_instance; +#endif std::unique_ptr m_rhi; std::unique_ptr m_color_buffer; + std::unique_ptr m_resolve_texture; std::unique_ptr m_render_target; std::unique_ptr m_render_pass_descriptor; @@ -198,6 +240,16 @@ class Benchmark_rhi_offscreen_runner float m_v_max = 110.0f; std::chrono::system_clock::time_point m_started_at; std::atomic m_samples_generated{0}; + Graphics_device_info m_graphics_info; + std::size_t m_measured_frame_count = 0; + double m_cold_setup_ms = 0.0; + double m_cold_backend_ms = 0.0; + double m_cold_first_submission_ms = 0.0; + double m_cold_shader_pipeline_prepare_ms = 0.0; + double m_cold_total_ms = 0.0; + double m_last_prepare_ms = 0.0; + std::uint64_t m_pixel_checksum = 0; + std::chrono::steady_clock::time_point m_phase_trace_started; }; } // namespace vnm::benchmark diff --git a/benchmark/src/benchmark_window.cpp b/benchmark/src/benchmark_window.cpp index f9c1886a..7bc2c5eb 100644 --- a/benchmark/src/benchmark_window.cpp +++ b/benchmark/src/benchmark_window.cpp @@ -10,23 +10,119 @@ #include #include #include +#include #include +#include #include +#include #include #include #include #include #include +#include +#include #include #include #include +#if defined(Q_OS_WIN) +#include +#include +#elif defined(Q_OS_UNIX) +#include +#endif + namespace vnm::benchmark { namespace { +std::string device_type_name(QRhiDriverInfo::DeviceType type) +{ + switch (type) { + case QRhiDriverInfo::IntegratedDevice: return "integrated"; + case QRhiDriverInfo::DiscreteDevice: return "discrete"; + case QRhiDriverInfo::ExternalDevice: return "external"; + case QRhiDriverInfo::VirtualDevice: return "virtual"; + case QRhiDriverInfo::CpuDevice: return "cpu"; + case QRhiDriverInfo::UnknownDevice: return "unknown"; + } + return "unknown"; +} + +Graphics_device_info graphics_device_info_from_rhi(QRhi& rhi) +{ + const QRhiDriverInfo driver = rhi.driverInfo(); + Graphics_device_info info; + info.backend = rhi.backendName(); + info.device_name = std::string(driver.deviceName.constData(), driver.deviceName.size()); + info.device_type = device_type_name(driver.deviceType); + info.device_id = driver.deviceId; + info.vendor_id = driver.vendorId; + return info; +} + +std::uint64_t process_memory_high_water_bytes() +{ +#if defined(Q_OS_WIN) + PROCESS_MEMORY_COUNTERS_EX counters{}; + counters.cb = sizeof(counters); + if (GetProcessMemoryInfo( + GetCurrentProcess(), + reinterpret_cast(&counters), + sizeof(counters))) + { + return static_cast(counters.PeakWorkingSetSize); + } +#elif defined(Q_OS_UNIX) + rusage usage{}; + if (getrusage(RUSAGE_SELF, &usage) == 0) { +#if defined(Q_OS_MACOS) + return static_cast(usage.ru_maxrss); +#else + return static_cast(usage.ru_maxrss) * 1024u; +#endif + } +#endif + return 0; +} + +template +void record_ring_statistics( + Benchmark_profiler& profiler, + const std::vector>>& buffers, + double measured_seconds) +{ + if (buffers.empty()) { + return; + } + typename Ring_buffer::Statistics total; + for (const auto& buffer : buffers) { + const auto stats = buffer->statistics(); + total.occupancy += stats.occupancy; + total.high_water_occupancy += stats.high_water_occupancy; + total.published_samples += stats.published_samples; + total.overwritten_samples += stats.overwritten_samples; + } + profiler.record_observation("benchmark.ring.occupancy", static_cast(total.occupancy)); + profiler.record_observation( + "benchmark.ring.high_water_occupancy", + static_cast(total.high_water_occupancy)); + profiler.record_observation( + "benchmark.ring.published_samples", + static_cast(total.published_samples)); + profiler.record_observation( + "benchmark.ring.overwritten_samples", + static_cast(total.overwritten_samples)); + if (measured_seconds > 0.0) { + profiler.record_observation( + "benchmark.ring.published_samples_per_second", + static_cast(total.published_samples) / measured_seconds); + } +} + glm::mat4 to_glm_mat4(const QMatrix4x4& matrix) { const float* data = matrix.constData(); @@ -90,6 +186,12 @@ void update_view_range_from_source( t_max = t_last; t_min = std::max(t_first, t_last - k_window_ns); + // Release the direct-view shared lock before query_v_range() takes its own + // snapshot. On writer-priority shared_mutex implementations, retaining the + // first read lock while a producer queues can deadlock this thread's nested + // read behind the waiting writer. + result = {}; + vnm::plot::Data_access_policy access = data_type == "Trades" ? make_trade_access_policy() : make_bar_access_policy(); @@ -137,19 +239,31 @@ Benchmark_rhi_window::Benchmark_rhi_window(const Benchmark_config& config) setFormat(format); setTitle("vnm_plot Benchmark QRhi"); - resize(1200, 720); + resize(m_config.framebuffer_width, m_config.framebuffer_height); if (m_config.data_type == "Trades") { - m_trade_buffer = std::make_unique>(m_config.ring_capacity); - m_trade_buffer->set_profiler(&m_profiler); - m_trade_source = std::make_unique>(*m_trade_buffer); - m_trade_source->set_profiler(&m_profiler); + m_trade_buffers.reserve(m_config.series_count); + m_trade_sources.reserve(m_config.series_count); + for (std::size_t index = 0; index < m_config.series_count; ++index) { + auto buffer = std::make_unique>(m_config.ring_capacity); + buffer->set_profiler(&m_profiler); + auto source = std::make_unique>(*buffer); + source->set_profiler(&m_profiler); + m_trade_buffers.push_back(std::move(buffer)); + m_trade_sources.push_back(std::move(source)); + } } else { - m_bar_buffer = std::make_unique>(m_config.ring_capacity); - m_bar_buffer->set_profiler(&m_profiler); - m_bar_source = std::make_unique>(*m_bar_buffer); - m_bar_source->set_profiler(&m_profiler); + m_bar_buffers.reserve(m_config.series_count); + m_bar_sources.reserve(m_config.series_count); + for (std::size_t index = 0; index < m_config.series_count; ++index) { + auto buffer = std::make_unique>(m_config.ring_capacity); + buffer->set_profiler(&m_profiler); + auto source = std::make_unique>(*buffer); + source->set_profiler(&m_profiler); + m_bar_buffers.push_back(std::move(buffer)); + m_bar_sources.push_back(std::move(source)); + } } m_render_config.dark_mode = true; @@ -185,11 +299,24 @@ Benchmark_rhi_window::Benchmark_rhi_window(const Benchmark_config& config) }); connect(&m_render_timer, &QTimer::timeout, this, &Benchmark_rhi_window::on_render_timer); connect(&m_benchmark_timer, &QTimer::timeout, this, &Benchmark_rhi_window::on_benchmark_timeout); + connect( + this, + &QQuickWindow::sceneGraphInitialized, + this, + [this]() { + auto* rhi = static_cast(rendererInterface()->getResource( + this, + QSGRendererInterface::RhiResource)); + if (!rhi) { + return; + } + std::lock_guard lock(m_graphics_info_mutex); + m_graphics_info = graphics_device_info_from_rhi(*rhi); + }, + Qt::DirectConnection); setup_series(); - m_started_at = std::chrono::system_clock::now(); - if (m_config.static_data) { fill_static_data(); } @@ -198,9 +325,15 @@ Benchmark_rhi_window::Benchmark_rhi_window(const Benchmark_config& config) m_generator_thread = std::thread(&Benchmark_rhi_window::generator_thread_func, this); } + m_warmup_frames_remaining = m_config.warmup_frames; + if (m_warmup_frames_remaining == 0) { + m_started_at = std::chrono::system_clock::now(); + if (m_config.measured_frames == 0) { + m_benchmark_timer.setSingleShot(true); + m_benchmark_timer.start(static_cast(m_config.duration_seconds * 1000)); + } + } m_render_timer.start(0); - m_benchmark_timer.setSingleShot(true); - m_benchmark_timer.start(static_cast(m_config.duration_seconds * 1000)); } Benchmark_rhi_window::~Benchmark_rhi_window() @@ -210,6 +343,12 @@ Benchmark_rhi_window::~Benchmark_rhi_window() m_plot = nullptr; } +Graphics_device_info Benchmark_rhi_window::graphics_device_info() const +{ + std::lock_guard lock(m_graphics_info_mutex); + return m_graphics_info; +} + void Benchmark_rhi_window::stop_generator_thread() { if (m_generator_thread.joinable()) { @@ -233,10 +372,16 @@ void Benchmark_rhi_window::generator_thread_func() while (current_count < static_cast(target_samples) && !m_stop_generator.load()) { if (m_config.data_type == "Trades") { - m_trade_buffer->push(m_generator.next_trade()); + const Trade_sample sample = m_generator.next_trade(); + for (auto& buffer : m_trade_buffers) { + buffer->push(sample); + } } else { - m_bar_buffer->push(m_generator.next_bar()); + const Bar_sample sample = m_generator.next_bar(); + for (auto& buffer : m_bar_buffers) { + buffer->push(sample); + } } ++m_samples_generated; ++current_count; @@ -263,7 +408,9 @@ void Benchmark_rhi_window::fill_static_data() s.timestamp = ts_ns[i]; s.price = vs[i]; s.size = 1.0f; - m_trade_buffer->push(s); + for (auto& buffer : m_trade_buffers) { + buffer->push(s); + } } else { Bar_sample b{}; @@ -273,49 +420,55 @@ void Benchmark_rhi_window::fill_static_data() b.low = vs[i]; b.close = vs[i]; b.volume = 1.0f; - m_bar_buffer->push(b); + for (auto& buffer : m_bar_buffers) { + buffer->push(b); + } } } } void Benchmark_rhi_window::setup_series() { - m_series = std::make_shared(); - m_series->enabled = true; - m_series->color = glm::vec4(0.2f, 0.7f, 0.9f, 1.0f); - - if (m_config.data_type == "Trades") { - m_series->set_data_source_ref(*m_trade_source); - m_series->access = make_trade_access_policy(); - } - else { - m_series->set_data_source_ref(*m_bar_source); - m_series->access = make_bar_access_policy(); - } - const std::string& style = !m_config.style.empty() ? m_config.style : (m_config.data_type == "Trades" ? std::string("Dots") : std::string("Area")); + m_series.reserve(m_config.series_count); + for (std::size_t index = 0; index < m_config.series_count; ++index) { + auto series = std::make_shared(); + series->enabled = true; + const float blend = static_cast(index % 8) / 8.0f; + series->color = glm::vec4(0.2f + 0.5f * blend, 0.7f, 0.9f - 0.5f * blend, 1.0f); - if (style == "Dots") { - m_series->style = vnm::plot::Display_style::DOTS; - } - else - if (style == "Line") { - m_series->style = vnm::plot::Display_style::LINE; - } - else { - m_series->style = vnm::plot::Display_style::AREA; - } + if (m_config.data_type == "Trades") { + series->set_data_source_ref(*m_trade_sources[index]); + series->access = make_trade_access_policy(); + } + else { + series->set_data_source_ref(*m_bar_sources[index]); + series->access = make_bar_access_policy(); + } - m_plot->add_series(1, m_series); + if (style == "Dots") { + series->style = vnm::plot::Display_style::DOTS; + } + else + if (style == "Line") { + series->style = vnm::plot::Display_style::LINE; + } + else { + series->style = vnm::plot::Display_style::AREA; + } + + m_plot->add_series(static_cast(index + 1), series); + m_series.push_back(std::move(series)); + } } void Benchmark_rhi_window::update_plot_view() { vnm::plot::Data_source* source = m_config.data_type == "Trades" - ? static_cast(m_trade_source.get()) - : static_cast(m_bar_source.get()); + ? static_cast(m_trade_sources.front().get()) + : static_cast(m_bar_sources.front().get()); update_view_range_from_source( source, @@ -336,6 +489,9 @@ void Benchmark_rhi_window::update_plot_view() void Benchmark_rhi_window::on_render_timer() { + if (m_measurement_finished) { + return; + } const auto now = std::chrono::steady_clock::now(); if (m_last_timer_tick.time_since_epoch().count() != 0) { const double elapsed_ms = @@ -344,27 +500,74 @@ void Benchmark_rhi_window::on_render_timer() m_timer_interval_total_ms += elapsed_ms; m_timer_interval_min_ms = std::min(m_timer_interval_min_ms, elapsed_ms); m_timer_interval_max_ms = std::max(m_timer_interval_max_ms, elapsed_ms); + if (m_warmup_frames_remaining == 0) { + m_profiler.record_observation("benchmark.frame.total_ms", elapsed_ms); + } } m_last_timer_tick = now; update_plot_view(); m_plot->update(); update(); + + if (m_warmup_frames_remaining > 0) { + --m_warmup_frames_remaining; + if (m_warmup_frames_remaining == 0) { + m_profiler.reset(); + m_started_at = std::chrono::system_clock::now(); + m_last_timer_tick = {}; + m_timer_interval_count = 0; + m_timer_interval_total_ms = 0.0; + m_timer_interval_min_ms = std::numeric_limits::max(); + m_timer_interval_max_ms = 0.0; + if (m_config.measured_frames == 0) { + m_benchmark_timer.setSingleShot(true); + m_benchmark_timer.start(static_cast(m_config.duration_seconds * 1000)); + } + } + return; + } + + ++m_measured_frame_count; + m_profiler.record_counter("benchmark.frame.output_count"); + if (m_config.measured_frames > 0 && + m_measured_frame_count >= m_config.measured_frames) + { + on_benchmark_timeout(); + } } void Benchmark_rhi_window::on_benchmark_timeout() { + if (m_measurement_finished) { + return; + } + m_measurement_finished = true; stop_generator_thread(); m_render_timer.stop(); + m_benchmark_timer.stop(); m_profiler.record_observation_summary( "qrhi.scheduler.timer_interval", m_timer_interval_count, m_timer_interval_total_ms, m_timer_interval_min_ms, m_timer_interval_max_ms); + record_final_statistics(); emit benchmark_finished(); } +void Benchmark_rhi_window::record_final_statistics() +{ + const double measured_seconds = m_timer_interval_total_ms > 0.0 + ? m_timer_interval_total_ms / 1000.0 + : m_config.duration_seconds; + record_ring_statistics(m_profiler, m_bar_buffers, measured_seconds); + record_ring_statistics(m_profiler, m_trade_buffers, measured_seconds); + m_profiler.record_observation( + "benchmark.memory.process_high_water_bytes", + static_cast(process_memory_high_water_bytes())); +} + Benchmark_rhi_offscreen_runner::Benchmark_rhi_offscreen_runner(const Benchmark_config& config) : m_config(config), @@ -389,16 +592,28 @@ Benchmark_rhi_offscreen_runner::~Benchmark_rhi_offscreen_runner() void Benchmark_rhi_offscreen_runner::setup_data_source() { if (m_config.data_type == "Trades") { - m_trade_buffer = std::make_unique>(m_config.ring_capacity); - m_trade_buffer->set_profiler(&m_profiler); - m_trade_source = std::make_unique>(*m_trade_buffer); - m_trade_source->set_profiler(&m_profiler); + m_trade_buffers.reserve(m_config.series_count); + m_trade_sources.reserve(m_config.series_count); + for (std::size_t index = 0; index < m_config.series_count; ++index) { + auto buffer = std::make_unique>(m_config.ring_capacity); + buffer->set_profiler(&m_profiler); + auto source = std::make_unique>(*buffer); + source->set_profiler(&m_profiler); + m_trade_buffers.push_back(std::move(buffer)); + m_trade_sources.push_back(std::move(source)); + } } else { - m_bar_buffer = std::make_unique>(m_config.ring_capacity); - m_bar_buffer->set_profiler(&m_profiler); - m_bar_source = std::make_unique>(*m_bar_buffer); - m_bar_source->set_profiler(&m_profiler); + m_bar_buffers.reserve(m_config.series_count); + m_bar_sources.reserve(m_config.series_count); + for (std::size_t index = 0; index < m_config.series_count; ++index) { + auto buffer = std::make_unique>(m_config.ring_capacity); + buffer->set_profiler(&m_profiler); + auto source = std::make_unique>(*buffer); + source->set_profiler(&m_profiler); + m_bar_buffers.push_back(std::move(buffer)); + m_bar_sources.push_back(std::move(source)); + } } } @@ -438,36 +653,37 @@ void Benchmark_rhi_offscreen_runner::setup_rendering() void Benchmark_rhi_offscreen_runner::setup_series() { - const int series_id = 1; - auto series = std::make_shared(); - series->enabled = true; - series->color = glm::vec4(0.2f, 0.7f, 0.9f, 1.0f); - - if (m_config.data_type == "Trades") { - series->set_data_source_ref(*m_trade_source); - series->access = make_trade_access_policy(); - } - else { - series->set_data_source_ref(*m_bar_source); - series->access = make_bar_access_policy(); - } - const std::string& style = !m_config.style.empty() ? m_config.style : (m_config.data_type == "Trades" ? std::string("Dots") : std::string("Area")); + for (std::size_t index = 0; index < m_config.series_count; ++index) { + auto series = std::make_shared(); + series->enabled = true; + const float blend = static_cast(index % 8) / 8.0f; + series->color = glm::vec4(0.2f + 0.5f * blend, 0.7f, 0.9f - 0.5f * blend, 1.0f); - if (style == "Dots") { - series->style = vnm::plot::Display_style::DOTS; - } - else - if (style == "Line") { - series->style = vnm::plot::Display_style::LINE; - } - else { - series->style = vnm::plot::Display_style::AREA; - } + if (m_config.data_type == "Trades") { + series->set_data_source_ref(*m_trade_sources[index]); + series->access = make_trade_access_policy(); + } + else { + series->set_data_source_ref(*m_bar_sources[index]); + series->access = make_bar_access_policy(); + } - m_series_map[series_id] = series; + if (style == "Dots") { + series->style = vnm::plot::Display_style::DOTS; + } + else + if (style == "Line") { + series->style = vnm::plot::Display_style::LINE; + } + else { + series->style = vnm::plot::Display_style::AREA; + } + + m_series_map[static_cast(index + 1)] = std::move(series); + } } void Benchmark_rhi_offscreen_runner::generator_thread_func() @@ -485,10 +701,16 @@ void Benchmark_rhi_offscreen_runner::generator_thread_func() while (current_count < static_cast(target_samples) && !m_stop_generator.load()) { if (m_config.data_type == "Trades") { - m_trade_buffer->push(m_generator.next_trade()); + const Trade_sample sample = m_generator.next_trade(); + for (auto& buffer : m_trade_buffers) { + buffer->push(sample); + } } else { - m_bar_buffer->push(m_generator.next_bar()); + const Bar_sample sample = m_generator.next_bar(); + for (auto& buffer : m_bar_buffers) { + buffer->push(sample); + } } ++m_samples_generated; ++current_count; @@ -523,7 +745,9 @@ void Benchmark_rhi_offscreen_runner::fill_static_data() s.timestamp = ts_ns[i]; s.price = vs[i]; s.size = 1.0f; - m_trade_buffer->push(s); + for (auto& buffer : m_trade_buffers) { + buffer->push(s); + } } else { Bar_sample b{}; @@ -533,19 +757,22 @@ void Benchmark_rhi_offscreen_runner::fill_static_data() b.low = vs[i]; b.close = vs[i]; b.volume = 1.0f; - m_bar_buffer->push(b); + for (auto& buffer : m_bar_buffers) { + buffer->push(b); + } } } } bool Benchmark_rhi_offscreen_runner::initialize_rhi(std::string& error_message) { - auto create_null_rhi = [&]() { + const auto create_null_rhi = [&]() { QRhiNullInitParams params; m_rhi.reset(QRhi::create(QRhi::Null, ¶ms)); + return m_rhi != nullptr; }; - auto create_opengl_rhi = [&]() { + const auto create_opengl_rhi = [&]() { #if QT_CONFIG(opengl) m_fallback_surface.reset(QRhiGles2InitParams::newFallbackSurface()); QRhiGles2InitParams params; @@ -560,59 +787,91 @@ bool Benchmark_rhi_offscreen_runner::initialize_rhi(std::string& error_message) #endif }; - const QByteArray forced_backend = qgetenv("QSG_RHI_BACKEND").trimmed().toLower(); - if (!forced_backend.isEmpty()) { - if (forced_backend == "opengl" || forced_backend == "gles" || - forced_backend == "gles2") - { - if (!create_opengl_rhi()) { - error_message = "QSG_RHI_BACKEND requests OpenGL, but offscreen OpenGL QRhi creation failed"; - return false; - } - } - else - if (forced_backend == "null") { - create_null_rhi(); - } - else - if (forced_backend == "d3d11") { + const auto create_d3d11_rhi = [&]() { #ifdef Q_OS_WIN - QRhiD3D11InitParams params; - m_rhi.reset(QRhi::create(QRhi::D3D11, ¶ms)); - if (!m_rhi) { - error_message = "QSG_RHI_BACKEND=d3d11 was requested, but D3D11 QRhi creation failed"; - return false; - } + QRhiD3D11InitParams params; + m_rhi.reset(QRhi::create(QRhi::D3D11, ¶ms)); + return m_rhi != nullptr; #else - error_message = "QSG_RHI_BACKEND=d3d11 is only supported on Windows"; - return false; + return false; #endif - } - else { - error_message = - "Unsupported QSG_RHI_BACKEND for offscreen benchmark: " + - std::string(forced_backend.constData(), forced_backend.size()); + }; + + const auto create_metal_rhi = [&]() { +#if defined(Q_OS_MACOS) && QT_CONFIG(metal) + QRhiMetalInitParams params; + m_rhi.reset(QRhi::create(QRhi::Metal, ¶ms)); + return m_rhi != nullptr; +#else + return false; +#endif + }; + + const auto create_vulkan_rhi = [&]() { +#if QT_CONFIG(vulkan) && __has_include() + m_vulkan_instance = std::make_unique(); + if (!m_vulkan_instance->create()) { + m_vulkan_instance.reset(); return false; } + QRhiVulkanInitParams params; + params.inst = m_vulkan_instance.get(); + m_rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms)); + if (!m_rhi) { + m_vulkan_instance.reset(); + } + return m_rhi != nullptr; +#else + return false; +#endif + }; + + const std::string& requested = m_config.graphics_backend; + bool created = false; + if (requested == "null") { + created = create_null_rhi(); } - else { -#ifdef Q_OS_WIN - QRhiD3D11InitParams params; - m_rhi.reset(QRhi::create(QRhi::D3D11, ¶ms)); + else + if (requested == "opengl") { + created = create_opengl_rhi(); + } + else + if (requested == "d3d11") { + created = create_d3d11_rhi(); + } + else + if (requested == "metal") { + created = create_metal_rhi(); + } + else + if (requested == "vulkan") { + created = create_vulkan_rhi(); + } + else + if (requested == "native") { +#if defined(Q_OS_WIN) + created = create_d3d11_rhi(); +#elif defined(Q_OS_MACOS) + created = create_metal_rhi(); #else - create_opengl_rhi(); + created = create_opengl_rhi(); #endif } - if (!m_rhi) { - create_null_rhi(); + if (!created || !m_rhi) { + error_message = "cold.backend_create: failed to create requested offscreen QRhi backend '" + + requested + "'"; + return false; } - if (!m_rhi) { - error_message = "Failed to create offscreen QRhi"; + if (m_rhi->backend() == QRhi::Null && requested != "null") { + error_message = "cold.backend_validate: requested '" + requested + + "' but QRhi created the Null backend"; return false; } - const QSize size(1200, 720); + m_graphics_info = graphics_device_info_from_rhi(*m_rhi); + + const QSize size(m_config.framebuffer_width, m_config.framebuffer_height); const int sample_count = 4; m_color_buffer.reset(m_rhi->newRenderBuffer( QRhiRenderBuffer::Color, @@ -625,8 +884,23 @@ bool Benchmark_rhi_offscreen_runner::initialize_rhi(std::string& error_message) return false; } + if (m_config.capture_pixel_checksum) { + m_resolve_texture.reset(m_rhi->newTexture( + QRhiTexture::RGBA8, + size, + 1, + QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource)); + if (!m_resolve_texture || !m_resolve_texture->create()) { + error_message = "cold.render_target: failed to create pixel readback resolve texture"; + return false; + } + } + QRhiColorAttachment color_attachment; color_attachment.setRenderBuffer(m_color_buffer.get()); + if (m_resolve_texture) { + color_attachment.setResolveTexture(m_resolve_texture.get()); + } QRhiTextureRenderTargetDescription rt_desc(color_attachment); m_render_target.reset(m_rhi->newTextureRenderTarget(rt_desc)); m_render_pass_descriptor.reset(m_render_target->newCompatibleRenderPassDescriptor()); @@ -639,8 +913,12 @@ bool Benchmark_rhi_offscreen_runner::initialize_rhi(std::string& error_message) return true; } -bool Benchmark_rhi_offscreen_runner::render_frame(std::string& error_message) +bool Benchmark_rhi_offscreen_runner::render_frame( + std::string& error_message, + bool measured) { + const auto frame_started = std::chrono::steady_clock::now(); + const auto submission_started = frame_started; QRhiCommandBuffer* cb = nullptr; if (m_rhi->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess || !cb) { error_message = "QRhi beginOffscreenFrame failed"; @@ -650,12 +928,12 @@ bool Benchmark_rhi_offscreen_runner::render_frame(std::string& error_message) VNM_PLOT_PROFILE_SCOPE(&m_profiler, "renderer"); VNM_PLOT_PROFILE_SCOPE(&m_profiler, "renderer.frame"); - const int fb_w = 1200; - const int fb_h = 720; + const int fb_w = m_config.framebuffer_width; + const int fb_h = m_config.framebuffer_height; vnm::plot::Data_source* source = m_config.data_type == "Trades" - ? static_cast(m_trade_source.get()) - : static_cast(m_bar_source.get()); + ? static_cast(m_trade_sources.front().get()) + : static_cast(m_bar_sources.front().get()); { VNM_PLOT_PROFILE_SCOPE(&m_profiler, "renderer.frame.update_view_range"); update_view_range_from_source( @@ -771,7 +1049,13 @@ bool Benchmark_rhi_offscreen_runner::render_frame(std::string& error_message) { VNM_PLOT_PROFILE_SCOPE(&m_profiler, "renderer.frame.render_passes"); + const auto planning_started = std::chrono::steady_clock::now(); m_series_renderer.prepare(frame_ctx, m_series_map); + m_last_prepare_ms = std::chrono::duration( + std::chrono::steady_clock::now() - planning_started).count(); + if (measured) { + m_profiler.record_observation("benchmark.planning.time_ms", m_last_prepare_ms); + } m_chrome_renderer.render_grid_and_backgrounds(frame_ctx, m_primitives); const std::size_t back_layer_end = m_primitives.queued_op_count(); m_chrome_renderer.render_zero_line(frame_ctx, m_primitives); @@ -803,27 +1087,85 @@ bool Benchmark_rhi_offscreen_runner::render_frame(std::string& error_message) m_primitives.reset_frame(); } + QRhiReadbackResult readback; + if (measured && m_config.capture_pixel_checksum && m_resolve_texture) { + QRhiResourceUpdateBatch* readback_updates = m_rhi->nextResourceUpdateBatch(); + readback_updates->readBackTexture( + QRhiReadbackDescription(m_resolve_texture.get()), + &readback); + cb->resourceUpdate(readback_updates); + } + m_rhi->endOffscreenFrame(); - if (m_config.finish) { + if (measured) { + const double submission_ms = std::chrono::duration( + std::chrono::steady_clock::now() - submission_started).count(); + m_profiler.record_observation("benchmark.frame.submission_ms", submission_ms); + } + if (m_config.finish || (measured && m_config.capture_pixel_checksum)) { VNM_PLOT_PROFILE_SCOPE(&m_profiler, "renderer.frame.finish"); + const auto finish_started = std::chrono::steady_clock::now(); m_rhi->finish(); + if (measured) { + const double finish_ms = std::chrono::duration( + std::chrono::steady_clock::now() - finish_started).count(); + m_profiler.record_observation("benchmark.frame.gpu_finish_ms", finish_ms); + } + } + if (measured && m_config.capture_pixel_checksum) { + if (readback.data.isEmpty()) { + error_message = "measure.pixel_readback: QRhi returned no pixel data"; + return false; + } + std::uint64_t checksum = 1'469'598'103'934'665'603ull; + for (const unsigned char byte : readback.data) { + checksum ^= byte; + checksum *= 1'099'511'628'211ull; + } + m_pixel_checksum = checksum; + m_profiler.record_observation( + "benchmark.frame.pixel_readback_bytes", + static_cast(readback.data.size())); + m_profiler.record_observation( + "benchmark.frame.pixel_checksum_low32", + static_cast(checksum & 0xffff'ffffull)); + } + if (measured) { + const double frame_ms = std::chrono::duration( + std::chrono::steady_clock::now() - frame_started).count(); + m_profiler.record_observation("benchmark.frame.total_ms", frame_ms); + m_profiler.record_counter("benchmark.frame.output_count"); + ++m_measured_frame_count; } return true; } bool Benchmark_rhi_offscreen_runner::run(std::string& error_message) { + m_phase_trace_started = std::chrono::steady_clock::now(); + std::error_code remove_error; + std::filesystem::remove( + std::filesystem::path(m_config.output_directory) / "benchmark_phase_trace.jsonl", + remove_error); + record_phase("cold.setup.begin"); + const auto cold_started = std::chrono::steady_clock::now(); + const auto setup_started = cold_started; setup_data_source(); setup_rendering(); setup_series(); + record_phase("cold.setup.end"); + m_cold_setup_ms = std::chrono::duration( + std::chrono::steady_clock::now() - setup_started).count(); + const auto backend_started = std::chrono::steady_clock::now(); + record_phase("cold.backend_create.begin"); if (!initialize_rhi(error_message)) { + record_phase("cold.backend_create.failed"); return false; } - - m_started_at = std::chrono::system_clock::now(); - const auto steady_start = std::chrono::steady_clock::now(); - const auto duration = std::chrono::duration(m_config.duration_seconds); + record_phase("cold.backend_create.end"); + m_cold_backend_ms = std::chrono::duration( + std::chrono::steady_clock::now() - backend_started).count(); if (m_config.static_data) { fill_static_data(); @@ -833,15 +1175,110 @@ bool Benchmark_rhi_offscreen_runner::run(std::string& error_message) m_generator_thread = std::thread(&Benchmark_rhi_offscreen_runner::generator_thread_func, this); } - while (std::chrono::steady_clock::now() - steady_start < duration) { - if (!render_frame(error_message)) { + for (std::size_t frame = 0; frame < m_config.warmup_frames; ++frame) { + record_phase("warmup.frame.begin", frame); + const auto warmup_started = std::chrono::steady_clock::now(); + if (!render_frame(error_message, false)) { + error_message = "warmup.frame: " + error_message; stop_generator_thread(); return false; } + record_phase("warmup.frame.end", frame); + if (frame == 0) { + m_cold_first_submission_ms = std::chrono::duration( + std::chrono::steady_clock::now() - warmup_started).count(); + m_cold_shader_pipeline_prepare_ms = m_last_prepare_ms; + } + } + + m_cold_total_ms = std::chrono::duration( + std::chrono::steady_clock::now() - cold_started).count(); + m_profiler.reset(); + m_profiler.record_observation("benchmark.cold.setup_ms", m_cold_setup_ms); + m_profiler.record_observation("benchmark.cold.backend_create_ms", m_cold_backend_ms); + if (m_config.warmup_frames > 0) { + m_profiler.record_observation( + "benchmark.cold.first_submission_ms", + m_cold_first_submission_ms); + m_profiler.record_observation( + "benchmark.cold.shader_pipeline_prepare_ms", + m_cold_shader_pipeline_prepare_ms); + } + m_profiler.record_observation("benchmark.cold.total_ms", m_cold_total_ms); + m_profiler.record_observation( + "benchmark.warmup.frame_count", + static_cast(m_config.warmup_frames)); + + m_started_at = std::chrono::system_clock::now(); + const auto measured_started = std::chrono::steady_clock::now(); + const auto duration = std::chrono::duration(m_config.duration_seconds); + + const auto render_measured_frame = [&](std::size_t frame) { + record_phase("measure.frame.begin", frame); + if (render_frame(error_message, true)) { + record_phase("measure.frame.end", frame); + return true; + } + record_phase("measure.frame.failed", frame); + error_message = "measure.frame: " + error_message; + return false; + }; + + if (m_config.measured_frames > 0) { + for (std::size_t frame = 0; frame < m_config.measured_frames; ++frame) { + if (!render_measured_frame(frame)) { + stop_generator_thread(); + return false; + } + } + } + else { + std::size_t frame = 0; + while (std::chrono::steady_clock::now() - measured_started < duration) { + if (!render_measured_frame(frame++)) { + stop_generator_thread(); + return false; + } + } } + const double measured_seconds = std::chrono::duration( + std::chrono::steady_clock::now() - measured_started).count(); + + const auto shutdown_started = std::chrono::steady_clock::now(); + record_phase("shutdown.generator.begin"); stop_generator_thread(); + record_phase("shutdown.generator.end"); + const double shutdown_ms = std::chrono::duration( + std::chrono::steady_clock::now() - shutdown_started).count(); + m_profiler.record_observation("benchmark.shutdown.generator_ms", shutdown_ms); + record_final_statistics(measured_seconds); + record_phase("complete"); return true; } +void Benchmark_rhi_offscreen_runner::record_phase( + const char* phase, + std::size_t frame) const +{ + const double elapsed_ms = std::chrono::duration( + std::chrono::steady_clock::now() - m_phase_trace_started).count(); + const std::filesystem::path trace_path = + std::filesystem::path(m_config.output_directory) / "benchmark_phase_trace.jsonl"; + std::ofstream trace(trace_path, std::ios::app); + if (trace) { + trace << "{\"elapsed_ms\":" << std::setprecision(17) << elapsed_ms + << ",\"phase\":\"" << phase << "\",\"frame\":" << frame << "}\n"; + } +} + +void Benchmark_rhi_offscreen_runner::record_final_statistics(double measured_seconds) +{ + record_ring_statistics(m_profiler, m_bar_buffers, measured_seconds); + record_ring_statistics(m_profiler, m_trade_buffers, measured_seconds); + m_profiler.record_observation( + "benchmark.memory.process_high_water_bytes", + static_cast(process_memory_high_water_bytes())); +} + } // namespace vnm::benchmark diff --git a/benchmark/src/main.cpp b/benchmark/src/main.cpp index 71d0cb04..91be5cd5 100644 --- a/benchmark/src/main.cpp +++ b/benchmark/src/main.cpp @@ -1,19 +1,27 @@ // vnm_plot Synthetic Benchmark // Stage 7: CLI polish with validation and improved UX -#include "benchmark_window.h" +#include "benchmark_build_metadata.h" #include "benchmark_profiler.h" +#include "benchmark_window.h" +#include #include #include +#include +#include #include #include +#include +#include +#include #include #include #include #include #include +#include #include namespace { @@ -25,6 +33,21 @@ constexpr int k_exit_success = 0; constexpr int k_exit_invalid_args = 1; constexpr int k_exit_runtime_error = 2; +std::string compiler_identity() +{ +#if defined(__GNUC__) && !defined(__clang__) + return "GNU " + std::to_string(__GNUC__) + "." + + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__); +#elif defined(__clang__) + return "Clang " + std::to_string(__clang_major__) + "." + + std::to_string(__clang_minor__) + "." + std::to_string(__clang_patchlevel__); +#elif defined(_MSC_VER) + return "MSVC " + std::to_string(_MSC_VER) + "." + std::to_string(_MSC_FULL_VER); +#else + return "unknown"; +#endif +} + void print_version() { std::cout << "vnm_plot_benchmark version " << k_version << "\n"; @@ -43,6 +66,7 @@ void print_usage(const char* program_name) << " --stream Stream name for report (default: SIM)\n" << " --data-type bars|trades (default: bars)\n" << " --backend qrhi|qrhi-offscreen (default: qrhi-offscreen)\n" + << " --graphics-backend native|d3d11|metal|vulkan|opengl|null (default: native)\n" << " --render-style