Blacksite/docs/adr/0036-surface-abi-and-solari-parity.md

4.5 KiB

ADR 0036: Surface ABI v1 and Solari Evaluator Parity

Status

Accepted

Context

Arbitrary full-pipeline WGSL cannot be carried safely between Bevy's raster pipelines and Solari's ray-hit shaders. A custom fragment shader may own bindings, entry points, derivatives, discard, or other stage-specific behavior that has no direct ray-tracing equivalent. Treating such a shader as a StandardMaterial in Solari would produce a different material, while tracing skinned source vertices would produce bind-pose geometry instead of the rasterized deformation.

Blacksite needs one constrained material expression that can produce the same surface values in forward/deferred raster rendering and at Solari ray hits, while leaving transforms, skinning, lighting, fog, shadows, and render-pipeline bindings under engine ownership.

Decision

  • blacksite_surface owns versioned Surface ABI v1. A custom evaluator implements:

    fn evaluate(
        input: SurfaceInput,
        params: SurfaceParams,
        samples: SurfaceSamples,
    ) -> Surface
    

    SurfaceInput provides UV0, world position, and world normal. Surface returns base color, tangent-space normal, emissive, metallic, perceptual roughness, reflectance, occlusion, alpha, and lit/unlit model selection.

  • The schema-driven authoring inputs and canonical processed Texture/ARM artifacts feeding this ABI are defined by ADR 0046.

  • The ABI has 16 vec4 parameter lanes, eight sampled 2D texture slots with UV transforms, and a 400-byte SurfaceUniform. Shader schemas map typed Bool/Float/Vec2/Vec3/Color/Enum properties and texture properties into that fixed layout. Exceeding either limit is a validation error.

  • Evaluators cannot declare bindings or shader entry points and cannot use compute/storage, ray-query, derivative, discard, barrier/subgroup, texture-store, or atomic constructs. The engine supplies resources, entry points, vertex transforms/skinning, lighting, fog, and shadows.

  • Raster rendering composes the evaluator between the engine-owned Surface header and footer and installs it as an ExtendedMaterial<StandardMaterial, SurfaceExtension> for forward, deferred, and prepass pipelines. Tangent-space normals are applied when the mesh supplies tangents.

  • The maintained third_party/bevy_solari fork packs the same uniform and texture set, namespaces validated evaluator functions, and generates a shader-ID dispatch library for ray hits. Eligible non-deformed geometry uses the evaluator for hit material fields, tangent-space normal, emissive, unlit behavior, and cutout candidate acceptance.

  • Opaque and cutout are the supported alpha modes. Solari treats geometry as potentially non-opaque and evaluates the exact Surface alpha and cutoff before accepting a cutout ray candidate.

  • Plain materials without a custom evaluator keep Bevy's standard raster and Solari material path. Dependency revisions cover Material Instances, their direct base, shader schema, and evaluator. Naga syntax/semantic validation and the cross-pipeline restrictions run before installation; invalid updates produce diagnostics and retain the last successfully installed evaluator/library.

  • Meshes with SkinnedMesh, runtime morph weights, or morph targets are excluded from Solari until an instance-keyed deformed-vertex and BLAS update path exists. They continue to render through Bevy's raster path; Solari diagnostics report the exclusion. No bind-pose ray-tracing fallback is allowed.

Consequences

  • Custom material code is portable because it describes a surface, not an entire render stage.
  • Raster and Solari evaluate the same source for supported, Solari-eligible static or rigid geometry. Normal parity requires tangents; Solari compatibility diagnostics identify missing tangents and other unsupported mesh layouts.
  • Dynamic skinned/morph Solari geometry remains deliberate future work. This is a geometry parity limit, not permission to substitute source/bind-pose vertices.
  • ABI layout or semantic changes require a new version and migration. The fixed lanes and texture count trade arbitrary resource layouts for deterministic cross-renderer packing.
  • Blend, transmission, refraction, custom vertex displacement, arbitrary entry points, and stage-specific shader behavior are unsupported by Surface ABI v1.
  • Maintaining evaluator parity requires carrying the focused Solari fork until the necessary hooks exist upstream; its dispatch and cutout behavior are covered by local tests.