Interface and supporting types for validating Slang shader source in the editor. Defines SlangEntryPoint record, SlangValidationRequest record with options (source, file path, entry points, includes, defines, target, language version, flags) and ISlangValidator interface with Available, Version and async Validate method.
using Editor.Prism.Core;
namespace Editor.Prism.Toolchain;
/// <summary>One entry point slangc should check. One invocation is issued per entry point.</summary>
public readonly record struct SlangEntryPoint( string Name, ShaderStage Stage )
{
/// <inheritdoc/>
public override string ToString() => $"{Name} ({Stage.SlangStage()})";
}
/// <summary>
/// A request to validate Slang source.
/// <para>
/// Either <see cref="Source"/> or <see cref="FilePath"/> must be set. When only <see cref="Source"/>
/// is set the text is fed through stdin, so an unsaved editor buffer can be validated without ever
/// touching disk — diagnostics then report <c><stdin></c> as the file.
/// </para>
/// </summary>
public sealed record SlangValidationRequest
{
/// <summary>The Slang source to check. Takes precedence over <see cref="FilePath"/>.</summary>
public string Source { get; init; }
/// <summary>Path of the file to check, when validating something already on disk.</summary>
public string FilePath { get; init; }
/// <summary>Entry points to check. One validator invocation per entry.</summary>
public IReadOnlyList<SlangEntryPoint> EntryPoints { get; init; } = Array.Empty<SlangEntryPoint>();
/// <summary>Additional include directories.</summary>
public IReadOnlyList<string> IncludePaths { get; init; } = Array.Empty<string>();
/// <summary>Preprocessor defines, as <c>NAME=VALUE</c> or bare <c>NAME</c>.</summary>
public IReadOnlyList<string> Defines { get; init; } = Array.Empty<string>();
/// <summary>Codegen target to type-check against.</summary>
public string Target { get; init; } = "hlsl";
/// <summary>Language version to pin, matching what the emitter writes.</summary>
public string LanguageVersion { get; init; } = PrismConstants.SlangLanguageVersion;
/// <summary>Skip code generation and only report front-end diagnostics. The fast path.</summary>
public bool NoCodegen { get; init; } = true;
/// <summary>Also request reflection JSON, so the emitted parameter set can be cross-checked.</summary>
public bool Reflection { get; init; }
/// <summary>Display name used in diagnostics when validating from a buffer.</summary>
public string DisplayName { get; init; } = "<stdin>";
}
/// <summary>
/// Validates Slang source.
/// <para>
/// Slang validation is Tier 2: it never gates rendering and never blocks the editor. When no
/// toolchain is present the implementation reports <see cref="Available"/> false and
/// <see cref="Validate"/> returns an empty list — Slang <em>emission</em> still works, because it is
/// pure text generation from the IR with no dependency on the toolchain at all.
/// </para>
/// <para>
/// This interface exists so an in-process native validator can be added later behind an experimental
/// toggle without touching a single call site.
/// </para>
/// </summary>
public interface ISlangValidator
{
/// <summary>True when a working toolchain was located.</summary>
bool Available { get; }
/// <summary>Version string of the located toolchain, or null when there is none.</summary>
string Version { get; }
/// <summary>
/// Validate a request. Never throws for a missing toolchain, a crashed process or malformed
/// output — every failure comes back as diagnostics, or as an empty list when nothing is known.
/// </summary>
Task<IReadOnlyList<Diagnostic>> Validate( SlangValidationRequest request, CancellationToken ct );
}