UnityShaderNav is a Visual Studio Code extension for navigating Unity shader projects. It understands ShaderLab wrappers, HLSL/CG include files, Unity Packages, declaration macros, and the kinds of symbol ambiguity that are common in URP/HDRP projects.
The extension focuses on fast code navigation:
- Go to Definition for functions, locals, parameters, structs, struct members,
macros,
#includepaths, and shader entry points. - Find References across indexed user files, with an option to include package references.
- Adapter-backed navigation for File-mode Shader Graph Custom Function nodes: F12 opens the precision-suffixed HLSL declaration, Find References returns to graph nodes, and Problems identifies missing includes, invalid suffixes, and port/signature mismatches.
- Adapter-backed ShaderLab Property references to source-fresh C# calls,
including constant
Shader.PropertyToIDflows and typedMaterial/MaterialPropertyBlockSet/Get accessors. Problems reports proven accessor type mismatches; name-only and dynamic evidence stays explicitly uncertain. The bridge does not register a competing C# language provider. - Workspace Rename for unambiguous indexed HLSL/CG symbols, including pragma entry-point references and same-file ShaderLab Property contracts, with conservative refusal for overload-like or preprocessor ambiguity.
- An explicit safe cross-asset Shader Property Rename preview groups Shader/HLSL, proven C#, and serialized Material edits. Revision conflicts, dynamic evidence, and read-only assets block Apply; prepared Adapter changes and source edits roll back together on cancellation or failure.
- Project-wide ShaderLab name intelligence for
Shader,Fallback,Name, andUsePass: Definition, References, Hover, Completion, Workspace Symbols, and conservative Rename.UsePasspass segments follow Unity's uppercase canonical form. - VS Code Problems diagnostics for unresolved
#pragma vertex,fragment,geometry,hull,domain,surface, andkernelentry points, refreshed from the same live published revision as navigation. - Conservative SRP Batcher contract diagnostics for scalar/vector ShaderLab
Properties missing from
UnityPerMaterial, incompatible field types, and deterministic cross-Pass layout drift. A Quick Fix is offered only when one exact insertion target is safe. - Explainable custom Shader portability reports for a selected URP target or Adapter graphics profile. Reports bind Unity and Package versions to the current published source, separate mechanical changes from human rewrites, unsupported semantics, and compiler verification, and expose Quick Fixes only for a narrow mechanically proven unlit slice.
- Hover for declarations of indexed shader symbols (functions, structs,
members, variables, parameters, macros), plus sourced Quick Documentation
for selected ShaderLab terms, Property syntax, semantics, and SRP helpers.
In Unity projects,
UNITY_VERSIONalso shows a presentation-only value derived fromProjectSettings/ProjectVersion.txt. Project and Package declarations win over these version-aware fallbacks. - Conservative completion and signature help for indexed HLSL/CG code, plus a
curated Unity/HLSL/ShaderLab/URP/HDRP built-in vocabulary covering common
intrinsics, helper macros, render states, and semantics. Receiver-aware
results include texture methods and overload signatures, vector swizzles,
non-square matrix components, and explicitly typed texture declarations such
as
Texture2D<float4>. - Context-scoped ShaderLab snippets for complete Surface and vertex/fragment Shaders, common Material Properties, Pass/program structures, and Blend states; editable presentations for normalized literal Color defaults; and safe ShaderLab indentation formatting.
- Document Symbols and semantic coloring for ShaderLab wrappers, Properties, Tags, render states, preprocessor lines, and HLSL symbols.
- Workspace symbol search (Ctrl+T / Cmd+T) across indexed shader functions,
structs, struct members, cbuffers, macros, and globals. Package symbols are
excluded by default and follow
findReferences.includePackages. - Conservative dimming of inactive and variant-dependent
#if/#ifdefpreprocessor branches, with a theme-adaptive marker distinguishing variant gates from definitely inactive code (presentation only; navigation is unaffected). - Optional variant-context picker (status bar + QuickPick) to resolve
multi_compile/shader_featureambiguity: active branches brighten, inactive ones dim, and navigation selects the provably active candidates; if the context proves none of them active, every conservative candidate remains available. Opt-in; default behaviour is unchanged. - Session-only Shader Context picker for shared HLSL/CG includes. Known Shader, Pass, stage, and include-point combinations come from one published index revision; selecting one sharpens dimming, semantic coloring, completion, diagnostics, and navigation. Provably active navigation candidates are selected; if none can be proven active, conservative candidates remain available.
- Adapter-backed Source, Preprocessed, and Generated compiler evidence views
for one selected Shader Context and verified compile profile. Exact
#lineregions navigate in both directions across ShaderLab and includes; macro expansions and generated-only regions stay visibly unmapped. Source changes mark old virtual documentsSTALEbefore replacement evidence arrives. - Selected Material Context from a connected Unity Editor Adapter. The status bar exposes the Material's Shader, optional SubShader/Pass, serialized Properties, textures, Material keywords, and provenance; matching source candidates rank first while every conservative result remains available. This is asset/editor evidence, not the final draw Context, so global and engine-added keyword state stays explicitly unknown.
- A read-only Explain Current Pass evidence ledger for the single question “Why was this Pass selected for the current Material Context?” It keeps the observed Material Pass separate from a causal claim, cites the exact source Pass when its revision can be proved, and requires an Adapter-authored actual selection rule as well as a closed verified identity chain before supporting a cause. Missing or contradictory evidence is listed instead of inferred. The deterministic engine is local, session-only, model-free, and emits no telemetry or edits.
- A persistent, session-only Visual Lab Webview for one explicitly pinned
persistent Material and published Shader include-point Context. Separate
Before and After buttons request real Unity 64x64 offscreen draws, show
complete source/Material/Context/pipeline/profile/color-space/Adapter/input
provenance, and render an exact independent R8 NaN/Inf mask. Identity changes
retain old frames only as
STALEuntil the user explicitly pins again. - Declared/static Variant cost CodeLens for explicit
multi_compileandshader_featurekeyword sets, including per-program upper bounds, scope, stage, and largest-multiplier facts without claiming Unity build counts. - An Adapter-backed Show Variant Build Comparison report that keeps Declared/static upper bounds, Unity Compile candidates, Kept Variants, and unavailable evidence visibly separate per Shader/Pass/Stage/build target, with the largest keyword-set gaps first.
- A repository-owned Shader Variant budget command for local verification and
CI. Per-Shader, Pass, stage, and platform declared/kept limits produce stable
human and JSON reports; missing required build evidence fails as
unverified, never as a silent pass. - One repository Shader compile contract for required platform profiles, compiler warning baselines, SRP Batcher Properties, and Variant budgets, with distinct pass, failed, and unverified CI results.
- A bounded macOS/Metal/Xcode GPU capture prototype that correlates one controlled draw to an exact Shader Context and source range, while source drift and replay/tool gaps remain stale or unavailable.
- Unity Package resolution through
Packages/packages-lock.json. - Persistent project-local indexing under
Library/UnityShaderNavCache/.
Status
This project is in public preview. Install the latest build from the Visual Studio Marketplace, or download it with its release notes from GitHub Releases. Current work is tracked in GitHub Issues.
Supported Files
UnityShaderNav activates for:
.shader.hlsl.cginc.hlslinc.compute.shadergraph(File-mode Custom Function navigation requires a compatible Unity Editor Adapter)
Standalone HLSL files get same-file navigation. Full cross-file navigation
requires a Unity project root containing Assets/ and ProjectSettings/.
Install
Option 1: Install from the Visual Studio Marketplace
- Open UnityShaderNav on the Visual Studio Marketplace.
- Select Install and let VS Code complete the installation.
Option 2: Download the VSIX from Releases
- Open the latest release.
- Download
unity-shader-nav-*.vsixfrom the release assets. - In VS Code, open the Extensions view.
- Choose
...->Install from VSIX.... - Select the downloaded VSIX file.
After installation, open a Unity project and then open a .shader, .hlsl,
.cginc, .hlslinc, .compute, or .shadergraph file.
Option 3: Build from Source
Use this path if you want to develop the extension or package a local build.
Requirements:
- VS Code 1.85 or newer
- Node.js 18 or newer
- npm
npm ci
npm run build
To run the extension from source:
- Open the repository root in VS Code.
- In a terminal, run
npm run watchand wait for[watch-runtime] build ok. - Press F5 and choose the extension launch configuration.
- In the Extension Development Host, open a Unity project.
- Open a
.shader,.hlsl,.cginc,.hlslinc,.compute, or.shadergraphfile. - After source edits, wait for
[watch-runtime] build ok, then reload the Extension Development Host window.
To package a local VSIX:
npm run package:vsix
Optional Unity Editor Adapter
Adapter-backed features, including Visual Lab, require the Editor-only UPM
package under unity-adapter/. From a repository checkout, open Unity Package
Manager, choose Add package from disk..., and select
unity-adapter/package.json. Installation is explicit: the extension never
edits a project's Packages/manifest.json or installs Editor code silently.
The Adapter exposes one authenticated local named-pipe or Unix-domain-socket stream per Unity project. Workspace folders resolving to the same project share that stream; different project roots remain isolated. See Unity-rendered Visual Lab for setup, trust boundaries, and the complete workflow.
Configuration
Common settings:
{
"unityShaderNav.projectRoot": "",
"unityShaderNav.includeDirectories": [],
"unityShaderNav.excludePatterns": ["**/Library/**", "**/Temp/**", "**/Logs/**"],
"unityShaderNav.declarationMacros": [],
"unityShaderNav.findReferences.includePackages": false
}
See Configuration for the full explanation and examples.
Documentation
- User Guide
- Configuration
- Development Guide
- Architecture
- Troubleshooting
- Technical Spec
- Evidence-constrained Pass Explanation
- Unity-rendered Visual Lab
- Shader Variant Budgets
- Shader Compile Contract
- GPU Capture-to-source Prototype
- Architecture Decision Records
Known Limits
- Preprocessor conditions are not evaluated by default; multiple valid
definitions can be returned through VS Code Peek Definition. The optional
Variant Context picker can resolve declared
multi_compile/shader_featurekeywords for presentation and candidate ordering, but this is user-driven and does not constitute compiler-accurate variant resolution. Shared include files can additionally select one known Shader include-point Context; it is revision-bound, session-only, and falls back to Auto after publication. - Material Context requires a connected Adapter and a selected persistent Material asset. It is invalidated on reconnect, selection changes, asset deletion, or source/content-hash mismatch. It does not claim renderer, camera, platform, graphics API, global keyword, or engine-added keyword state without identity-matching draw evidence.
- Pass explanation v1 is an explicit, read-only request and supports only its
documented Material-to-Pass question. The production projector can cite the
current Material Context and, when upstream evidence identifies a program, a
hash-matched exact source Pass. The bundled Adapter does not currently author
selectedProgramor the selection decision. The command therefore reports them as missing and never manufactures Shader Context, Variant, compiler, or generated-source evidence. Complete supported graphs remain test fixtures until a versioned provider also supplies unified evidence freshness and invalidation. - Visual Lab v1 renders only an explicitly pinned persistent Material and
published Shader include-point Context through its fixed 64x64 full-screen
input. It does not follow the Unity selection, render an arbitrary Scene or
Renderer, refresh continuously, repair Shaders, or infer diagnostic
correctness from image differences. Frames are session-only; any
selection/Material/source/Context/pipeline/profile/color/Adapter/input change
keeps the old image only as
STALEand requires an explicit re-pin. - Variant build comparison requires a connected Editor Adapter advertising the
versioned
variant-build-evidencecapability. Missing, oversized, foreign, stale, or source-drifted evidence remains explicitly unavailable; it never changes the Declared/static CodeLens or the source index. - Macro bodies are not expanded. Built-in and user-configured declaration
patterns cover common Unity macro declarations. Compiler evidence maps only
unchanged lines whose
#linesource name resolves to one hash-identified snapshot; expanded lines remain visible mapping gaps rather than approximate locations. - Surface Shader implicit parameters and Shader Graph generated code are not
indexed as special sources. File-mode Custom Function navigation consumes
only version-supported logical facts from the Unity Editor Adapter; when the
Adapter or capability is unavailable, raw
.shadergraphserialization is never guessed and the feature stays neutral. - Built-in completion and signature help are curated and non-exhaustive. Receiver members are offered only when an indexed declaration supplies a supported type; project symbols are preferred when names collide with built-ins.
- Quick Documentation is curated and non-exhaustive. Package-specific fallback appears only for a compatible, include-visible built-in or default-registry Unity Package. Unity-scoped prose is currently verified for Editor 2022.3; other and unknown Editor versions keep the fallback with an explicit verification note. Scoped-registry, forked, local, and incompatible Package facts remain neutral unless an actual indexed declaration is available.
- Color presentations exclude HDR, Vector, expressions, and out-of-range components. Formatting changes only leading ShaderLab indentation, preserves complete embedded program/include blocks byte-for-byte, and refuses malformed structure. HLSL formatting is out of scope.
- Chain lookup intentionally stays conservative for multiline receivers, macro-expanded receivers, branch-dependent types, and overload-specific return type inference.
- Rename requires a unique indexed declaration identity. ShaderLab Property
edits stay inside the selected
.shaderfile and include at most one matching HLSL/CG declaration plus its proven references. Built-ins, Package declarations, include-supplied Property contracts, and ambiguous Shader, Pass, or HLSL candidates are intentionally refused rather than edited by name. Use Preview Safe Cross-asset Shader Property Rename for the separately reviewed C# and Material transaction; unavailable or uncertain evidence blocks that command. - ShaderLab name intelligence is declaration-backed and limited to
FallbackandUsePass; external or Unity built-in names without an indexed declaration stay unresolved rather than being guessed from a catalog. - Entry-point diagnostics prove name visibility only; they do not compile signatures or preprocessor variants. Any visible function, ambiguity, or same-name macro suppresses the error to avoid false positives.
- SRP Batcher checks require explicit SRP evidence and cover
Color,Vector,Float,Range, legacy float-backedInt, andIntegerProperties. Texture resources, conditional or macro-generated cbuffer layouts, and ambiguous multi-block edits stay neutral or require manual repair. Multi-SubShader files stay neutral until per-SubShader pipeline ownership can be proven. - Portability reports are not whole-shader converters and never claim rendered equivalence. The checked-in BiRP-to-URP fixture validates safe edits and the exact-source Adapter protocol with a mock compiler boundary; a real Unity Editor compile capture for both revisions is still pending.
Contributing
Bug reports, focused repro cases, and small pull requests are welcome. Please start with CONTRIBUTING.md, then check the current issue tracker.
License
UnityShaderNav is released under the MIT License.