Enhance .usl compile error display

This commit is contained in:
Eragon-Brisingr
2026-07-01 18:23:46 +08:00
parent c21efdc64e
commit 0d7db515ae
6 changed files with 141 additions and 19 deletions

View File

@@ -1194,3 +1194,51 @@ bool FShaderLabGraphBuilder::BuildInto(UMaterial& Material, const FShaderLabMode
Material.UpdateCachedExpressionData();
return true;
}
void FShaderLabGraphBuilder::BuildPoisonInto(UMaterial& Material, const TArray<FString>& Diagnostics, const FString& SrcPath)
{
using namespace ShaderLabGraph;
// A minimal, structurally-valid Substrate material: one Custom node -> Slab.DiffuseAlbedo -> FrontMaterial,
// so the Custom code is reached by translation. The code `#error`s with the diagnostics; that aborts the
// shader preprocessor, so the material fails to compile with our messages — surfacing everywhere real
// shader errors do (MIC editor red text, FMaterialResource::GetCompileErrors, cook). DiffuseAlbedo (a core
// BSDF pin) is used deliberately: EmissiveColor gets dead-stripped from the compiled permutation, which
// would drop the Custom function (and its #error) before the preprocessor ever sees it.
Material.AssignExpressionCollection(FMaterialExpressionCollection());
Material.MaterialDomain = MD_Surface;
Material.BlendMode = BLEND_Opaque;
Material.TwoSided = 0;
Material.bUseMaterialAttributes = false;
UMaterialEditorOnlyData* EditorOnly = Material.GetEditorOnlyData();
check(EditorOnly); // A UMaterial always has editor-only data in the editor (contract).
// `#error` halts at the first hit, so merge every diagnostic into one directive (newlines stripped to
// keep it a single preprocessor line). The `#line` makes the compiler error click through to the .usl;
// each merged message still carries its own precise `(line,col)` as text.
FString Combined;
for (int32 Index = 0; Index < Diagnostics.Num(); ++Index)
{
if (Index > 0) { Combined += TEXT(" ; "); }
Combined += Diagnostics[Index];
}
Combined.ReplaceInline(TEXT("\r"), TEXT(""));
Combined.ReplaceInline(TEXT("\n"), TEXT(" "));
if (Combined.IsEmpty()) { Combined = TEXT("ShaderLab: shader failed to build"); }
int32 IoY = 0;
UMaterialExpressionCustom* Custom = NewExpr<UMaterialExpressionCustom>(Material, IoY, -300);
Custom->Description = TEXT("ShaderLab Error");
Custom->OutputType = CMOT_Float3;
Custom->Code = FString::Printf(
TEXT("#line 1 \"%s\"\n#error ShaderLab: %s\n#line 1 \"ShaderLabGenerated.ush\"\nreturn float3(1,0,1);\n"),
*SrcPath, *Combined);
Custom->RebuildOutputs();
UMaterialExpressionSubstrateSlabBSDF* Slab = NewExpr<UMaterialExpressionSubstrateSlabBSDF>(Material, IoY, 0);
Slab->DiffuseAlbedo.Connect(0, Custom);
EditorOnly->FrontMaterial.Connect(0, Slab);
Material.UpdateCachedExpressionData();
}