mirror of
https://github.com/Eragon-Brisingr/UShaderLab.git
synced 2026-09-15 14:54:36 +00:00
99 lines
4.3 KiB
C++
99 lines
4.3 KiB
C++
// Copyright UShaderLab. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
class UMaterial;
|
|
class UMaterialExpression;
|
|
struct FShaderLabModel;
|
|
|
|
/**
|
|
* One body of HLSL scanned for capability triggers: the verbatim text plus its 1-based `.usl` source line
|
|
* (so a capability can map a contract violation back to the exact authored line). Covers a shader's own
|
|
* pixel/vertex bodies AND every reachable `.uslfunc` library-function body, since a library function called
|
|
* from a body is inlined into the same Custom node and can equally reference a raw scene-texture helper.
|
|
*/
|
|
struct FShaderLabScannedBody
|
|
{
|
|
/** Non-owning pointer to the body text (lives in the FShaderLabModel / resolved program). */
|
|
const FString* Text = nullptr;
|
|
/** 1-based source line of the body's first character, for error line-mapping. */
|
|
int32 SourceLine = 0;
|
|
};
|
|
|
|
/** Everything a capability needs to detect usage, validate it, and create its hidden anchor node(s). */
|
|
struct FShaderLabAnchorCapabilityContext
|
|
{
|
|
/** The material being built (target of MakeNode). */
|
|
UMaterial& Material;
|
|
/** The parsed shader model (domain / blend mode live here for per-id domain validation). */
|
|
const FShaderLabModel& Model;
|
|
/** Shader bodies + reachable library-function bodies to scan. */
|
|
const TArray<FShaderLabScannedBody>& Bodies;
|
|
/** The shader's `.usl` absolute path (`#line` directive target for mapped errors). */
|
|
const FString& SourcePath;
|
|
/**
|
|
* Create a material expression of `Class`, add it to the material's expression collection, and lay it
|
|
* out on the canvas — the capability then sets any type-specific fields (e.g. SceneTextureId) on the
|
|
* CastChecked<> result. Mirrors the builder's internal NewExpr helper.
|
|
*/
|
|
TFunction<UMaterialExpression*(UClass* /*Class*/)> MakeNode;
|
|
};
|
|
|
|
/**
|
|
* A "capability" that a raw-HLSL body helper depends on: the helper (e.g. `SceneTextureLookup`,
|
|
* `GetDistanceToNearestSurfaceGlobal`) compiles fine as bare HLSL inside a Custom node, but the runtime
|
|
* resource binding it needs is only established as a side effect of compiling a matching UMaterialExpression
|
|
* (via `UseSceneTextureId` / `bUsesGlobalDistanceField` / ...). Because the Custom body bypasses that node,
|
|
* we synthesize a hidden expression, wired into the before-attributes ParameterAnchor, purely for the
|
|
* side effect. This registry is the general mechanism; each dynamic-input helper family registers one entry.
|
|
*
|
|
* (Helpers with NO dynamic body input — e.g. EyeAdaptation — do not need this: they are exposed as ordinary
|
|
* `UE_` wired intrinsics whose real node is connected into the Custom input, so its Compile side effect fires
|
|
* naturally. This mechanism is only for helpers that take a body-computed argument, which cannot be fed into
|
|
* a node from inside the opaque Custom body.)
|
|
*/
|
|
struct FShaderLabAnchorCapability
|
|
{
|
|
/** Identifier for diagnostics / tests (e.g. "SceneTexture", "GlobalDistanceField"). */
|
|
FName Id;
|
|
|
|
/**
|
|
* HLSL tokens whose presence in any scanned body activates this capability (e.g. "UE_SceneTexture",
|
|
* "UE_SceneDepth"). Matched delimited by non-identifier characters.
|
|
*/
|
|
TArray<FString> TriggerTokens;
|
|
|
|
/**
|
|
* Emit the hidden before-attributes node(s) for this capability into OutNodes. Runs only when at least
|
|
* one TriggerToken is present. Returns false and appends `.usl`-mapped messages to OutErrors on a
|
|
* contract violation (e.g. a non-literal id) or an illegal domain — contract style, aborting the build.
|
|
*/
|
|
TFunction<bool(const FShaderLabAnchorCapabilityContext& /*Ctx*/,
|
|
TArray<UMaterialExpression*>& /*OutNodes*/, TArray<FString>& /*OutErrors*/)> Emit;
|
|
};
|
|
|
|
/**
|
|
* Open registry of anchor side-effect capabilities. ShaderLab seeds its builtins (SceneTexture, Global
|
|
* Distance Field) on first use; other editor modules may register their own from their StartupModule via
|
|
* Get().Register(...). The graph builder queries it once per build.
|
|
*/
|
|
class USHADERLABBUILDER_API FShaderLabAnchorCapabilityRegistry
|
|
{
|
|
public:
|
|
static FShaderLabAnchorCapabilityRegistry& Get();
|
|
|
|
/** Register (or override, by Id) a capability. */
|
|
void Register(FShaderLabAnchorCapability Capability);
|
|
|
|
/** Visit every registered capability. */
|
|
void ForEach(TFunctionRef<void(const FShaderLabAnchorCapability&)> Fn) const;
|
|
|
|
private:
|
|
FShaderLabAnchorCapabilityRegistry();
|
|
void RegisterBuiltins();
|
|
|
|
TArray<FShaderLabAnchorCapability> Capabilities;
|
|
};
|