IR types for material/global declarations. Defines enums for GlobalKind and UiControl, a UiHints record for editor metadata, and the GlobalDecl record representing a module-level shader/global parameter with properties and simple helpers.
using Editor.Prism.Core;
namespace Editor.Prism.Compiler.Ir;
/// <summary>What kind of module-level declaration this is.</summary>
public enum GlobalKind
{
/// <summary>A scalar, vector or matrix uniform.</summary>
Uniform,
/// <summary>A texture.</summary>
Texture,
/// <summary>A sampler.</summary>
Sampler,
/// <summary>A read-only buffer.</summary>
Buffer,
/// <summary>A writable texture. Compute only.</summary>
RwTexture,
/// <summary>A writable buffer. Compute only.</summary>
RwBuffer,
/// <summary>A compile-time constant, emitted as <c>static const</c>.</summary>
Constant
}
/// <summary>Which inline editor the material UI should show for a parameter.</summary>
public enum UiControl
{
/// <summary>Pick from the type.</summary>
Default,
/// <summary>Numeric slider with a range.</summary>
Slider,
/// <summary>Colour swatch.</summary>
Color,
/// <summary>Checkbox.</summary>
Toggle,
/// <summary>Enumeration dropdown.</summary>
Dropdown,
/// <summary>Component-wise vector fields.</summary>
Vector,
/// <summary>Texture picker.</summary>
Texture
}
/// <summary>
/// Material-UI metadata for a parameter. Lowered into the VFX annotation grammar
/// (<c>UiType( Slider ); Default( 0.62 ); Range( 0, 1 ); UiGroup( "Surface,10/20" );</c>) by the
/// HLSL backend, and into Slang user-defined attributes by the Slang backend.
/// </summary>
public sealed record UiHints
{
/// <summary>Which editor to show.</summary>
public UiControl Control { get; init; }
/// <summary>Slider minimum.</summary>
public float Min { get; init; }
/// <summary>Slider maximum.</summary>
public float Max { get; init; } = 1f;
/// <summary>Slider step. Zero means continuous.</summary>
public float Step { get; init; }
/// <summary>Group heading in the material editor.</summary>
public string Group { get; init; }
/// <summary>Sort order within the group.</summary>
public int Order { get; init; }
/// <summary>Tooltip text.</summary>
public string Tooltip { get; init; }
/// <summary>Values offered by a dropdown.</summary>
public IReadOnlyList<string> Options { get; init; }
}
/// <summary>
/// A module-level declaration: a uniform, texture, sampler or buffer, plus everything the material
/// UI and the preview attribute bus need to bind to it.
/// <para>
/// Globals are deduplicated by <see cref="Name"/> when added to an <see cref="IrModule"/>; two
/// different declarations claiming the same name is a compile error, not a silent overwrite.
/// </para>
/// </summary>
public sealed record GlobalDecl( string Name, ShaderType Type, GlobalKind Kind )
{
/// <summary>The blackboard parameter this global was generated from, when there is one.</summary>
public ParamId Parameter { get; init; }
/// <summary>
/// Render-attribute name, so the value can be pushed at runtime without a recompile.
/// In preview mode every literal gets one of these; that is what makes slider drags free.
/// </summary>
public string AttributeName { get; init; }
/// <summary>Numeric default value.</summary>
public ConstValue? Default { get; init; }
/// <summary>Asset path default, for textures.</summary>
public string DefaultAsset { get; init; }
/// <summary>True when a texture's contents are sRGB encoded.</summary>
public bool Srgb { get; init; }
/// <summary>Name of the sampler paired with this texture, when the backend declares one.</summary>
public string SamplerName { get; init; }
/// <summary>Material UI metadata.</summary>
public UiHints Ui { get; init; }
/// <summary>Array length, or zero for a non-array declaration.</summary>
public int ArraySize { get; init; }
/// <summary>True when this global exists only for preview and is stripped from the final shader.</summary>
public bool PreviewOnly { get; init; }
/// <summary>Stages that read this global. Used to place it in the right block.</summary>
public StageMask Stages { get; init; } = StageMask.All;
/// <summary>True when the declaration is an opaque resource rather than a numeric uniform.</summary>
public bool IsResource => Kind is not ( GlobalKind.Uniform or GlobalKind.Constant );
/// <summary>
/// True when two declarations share a name but disagree about anything that matters —
/// the collision that must be reported instead of silently resolved.
/// </summary>
public bool ConflictsWith( GlobalDecl other )
{
if ( other is null || ReferenceEquals( this, other ) ) return false;
if ( Name != other.Name ) return false;
return Type != other.Type || Kind != other.Kind || ArraySize != other.ArraySize;
}
/// <inheritdoc/>
public override string ToString() => $"{Kind} {Type.Hlsl} {Name}";
}