You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Investigation found the shared code (esp. the Kooima math display3d_view/camera3d_view) is vendored in six places — not just the two demos — including displayxr-unreal (Private/Native/) and displayxr-unity (native~). The plan changed accordingly:
One repo, two CMake targets — not a new repo. Repurpose the dormant kooima-projection → displayxr-common, exposing displayxr::math (pure C, linked by the engines too) + displayxr::common (C++ scaffolding, depends on math). Net new repos: 0.
The "new repo / FetchContent by tag / divergence policy / reconcile-first" detail below still applies to the displayxr::common target; read "new displayxr-common repo" as "the displayxr::common target in the renamed repo."
See #396 for the full inventory, architecture, and ordering.
Problem
The native C++ demos each carry a checked-in common/ directory (view math,
atlas capture, HUD, input, window manager, window-space-layer UI, logging,
xr-session glue, stb wrappers). These copies were originally seeded from this
runtime repo but are now maintained independently in each demo — so they drift. The runtime no longer carries these files, so there is no canonical
home, and "common" is a misnomer: the copies are diverging.
Concrete snapshot today (displayxr-demo-modelviewer vs displayxr-demo-gaussiansplat, ~28 files in common/):
File
Δ lines
Nature
display3d_view.c/.h
183 / 57
mostly gauss's unmerged feat/zdp-clip-soft-fade-pick WIP (near_z/far_z, selftest, center_view, vulkan_flip_y) + a Vulkan [0,1] projection fix landed in modelviewer
xr_session_common.cpp/.h
98 / 31
gauss-side changes
hud_renderer.cpp/.h
31 / 10
gauss-side
input_handler.cpp/.h
8 / 7
gauss-side
stb_image_impl_macos.cpp
—
modelviewer-only (legit app-local)
~20 of the ~28 files are byte-identical. Almost all the drift is accidental
(two checked-in copies edited independently, plus one repo on an unmerged
branch), not essential divergence.
Most recently this bit us in the clip-plane work: the model viewer's raster PBR
pass needed a Vulkan [0,1] projection (the GL [-1,1] form silently clipped
the model once far = ez + 1000·vH), while the gauss splat renderer is immune
(it culls in software, not against the projection planes). That fix had to be
hand-applied to one copy with no mechanism to keep the other in sync.
Why now (motivation beyond de-dup)
The window-space-layer UI is becoming a genuinely reusable building block. With
the #389 fix (VK native compositor now reliably composites many window-space
layers; new windowspace_handle_{d3d11,d3d12,vk,gl}_win test apps added here),
every native app — both demos and this repo's native test apps — wants the
same window-space-layer + HUD + input scaffolding. That's a library, not a
vendored folder.
Goal
Make common/ a versioned dependency rather than a checked-in directory, so
that editing-a-local-copy (the drift failure mode) becomes structurally
impossible, and the same module is reused by:
displayxr-demo-modelviewer
displayxr-demo-gaussiansplat
this repo's native C++ test apps (*_handle_*_win, windowspace_handle_*_win)
2. Consume via CMake FetchContent pinned to a tag — same pattern this repo
the demos already use for tinygltf/glm/OpenXR-loader. Rationale vs
alternatives:
FetchContent by tag (recommended): plain git clone + cmake works (no --recursive); a version bump is a one-line GIT_TAG diff; nothing is
checked into the consumer tree so the vendored-copy edit is impossible; local
co-development via FETCHCONTENT_SOURCE_DIR_DISPLAYXRCOMMON=../displayxr-common
(edit a sibling checkout live, no re-fetch).
git submodule: source visible in-tree but --recursive/detached-HEAD/
forgotten-pointer-bump friction; rejected.
git subtree: no clone pain, but the vendored copy stays editable so drift
can creep back; rejected.
3. Divergence policy — mechanism, not policy, lives in the lib. App-specific
behavior is expressed at the call site, never via #ifdef APP inside the lib:
Parameterize (preferred): the clip/cull case is the worked example — the lib
exposes display3d_compute_view(..., near_offset, far_offset, ...) and outputs both the projection matrix and the resolved near_z/far_z. The model
viewer uses the projection's hardware clip; gauss feeds near_z/far_z into
its software splat cull. Same call, different consumption — no fork. The
Vulkan [0,1] projection is correct for both (splats are insensitive to the
z-range).
Inject the renderer-specific bit via a small callback/strategy when a param
isn't enough.
Keep app-local what is genuinely app-specific (e.g. stb_image_impl_macos.cpp). Not everything must live in the lib.
Never#ifdef MODELVIEWER / #ifdef GAUSS inside the lib — that re-creates
drift inside the shared repo.
Migration steps
Reconcile first (while still vendored): unify display3d_view.{c,h} into
one file that is the superset — Vulkan [0,1] projection + gauss's near_offset/far_offset API + near_z/far_z outputs (+ selftest /
center_view as they land). Fold in the hud/input/xr_session deltas.
Land gauss's feat/zdp-clip-soft-fade-pick so there's a single reconciled
baseline.
Create displayxr-common seeded from the reconciled baseline; define the
CMake target(s); tag v0.1.0.
Migrate consumers: delete each common/ dir; add a FetchContent block
pinned to the tag; wire the target into the existing CMake. Verify Windows +
macOS builds (CI already runs both per demo).
Adopt in this repo's native test apps (*_handle_*_win, windowspace_handle_*_win) so the window-space-layer UI is shared, not
re-copied.
Release discipline: displayxr-common gets its own tags; consumers bump
the pin when ready (independent cadence preserved). Optional CI guard: a hash
check if any app ever keeps a vendored mirror.
Non-goals
Monorepo (contradicts the independent release cadence).
Folding engine-based test apps (Unity/Unreal) — they don't use this C++ code.
Renaming common/ in place without extraction (documents drift, doesn't
prevent it).
Open questions
Home: dedicated displayxr-common repo (recommended) vs a subdir of this
runtime repo (zero-fetch for runtime test apps, but couples demo builds to the
large runtime repo).
Lib surface: exact split between shared lib vs app-local files (esp. the
stb implementation TU and any platform glue).
Versioning: tag-per-change vs periodic tags; whether to gate demo releases
on a minimum displayxr-common version the way they already gate on a minimum
runtime version.
Problem
The native C++ demos each carry a checked-in
common/directory (view math,atlas capture, HUD, input, window manager, window-space-layer UI, logging,
xr-session glue, stb wrappers). These copies were originally seeded from this
runtime repo but are now maintained independently in each demo — so they
drift. The runtime no longer carries these files, so there is no canonical
home, and "common" is a misnomer: the copies are diverging.
Concrete snapshot today (
displayxr-demo-modelviewervsdisplayxr-demo-gaussiansplat, ~28 files incommon/):display3d_view.c/.hfeat/zdp-clip-soft-fade-pickWIP (near_z/far_z, selftest, center_view, vulkan_flip_y) + a Vulkan[0,1]projection fix landed in modelviewerxr_session_common.cpp/.hhud_renderer.cpp/.hinput_handler.cpp/.hstb_image_impl_macos.cpp~20 of the ~28 files are byte-identical. Almost all the drift is accidental
(two checked-in copies edited independently, plus one repo on an unmerged
branch), not essential divergence.
Most recently this bit us in the clip-plane work: the model viewer's raster PBR
pass needed a Vulkan
[0,1]projection (the GL[-1,1]form silently clippedthe model once
far = ez + 1000·vH), while the gauss splat renderer is immune(it culls in software, not against the projection planes). That fix had to be
hand-applied to one copy with no mechanism to keep the other in sync.
Why now (motivation beyond de-dup)
The window-space-layer UI is becoming a genuinely reusable building block. With
the #389 fix (VK native compositor now reliably composites many window-space
layers; new
windowspace_handle_{d3d11,d3d12,vk,gl}_wintest apps added here),every native app — both demos and this repo's native test apps — wants the
same window-space-layer + HUD + input scaffolding. That's a library, not a
vendored folder.
Goal
Make
common/a versioned dependency rather than a checked-in directory, sothat editing-a-local-copy (the drift failure mode) becomes structurally
impossible, and the same module is reused by:
displayxr-demo-modelviewerdisplayxr-demo-gaussiansplat*_handle_*_win,windowspace_handle_*_win)Proposed design
1. New repo
displayxr-common(org-level, lightweight), exporting CMaketargets (e.g.
displayxr::common). Contents = the genuinely shared files:view math (
display3d_view,camera3d_view,leia_math), atlas capture,HUD renderer, input handler, window manager + window-space-layer UI helpers,
logging,
xr_session_common, stb wrappers,view_params, manifest cmake.2. Consume via CMake
FetchContentpinned to a tag — same pattern this repoalternatives:
git clone+cmakeworks (no--recursive); a version bump is a one-lineGIT_TAGdiff; nothing ischecked into the consumer tree so the vendored-copy edit is impossible; local
co-development via
FETCHCONTENT_SOURCE_DIR_DISPLAYXRCOMMON=../displayxr-common(edit a sibling checkout live, no re-fetch).
--recursive/detached-HEAD/forgotten-pointer-bump friction; rejected.
can creep back; rejected.
3. Divergence policy — mechanism, not policy, lives in the lib. App-specific
behavior is expressed at the call site, never via
#ifdef APPinside the lib:exposes
display3d_compute_view(..., near_offset, far_offset, ...)and outputsboth the projection matrix and the resolved
near_z/far_z. The modelviewer uses the projection's hardware clip; gauss feeds
near_z/far_zintoits software splat cull. Same call, different consumption — no fork. The
Vulkan
[0,1]projection is correct for both (splats are insensitive to thez-range).
isn't enough.
stb_image_impl_macos.cpp). Not everything must live in the lib.#ifdef MODELVIEWER / #ifdef GAUSSinside the lib — that re-createsdrift inside the shared repo.
Migration steps
display3d_view.{c,h}intoone file that is the superset — Vulkan
[0,1]projection + gauss'snear_offset/far_offsetAPI +near_z/far_zoutputs (+ selftest /center_view as they land). Fold in the
hud/input/xr_sessiondeltas.Land gauss's
feat/zdp-clip-soft-fade-pickso there's a single reconciledbaseline.
displayxr-commonseeded from the reconciled baseline; define theCMake target(s); tag
v0.1.0.common/dir; add aFetchContentblockpinned to the tag; wire the target into the existing CMake. Verify Windows +
macOS builds (CI already runs both per demo).
*_handle_*_win,windowspace_handle_*_win) so the window-space-layer UI is shared, notre-copied.
displayxr-commongets its own tags; consumers bumpthe pin when ready (independent cadence preserved). Optional CI guard: a hash
check if any app ever keeps a vendored mirror.
Non-goals
common/in place without extraction (documents drift, doesn'tprevent it).
Open questions
displayxr-commonrepo (recommended) vs a subdir of thisruntime repo (zero-fetch for runtime test apps, but couples demo builds to the
large runtime repo).
stb implementation TU and any platform glue).
on a minimum
displayxr-commonversion the way they already gate on a minimumruntime version.