Global Shaders und Compute Shader: Unterschied zwischen den Versionen
Elaina (Diskussion | Beiträge) Die Seite wurde neu angelegt: „'''Global Shaders''' sind Shader, die in Unreal Engine direkt über C++ registriert und verwendet werden. Sie sind nicht an ein Material oder ein bestimmtes Mesh gebunden und eignen sich deshalb für allgemeine Rendering- und Compute-Aufgaben wie Post-Processing, Bildoperationen, Buffer-Verarbeitung oder eigene Render-Passes. {| class="wikitable" |+ Artikelstatus |- ! Bezugsstand | Unreal Engine 5.8 |- ! Letzte Aktualisierung | 2. September 2026 |- ! Zen…“ |
Elaina (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}} | |||
'''Global Shaders''' sind Shader, die in Unreal Engine direkt über C++ registriert und verwendet werden. Sie sind nicht an ein Material oder ein bestimmtes Mesh gebunden und eignen sich deshalb für allgemeine Rendering- und Compute-Aufgaben wie Post-Processing, Bildoperationen, Buffer-Verarbeitung oder eigene Render-Passes. | '''Global Shaders''' sind Shader, die in Unreal Engine direkt über C++ registriert und verwendet werden. Sie sind nicht an ein Material oder ein bestimmtes Mesh gebunden und eignen sich deshalb für allgemeine Rendering- und Compute-Aufgaben wie Post-Processing, Bildoperationen, Buffer-Verarbeitung oder eigene Render-Passes. | ||
Version vom 3. September 2026, 14:19 Uhr
Hinweis: Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.
Global Shaders sind Shader, die in Unreal Engine direkt über C++ registriert und verwendet werden. Sie sind nicht an ein Material oder ein bestimmtes Mesh gebunden und eignen sich deshalb für allgemeine Rendering- und Compute-Aufgaben wie Post-Processing, Bildoperationen, Buffer-Verarbeitung oder eigene Render-Passes.
| Bezugsstand | Unreal Engine 5.8 |
|---|---|
| Letzte Aktualisierung | 2. September 2026 |
| Zentrale Klassen und Hilfen | FGlobalShader, FComputeShaderUtils, FRDGBuilder
|
| Shader-Dateityp | .usf (Unreal Shader File)
|
Einsatzgebiete
Global Shaders kommen zum Einsatz, wenn eine Aufgabe nicht sinnvoll über den Material Editor abgebildet werden kann oder bewusst unabhängig von Materialien und Meshes bleiben soll. Typische Beispiele sind:
- Compute-Berechnungen auf Buffern oder Texturen
- eigene Post-Processing-Schritte
- Fullscreen-Passes
- Erzeugen, Kopieren oder Umwandeln von GPU-Daten
- Debug- und Visualisierungs-Passes
- experimentelle Rendering-Pipelines
Ein Compute Shader ist dabei ein möglicher Shader-Typ. Er verarbeitet Daten in frei definierbaren Thread-Gruppen und erzeugt nicht unmittelbar Rastergrafik.
Bausteine eines Global Shaders
Ein Global Shader besteht in der Regel aus mehreren Teilen:
- einer Shader-Datei mit HLSL-Code (
.usf) - einer von
FGlobalShaderabgeleiteten C++-Klasse - einer Parameterstruktur für Eingaben und Ausgaben
- einem Registrierungs-Makro, das Klasse, Datei, Einstiegspunkt und Shader-Stufe verbindet
- Code, der den Shader auswählt, Parameter bindet und den Dispatch oder Draw-Aufruf ausführt
Speicherort der Shader-Dateien
Engine-eigene Shader liegen unter Engine/Shaders. Shader eines Plugins gehören in dessen Shaders-Verzeichnis. Die Trennung hält experimentellen Code von den Engine-Dateien fern und erleichtert Updates sowie Versionsverwaltung.
Minimaler Compute Shader
Das folgende vereinfachte Beispiel verdoppelt jeden Wert eines Eingabebuffers. Es dient der Orientierung und muss an die konkrete Modul- und Ressourcenstruktur angepasst werden.
StructuredBuffer<uint> InputValues;
RWStructuredBuffer<uint> OutputValues;
uint ElementCount;
[numthreads(64, 1, 1)]
void MainCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
const uint Index = DispatchThreadId.x;
if (Index >= ElementCount)
{
return;
}
OutputValues[Index] = InputValues[Index] * 2;
}
numthreads(64, 1, 1) legt fest, dass jede Thread-Gruppe 64 Threads in X-Richtung enthält. Die Gesamtzahl der Gruppen muss auf der CPU-Seite passend zur Elementzahl berechnet werden.
C++-Repräsentation
Die C++-Klasse beschreibt den Shader gegenüber Unreal und definiert seine Parameter. Ein typisches Grundmuster sieht so aus:
class FExampleComputeShader : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FExampleComputeShader);
SHADER_USE_PARAMETER_STRUCT(FExampleComputeShader, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(uint32, ElementCount)
SHADER_PARAMETER_SRV(StructuredBuffer<uint32>, InputValues)
SHADER_PARAMETER_UAV(RWStructuredBuffer<uint32>, OutputValues)
END_SHADER_PARAMETER_STRUCT()
};
IMPLEMENT_GLOBAL_SHADER(
FExampleComputeShader,
"/Plugin/Example/Private/ExampleCompute.usf",
"MainCS",
SF_Compute
);
Wichtige Punkte:
DECLARE_GLOBAL_SHADERdeklariert den Shader-Typ.SHADER_USE_PARAMETER_STRUCTaktiviert die strukturierte Parameterbindung.BEGIN_SHADER_PARAMETER_STRUCTbeschreibt Konstanten, SRVs und UAVs.IMPLEMENT_GLOBAL_SHADERverbindet C++-Klasse, virtuellen Shader-Pfad, Einstiegspunkt und Shader-Stufe.SF_Computekennzeichnet den Shader als Compute Shader.
Je nach Modulgrenze kann statt DECLARE_GLOBAL_SHADER eine exportierte Shader-Deklaration nötig sein.
Kompilierungsbedingungen
Nicht jeder Shader sollte für jede Plattform oder jedes Feature Level gebaut werden. Dafür kann die Klasse eine Kompilierungsbedingung definieren. So lässt sich beispielsweise verhindern, dass ein Compute Shader für eine Plattform ohne die benötigten Fähigkeiten kompiliert wird.
Auch Compile-Time-Definitionen können aus C++ an den Shader übergeben werden. Das ist nützlich für feste Gruppengrößen, optionale Codepfade oder plattformspezifische Varianten.
Das Modul, das einen neuen Shader-Typ registriert, muss früh genug geladen werden. Wird der Typ erst nach der Initialisierung der Engine bekannt, kann Unreal die Registrierung mit einem Assert ablehnen. Für Shader-Module ist deshalb eine frühe Ladephase wie PostConfigInit relevant.
Dispatch über das RHI
FComputeShaderUtils::Dispatch sendet einen Compute Shader mit Parametern und Gruppenzahl an eine FRHIComputeCommandList. Das ist die direkte Variante auf RHI-Ebene.
const FIntVector GroupCount =
FComputeShaderUtils::GetGroupCount(ElementCount, 64);
FComputeShaderUtils::Dispatch(
RHICmdList,
ComputeShader,
Parameters,
GroupCount
);
Die Hilfsfunktion GetGroupCount rundet die benötigte Gruppenzahl passend auf. Der Bounds-Check im Shader bleibt trotzdem notwendig, weil die letzte Gruppe mehr Threads als verbleibende Elemente enthalten kann.
Dispatch über den Render Dependency Graph
Für regulären High-Level-Rendering-Code empfiehlt Unreal den Render Dependency Graph (RDG). Ein Compute-Pass kann dort über FComputeShaderUtils::AddPass registriert werden.
RDG kennt dadurch die beteiligten Ressourcen und kann unter anderem:
- Abhängigkeiten zwischen Passes bestimmen
- Ressourcenübergänge und Barriers verwalten
- ungenutzte Passes entfernen
- Lebenszeiten temporärer Ressourcen optimieren
- geeignete Arbeit parallelisieren
- Async-Compute-Passes synchronisieren
Die Parameter müssen alle verwendeten RDG-Ressourcen korrekt deklarieren. Innerhalb des Passes darf nur auf Ressourcen zugegriffen werden, die über die Parameterstruktur als Abhängigkeit bekannt sind.
Shader-Entwicklung und Fehlersuche
Für die Entwicklung sind folgende Maßnahmen hilfreich:
r.ShaderDevelopmentMode=1inConsoleVariables.iniaktivieren, um ausführlichere Shader-Compile-Logs zu erhalten.- Einstiegspunkt, virtuellen Shader-Pfad und Shader-Stufe kontrollieren.
- Sicherstellen, dass das Plugin und alle benötigten Module als Abhängigkeiten eingetragen sind.
- Modul-Ladephase prüfen, wenn Unreal meldet, dass ein Shader-Typ zu spät registriert wurde.
- Parameterstruktur zwischen HLSL und C++ sorgfältig abgleichen.
- Thread-Gruppengröße und Bounds-Checks prüfen.
- Ressourcenstatus, SRV-/UAV-Bindung und Synchronisation kontrollieren.
- Bei RDG-Passes aussagekräftige Event-Namen verwenden und bei Bedarf RDG Insights einsetzen.
Bezug zum Heterogeneous-Multi-GPU-Projekt
Für das Projekt UE5 Heterogeneous Multi-GPU ist der Global-Shader-Weg besonders interessant: Unreal kann den Shader wie gewohnt kompilieren und das resultierende Shader-Bytecode-Blob bereitstellen. Dieses Blob kann anschließend als Grundlage für eine Compute Pipeline State auf dem separaten Worker-Device dienen.
Der geplante erste Test lässt sich in folgende Schritte zerlegen:
- einfachen Global Compute Shader in einem früh geladenen Modul registrieren
- Shader über Unreals reguläre Shader-Pipeline kompilieren lassen
- kompilierten Bytecode für den gewählten Worker-Adapter prüfen
- passende Root Signature und Compute Pipeline State auf dem Worker-
ID3D12Deviceerzeugen - Input- und Output-Buffer auf dem Worker-Device bereitstellen
- Compute Dispatch auf der eigenen Worker-Command-Queue ausführen
- Ergebnis über Readback zurückholen und auf der CPU verifizieren
Dabei ist wichtig, zwischen zwei Ebenen zu unterscheiden: Unreal übernimmt zunächst Registrierung und Kompilierung des Shaders; die Ausführung auf dem unabhängigen Worker-Device folgt im experimentellen Projekt über den eigenen D3D12-Pfad und nicht automatisch über Unreals normales RHI oder RDG.
Quellen und weiterführende Dokumentation
- Adding Global Shaders to Unreal Engine – Epic Games, UE 5.8
- Overview of Shaders in Plugins – Epic Games, UE 5.8
- Shader Development in Unreal Engine – Epic Games, UE 5.8
- FComputeShaderUtils::Dispatch – API-Referenz, Epic Games, UE 5.8
- FComputeShaderUtils::AddPass – API-Referenz, Epic Games, UE 5.8
- Render Dependency Graph – Epic Games, UE 5.8
Dieser Artikel ist eine eigenständige deutschsprachige Zusammenfassung mit Projektbezug und keine vollständige Übersetzung der Epic-Dokumentation.
