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
Follow-up to PR #159 (cvar UX: CVAR_PLATFORM_MAC / CVAR_PLATFORM_WIN flag bits + 0-as-off enum alias). That PR added platform gating at the CVAR level. This issue adds two missing dimensions of UX hygiene to the same code area:
Per-value platform gating inside enum cvars — the cvar itself is cross-platform but specific allowed-values aren't.
Cross-cvar dependency warnings — when the user sets a cvar whose prerequisite condition isn't met, print a clear hint instead of silently no-op'ing.
Part 1: per-value platform gating
The cvar is cross-platform but its enum has platform-only values:
Per-value platform tag in the allowed-values metadata. Concretely: where r_denoiser declares its enum in src/engine/Engine.cpp, each value gets an optional CVAR_VALUE_MAC / CVAR_VALUE_WIN / CVAR_VALUE_LINUX flag. At cvar_list / cvar autocomplete time, the console filters out values whose tag doesn't match the current platform. At cvar set time, picking a disallowed value errors with:
[error] r_denoiser=nrd_relax is Windows/Linux-only; not available on macOS.
Available on this platform: none, svgf_basic, svgf_atrous, metalfx, svgf_basic_metalfx, svgf_atrous_metalfx
Part 2: cross-cvar dependency warnings
When the user sets a cvar whose effect requires another cvar to be in a specific state, print a clear warning + actionable hint. Currently those settings just silently no-op or produce surprising behavior.
Examples from the codebase
Cvar
Prerequisite
Hint when unmet
r_sun_elevation, r_sun_azimuth, r_sky_day
r_sky_mode procedural
r_sky_mode=astronomical: solar position derives from datetime/lat/lon, not these cvars
r_clouds_coverage, r_clouds_curl_amount, etc.
r_clouds 1
r_clouds=0: cloud march disabled
r_svgf_atrous_passes, r_svgf_albedo_demod
r_denoiser starts with svgf_
r_denoiser=none: SVGF inactive
r_smoke_max_emitters
r_smoke_enabled 1
r_smoke_enabled=0: smoke loop disabled
r_water_ior, r_water_absorption_*
scene has a MAT_WATER primitive
(warn at primitive-list time, harder to detect at cvar-set time)
r_restir_k_candidates, r_restir_temporal
r_restir 1 AND denoiser active
r_restir=0 or no denoiser: ReSTIR dispatch skipped
Or more generally a lambda for compound conditions:
CVAR_REQUIRES_PREDICATE([](){
auto* m = C.FindCVar("r_sky_mode");
return m && m->value == "procedural";
}, "r_sky_mode=procedural")
At cvar set time, after the value is written, evaluate the predicate. If false, print warning. Don't BLOCK the set — the cvar still takes the new value (so a single cfg-load script can set the dependency cvar second and have the first one apply correctly). The warning is informational.
At cvar_list time, append [inactive: requires <dep>] to the description if predicate fails.
Acceptance criteria
r_denoiser nrd_relax on Mac errors with the platform-mismatch message + lists available values
cvar_list r_denoiser on Mac shows only Mac values; on Win shows only Win values
cvar set r_sun_elevation 30 when r_sky_mode=astronomical prints the warning hint
All existing cfg files (cornell_csg.cfg, etc.) still load cleanly without spurious warnings; predicates are only evaluated after explicit user cvar set, not during cfg replay (configurable via a flag — the cfg might set the dep cvar after the dependent one)
~300-500 LoC across Console.cpp / Console.h + the PT_CVAR macro + the per-cvar dependency declarations in Engine.cpp. Doctest fixture in tests/cvar_ux_test.cpp extending PR #159's coverage with platform-value-gating cases + dep-warning cases.
Out of scope
Runtime predicate evaluation on EVERY cvar access — only at set time + list time.
Auto-correcting / cascading sets (e.g. "you set r_clouds_curl_amount, would you like to also enable r_clouds? [y/n]") — too prompt-heavy for a console UX. The warning + hint is enough.
Dependencies
Lands on top of PR #159 (already in integration). No conflicts expected — separate code areas inside the same files.
Context
Follow-up to PR #159 (cvar UX:
CVAR_PLATFORM_MAC/CVAR_PLATFORM_WINflag bits + 0-as-off enum alias). That PR added platform gating at the CVAR level. This issue adds two missing dimensions of UX hygiene to the same code area:Part 1: per-value platform gating
The cvar is cross-platform but its enum has platform-only values:
r_denoiser:none, svgf_basic, svgf_atrous, metalfx, svgf_basic_metalfx, svgf_atrous_metalfxnone, svgf_basic, svgf_atrous, nrd_relax, nrd_sigma, optix_hdr, optix_temporal_hdr, optix_hdr_aov, optix_temporal_hdr_aovr_backend:metal, vulkan, softwarevulkan, software(nometal)r_software_blit:vulkan, gdivulkan(gdi is Win-only)Implementation sketch
Per-value platform tag in the allowed-values metadata. Concretely: where
r_denoiserdeclares its enum insrc/engine/Engine.cpp, each value gets an optionalCVAR_VALUE_MAC/CVAR_VALUE_WIN/CVAR_VALUE_LINUXflag. Atcvar_list/cvar autocompletetime, the console filters out values whose tag doesn't match the current platform. Atcvar settime, picking a disallowed value errors with:Part 2: cross-cvar dependency warnings
When the user sets a cvar whose effect requires another cvar to be in a specific state, print a clear warning + actionable hint. Currently those settings just silently no-op or produce surprising behavior.
Examples from the codebase
r_sun_elevation,r_sun_azimuth,r_sky_dayr_sky_mode proceduralr_sky_mode=astronomical: solar position derives from datetime/lat/lon, not these cvarsr_clouds_coverage,r_clouds_curl_amount, etc.r_clouds 1r_clouds=0: cloud march disabledr_svgf_atrous_passes,r_svgf_albedo_demodr_denoiserstarts withsvgf_r_denoiser=none: SVGF inactiver_smoke_max_emittersr_smoke_enabled 1r_smoke_enabled=0: smoke loop disabledr_water_ior,r_water_absorption_*MAT_WATERprimitiver_restir_k_candidates,r_restir_temporalr_restir 1AND denoiser activer_restir=0or no denoiser: ReSTIR dispatch skippedr_light_tree_*(future tuning cvars)r_light_tree 1r_light_tree=0: naive uniform NEE pickr_voxel_sizer_voxelize_demo 1(to actually see the effect)r_voxelize_demo=0: voxel grids hiddenr_metalfx_*(any future MetalFX cvars)r_denoiseris MetalFX-familyr_denoiser=svgf_atrous: MetalFX specular guidance inactiver_optix_*(any future OptiX cvars)r_denoiseris OptiX-familyr_denoiser=none: OptiX denoiser inactiveImplementation sketch
Extend
PT_CVARmacro with an optional dependency predicate, e.g.:Or more generally a lambda for compound conditions:
At
cvar settime, after the value is written, evaluate the predicate. If false, print warning. Don't BLOCK the set — the cvar still takes the new value (so a single cfg-load script can set the dependency cvar second and have the first one apply correctly). The warning is informational.At
cvar_listtime, append[inactive: requires <dep>]to the description if predicate fails.Acceptance criteria
r_denoiser nrd_relaxon Mac errors with the platform-mismatch message + lists available valuescvar_list r_denoiseron Mac shows only Mac values; on Win shows only Win valuescvar set r_sun_elevation 30whenr_sky_mode=astronomicalprints the warning hintcvar set, not during cfg replay (configurable via a flag — the cfg might set the dep cvar after the dependent one)r_denoiser=metalfxis still PARSED on Win for portability of demont.cfg (just warns + no-ops with the "this platform doesn't support that denoiser" reason); same pattern as PR feat(console): platform-filter cvar listing + accept "0" as off alias #159's flag-bit cvarsScope estimate
~300-500 LoC across Console.cpp / Console.h + the
PT_CVARmacro + the per-cvar dependency declarations in Engine.cpp. Doctest fixture intests/cvar_ux_test.cppextending PR #159's coverage with platform-value-gating cases + dep-warning cases.Out of scope
Dependencies
Lands on top of PR #159 (already in integration). No conflicts expected — separate code areas inside the same files.