Builtin Library
README.md
shader_includes Module
Resolves the #include lines of a WGSL source against the asset system, so a
shader includes a .shaderModule by every name form require and
asset.resolve accept.
Purpose
A shader names a module the way any content names any asset — a guid, an
identity, a package-relative ~.tail, a .relative.tail, an @root:: or
@builtin:: path. The engine's include expansion is a flat key lookup, so a
relative form means nothing on its own: ~.tail is a different module depending
on which package asked for it.
This module closes that gap in the one place that knows both — the including
asset, which holds its own VFS path. Every literal is resolved against that path
and rewritten to the module's guid before the source reaches the compiler, so a
relative include resolves exactly where a relative require would.
The rewrite applies to the source handed to the compiler. What the author wrote stays on disk, which is what the reference extractor records, with its line, when the file is written.
Usage
An assetType canonicalizes its own WGSL, passing the asset's path as the base the relative literals expand against:
local ShaderIncludes = require("modules.shader_includes")
local wgsl = ShaderIncludes.canonicalize(vfs.read(path .. "/shader.wgsl"), path)
Given path inside a package, both of these reach the compiler as the same
guid-keyed include:
#include "~.ssr_common"
#include "@builtin::systems.reflections.ssr_common"
A literal that resolves to no asset is left as it was written, so a
framework name — zero::surface and its siblings, which are
registry keys rather than assets — reaches the expander untouched. Source
carrying no #include is returned unchanged.
Programs no asset holds
WGSL generated at runtime and compiled under a key (compute.program.compile)
is canonicalized without a base path: canonicalize resolves each literal that
names its module absolutely (a guid, an identity, an @root:: or @builtin::
path), files that module and rewrites the literal to its guid, and leaves a
relative literal as it was written:
local wgsl = ShaderIncludes.canonicalize('#include "@builtin::systems.procgen.kernels.rand"\n' .. body)
compute.program.compile canonicalizes every source it is handed this way, so a
program compiled at any point of a session expands the modules it names.