6.5 KiB
Material preparation contracts
asset_material::compile_material_catalog translates captured definitions into a runtime catalog through private family compilers. It owns argument translation, shader/declaration references, pass color and shadow policy, compiled state rows, material sort order and source selection provenance. Catalog compilation is separate from shader-port admission and dynamic binding; a missing shader/declaration remains explicit metadata for admission to refuse. A prepared table contains reusable local banks, sampler bindings, admitted ports and compiled state. It does not by itself guarantee that a draw can execute: the requested technique and vertex layout must have an admitted port, and every dynamic code source must bind successfully.
PreparedMaterialTable::from_catalog binds products to the catalog's MaterialGenerationId. Material execution, prepared technique queries and stable-shell capture reject a different catalog generation. A catalog replacement requires a rebuilt table. Shader-port identity still includes programs, declaration, arguments, sampler policy and color space. The owner must advance the generation whenever replacing catalog content; mutating content while retaining a generation is outside this contract.
Family catalog compilation calls compile_material_state with two authored state words and stores CompiledPassState rows. Shared table preparation indexes these products; FPV reads their prepared cull mode. compile_material_state remains the low-level state compiler for capture/preparation owners, including HUD installation. CompiledPassState owns decoded blend, alpha-test, cull, color-write, sRGB-write, fill, depth, stencil and offset rules, plus authored-field and unsupported-field diagnostics. Its fields and raw constructors are private. Authored words are available for provenance and exact-state admission checks. GPU adapters consume the semantic getters and convert them to wgpu values; they do not decode source state or choose an alpha-test family.
IW4 and IW5 share the captured state encoding. T5 alpha testing uses its own source decoder. T6 retains the existing absent alpha-test contract. The remaining state fields retain the current shared encoding and host behavior. This is preservation of the existing supported runtime contract, not a claim that every native source state is implemented.
Both the ordinary blend and the existing multiply-pass adaptation are compiled together. The execution caller selects the already prepared multiply policy. Unknown blend factors and operations remain explicit UnsupportedState refusals; authored state words are never repaired. Stencil provenance and the existing host treatment are preserved.
Technique selection keeps SourceTechniqueSelection: source namespace, source slot and the named policy (Exact, DfogCompatibility, UnshadowedCompatibility, LitFallbackCompatibility, EmissiveCompatibility or DepthToColourCompatibility). State compilation does not replace or relabel these adaptations. Source technique mapping remains in asset_material capture/preparation. Its private MaterialCompiler projects selected techniques and arguments into the runtime catalog. render_material::prepare_program_abi owns exact source/stage lookup, SM3/DXBC decoding, declaration routing and ABI bindings. Its prepared product has a private constructor; low-level ABI builders are crate-private. Decoded DXBC stage mismatches refuse before lowering. The frontend lowers those prepared programs, validates WGSL and derives the GPU layout.
ABI preparation success establishes program decoding and register-source/layout bindings, not material literal/texture residency, supported WGSL lowering or frame-specific source readiness. Prepared ABI products borrow source names from their catalog, while admitted ports own validated modules and ABI data. Catalog replacement requires renewed admission and prepared tables under the current generation.
Stable material shells retain catalog generation, material/technique/vertex identity, selection provenance, compiled state and local bindings. Constructors and retained fields are private; capture rejects a mismatched execution identity, and rebinding requires the owner generation and refuses a stale shell. Rebinding resolves dynamic code constants and textures again and preserves typed failures. The renderer owns current-generation checks for retained frame products and GPU resources; a shell alone does not establish residency in a newer scene.
HUD chrome compiles its state when installing its menu catalog and caches the result with that catalog. Unsupported HUD state is refused during installation; blood composition also reports its material-state failure before creating a batch. Tess batches and pipeline keys carry compiled products. The current chrome namespace remains an explicit HUD ownership rule.
Family compilation also publishes colour camera routing, smodel colour admission, unlit sky routing and the explicit IW4 host-postfx admission rule. Shared draw consumers read these rules; authored camera regions remain available as provenance.
Material execution still uses one shared drawsurf path. Compiled state is independent of shader compilation success, texture residency, GPU pipeline availability and frame-specific dynamic sources. These dependencies must all succeed before drawing.
asset_material::compile_material_bindings prepares the catalog generation and union of requested code constants. Its private product accepts camera, time, exposure, sky, fog and light values through frame inputs; family indices, defaults and packing stay private to material preparation. Binding writes only requested constants and rejects a stale generation before mutation. The frontend retains one product per scene catalog generation; it supplies dynamic values without selecting a material family. Missing optional inputs keep their existing absence/default behavior. Local-light preparation uses the same demanded-code product. Frontend prepares each scene light once per frame after appending FX lights, using current camera/time and authored light overrides; private material code owns attenuation, falloff, cone, cookie and spot-matrix packing. MaterialExecFrame carries generation-bound CompiledConstantOverlay products; backend applies their rows after shared light/shadow/texture bindings. Missing products and stale generations refuse before reuse, including cached draws. Frame refresh/teardown replaces or clears the products, and MaterialRunExecutor clears run/shell/overlay caches on catalog replacement. Callers begin each draw list before consuming a new frame.