<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki.janvolkland.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Elaina</id>
	<title>UnrealWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.janvolkland.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Elaina"/>
	<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php/Spezial:Beitr%C3%A4ge/Elaina"/>
	<updated>2026-10-11T22:06:44Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=DLSS5ForUE5&amp;diff=197</id>
		<title>DLSS5ForUE5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=DLSS5ForUE5&amp;diff=197"/>
		<updated>2026-09-17T19:37:41Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 17. September 2026, Engine-Checkpoint &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt;. DLSS5ForUE5 ist ein inoffizielles Community-Projekt und nicht mit NVIDIA oder Epic Games verbunden. Die Integration ist experimentell.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DLSS5ForUE5&#039;&#039;&#039; ist ein Plugin, das NVIDIA NGX Neural Rendering in den Unreal Editor integriert. Es stellt Einstellungen, Szenendaten und Diagnosefunktionen für DLSS 5 bereit. Der Fork des Projekts wird im GitHub-Repository &#039;&#039;&#039;[https://github.com/jan1009/DLSS5ForUE5 jan1009/DLSS5ForUE5]&#039;&#039;&#039; gepflegt.&lt;br /&gt;
&lt;br /&gt;
== Unterstützte Versionen ==&lt;br /&gt;
&lt;br /&gt;
Das Repository enthält einen gemeinsamen, versionsabhängigen Quellcode für:&lt;br /&gt;
&lt;br /&gt;
* Unreal Engine 5.5&lt;br /&gt;
* Unreal Engine 5.6&lt;br /&gt;
* Unreal Engine 5.7&lt;br /&gt;
* Unreal Engine 5.8&lt;br /&gt;
&lt;br /&gt;
Getestet wurde die Integration unter Windows mit DirectX 12 und einer NVIDIA-RTX-Grafikkarte. Das offizielle NVIDIA-DLSS-Plugin muss für dieselbe Unreal-Engine-Version installiert und aktiviert sein. Der Stand vom 17. September 2026 wurde in Unreal Engine 5.8 sowohl im Editor als auch in einem Development-Package und im eigentlichen Spielprojekt validiert.&lt;br /&gt;
&lt;br /&gt;
== Funktionen ==&lt;br /&gt;
&lt;br /&gt;
* eigenes Werkzeugfenster unter &#039;&#039;Tools → DLSS 5 for UE5&#039;&#039;&lt;br /&gt;
* Natural- und Cinematic-Stile&lt;br /&gt;
* Regler für Preset, Intensität, Local Tone, Local Structure und Skin Structure&lt;br /&gt;
* Scene-Depth- und Motion-Vector-Guides&lt;br /&gt;
* zeitliche Daten wie Jitter, Pre-Exposure, Camera Cut und History Reset&lt;br /&gt;
* ein bis vier aufeinanderfolgende Neural-Rendering-Durchläufe&lt;br /&gt;
* Live-Diagnose für Laufzeit, NGX, Szenendaten und zeitlichen Zustand&lt;br /&gt;
* Safe Mode zur Wiederherstellung&lt;br /&gt;
* Konsolenbefehle unter &amp;lt;code&amp;gt;DLSS5.*&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;r.DLSS5.*&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Runtime-Architektur ==&lt;br /&gt;
&lt;br /&gt;
Das Plugin verwendet den bereits durch das offizielle NVIDIA-DLSS-Plugin initialisierten NGX-Core. Es eröffnet keine zweite konkurrierende NGX-Application-Session.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Schicht&lt;br /&gt;
! Aufgabe&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UDLSS5NRSettings&amp;lt;/code&amp;gt;&lt;br /&gt;
| Projektkonfiguration, Übernahme in Konsolenvariablen und Diagnose&lt;br /&gt;
|-&lt;br /&gt;
| View Extension&lt;br /&gt;
| Post-Process-/RDG-Integration sowie Übergabe von Color, Depth, Motion und Passzahl&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FDLSS5NRRuntime&amp;lt;/code&amp;gt;&lt;br /&gt;
| NGX-Core-Parameter, Feature-Lifecycle, Create, Evaluate, Release und Telemetrie&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DLSS5ForUE5_nvngx.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
| Native Bridge für den NVIDIA-Caller-Gate&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;nvngx_dlssnr.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
| Proprietäre NVIDIA-Neural-Rendering-Runtime; nicht Bestandteil des Git-Checkpoints&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Projektkonfiguration und Safe Boot ==&lt;br /&gt;
&lt;br /&gt;
Die Einstellungen werden explizit in &amp;lt;code&amp;gt;Config/DLSS5ForUE5.ini&amp;lt;/code&amp;gt; gespeichert. Die Datei enthält 20 projektbezogene Werte für Neural Rendering, Bildstruktur, Scene Guides, temporales Verhalten und Diagnose und wird beim Cook in das Paket übernommen.&lt;br /&gt;
&lt;br /&gt;
Im Editor deaktiviert der Safe Boot Neural Rendering, Scene Guides, Guide Feeding und Motion Vectors zunächst nur für die laufende Session. Die Abschaltung ist auf &amp;lt;code&amp;gt;WITH_EDITOR&amp;lt;/code&amp;gt; begrenzt und schreibt die Projektwerte nicht zurück. Ein Packaged Build lädt dagegen die gespeicherte Konfiguration und startet mit den dort hinterlegten Einstellungen.&lt;br /&gt;
&lt;br /&gt;
== Packaged Runtime und Caller-Gate ==&lt;br /&gt;
&lt;br /&gt;
Im Editor kommt der NGX-Aufruf aus &amp;lt;code&amp;gt;UnrealEditor-DLSS5ForUE5_nvngx.dll&amp;lt;/code&amp;gt;. In einem monolithischen Packaged Game wurde derselbe Code zunächst in die Spiel-EXE gelinkt; die NVIDIA-Runtime lehnte &amp;lt;code&amp;gt;Init_Ext&amp;lt;/code&amp;gt; deshalb mit &amp;lt;code&amp;gt;0xBAD00002&amp;lt;/code&amp;gt; ab.&lt;br /&gt;
&lt;br /&gt;
Die Lösung ist eine native &amp;lt;code&amp;gt;DLSS5ForUE5_nvngx.dll&amp;lt;/code&amp;gt;, die als Runtime Dependency zusammen mit &amp;lt;code&amp;gt;nvngx_dlssnr.dll&amp;lt;/code&amp;gt; gestaged wird. Sie forwardet die benötigten NGX-Entry-Points und bleibt als unmittelbarer Windows-DLL-Caller im Stack. Dabei musste zusätzlich eine MSVC-Tail-Call-Optimierung verhindert werden: Ein bloßer Sprung in die NVIDIA-Runtime ließ weiterhin die Spiel-EXE als Caller erscheinen. Ein echter &amp;lt;code&amp;gt;call&amp;lt;/code&amp;gt; mit Post-Call-Operation und erhaltenem Bridge-Stackframe beseitigte den Fehler.&lt;br /&gt;
&lt;br /&gt;
Der validierte Packaged Build meldete NGX-Core, Parameter, Runtime, Snippet und Caller-Gate erfolgreich. Depth und Motion waren jeweils angefordert, verfügbar und verwendet. In einem Lauf wurden &#039;&#039;&#039;2036 von 2036 Evaluierungen erfolgreich&#039;&#039;&#039; abgeschlossen, ohne Fehler.&lt;br /&gt;
&lt;br /&gt;
== Supportstatus und Fallback ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Status&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AVAILABLE&amp;lt;/code&amp;gt;&lt;br /&gt;
| Aktiver D3D12-NVIDIA-Pfad ist nutzbar; Neural Rendering darf initialisieren und evaluieren.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UNAVAILABLE&amp;lt;/code&amp;gt;&lt;br /&gt;
| Noch kein nutzbarer NGX-Core oder transienter Startzustand; ein späterer Versuch bleibt möglich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UNSUPPORTED&amp;lt;/code&amp;gt;&lt;br /&gt;
| Nicht-D3D12 oder aktiver AMD-/Intel-Renderadapter; einmalige Fallback-Meldung statt wiederholter Init-Versuche.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;WAITING&amp;lt;/code&amp;gt;&lt;br /&gt;
| Editor-Safe-Boot oder Neural Rendering noch nicht aktiviert; kein Fehlerzustand.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Auf dem Hybrid-Testsystem mit RTX 5060 und Intel UHD blieb der Status nach &amp;lt;code&amp;gt;r.DLSS5.Enable 1&amp;lt;/code&amp;gt; korrekt &amp;lt;code&amp;gt;AVAILABLE&amp;lt;/code&amp;gt;. Entscheidend ist der aktive Renderadapter, nicht die bloße Anwesenheit einer zusätzlichen Intel-GPU.&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
# Das zur verwendeten Unreal-Engine-Version passende Plugin-Paket herunterladen.&lt;br /&gt;
# Den Ordner &amp;lt;code&amp;gt;DLSS5ForUE5&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;Projekt/Plugins/&amp;lt;/code&amp;gt; entpacken.&lt;br /&gt;
# Das Projekt öffnen und die Plugins &#039;&#039;DLSS&#039;&#039; sowie &#039;&#039;DLSS 5 for UE5&#039;&#039; aktivieren.&lt;br /&gt;
# Den Editor neu starten.&lt;br /&gt;
# Das Werkzeug über &#039;&#039;Tools → DLSS 5 for UE5&#039;&#039; öffnen.&lt;br /&gt;
&lt;br /&gt;
Bei einem passenden vorkompilierten Paket ist für die normale Installation keine eigene Übersetzung mit Visual Studio erforderlich.&lt;br /&gt;
&lt;br /&gt;
== Verwendung und Grenzen ==&lt;br /&gt;
&lt;br /&gt;
Die Anzahl der Durchläufe lässt sich von eins bis vier einstellen. Jeder weitere Durchlauf verarbeitet das Ergebnis des vorherigen Durchlaufs und erhöht die GPU-Last deutlich. Ein Durchlauf ist deshalb ein sinnvoller Ausgangspunkt.&lt;br /&gt;
&lt;br /&gt;
Scene Depth und erzeugte Bewegungsvektoren können die zeitliche Stabilität verbessern. Die Verarbeitung der Motion Vectors ist jedoch weiterhin experimentell, da Unreal Engine in einigen Render-Hook-Zuständen keine direkt nutzbare Objektgeschwindigkeit liefert. Bekannte Probleme und Workarounds sind in der Repository-Dokumentation beschrieben.&lt;br /&gt;
&lt;br /&gt;
== Performance-Messungen ==&lt;br /&gt;
&lt;br /&gt;
Eine frühe Messreihe lief im eigentlichen Spielprojekt in einer schweren Wald-/Wasserszene auf der RTX 5060 Laptop GPU. Verwendet wurden Epic Scalability und 83,4 % Render Resolution, ungefähr 1404×715 Pixel im Viewport. Die Werte sind Momentaufnahmen und kein allgemeiner Benchmark.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Zustand&lt;br /&gt;
! FPS&lt;br /&gt;
! Framezeit&lt;br /&gt;
! GPU-Zeit&lt;br /&gt;
! Zusatz gegenüber aus&lt;br /&gt;
|-&lt;br /&gt;
| Neural Rendering aus&lt;br /&gt;
| 41,68&lt;br /&gt;
| 23,99 ms&lt;br /&gt;
| 17,19 ms&lt;br /&gt;
| –&lt;br /&gt;
|-&lt;br /&gt;
| 1 Pass&lt;br /&gt;
| 30,87&lt;br /&gt;
| 32,38 ms&lt;br /&gt;
| 26,75 ms&lt;br /&gt;
| +9,56 ms&lt;br /&gt;
|-&lt;br /&gt;
| 2 Passes&lt;br /&gt;
| 23,16&lt;br /&gt;
| 43,05 ms&lt;br /&gt;
| 35,84 ms&lt;br /&gt;
| +18,65 ms&lt;br /&gt;
|-&lt;br /&gt;
| 4 Passes&lt;br /&gt;
| 16,07&lt;br /&gt;
| 62,27 ms&lt;br /&gt;
| 54,19 ms&lt;br /&gt;
| +37,00 ms&lt;br /&gt;
|-&lt;br /&gt;
| 2 Passes mit Depth und Motion&lt;br /&gt;
| 23,52&lt;br /&gt;
| 42,39 ms&lt;br /&gt;
| 35,99 ms&lt;br /&gt;
| +18,80 ms&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In dieser Reihe kostete ein Neural-Pass ungefähr 9 bis 9,5 ms zusätzliche GPU-Zeit. Depth und Motion erhöhten die GPU-Zeit bei zwei Passes nur um ungefähr 0,15 ms und lagen damit im Bereich der Messschwankung. Spätere Versuche mit Preset 3 und vier Passes lagen in einer anderen Szeneneinstellung deutlich niedriger, beispielsweise bei ungefähr 26 ms GPU-Zeit. Die Kosten hängen damit stark von Preset, Passzahl, Szene, Feature-Vertrag und Auflösung ab; künftige Vergleiche müssen diese Parameter mitprotokollieren.&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen ==&lt;br /&gt;
&lt;br /&gt;
* Neural Rendering ist aktuell auf Win64, Direct3D 12 und einen aktiven NVIDIA-Renderadapter begrenzt.&lt;br /&gt;
* Depth und Motion funktionieren technisch, benötigen aber weitere Qualitäts- und Stabilitätsprüfung in Bewegung.&lt;br /&gt;
* Direktes Umschalten von &amp;lt;code&amp;gt;r.DLSS5.PassCount&amp;lt;/code&amp;gt; war im Editor zeitweise nicht zuverlässig; der Settings-Slider setzte denselben Wert korrekt.&lt;br /&gt;
* Mehrere Spatial Upscaler dürfen nicht gleichzeitig aktiv konfiguriert werden.&lt;br /&gt;
* Die proprietäre NVIDIA-Runtime wird nicht im Git-Checkpoint versioniert.&lt;br /&gt;
* Die in [[UE5 Heterogeneous Multi-GPU]] untersuchte Worker-Auslagerung ist noch nicht implementiert. Neural Rendering läuft derzeit auf der Primary-NVIDIA-GPU.&lt;br /&gt;
&lt;br /&gt;
== Repository und Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[https://github.com/jan1009/DLSS5ForUE5 Unser GitHub-Repository]&#039;&#039;&#039;&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/INSTALLATION.md Installation]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/USAGE.md Verwendung]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/COMMANDS.md Befehle und Konsolenvariablen]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/KNOWN_ISSUES.md Bekannte Probleme]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/TROUBLESHOOTING.md Fehlerbehebung]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/ARCHITECTURE.md Architektur]&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Deep Learning Super Sampling]]&lt;br /&gt;
* [[UE5 Heterogeneous Multi-GPU]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Grafik]]&lt;br /&gt;
[[Kategorie:NVIDIA]]&lt;br /&gt;
[[Kategorie:Plugin]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=196</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=196"/>
		<updated>2026-09-17T19:37:35Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 17. September 2026. Aktueller Engine-Checkpoint: &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add DLSS5 NR integration and packaged shader support&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Der vorherige Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; bleibt die Grundlage des Worker-, Workload- und GPU-Timing-Pfads. Neu sind cook-fähige ExperimentalMultiGPU-Global-Shader sowie die Integration von [[DLSS5ForUE5]] als realer Neural-Rendering-Workload. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus. Der Proof of Concept besitzt inzwischen einen durchgängigen Worker-Rasterpfad aus echten UE-Weltdaten bis zur zweiten physischen GPU und zurück in eine persistente UE-Textur. Eine backend-neutrale Workload-Schicht erfasst Aufgaben, Lifecycle-Daten und echte Worker-GPU-Zeiten; automatische Scheduling-Entscheidungen trifft sie noch nicht. Seit Commit &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt; funktioniert der ExperimentalMultiGPU-Shaderpfad außerdem in Development-Packages. Parallel liefert DLSS5 Neural Rendering einen ersten realen, klar messbaren Kandidaten für eine spätere grobe Worker-Auslagerung; aktuell läuft dieser Workload noch vollständig auf der Primary-NVIDIA-GPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; später außerdem RX 6900 XT ↔ Intel&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; vorheriger Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt;; Working Tree nach dem Commit ohne ausstehende versionierte Änderungen&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Mess- und Workload-Schicht&lt;br /&gt;
| Generische Workload-Registry, Runtime Metrics V1 und echte D3D12-Timestamp-Messungen des Worker-Rasterabschnitts implementiert&lt;br /&gt;
|-&lt;br /&gt;
! Packaged Build&lt;br /&gt;
| Alle neun ExperimentalMultiGPU-Global-Shader nach RenderCore verlagert, beim Cook registriert und im Development-Package erfolgreich gestartet&lt;br /&gt;
|-&lt;br /&gt;
! Neural Rendering&lt;br /&gt;
| [[DLSS5ForUE5]] in Source-Engine, Editor und Packaged Game integriert; Project-Config, native Caller-Gate-Bridge, Depth-/Motion-Guides und robuster Support-Fallback validiert&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Kostenmodell, Scheduler, weitere echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Skeletal Skinning ist erst vorgesehen, wenn ein echter Worker-Workload wie CCTV oder Spiegel animierte Figuren in seiner eigenen Ansicht benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Generische Workload-Registry ===&lt;br /&gt;
&lt;br /&gt;
Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; führt erstmals eine backend-neutrale Workload-Schicht ein. Sie beschreibt Aufgaben unabhängig vom konkreten Grafik-Backend und bildet die Grundlage für einen späteren Scheduler, trifft selbst aber noch keine GPU-Entscheidung.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bestandteil&lt;br /&gt;
! Inhalt&lt;br /&gt;
|-&lt;br /&gt;
| Workload-Typ&lt;br /&gt;
| &amp;lt;code&amp;gt;Unknown&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SceneCapture&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Compute&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Raster&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Gewünschte Zuweisung&lt;br /&gt;
| &amp;lt;code&amp;gt;Primary&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Worker&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Auto&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;Auto&amp;lt;/code&amp;gt; ist derzeit nur Metadatum&lt;br /&gt;
|-&lt;br /&gt;
| Priorität&lt;br /&gt;
| &amp;lt;code&amp;gt;Low&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;High&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Descriptor&lt;br /&gt;
| Sessionweit monotone ID, Typ, Zuweisung, Priorität, Auflösung, Zielrate, Debugname und Running-Status&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Registry stellt &amp;lt;code&amp;gt;RegisterWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UpdateWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UnregisterWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;GetWorkload&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;GetActiveWorkloads&amp;lt;/code&amp;gt; bereit und schützt ihre Daten per &amp;lt;code&amp;gt;FCriticalSection&amp;lt;/code&amp;gt;. Descriptoren enthalten weder &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;- noch D3D12-Pointer. Der SceneCapture-Stream registriert genau einen Worker-Workload mit normaler Priorität und entfernt ihn bei Stop oder Auto-Stop wieder vollständig.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt; zeigt die aktiven Descriptoren und ihre Laufzeitwerte an.&lt;br /&gt;
&lt;br /&gt;
=== Runtime Metrics V1 ===&lt;br /&gt;
&lt;br /&gt;
Descriptor und Laufzeitstatistik sind getrennt. Pro Workload werden Ticks, angenommene Submits, Busy- und Fehlerfälle, fertige Frames, aktuell ausstehende Jobs, Laufzeit sowie effektive Tick-, Submit- und Ready-Raten erfasst. Der SceneCapture-Pfad spiegelt dafür seine vorhandenen Stream-Zähler in die Registry, statt eine zweite Statistiklogik aufzubauen. Die Messwerte werden derzeit nur beobachtet und ändern weder Zuweisung noch Auflösung oder Zielrate.&lt;br /&gt;
&lt;br /&gt;
Editor-Fokus und Background-Throttling können die Lifecycle-Raten deutlich verfälschen. In einem sauberen 1280×720-Referenzlauf wurden 1000/1000 Ready-Frames ohne Busy bei 29,84 Ready-Hz gemessen; bei wechselndem Fensterfokus entstanden dagegen 459 Busy-Ticks und nur 16,69 Ready-Hz, ohne dass die Worker-GPU-Zeit entsprechend einbrach. Solche Raten sind daher kein verlässlicher Ersatz für echte GPU-Kostenmessungen.&lt;br /&gt;
&lt;br /&gt;
=== Worker GPU Timing V1 ===&lt;br /&gt;
&lt;br /&gt;
Der SceneCapture-Worker verwendet persistente native D3D12-Timestamp-Queries auf seiner vorhandenen DIRECT-Queue: einen Query Heap mit zwei Slots, einen kleinen Readback-Buffer und die per &amp;lt;code&amp;gt;GetTimestampFrequency()&amp;lt;/code&amp;gt; ermittelte Zeitbasis. Das Ergebnis wird erst nach non-blocking geprüftem Fence-Abschluss gelesen; CPU-Waits entstehen nicht. Die Workload-ID wird als POD bis zum Worker mitgeführt, während einmalige Tests die ID 0 verwenden.&lt;br /&gt;
&lt;br /&gt;
Gemessen wird ausschließlich der Worker-Rasterabschnitt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Start Timestamp&lt;br /&gt;
  -&amp;gt; COPY_SOURCE nach RENDER_TARGET&lt;br /&gt;
  -&amp;gt; Color- und Depth-Clear&lt;br /&gt;
  -&amp;gt; alle DrawIndexedInstanced-Aufrufe&lt;br /&gt;
  -&amp;gt; RENDER_TARGET nach COPY_SOURCE&lt;br /&gt;
End Timestamp&lt;br /&gt;
  -&amp;gt; ResolveQueryData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nicht enthalten sind der Cross-Adapter-Transfer, die Primary-SafeCopy und die Integration auf der Primary-GPU. Erfasst werden Sample-Anzahl sowie letzter, mittlerer, minimaler und maximaler Messwert.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Auflösung&lt;br /&gt;
! Samples&lt;br /&gt;
! Mittelwert&lt;br /&gt;
! Minimum&lt;br /&gt;
! Maximum&lt;br /&gt;
|-&lt;br /&gt;
| 1280×720&lt;br /&gt;
| 845&lt;br /&gt;
| 0,166 ms&lt;br /&gt;
| 0,165 ms&lt;br /&gt;
| 0,181 ms&lt;br /&gt;
|-&lt;br /&gt;
| 3840×2160&lt;br /&gt;
| 599&lt;br /&gt;
| 0,683 ms&lt;br /&gt;
| 0,594 ms&lt;br /&gt;
| 0,751 ms&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei identischem, bewusst einfachem Szeneninhalt mit sieben Draw Calls steigt die gemessene Worker-Rasterzeit damit ungefähr um Faktor 4,1. Die Pixelzahl allein erklärt die Skalierung nicht vollständig. Für ein belastbares Kostenmodell müssen als Nächstes Transfer und Primary-Integration separat gemessen werden.&lt;br /&gt;
&lt;br /&gt;
=== Cook- und Packaged-Support der Multi-GPU-Shader ===&lt;br /&gt;
&lt;br /&gt;
Vor Commit &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt; startete ein Packaged Build nicht, weil unter anderem die Permutation von &amp;lt;code&amp;gt;FExperimentalMultiGPUStaticMeshPS&amp;lt;/code&amp;gt; in der cooked Global Shader Map fehlte. Die Shader selbst waren korrekt; ihre neun &amp;lt;code&amp;gt;FGlobalShader&amp;lt;/code&amp;gt;-Typen wurden jedoch im D3D12RHI registriert, das beim Cook zu diesem Zeitpunkt noch nicht geladen war.&lt;br /&gt;
&lt;br /&gt;
Die Deklarationen liegen nun im RenderCore-Header &amp;lt;code&amp;gt;ExperimentalMultiGPUShaders.h&amp;lt;/code&amp;gt;, die zugehörigen &amp;lt;code&amp;gt;IMPLEMENT_GLOBAL_SHADER&amp;lt;/code&amp;gt;-Registrierungen in &amp;lt;code&amp;gt;ExperimentalMultiGPUShaders.cpp&amp;lt;/code&amp;gt;. D3D12RHI verwendet nur noch die exportierten RenderCore-Typen. Shaderpfade, Entry Points und die bestehende Shader-Blob-Erkennung bleiben unverändert. Der Cook kompilierte die ExperimentalMultiGPU-Shader nachweislich; das anschließende Development-Package startete ohne den früheren &amp;lt;code&amp;gt;Missing global shader&amp;lt;/code&amp;gt;-Fatal. Damit ist der Worker-Pfad shaderseitig nicht mehr auf den Editor beschränkt.&lt;br /&gt;
&lt;br /&gt;
=== DLSS5 Neural Rendering als späterer Worker-Kandidat ===&lt;br /&gt;
&lt;br /&gt;
Der Branch enthält nun auch [[DLSS5ForUE5]] als quelltextbasierte Win64-/D3D12-Integration für NVIDIA Neural Rendering. Das Plugin verwendet den bereits vom offiziellen NVIDIA-DLSS-Plugin initialisierten NGX-Core und eröffnet keine konkurrierende NGX-Application-Session. Neural Rendering läuft derzeit auf der Primary-NVIDIA-GPU; ein Multi-GPU-Offload ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
Die Integration umfasst:&lt;br /&gt;
&lt;br /&gt;
* eine eigene &amp;lt;code&amp;gt;Config/DLSS5ForUE5.ini&amp;lt;/code&amp;gt; mit 20 projektbezogenen Einstellungen,&lt;br /&gt;
* einen ausschließlich im Editor wirksamen Safe Boot, der Neural Rendering und Scene Guides nur für die aktuelle Session deaktiviert,&lt;br /&gt;
* eine native &amp;lt;code&amp;gt;DLSS5ForUE5_nvngx.dll&amp;lt;/code&amp;gt; als unmittelbaren Caller für den NVIDIA-Caller-Gate,&lt;br /&gt;
* Depth- und Motion-Guides aus der laufenden UE-Szene,&lt;br /&gt;
* die Supportzustände &amp;lt;code&amp;gt;AVAILABLE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UNAVAILABLE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UNSUPPORTED&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;WAITING&amp;lt;/code&amp;gt; mit sauberem Fallback statt wiederholtem Init-Logspam.&lt;br /&gt;
&lt;br /&gt;
Im monolithischen Packaged Game wurde der NGX-Init zunächst mit &amp;lt;code&amp;gt;0xBAD00002&amp;lt;/code&amp;gt; abgelehnt, weil der Aufruf aus der Spiel-EXE kam. Eine native Bridge löst dieses Problem. Zusätzlich musste die MSVC-Tail-Call-Optimierung verhindert werden: Erst ein echter &amp;lt;code&amp;gt;call&amp;lt;/code&amp;gt; mit erhaltenem Bridge-Stackframe ließ die DLL als unmittelbaren Caller sichtbar bleiben. Danach meldete die Runtime Caller Gate, NGX-Core, Parameter und Initialisierung erfolgreich. In einem Packaged-Lauf waren 2036 von 2036 Evaluierungen erfolgreich; Depth und Motion waren jeweils angefordert, verfügbar und verwendet.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde sowohl im kleinen &amp;lt;code&amp;gt;UpscalerTest&amp;lt;/code&amp;gt; als auch im eigentlichen Spielprojekt mit vorhandenen DLSS-, FSR- und XeSS-Plugins validiert. Auf dem Hybrid-Laptop blieb der Support trotz zusätzlicher Intel UHD korrekt &amp;lt;code&amp;gt;AVAILABLE&amp;lt;/code&amp;gt;, weil der aktive Renderadapter statt der bloßen Existenz eines Intel-Adapters ausgewertet wird.&lt;br /&gt;
&lt;br /&gt;
==== Gemessene Kosten ====&lt;br /&gt;
&lt;br /&gt;
Eine bewusst schwere Wald-/Wasserszene auf der RTX 5060 Laptop GPU wurde bei Epic Scalability und 83,4 % Render Resolution, ungefähr 1404×715 Pixel im Viewport, gemessen. Die Ergebnisse sind Momentaufnahmen und kein allgemeiner Leistungswert.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Zustand&lt;br /&gt;
! FPS&lt;br /&gt;
! Framezeit&lt;br /&gt;
! GPU-Zeit&lt;br /&gt;
! Zusätzliche GPU-Zeit gegenüber aus&lt;br /&gt;
|-&lt;br /&gt;
| Neural Rendering aus&lt;br /&gt;
| 41,68&lt;br /&gt;
| 23,99 ms&lt;br /&gt;
| 17,19 ms&lt;br /&gt;
| –&lt;br /&gt;
|-&lt;br /&gt;
| 1 Pass&lt;br /&gt;
| 30,87&lt;br /&gt;
| 32,38 ms&lt;br /&gt;
| 26,75 ms&lt;br /&gt;
| +9,56 ms&lt;br /&gt;
|-&lt;br /&gt;
| 2 Passes&lt;br /&gt;
| 23,16&lt;br /&gt;
| 43,05 ms&lt;br /&gt;
| 35,84 ms&lt;br /&gt;
| +18,65 ms&lt;br /&gt;
|-&lt;br /&gt;
| 4 Passes&lt;br /&gt;
| 16,07&lt;br /&gt;
| 62,27 ms&lt;br /&gt;
| 54,19 ms&lt;br /&gt;
| +37,00 ms&lt;br /&gt;
|-&lt;br /&gt;
| 2 Passes mit Depth/Motion&lt;br /&gt;
| 23,52&lt;br /&gt;
| 42,39 ms&lt;br /&gt;
| 35,99 ms&lt;br /&gt;
| +18,80 ms&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In dieser frühen Testreihe kostete ein Neural-Pass ungefähr 9 bis 9,5 ms zusätzliche GPU-Zeit. Depth und Motion erhöhten den Zwei-Pass-Wert nur um etwa 0,15 ms und lagen damit im Bereich der Messschwankung. Spätere Läufe mit Preset 3 und vier Passes lagen deutlich niedriger, beispielsweise bei ungefähr 26 ms GPU-Zeit in einer anderen Szeneneinstellung. Preset, Feature-Vertrag, Szene und Viewport müssen deshalb bei künftigen Benchmarks immer mitprotokolliert werden. Gerade der große, klar abgrenzbare Evaluierungsblock macht Neural Rendering zu einem interessanten späteren Scheduler-Workload.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
Die vorhandenen Compute-, Texture-, Raster-, StaticMesh-, World- und QueueProbe-Kommandos bleiben bestehen. Neu hinzugekommen ist:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt;&lt;br /&gt;
| Listet aktive Workloads mit ID, Typ, gewünschter Zuweisung, Priorität, Auflösung, Zielrate, Lifecycle-Statistik und Worker-GPU-Timing auf.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für den aktuellen Hauptpfad sind außerdem besonders relevant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.GetSceneCaptureResolution&lt;br /&gt;
ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&lt;br /&gt;
ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
ExperimentalMultiGPU.StopSceneCaptureStaticMeshSceneStream&lt;br /&gt;
ExperimentalMultiGPU.TestSkeletalMeshWorker&lt;br /&gt;
ExperimentalMultiGPU.ListWorkloads&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine Ziel- beziehungsweise Request-Frequenz. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht. &amp;lt;code&amp;gt;quiet&amp;lt;/code&amp;gt; unterdrückt Per-Job- und Busy-Logspam.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartQueueProbe &amp;amp;lt;Hz&amp;amp;gt; &amp;amp;lt;MaxSubmits&amp;amp;gt; [quiet] &amp;amp;lt;Mode&amp;amp;gt; &amp;amp;lt;Queue&amp;amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Diagnosemodi &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt; bleiben verfügbar. Als Queue können &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; gewählt werden. Private native Queues dienen weiterhin nur der Diagnose und bilden keinen fertigen Experimental-/Direct-Modus.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt; deaktiviert VSync. &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt; erzeugt reproduzierbare Frame-Coupling-Tests; &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt; entfernt das normale Framerate-Limit.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Als Nächstes wird die Source-Engine auf dem Desktop-System mit AMD RX 6900 XT und Intel Arc validiert. DLSS5 soll dort sauber &amp;lt;code&amp;gt;UNSUPPORTED&amp;lt;/code&amp;gt; melden und das normale Rendering nicht beeinflussen. Parallel wird die GPU-Zeit des Transfers vom Worker-ColorTarget in den Shared Cross-Adapter Buffer separat gemessen; danach folgt das Timing der Primary-SafeCopy. Erst aus den getrennten Blöcken Worker-Raster, Cross-Adapter-Transfer und Primary-Integration soll ein belastbares Kostenmodell V1 entstehen. Dieses bildet anschließend die Grundlage für automatische Primary-/Worker-Zuweisungen; die aktuelle Registry plant bewusst noch nichts selbst.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Die sichtbare Normal-/SafeCopy-/Ready-Kette bleibt an Unreals Submission- und Frame-System gekoppelt. Für sichtbare Outputs ist das akzeptabel; hochfrequente Hintergrundjobs benötigen weitere Architekturtests.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter sichtbarer Runtime-Slot. Mehrere parallele In-Flight-Jobs und Ringbuffer fehlen noch.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Mehrere Worker sind architektonisch vorgesehen, aber noch nicht praktisch validiert.&lt;br /&gt;
* World- und SceneCapture-Pfade verarbeiten pro Snapshot höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* Der Static-Mesh-Pfad verwendet LOD0-Positionen, Normalen und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Culling. Für Cooked/Shipping wird ein eigener Geometrie-Cache oder Build-Schritt benötigt.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen.&lt;br /&gt;
* Die Workload-Registry sammelt Metadaten und Messwerte, führt aber noch keine automatische Zuweisung, Auflösungsänderung oder Ratenanpassung aus.&lt;br /&gt;
* Worker GPU Timing V1 misst nur den Rasterabschnitt. Cross-Adapter-Transfer und Primary-SafeCopy fehlen noch im Kostenmodell.&lt;br /&gt;
* Lifecycle-Raten können im Editor durch Fensterfokus und Background-Throttling verfälscht werden. Für Kostenentscheidungen sind echte GPU-Timestamps und geglättete Mehrfachmessungen maßgeblich.&lt;br /&gt;
* QueueProbe und private native Queues bleiben Diagnosepfade; Experimental/Direct ist noch nicht implementiert.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden. Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* DLSS5 Neural Rendering ist aktuell auf Win64, D3D12 und einen aktiven NVIDIA-Renderadapter beschränkt. Der Workload läuft noch auf der Primary-GPU und ist nicht an den heterogenen Worker-Pfad angebunden.&lt;br /&gt;
* Depth- und Motion-Guides funktionieren technisch; Bildqualität und temporale Stabilität in Bewegung benötigen weitere Bewertung.&lt;br /&gt;
* Direktes Umschalten von &amp;lt;code&amp;gt;r.DLSS5.PassCount&amp;lt;/code&amp;gt; war im Editor zeitweise nicht zuverlässig, während der Settings-Slider den Wert korrekt setzte.&lt;br /&gt;
* Die Kosten von Neural Rendering hängen stark von Preset, Passzahl, Szene, Feature-Vertrag und Auflösung ab. Einzelmessungen dürfen nicht als feste Kosten pro Pass verallgemeinert werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen; DLSS5 muss auf AMD/Intel sauber zurückfallen.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden.&lt;br /&gt;
# Neural Rendering als groben Worker-Workload untersuchen: zuerst Datenpfad, Ressourcenbedarf und Synchronisation modellieren, danach erst den Offload implementieren.&lt;br /&gt;
# DLSS5-Benchmarks nach Preset, Passzahl, Scene Guides, Szene und Auflösung standardisieren; direktes &amp;lt;code&amp;gt;PassCount&amp;lt;/code&amp;gt;-CVar-Verhalten vereinheitlichen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Add DLSS5 NR integration and packaged shader support&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt;). Der Diff umfasst 29 Dateien mit 4037 Einfügungen und 281 Löschungen. Versioniert wurden gezielt relevante Source-, Build- und Plugin-Dateien; &amp;lt;code&amp;gt;Intermediate&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Saved&amp;lt;/code&amp;gt;, DDC sowie EXE-, DLL-, LIB- und PDB-Dateien und die proprietäre &amp;lt;code&amp;gt;nvngx_dlssnr.dll&amp;lt;/code&amp;gt; blieben ausgeschlossen. Nach dem Commit bestanden keine ausstehenden versionierten Änderungen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 17. September 2026; Commit &amp;lt;code&amp;gt;1fc0d24&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind cook-fähige ExperimentalMultiGPU-Global-Shader, DLSS5-NR-Integration, Packaged-Runtime, Caller-Gate-Bridge, Scene Guides, Support-Fallback und Performance-Messungen im eigentlichen Spielprojekt.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=DLSS5ForUE5&amp;diff=195</id>
		<title>DLSS5ForUE5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=DLSS5ForUE5&amp;diff=195"/>
		<updated>2026-09-16T06:07:13Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|DLSS5ForUE5 ist ein inoffizielles Community-Projekt und nicht mit NVIDIA oder Epic Games verbunden. Die Integration ist experimentell.}}  &amp;#039;&amp;#039;&amp;#039;DLSS5ForUE5&amp;#039;&amp;#039;&amp;#039; ist ein Plugin, das NVIDIA NGX Neural Rendering in den Unreal Editor integriert. Es stellt Einstellungen, Szenendaten und Diagnosefunktionen für DLSS 5 bereit. Der Fork des Projekts wird im GitHub-Repository &amp;#039;&amp;#039;&amp;#039;[https://github.com/jan1009/DLSS5ForUE5 jan1009/DLSS5ForUE5]&amp;#039;&amp;#039;&amp;#039; gepflegt.  == Unt…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|DLSS5ForUE5 ist ein inoffizielles Community-Projekt und nicht mit NVIDIA oder Epic Games verbunden. Die Integration ist experimentell.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DLSS5ForUE5&#039;&#039;&#039; ist ein Plugin, das NVIDIA NGX Neural Rendering in den Unreal Editor integriert. Es stellt Einstellungen, Szenendaten und Diagnosefunktionen für DLSS 5 bereit. Der Fork des Projekts wird im GitHub-Repository &#039;&#039;&#039;[https://github.com/jan1009/DLSS5ForUE5 jan1009/DLSS5ForUE5]&#039;&#039;&#039; gepflegt.&lt;br /&gt;
&lt;br /&gt;
== Unterstützte Versionen ==&lt;br /&gt;
&lt;br /&gt;
Das Repository enthält einen gemeinsamen, versionsabhängigen Quellcode für:&lt;br /&gt;
&lt;br /&gt;
* Unreal Engine 5.5&lt;br /&gt;
* Unreal Engine 5.6&lt;br /&gt;
* Unreal Engine 5.7&lt;br /&gt;
* Unreal Engine 5.8&lt;br /&gt;
&lt;br /&gt;
Getestet wurde die Integration unter Windows mit DirectX 12 und einer NVIDIA-RTX-Grafikkarte. Das offizielle NVIDIA-DLSS-Plugin muss für dieselbe Unreal-Engine-Version installiert und aktiviert sein.&lt;br /&gt;
&lt;br /&gt;
== Funktionen ==&lt;br /&gt;
&lt;br /&gt;
* eigenes Werkzeugfenster unter &#039;&#039;Tools → DLSS 5 for UE5&#039;&#039;&lt;br /&gt;
* Natural- und Cinematic-Stile&lt;br /&gt;
* Regler für Preset, Intensität, Local Tone, Local Structure und Skin Structure&lt;br /&gt;
* Scene-Depth- und Motion-Vector-Guides&lt;br /&gt;
* zeitliche Daten wie Jitter, Pre-Exposure, Camera Cut und History Reset&lt;br /&gt;
* ein bis vier aufeinanderfolgende Neural-Rendering-Durchläufe&lt;br /&gt;
* Live-Diagnose für Laufzeit, NGX, Szenendaten und zeitlichen Zustand&lt;br /&gt;
* Safe Mode zur Wiederherstellung&lt;br /&gt;
* Konsolenbefehle unter &amp;lt;code&amp;gt;DLSS5.*&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;r.DLSS5.*&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
# Das zur verwendeten Unreal-Engine-Version passende Plugin-Paket herunterladen.&lt;br /&gt;
# Den Ordner &amp;lt;code&amp;gt;DLSS5ForUE5&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;Projekt/Plugins/&amp;lt;/code&amp;gt; entpacken.&lt;br /&gt;
# Das Projekt öffnen und die Plugins &#039;&#039;DLSS&#039;&#039; sowie &#039;&#039;DLSS 5 for UE5&#039;&#039; aktivieren.&lt;br /&gt;
# Den Editor neu starten.&lt;br /&gt;
# Das Werkzeug über &#039;&#039;Tools → DLSS 5 for UE5&#039;&#039; öffnen.&lt;br /&gt;
&lt;br /&gt;
Bei einem passenden vorkompilierten Paket ist für die normale Installation keine eigene Übersetzung mit Visual Studio erforderlich.&lt;br /&gt;
&lt;br /&gt;
== Verwendung und Grenzen ==&lt;br /&gt;
&lt;br /&gt;
Die Anzahl der Durchläufe lässt sich von eins bis vier einstellen. Jeder weitere Durchlauf verarbeitet das Ergebnis des vorherigen Durchlaufs und erhöht die GPU-Last deutlich. Ein Durchlauf ist deshalb ein sinnvoller Ausgangspunkt.&lt;br /&gt;
&lt;br /&gt;
Scene Depth und erzeugte Bewegungsvektoren können die zeitliche Stabilität verbessern. Die Verarbeitung der Motion Vectors ist jedoch weiterhin experimentell, da Unreal Engine in einigen Render-Hook-Zuständen keine direkt nutzbare Objektgeschwindigkeit liefert. Bekannte Probleme und Workarounds sind in der Repository-Dokumentation beschrieben.&lt;br /&gt;
&lt;br /&gt;
== Repository und Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[https://github.com/jan1009/DLSS5ForUE5 Unser GitHub-Repository]&#039;&#039;&#039;&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/INSTALLATION.md Installation]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/USAGE.md Verwendung]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/COMMANDS.md Befehle und Konsolenvariablen]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/KNOWN_ISSUES.md Bekannte Probleme]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/TROUBLESHOOTING.md Fehlerbehebung]&lt;br /&gt;
* [https://github.com/jan1009/DLSS5ForUE5/blob/main/docs/ARCHITECTURE.md Architektur]&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Deep Learning Super Sampling]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Grafik]]&lt;br /&gt;
[[Kategorie:NVIDIA]]&lt;br /&gt;
[[Kategorie:Plugin]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=194</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=194"/>
		<updated>2026-09-14T18:25:07Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Projektstand auf 14.09.2026 und Commit 37c6d02 aktualisiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 14. September 2026. Aktueller Engine-Checkpoint: &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Der Commit umfasst die dynamische SceneCapture-Auflösung, die Scheduler-/Polling-Korrektur, den SkeletalMesh-ReferencePose-Proof, die generische Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus. Der Proof of Concept besitzt inzwischen einen durchgängigen Worker-Rasterpfad aus echten UE-Weltdaten bis zur zweiten physischen GPU und zurück in eine persistente UE-Textur. Eine backend-neutrale Workload-Schicht erfasst dabei erstmals Aufgaben, Lifecycle-Daten und echte Worker-GPU-Zeiten; automatische Scheduling-Entscheidungen trifft sie noch nicht.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; später außerdem RX 6900 XT ↔ Intel&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; vorheriger Checkpoint &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt;; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Mess- und Workload-Schicht&lt;br /&gt;
| Generische Workload-Registry, Runtime Metrics V1 und echte D3D12-Timestamp-Messungen des Worker-Rasterabschnitts implementiert&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Kostenmodell, Scheduler, weitere echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Skeletal Skinning ist erst vorgesehen, wenn ein echter Worker-Workload wie CCTV oder Spiegel animierte Figuren in seiner eigenen Ansicht benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Generische Workload-Registry ===&lt;br /&gt;
&lt;br /&gt;
Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; führt erstmals eine backend-neutrale Workload-Schicht ein. Sie beschreibt Aufgaben unabhängig vom konkreten Grafik-Backend und bildet die Grundlage für einen späteren Scheduler, trifft selbst aber noch keine GPU-Entscheidung.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bestandteil&lt;br /&gt;
! Inhalt&lt;br /&gt;
|-&lt;br /&gt;
| Workload-Typ&lt;br /&gt;
| &amp;lt;code&amp;gt;Unknown&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SceneCapture&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Compute&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Raster&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Gewünschte Zuweisung&lt;br /&gt;
| &amp;lt;code&amp;gt;Primary&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Worker&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Auto&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;Auto&amp;lt;/code&amp;gt; ist derzeit nur Metadatum&lt;br /&gt;
|-&lt;br /&gt;
| Priorität&lt;br /&gt;
| &amp;lt;code&amp;gt;Low&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;High&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Descriptor&lt;br /&gt;
| Sessionweit monotone ID, Typ, Zuweisung, Priorität, Auflösung, Zielrate, Debugname und Running-Status&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Registry stellt &amp;lt;code&amp;gt;RegisterWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UpdateWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UnregisterWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;GetWorkload&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;GetActiveWorkloads&amp;lt;/code&amp;gt; bereit und schützt ihre Daten per &amp;lt;code&amp;gt;FCriticalSection&amp;lt;/code&amp;gt;. Descriptoren enthalten weder &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;- noch D3D12-Pointer. Der SceneCapture-Stream registriert genau einen Worker-Workload mit normaler Priorität und entfernt ihn bei Stop oder Auto-Stop wieder vollständig.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt; zeigt die aktiven Descriptoren und ihre Laufzeitwerte an.&lt;br /&gt;
&lt;br /&gt;
=== Runtime Metrics V1 ===&lt;br /&gt;
&lt;br /&gt;
Descriptor und Laufzeitstatistik sind getrennt. Pro Workload werden Ticks, angenommene Submits, Busy- und Fehlerfälle, fertige Frames, aktuell ausstehende Jobs, Laufzeit sowie effektive Tick-, Submit- und Ready-Raten erfasst. Der SceneCapture-Pfad spiegelt dafür seine vorhandenen Stream-Zähler in die Registry, statt eine zweite Statistiklogik aufzubauen. Die Messwerte werden derzeit nur beobachtet und ändern weder Zuweisung noch Auflösung oder Zielrate.&lt;br /&gt;
&lt;br /&gt;
Editor-Fokus und Background-Throttling können die Lifecycle-Raten deutlich verfälschen. In einem sauberen 1280×720-Referenzlauf wurden 1000/1000 Ready-Frames ohne Busy bei 29,84 Ready-Hz gemessen; bei wechselndem Fensterfokus entstanden dagegen 459 Busy-Ticks und nur 16,69 Ready-Hz, ohne dass die Worker-GPU-Zeit entsprechend einbrach. Solche Raten sind daher kein verlässlicher Ersatz für echte GPU-Kostenmessungen.&lt;br /&gt;
&lt;br /&gt;
=== Worker GPU Timing V1 ===&lt;br /&gt;
&lt;br /&gt;
Der SceneCapture-Worker verwendet persistente native D3D12-Timestamp-Queries auf seiner vorhandenen DIRECT-Queue: einen Query Heap mit zwei Slots, einen kleinen Readback-Buffer und die per &amp;lt;code&amp;gt;GetTimestampFrequency()&amp;lt;/code&amp;gt; ermittelte Zeitbasis. Das Ergebnis wird erst nach non-blocking geprüftem Fence-Abschluss gelesen; CPU-Waits entstehen nicht. Die Workload-ID wird als POD bis zum Worker mitgeführt, während einmalige Tests die ID 0 verwenden.&lt;br /&gt;
&lt;br /&gt;
Gemessen wird ausschließlich der Worker-Rasterabschnitt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Start Timestamp&lt;br /&gt;
  -&amp;gt; COPY_SOURCE nach RENDER_TARGET&lt;br /&gt;
  -&amp;gt; Color- und Depth-Clear&lt;br /&gt;
  -&amp;gt; alle DrawIndexedInstanced-Aufrufe&lt;br /&gt;
  -&amp;gt; RENDER_TARGET nach COPY_SOURCE&lt;br /&gt;
End Timestamp&lt;br /&gt;
  -&amp;gt; ResolveQueryData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nicht enthalten sind der Cross-Adapter-Transfer, die Primary-SafeCopy und die Integration auf der Primary-GPU. Erfasst werden Sample-Anzahl sowie letzter, mittlerer, minimaler und maximaler Messwert.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Auflösung&lt;br /&gt;
! Samples&lt;br /&gt;
! Mittelwert&lt;br /&gt;
! Minimum&lt;br /&gt;
! Maximum&lt;br /&gt;
|-&lt;br /&gt;
| 1280×720&lt;br /&gt;
| 845&lt;br /&gt;
| 0,166 ms&lt;br /&gt;
| 0,165 ms&lt;br /&gt;
| 0,181 ms&lt;br /&gt;
|-&lt;br /&gt;
| 3840×2160&lt;br /&gt;
| 599&lt;br /&gt;
| 0,683 ms&lt;br /&gt;
| 0,594 ms&lt;br /&gt;
| 0,751 ms&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei identischem, bewusst einfachem Szeneninhalt mit sieben Draw Calls steigt die gemessene Worker-Rasterzeit damit ungefähr um Faktor 4,1. Die Pixelzahl allein erklärt die Skalierung nicht vollständig. Für ein belastbares Kostenmodell müssen als Nächstes Transfer und Primary-Integration separat gemessen werden.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
Die vorhandenen Compute-, Texture-, Raster-, StaticMesh-, World- und QueueProbe-Kommandos bleiben bestehen. Neu hinzugekommen ist:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt;&lt;br /&gt;
| Listet aktive Workloads mit ID, Typ, gewünschter Zuweisung, Priorität, Auflösung, Zielrate, Lifecycle-Statistik und Worker-GPU-Timing auf.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für den aktuellen Hauptpfad sind außerdem besonders relevant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.GetSceneCaptureResolution&lt;br /&gt;
ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&lt;br /&gt;
ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
ExperimentalMultiGPU.StopSceneCaptureStaticMeshSceneStream&lt;br /&gt;
ExperimentalMultiGPU.TestSkeletalMeshWorker&lt;br /&gt;
ExperimentalMultiGPU.ListWorkloads&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine Ziel- beziehungsweise Request-Frequenz. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht. &amp;lt;code&amp;gt;quiet&amp;lt;/code&amp;gt; unterdrückt Per-Job- und Busy-Logspam.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartQueueProbe &amp;amp;lt;Hz&amp;amp;gt; &amp;amp;lt;MaxSubmits&amp;amp;gt; [quiet] &amp;amp;lt;Mode&amp;amp;gt; &amp;amp;lt;Queue&amp;amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Diagnosemodi &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt; bleiben verfügbar. Als Queue können &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; gewählt werden. Private native Queues dienen weiterhin nur der Diagnose und bilden keinen fertigen Experimental-/Direct-Modus.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt; deaktiviert VSync. &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt; erzeugt reproduzierbare Frame-Coupling-Tests; &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt; entfernt das normale Framerate-Limit.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Als Nächstes wird die GPU-Zeit des Transfers vom Worker-ColorTarget in den Shared Cross-Adapter Buffer separat gemessen. Danach folgt das Timing der Primary-SafeCopy. Erst aus den getrennten Blöcken Worker-Raster, Cross-Adapter-Transfer und Primary-Integration soll ein belastbares Kostenmodell V1 entstehen. Dieses bildet anschließend die Grundlage für automatische Primary-/Worker-Zuweisungen; die aktuelle Registry plant bewusst noch nichts selbst.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Die sichtbare Normal-/SafeCopy-/Ready-Kette bleibt an Unreals Submission- und Frame-System gekoppelt. Für sichtbare Outputs ist das akzeptabel; hochfrequente Hintergrundjobs benötigen weitere Architekturtests.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter sichtbarer Runtime-Slot. Mehrere parallele In-Flight-Jobs und Ringbuffer fehlen noch.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Mehrere Worker sind architektonisch vorgesehen, aber noch nicht praktisch validiert.&lt;br /&gt;
* World- und SceneCapture-Pfade verarbeiten pro Snapshot höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* Der Static-Mesh-Pfad verwendet LOD0-Positionen, Normalen und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Culling. Für Cooked/Shipping wird ein eigener Geometrie-Cache oder Build-Schritt benötigt.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen.&lt;br /&gt;
* Die Workload-Registry sammelt Metadaten und Messwerte, führt aber noch keine automatische Zuweisung, Auflösungsänderung oder Ratenanpassung aus.&lt;br /&gt;
* Worker GPU Timing V1 misst nur den Rasterabschnitt. Cross-Adapter-Transfer und Primary-SafeCopy fehlen noch im Kostenmodell.&lt;br /&gt;
* Lifecycle-Raten können im Editor durch Fensterfokus und Background-Throttling verfälscht werden. Für Kostenentscheidungen sind echte GPU-Timestamps und geglättete Mehrfachmessungen maßgeblich.&lt;br /&gt;
* QueueProbe und private native Queues bleiben Diagnosepfade; Experimental/Direct ist noch nicht implementiert.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden. Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden; später Post Process oder neuronale Aufgaben untersuchen.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=193</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=193"/>
		<updated>2026-09-14T18:25:01Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Workload-Registry, Runtime Metrics und Worker GPU Timing dokumentiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Skeletal Skinning ist erst vorgesehen, wenn ein echter Worker-Workload wie CCTV oder Spiegel animierte Figuren in seiner eigenen Ansicht benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Generische Workload-Registry ===&lt;br /&gt;
&lt;br /&gt;
Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; führt erstmals eine backend-neutrale Workload-Schicht ein. Sie beschreibt Aufgaben unabhängig vom konkreten Grafik-Backend und bildet die Grundlage für einen späteren Scheduler, trifft selbst aber noch keine GPU-Entscheidung.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bestandteil&lt;br /&gt;
! Inhalt&lt;br /&gt;
|-&lt;br /&gt;
| Workload-Typ&lt;br /&gt;
| &amp;lt;code&amp;gt;Unknown&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SceneCapture&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Compute&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Raster&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Gewünschte Zuweisung&lt;br /&gt;
| &amp;lt;code&amp;gt;Primary&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Worker&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Auto&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;Auto&amp;lt;/code&amp;gt; ist derzeit nur Metadatum&lt;br /&gt;
|-&lt;br /&gt;
| Priorität&lt;br /&gt;
| &amp;lt;code&amp;gt;Low&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;High&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Descriptor&lt;br /&gt;
| Sessionweit monotone ID, Typ, Zuweisung, Priorität, Auflösung, Zielrate, Debugname und Running-Status&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Registry stellt &amp;lt;code&amp;gt;RegisterWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UpdateWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UnregisterWorkload&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;GetWorkload&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;GetActiveWorkloads&amp;lt;/code&amp;gt; bereit und schützt ihre Daten per &amp;lt;code&amp;gt;FCriticalSection&amp;lt;/code&amp;gt;. Descriptoren enthalten weder &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;- noch D3D12-Pointer. Der SceneCapture-Stream registriert genau einen Worker-Workload mit normaler Priorität und entfernt ihn bei Stop oder Auto-Stop wieder vollständig.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt; zeigt die aktiven Descriptoren und ihre Laufzeitwerte an.&lt;br /&gt;
&lt;br /&gt;
=== Runtime Metrics V1 ===&lt;br /&gt;
&lt;br /&gt;
Descriptor und Laufzeitstatistik sind getrennt. Pro Workload werden Ticks, angenommene Submits, Busy- und Fehlerfälle, fertige Frames, aktuell ausstehende Jobs, Laufzeit sowie effektive Tick-, Submit- und Ready-Raten erfasst. Der SceneCapture-Pfad spiegelt dafür seine vorhandenen Stream-Zähler in die Registry, statt eine zweite Statistiklogik aufzubauen. Die Messwerte werden derzeit nur beobachtet und ändern weder Zuweisung noch Auflösung oder Zielrate.&lt;br /&gt;
&lt;br /&gt;
Editor-Fokus und Background-Throttling können die Lifecycle-Raten deutlich verfälschen. In einem sauberen 1280×720-Referenzlauf wurden 1000/1000 Ready-Frames ohne Busy bei 29,84 Ready-Hz gemessen; bei wechselndem Fensterfokus entstanden dagegen 459 Busy-Ticks und nur 16,69 Ready-Hz, ohne dass die Worker-GPU-Zeit entsprechend einbrach. Solche Raten sind daher kein verlässlicher Ersatz für echte GPU-Kostenmessungen.&lt;br /&gt;
&lt;br /&gt;
=== Worker GPU Timing V1 ===&lt;br /&gt;
&lt;br /&gt;
Der SceneCapture-Worker verwendet persistente native D3D12-Timestamp-Queries auf seiner vorhandenen DIRECT-Queue: einen Query Heap mit zwei Slots, einen kleinen Readback-Buffer und die per &amp;lt;code&amp;gt;GetTimestampFrequency()&amp;lt;/code&amp;gt; ermittelte Zeitbasis. Das Ergebnis wird erst nach non-blocking geprüftem Fence-Abschluss gelesen; CPU-Waits entstehen nicht. Die Workload-ID wird als POD bis zum Worker mitgeführt, während einmalige Tests die ID 0 verwenden.&lt;br /&gt;
&lt;br /&gt;
Gemessen wird ausschließlich der Worker-Rasterabschnitt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Start Timestamp&lt;br /&gt;
  -&amp;gt; COPY_SOURCE nach RENDER_TARGET&lt;br /&gt;
  -&amp;gt; Color- und Depth-Clear&lt;br /&gt;
  -&amp;gt; alle DrawIndexedInstanced-Aufrufe&lt;br /&gt;
  -&amp;gt; RENDER_TARGET nach COPY_SOURCE&lt;br /&gt;
End Timestamp&lt;br /&gt;
  -&amp;gt; ResolveQueryData&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nicht enthalten sind der Cross-Adapter-Transfer, die Primary-SafeCopy und die Integration auf der Primary-GPU. Erfasst werden Sample-Anzahl sowie letzter, mittlerer, minimaler und maximaler Messwert.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Auflösung&lt;br /&gt;
! Samples&lt;br /&gt;
! Mittelwert&lt;br /&gt;
! Minimum&lt;br /&gt;
! Maximum&lt;br /&gt;
|-&lt;br /&gt;
| 1280×720&lt;br /&gt;
| 845&lt;br /&gt;
| 0,166 ms&lt;br /&gt;
| 0,165 ms&lt;br /&gt;
| 0,181 ms&lt;br /&gt;
|-&lt;br /&gt;
| 3840×2160&lt;br /&gt;
| 599&lt;br /&gt;
| 0,683 ms&lt;br /&gt;
| 0,594 ms&lt;br /&gt;
| 0,751 ms&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bei identischem, bewusst einfachem Szeneninhalt mit sieben Draw Calls steigt die gemessene Worker-Rasterzeit damit ungefähr um Faktor 4,1. Die Pixelzahl allein erklärt die Skalierung nicht vollständig. Für ein belastbares Kostenmodell müssen als Nächstes Transfer und Primary-Integration separat gemessen werden.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
Die vorhandenen Compute-, Texture-, Raster-, StaticMesh-, World- und QueueProbe-Kommandos bleiben bestehen. Neu hinzugekommen ist:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt;&lt;br /&gt;
| Listet aktive Workloads mit ID, Typ, gewünschter Zuweisung, Priorität, Auflösung, Zielrate, Lifecycle-Statistik und Worker-GPU-Timing auf.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für den aktuellen Hauptpfad sind außerdem besonders relevant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.GetSceneCaptureResolution&lt;br /&gt;
ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&lt;br /&gt;
ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
ExperimentalMultiGPU.StopSceneCaptureStaticMeshSceneStream&lt;br /&gt;
ExperimentalMultiGPU.TestSkeletalMeshWorker&lt;br /&gt;
ExperimentalMultiGPU.ListWorkloads&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine Ziel- beziehungsweise Request-Frequenz. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht. &amp;lt;code&amp;gt;quiet&amp;lt;/code&amp;gt; unterdrückt Per-Job- und Busy-Logspam.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartQueueProbe &amp;amp;lt;Hz&amp;amp;gt; &amp;amp;lt;MaxSubmits&amp;amp;gt; [quiet] &amp;amp;lt;Mode&amp;amp;gt; &amp;amp;lt;Queue&amp;amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Diagnosemodi &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt; bleiben verfügbar. Als Queue können &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; gewählt werden. Private native Queues dienen weiterhin nur der Diagnose und bilden keinen fertigen Experimental-/Direct-Modus.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt; deaktiviert VSync. &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt; erzeugt reproduzierbare Frame-Coupling-Tests; &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt; entfernt das normale Framerate-Limit.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Als Nächstes wird die GPU-Zeit des Transfers vom Worker-ColorTarget in den Shared Cross-Adapter Buffer separat gemessen. Danach folgt das Timing der Primary-SafeCopy. Erst aus den getrennten Blöcken Worker-Raster, Cross-Adapter-Transfer und Primary-Integration soll ein belastbares Kostenmodell V1 entstehen. Dieses bildet anschließend die Grundlage für automatische Primary-/Worker-Zuweisungen; die aktuelle Registry plant bewusst noch nichts selbst.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Die sichtbare Normal-/SafeCopy-/Ready-Kette bleibt an Unreals Submission- und Frame-System gekoppelt. Für sichtbare Outputs ist das akzeptabel; hochfrequente Hintergrundjobs benötigen weitere Architekturtests.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter sichtbarer Runtime-Slot. Mehrere parallele In-Flight-Jobs und Ringbuffer fehlen noch.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Mehrere Worker sind architektonisch vorgesehen, aber noch nicht praktisch validiert.&lt;br /&gt;
* World- und SceneCapture-Pfade verarbeiten pro Snapshot höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* Der Static-Mesh-Pfad verwendet LOD0-Positionen, Normalen und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Culling. Für Cooked/Shipping wird ein eigener Geometrie-Cache oder Build-Schritt benötigt.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen.&lt;br /&gt;
* Die Workload-Registry sammelt Metadaten und Messwerte, führt aber noch keine automatische Zuweisung, Auflösungsänderung oder Ratenanpassung aus.&lt;br /&gt;
* Worker GPU Timing V1 misst nur den Rasterabschnitt. Cross-Adapter-Transfer und Primary-SafeCopy fehlen noch im Kostenmodell.&lt;br /&gt;
* Lifecycle-Raten können im Editor durch Fensterfokus und Background-Throttling verfälscht werden. Für Kostenentscheidungen sind echte GPU-Timestamps und geglättete Mehrfachmessungen maßgeblich.&lt;br /&gt;
* QueueProbe und private native Queues bleiben Diagnosepfade; Experimental/Direct ist noch nicht implementiert.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden. Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden; später Post Process oder neuronale Aufgaben untersuchen.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=192</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=192"/>
		<updated>2026-09-14T18:24:56Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Befehlsreferenz um ListWorkloads ergänzt und gestrafft&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
Die vorhandenen Compute-, Texture-, Raster-, StaticMesh-, World- und QueueProbe-Kommandos bleiben bestehen. Neu hinzugekommen ist:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.ListWorkloads&amp;lt;/code&amp;gt;&lt;br /&gt;
| Listet aktive Workloads mit ID, Typ, gewünschter Zuweisung, Priorität, Auflösung, Zielrate, Lifecycle-Statistik und Worker-GPU-Timing auf.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für den aktuellen Hauptpfad sind außerdem besonders relevant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.GetSceneCaptureResolution&lt;br /&gt;
ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&lt;br /&gt;
ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
ExperimentalMultiGPU.StopSceneCaptureStaticMeshSceneStream&lt;br /&gt;
ExperimentalMultiGPU.TestSkeletalMeshWorker&lt;br /&gt;
ExperimentalMultiGPU.ListWorkloads&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine Ziel- beziehungsweise Request-Frequenz. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht. &amp;lt;code&amp;gt;quiet&amp;lt;/code&amp;gt; unterdrückt Per-Job- und Busy-Logspam.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartQueueProbe &amp;amp;lt;Hz&amp;amp;gt; &amp;amp;lt;MaxSubmits&amp;amp;gt; [quiet] &amp;amp;lt;Mode&amp;amp;gt; &amp;amp;lt;Queue&amp;amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Diagnosemodi &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt; bleiben verfügbar. Als Queue können &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; gewählt werden. Private native Queues dienen weiterhin nur der Diagnose und bilden keinen fertigen Experimental-/Direct-Modus.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt; deaktiviert VSync. &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;60&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;120&amp;lt;/code&amp;gt; erzeugt reproduzierbare Frame-Coupling-Tests; &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt; entfernt das normale Framerate-Limit.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Als Nächstes wird die GPU-Zeit des Transfers vom Worker-ColorTarget in den Shared Cross-Adapter Buffer separat gemessen. Danach folgt das Timing der Primary-SafeCopy. Erst aus den getrennten Blöcken Worker-Raster, Cross-Adapter-Transfer und Primary-Integration soll ein belastbares Kostenmodell V1 entstehen. Dieses bildet anschließend die Grundlage für automatische Primary-/Worker-Zuweisungen; die aktuelle Registry plant bewusst noch nichts selbst.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Die sichtbare Normal-/SafeCopy-/Ready-Kette bleibt an Unreals Submission- und Frame-System gekoppelt. Für sichtbare Outputs ist das akzeptabel; hochfrequente Hintergrundjobs benötigen weitere Architekturtests.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter sichtbarer Runtime-Slot. Mehrere parallele In-Flight-Jobs und Ringbuffer fehlen noch.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Mehrere Worker sind architektonisch vorgesehen, aber noch nicht praktisch validiert.&lt;br /&gt;
* World- und SceneCapture-Pfade verarbeiten pro Snapshot höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* Der Static-Mesh-Pfad verwendet LOD0-Positionen, Normalen und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Culling. Für Cooked/Shipping wird ein eigener Geometrie-Cache oder Build-Schritt benötigt.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen.&lt;br /&gt;
* Die Workload-Registry sammelt Metadaten und Messwerte, führt aber noch keine automatische Zuweisung, Auflösungsänderung oder Ratenanpassung aus.&lt;br /&gt;
* Worker GPU Timing V1 misst nur den Rasterabschnitt. Cross-Adapter-Transfer und Primary-SafeCopy fehlen noch im Kostenmodell.&lt;br /&gt;
* Lifecycle-Raten können im Editor durch Fensterfokus und Background-Throttling verfälscht werden. Für Kostenentscheidungen sind echte GPU-Timestamps und geglättete Mehrfachmessungen maßgeblich.&lt;br /&gt;
* QueueProbe und private native Queues bleiben Diagnosepfade; Experimental/Direct ist noch nicht implementiert.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden. Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden; später Post Process oder neuronale Aufgaben untersuchen.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=191</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=191"/>
		<updated>2026-09-14T18:24:51Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Nächsten Schritt auf Transfer- und SafeCopy-Timing gesetzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt beziehungsweise zeigt die gemeinsame SceneCapture-Auflösung. Erlaubt sind ganzzahlige Werte von 1 bis 4096 je Achse; Änderungen während eines laufenden Streams werden abgelehnt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert das erste sichtbare, getaggte Skeletal Mesh in LOD0 und Reference Pose sectionsweise auf der Worker-GPU.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Als Nächstes wird die GPU-Zeit des Transfers vom Worker-ColorTarget in den Shared Cross-Adapter Buffer separat gemessen. Danach folgt das Timing der Primary-SafeCopy. Erst aus den getrennten Blöcken Worker-Raster, Cross-Adapter-Transfer und Primary-Integration soll ein belastbares Kostenmodell V1 entstehen. Dieses bildet anschließend die Grundlage für automatische Primary-/Worker-Zuweisungen; die aktuelle Registry plant bewusst noch nichts selbst.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Die sichtbare Normal-/SafeCopy-/Ready-Kette bleibt an Unreals Submission- und Frame-System gekoppelt. Für sichtbare Outputs ist das akzeptabel; hochfrequente Hintergrundjobs benötigen weitere Architekturtests.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter sichtbarer Runtime-Slot. Mehrere parallele In-Flight-Jobs und Ringbuffer fehlen noch.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Mehrere Worker sind architektonisch vorgesehen, aber noch nicht praktisch validiert.&lt;br /&gt;
* World- und SceneCapture-Pfade verarbeiten pro Snapshot höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* Der Static-Mesh-Pfad verwendet LOD0-Positionen, Normalen und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Culling. Für Cooked/Shipping wird ein eigener Geometrie-Cache oder Build-Schritt benötigt.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen.&lt;br /&gt;
* Die Workload-Registry sammelt Metadaten und Messwerte, führt aber noch keine automatische Zuweisung, Auflösungsänderung oder Ratenanpassung aus.&lt;br /&gt;
* Worker GPU Timing V1 misst nur den Rasterabschnitt. Cross-Adapter-Transfer und Primary-SafeCopy fehlen noch im Kostenmodell.&lt;br /&gt;
* Lifecycle-Raten können im Editor durch Fensterfokus und Background-Throttling verfälscht werden. Für Kostenentscheidungen sind echte GPU-Timestamps und geglättete Mehrfachmessungen maßgeblich.&lt;br /&gt;
* QueueProbe und private native Queues bleiben Diagnosepfade; Experimental/Direct ist noch nicht implementiert.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden. Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden; später Post Process oder neuronale Aufgaben untersuchen.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=190</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=190"/>
		<updated>2026-09-14T18:24:46Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Bekannte Grenzen an Workload- und Timing-Stand angepasst&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt beziehungsweise zeigt die gemeinsame SceneCapture-Auflösung. Erlaubt sind ganzzahlige Werte von 1 bis 4096 je Achse; Änderungen während eines laufenden Streams werden abgelehnt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert das erste sichtbare, getaggte Skeletal Mesh in LOD0 und Reference Pose sectionsweise auf der Worker-GPU.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der Live-SceneCapture-Kanal ist funktional nachgewiesen, frei von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 geprüft. Der nächste Produktmeilenstein ist ein echter Nutzlast-Proof als CCTV, Spiegel oder Minimap. Beim Skeletal Mesh folgen Bone-Matrizen, Skin Weights und Animation. Parallel bleiben Material-/Textur-Bindings, Culling, Cross-Vendor-Tests und ein späterer Autotuner offen. QueueProbe bleibt ein Diagnosewerkzeug; Experimental/Direct, Nanite, Lumen und automatische Workload-Verteilung sind eigenständige Ausbaustufen.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Die sichtbare Normal-/SafeCopy-/Ready-Kette bleibt an Unreals Submission- und Frame-System gekoppelt. Für sichtbare Outputs ist das akzeptabel; hochfrequente Hintergrundjobs benötigen weitere Architekturtests.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter sichtbarer Runtime-Slot. Mehrere parallele In-Flight-Jobs und Ringbuffer fehlen noch.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Mehrere Worker sind architektonisch vorgesehen, aber noch nicht praktisch validiert.&lt;br /&gt;
* World- und SceneCapture-Pfade verarbeiten pro Snapshot höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s.&lt;br /&gt;
* Der Static-Mesh-Pfad verwendet LOD0-Positionen, Normalen und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Culling. Für Cooked/Shipping wird ein eigener Geometrie-Cache oder Build-Schritt benötigt.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen.&lt;br /&gt;
* Die Workload-Registry sammelt Metadaten und Messwerte, führt aber noch keine automatische Zuweisung, Auflösungsänderung oder Ratenanpassung aus.&lt;br /&gt;
* Worker GPU Timing V1 misst nur den Rasterabschnitt. Cross-Adapter-Transfer und Primary-SafeCopy fehlen noch im Kostenmodell.&lt;br /&gt;
* Lifecycle-Raten können im Editor durch Fensterfokus und Background-Throttling verfälscht werden. Für Kostenentscheidungen sind echte GPU-Timestamps und geglättete Mehrfachmessungen maßgeblich.&lt;br /&gt;
* QueueProbe und private native Queues bleiben Diagnosepfade; Experimental/Direct ist noch nicht implementiert.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden. Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden; später Post Process oder neuronale Aufgaben untersuchen.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=189</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=189"/>
		<updated>2026-09-14T18:24:40Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Roadmap um getrennte Timing-Blöcke und Kostenmodell ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt beziehungsweise zeigt die gemeinsame SceneCapture-Auflösung. Erlaubt sind ganzzahlige Werte von 1 bis 4096 je Achse; Änderungen während eines laufenden Streams werden abgelehnt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert das erste sichtbare, getaggte Skeletal Mesh in LOD0 und Reference Pose sectionsweise auf der Worker-GPU.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der Live-SceneCapture-Kanal ist funktional nachgewiesen, frei von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 geprüft. Der nächste Produktmeilenstein ist ein echter Nutzlast-Proof als CCTV, Spiegel oder Minimap. Beim Skeletal Mesh folgen Bone-Matrizen, Skin Weights und Animation. Parallel bleiben Material-/Textur-Bindings, Culling, Cross-Vendor-Tests und ein späterer Autotuner offen. QueueProbe bleibt ein Diagnosewerkzeug; Experimental/Direct, Nanite, Lumen und automatische Workload-Verteilung sind eigenständige Ausbaustufen.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel. Der sichtbare Runtime-Pfad ist über dynamische Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein vollständiger Pixel-Readback für jede dynamische Größe ist kein Bestandteil des Normal-Pfads.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Raster3D, einzelne UE-Static-Meshes, die Drei-Mesh-Szene sowie WorldStaticMeshScene sind sichtbar nachgewiesen. World- und SceneCapture-Pfade besitzen laufende Streams; pro Snapshot werden weiterhin höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s verarbeitet.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen noch.&lt;br /&gt;
* Der Static-Mesh-Pfad verarbeitet weiterhin LOD0-POSITION/NORMAL-Daten und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Frustum-/Occlusion-Culling. Mehrere Sections sind bislang nur im Skeletal-Mesh-Proof gezeigt. Für Cooked/Shipping muss der Zugriff auf benötigte Geometrie über einen eigenen Cache oder Build-Schritt abgesichert werden.&lt;br /&gt;
* Der SceneCapture-Output ist von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 getestet. RGBA8 ist fest; andere Formate, MSAA und produktive Resolution-Policies fehlen noch.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil des Engine-Commits &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Cross-Adapter Transfer Timing V1: Worker-ColorTarget → Shared Buffer separat messen.&lt;br /&gt;
# Primary SafeCopy Timing ergänzen und die Integrationskosten getrennt halten.&lt;br /&gt;
# Kostenmodell V1 aus Worker-Raster, Transfer und Primary-Integration pro Workload ableiten.&lt;br /&gt;
# Weitere echte Workload-Klassen wie CCTV, Spiegel, Minimap und Compute anbinden; später Post Process oder neuronale Aufgaben untersuchen.&lt;br /&gt;
# D3D12-Pfade mit Intel Arc A750/A380 und RX 6900 XT in unterschiedlichen Primary-/Worker-Rollen gegenprüfen.&lt;br /&gt;
# Scheduler und Autotuner auf GPU-Eignung und gemessene Nettokosten statt Auslastungsprozent aufbauen.&lt;br /&gt;
# Material-, Textur- und Culling-Pfade für realistischere Worker-Szenen ergänzen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights erst bei einem echten animierten Worker-Workload ausbauen.&lt;br /&gt;
# Einen softwareseitigen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM, RAM und später Storage untersuchen.&lt;br /&gt;
# Experimental-/Direct-Fast-Path nur mit State-Tracking, Residency, Hazards und sicherem Fallback entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=188</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=188"/>
		<updated>2026-09-14T18:24:35Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Git-Checkpoint 37c6d02 dokumentiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt beziehungsweise zeigt die gemeinsame SceneCapture-Auflösung. Erlaubt sind ganzzahlige Werte von 1 bis 4096 je Achse; Änderungen während eines laufenden Streams werden abgelehnt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert das erste sichtbare, getaggte Skeletal Mesh in LOD0 und Reference Pose sectionsweise auf der Worker-GPU.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der Live-SceneCapture-Kanal ist funktional nachgewiesen, frei von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 geprüft. Der nächste Produktmeilenstein ist ein echter Nutzlast-Proof als CCTV, Spiegel oder Minimap. Beim Skeletal Mesh folgen Bone-Matrizen, Skin Weights und Animation. Parallel bleiben Material-/Textur-Bindings, Culling, Cross-Vendor-Tests und ein späterer Autotuner offen. QueueProbe bleibt ein Diagnosewerkzeug; Experimental/Direct, Nanite, Lumen und automatische Workload-Verteilung sind eigenständige Ausbaustufen.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel. Der sichtbare Runtime-Pfad ist über dynamische Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein vollständiger Pixel-Readback für jede dynamische Größe ist kein Bestandteil des Normal-Pfads.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Raster3D, einzelne UE-Static-Meshes, die Drei-Mesh-Szene sowie WorldStaticMeshScene sind sichtbar nachgewiesen. World- und SceneCapture-Pfade besitzen laufende Streams; pro Snapshot werden weiterhin höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s verarbeitet.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen noch.&lt;br /&gt;
* Der Static-Mesh-Pfad verarbeitet weiterhin LOD0-POSITION/NORMAL-Daten und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Frustum-/Occlusion-Culling. Mehrere Sections sind bislang nur im Skeletal-Mesh-Proof gezeigt. Für Cooked/Shipping muss der Zugriff auf benötigte Geometrie über einen eigenen Cache oder Build-Schritt abgesichert werden.&lt;br /&gt;
* Der SceneCapture-Output ist von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 getestet. RGBA8 ist fest; andere Formate, MSAA und produktive Resolution-Policies fehlen noch.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil des Engine-Commits &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Einen echten Nutzlast-Proof als CCTV, Spiegel oder Minimap aufbauen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights anbinden und Quinn von der Reference Pose zur laufenden Animation bringen.&lt;br /&gt;
# Mehrere Mesh-Sections, Material-/Textur-Bindings und anschließend Culling ergänzen.&lt;br /&gt;
# D3D12-Adapter-, Raster- und SceneCapture-Pfade auf Intel Arc A750/A380 und später mit RX 6900 XT als Primary gegenprüfen.&lt;br /&gt;
# Microbenchmarks und echte Workloads zu einem Autotuner für sinnvolle GPU-Paare und Jobzahlen ausbauen.&lt;br /&gt;
# Experimental-/Direct-Architektur mit State-Tracking, Residency, Hazards, Capability-Selftest und automatischem Fallback entwerfen.&lt;br /&gt;
# Mehrere Runtime-Slots beziehungsweise einen Ringbuffer erst bei echtem Workload-Bedarf ergänzen.&lt;br /&gt;
# Langfristig einen Engine-eigenen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM und RAM untersuchen; kein transparenter gemeinsamer Hardware-VRAM.&lt;br /&gt;
# Linux/Vulkan mit External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der aktuelle Engine-Checkpoint &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; trägt die Nachricht &amp;lt;code&amp;gt;Extend worker capture and workload instrumentation&amp;lt;/code&amp;gt; und folgt auf &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;). Er umfasst acht Dateien mit 877 Einfügungen und 26 Löschungen. Enthalten sind der seit dem vorherigen Checkpoint weiterentwickelte Engine-Stand mit dynamischer SceneCapture-Auflösung, Scheduler-/Polling-Korrektur, SkeletalMesh-ReferencePose, generischer Workload-Registry, Runtime Metrics V1 und Worker GPU Timing V1. Ein Push wurde in diesem Dokumentationsschritt nicht ausgeführt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=187</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=187"/>
		<updated>2026-09-14T18:24:29Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Quellenstand auf Commit 37c6d02 aktualisiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt beziehungsweise zeigt die gemeinsame SceneCapture-Auflösung. Erlaubt sind ganzzahlige Werte von 1 bis 4096 je Achse; Änderungen während eines laufenden Streams werden abgelehnt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert das erste sichtbare, getaggte Skeletal Mesh in LOD0 und Reference Pose sectionsweise auf der Worker-GPU.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der Live-SceneCapture-Kanal ist funktional nachgewiesen, frei von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 geprüft. Der nächste Produktmeilenstein ist ein echter Nutzlast-Proof als CCTV, Spiegel oder Minimap. Beim Skeletal Mesh folgen Bone-Matrizen, Skin Weights und Animation. Parallel bleiben Material-/Textur-Bindings, Culling, Cross-Vendor-Tests und ein späterer Autotuner offen. QueueProbe bleibt ein Diagnosewerkzeug; Experimental/Direct, Nanite, Lumen und automatische Workload-Verteilung sind eigenständige Ausbaustufen.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel. Der sichtbare Runtime-Pfad ist über dynamische Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein vollständiger Pixel-Readback für jede dynamische Größe ist kein Bestandteil des Normal-Pfads.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Raster3D, einzelne UE-Static-Meshes, die Drei-Mesh-Szene sowie WorldStaticMeshScene sind sichtbar nachgewiesen. World- und SceneCapture-Pfade besitzen laufende Streams; pro Snapshot werden weiterhin höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s verarbeitet.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen noch.&lt;br /&gt;
* Der Static-Mesh-Pfad verarbeitet weiterhin LOD0-POSITION/NORMAL-Daten und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Frustum-/Occlusion-Culling. Mehrere Sections sind bislang nur im Skeletal-Mesh-Proof gezeigt. Für Cooked/Shipping muss der Zugriff auf benötigte Geometrie über einen eigenen Cache oder Build-Schritt abgesichert werden.&lt;br /&gt;
* Der SceneCapture-Output ist von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 getestet. RGBA8 ist fest; andere Formate, MSAA und produktive Resolution-Policies fehlen noch.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil des Engine-Commits &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Einen echten Nutzlast-Proof als CCTV, Spiegel oder Minimap aufbauen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights anbinden und Quinn von der Reference Pose zur laufenden Animation bringen.&lt;br /&gt;
# Mehrere Mesh-Sections, Material-/Textur-Bindings und anschließend Culling ergänzen.&lt;br /&gt;
# D3D12-Adapter-, Raster- und SceneCapture-Pfade auf Intel Arc A750/A380 und später mit RX 6900 XT als Primary gegenprüfen.&lt;br /&gt;
# Microbenchmarks und echte Workloads zu einem Autotuner für sinnvolle GPU-Paare und Jobzahlen ausbauen.&lt;br /&gt;
# Experimental-/Direct-Architektur mit State-Tracking, Residency, Hazards, Capability-Selftest und automatischem Fallback entwerfen.&lt;br /&gt;
# Mehrere Runtime-Slots beziehungsweise einen Ringbuffer erst bei echtem Workload-Bedarf ergänzen.&lt;br /&gt;
# Langfristig einen Engine-eigenen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM und RAM untersuchen; kein transparenter gemeinsamer Hardware-VRAM.&lt;br /&gt;
# Linux/Vulkan mit External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der letzte Engine-Checkpoint &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; mit der Nachricht &amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt; folgt auf &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;. Er umfasst 13 Dateien mit 4443 Einfügungen und 11 Löschungen. Enthalten sind Raster3D, StaticMesh-, Multi-Mesh-, WorldScene- und Live-SceneCapture-Enginepfade. Die projektseitige Datei &amp;lt;code&amp;gt;UpscalerTest/Private/ExperimentalMultiGPUDisplayActor.cpp&amp;lt;/code&amp;gt; liegt außerhalb des Engine-Repositories und ist daher nicht Teil des Commits. Binaries, Intermediate-, Cache-, Saved- und Log-Dateien wurden nicht aufgenommen. Seit diesem Checkpoint wurden Dynamic Resolution, der SceneCapture-Scheduler-/Polling-Fix, der 4K60-Stresstest und der SkeletalMesh-ReferencePose-Proof weiterentwickelt; diese Änderungen sind zum Stand vom 12. September 2026 noch nicht als neuer Engine-Commit dokumentiert. Ein Push erfolgte nicht.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 14. September 2026; Commit &amp;lt;code&amp;gt;37c6d02&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Neu belegt sind Workload-Registry, Runtime Metrics V1 und native D3D12-Timestamp-Messungen des Worker-Rasterabschnitts.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing Microsoft: Timing und Timestamp Queries in Direct3D 12]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=186</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=186"/>
		<updated>2026-09-12T19:38:40Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Entwicklungsstand 12.09.2026: Dynamic Resolution, Scheduler-Fix, 4K60 und SkeletalMesh-ReferencePose&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 12. September 2026. Letzter Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;. Dynamische SceneCapture-Auflösung, Scheduler-Korrektur und SkeletalMesh-ReferencePose gehören zum neueren, noch nicht als eigener Commit dokumentierten Working State. Der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A750 und Arc A380 als zusätzliche dGPU-Worker-Gegenchecks vorgesehen; belastbare Messwerte liegen noch nicht vor&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; neuerer Working State mit Dynamic Resolution, Scheduler-Fix und SkeletalMesh-ReferencePose; nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static und Skeletal Meshes sowie eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; dynamisch bis 3840×2160 und 4K60 mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Dynamische SceneCapture-Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Die SceneCapture-Ausgabe ist nicht mehr fest auf 128×96 Pixel begrenzt. &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; setzt ganzzahlige Dimensionen von 1 bis 4096; &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt; zeigt die aktive Einstellung. 128×96 bleibt der Standard. Während ein SceneCapture-Stream läuft, wird ein Auflösungswechsel absichtlich abgelehnt, damit keine In-Flight-Ressourcen ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
Color Target, D32-Depth-Buffer, Row Pitch, Shared-Buffer-Transport, SafeCopy, persistente Primary-Textur und &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; übernehmen die gewählten Dimensionen. Projektion und Display-Plane verwenden das echte Seitenverhältnis. Die bestätigte Anzeigeorientierung &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt; bleibt eine reine Presentation-Korrektur; Worker-Basis und Kameramathematik ändern sich nicht.&lt;br /&gt;
&lt;br /&gt;
=== Scheduler-Korrektur bei SceneCapture ===&lt;br /&gt;
&lt;br /&gt;
Ein 1920×1080-Test mit 25 Hz erreichte zunächst trotz fehlerfreier Frames nur 13,90 Ready-Hz und erzeugte 222 Busy-Ticks. Ursache war kein GPU-Limit, sondern ein Polling-Aliasing: Eine frühe Game-Thread-Prüfung konnte den Timer-Slot verwerfen, obwohl die Completion kurz darauf im CoreTicker/RHI-Pump sichtbar geworden wäre.&lt;br /&gt;
&lt;br /&gt;
Die frühe &amp;lt;code&amp;gt;IsRuntimeTextureUpdateInFlight()&amp;lt;/code&amp;gt;-Prüfung wurde für diesen Stream entfernt. Der Pending-Request bleibt als Backpressure-Gate erhalten; die maßgebliche Busy-Entscheidung fällt nun erst im Render Command nach &amp;lt;code&amp;gt;TickNormalTextureTransfers(nullptr, true)&amp;lt;/code&amp;gt;. Single-Slot, POD-Snapshots und non-blocking &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; bleiben erhalten. Es wurden weder CPU-Waits noch zusätzliche Threads eingeführt.&lt;br /&gt;
&lt;br /&gt;
Nach der Korrektur erreicht 1080p bei 25 Hz 24,79 Ready-Hz mit 1 Busy; bei 30 Hz sind es 29,43 Ready-Hz mit 4 Busy.&lt;br /&gt;
&lt;br /&gt;
=== Skalierung bis 4K60 ===&lt;br /&gt;
&lt;br /&gt;
Die Pipeline wurde von 640×360 bis 3840×2160 getestet. Bei 640×360/30 Hz und 1280×720/30 Hz wurden 29,85 beziehungsweise 29,82 Ready-Hz ohne Busy erreicht. 1920×1080/60 Hz lieferte 59,40 Ready-Hz ohne Busy, 2560×1440/60 Hz 59,21 Ready-Hz mit 1 Busy und 3840×2160/60 Hz 59,02 Ready-Hz mit 2 Busy.&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher 4K60-Stresstest mit acht Static-Mesh-Instanzen und drei gecachten Unique Meshes erreichte in 5,049 Sekunden &#039;&#039;&#039;300 von 300 Ready-Frames, 0 Busy, 0 Fehler und 59,42 effektive Ready-Hz&#039;&#039;&#039;. Acht Draw Calls, gemeinsamer Depth Buffer, Cross-Adapter-Transport und SafeCopy liefen dabei im vorhandenen Single-Slot. Das ist ein Stabilitätsnachweis der aktuellen Mini-Szene, kein allgemeiner GPU-Benchmark.&lt;br /&gt;
&lt;br /&gt;
=== Skeletal Mesh in Reference Pose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt; erweitert den Geometriepfad auf &amp;lt;code&amp;gt;USkeletalMeshComponent&amp;lt;/code&amp;gt;. Der Engine-Layer sucht deterministisch die erste sichtbare, getaggte Komponente und extrahiert LOD0-Positionen, Normalen, Indices und Render Sections. D3D12RHI erhält wie bisher ausschließlich POD-Geometrie und Modelmatrizen.&lt;br /&gt;
&lt;br /&gt;
Der sichtbare Test mit &amp;lt;code&amp;gt;SKM_Quinn_Simple&amp;lt;/code&amp;gt; rendert Quinn in der Reference Pose mit &#039;&#039;&#039;45.993 Vertices, 261.840 Indices, zwei Sections und zwei Draw Calls&#039;&#039;&#039;. Die beiden Sections umfassen 35.612 und 51.668 Dreiecke. Worker-VB/IB, gemeinsamer D32-Depth-Buffer, dynamische Auflösung, Cross-Adapter-Transport und Normal/SafeCopy werden wiederverwendet.&lt;br /&gt;
&lt;br /&gt;
Eine Reference Pose ist die unverformte Ausgangshaltung des Skeletal Meshes. Bone-Matrizen, Skin Weights, laufende Animationen, Morph Targets und Cloth sind noch nicht angebunden. Der nächste Geometrieschritt ist daher echtes Worker-Skinning.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SetSceneCaptureResolution &amp;amp;lt;Width&amp;amp;gt; &amp;amp;lt;Height&amp;amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;GetSceneCaptureResolution&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt beziehungsweise zeigt die gemeinsame SceneCapture-Auflösung. Erlaubt sind ganzzahlige Werte von 1 bis 4096 je Achse; Änderungen während eines laufenden Streams werden abgelehnt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSkeletalMeshWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert das erste sichtbare, getaggte Skeletal Mesh in LOD0 und Reference Pose sectionsweise auf der Worker-GPU.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der Live-SceneCapture-Kanal ist funktional nachgewiesen, frei von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 geprüft. Der nächste Produktmeilenstein ist ein echter Nutzlast-Proof als CCTV, Spiegel oder Minimap. Beim Skeletal Mesh folgen Bone-Matrizen, Skin Weights und Animation. Parallel bleiben Material-/Textur-Bindings, Culling, Cross-Vendor-Tests und ein späterer Autotuner offen. QueueProbe bleibt ein Diagnosewerkzeug; Experimental/Direct, Nanite, Lumen und automatische Workload-Verteilung sind eigenständige Ausbaustufen.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel. Der sichtbare Runtime-Pfad ist über dynamische Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein vollständiger Pixel-Readback für jede dynamische Größe ist kein Bestandteil des Normal-Pfads.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Raster3D, einzelne UE-Static-Meshes, die Drei-Mesh-Szene sowie WorldStaticMeshScene sind sichtbar nachgewiesen. World- und SceneCapture-Pfade besitzen laufende Streams; pro Snapshot werden weiterhin höchstens acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s verarbeitet.&lt;br /&gt;
* &amp;lt;code&amp;gt;USkeletalMesh&amp;lt;/code&amp;gt; ist bislang ein LOD0-ReferencePose-Proof. Bone-Skinning, Animation, Morph Targets und Cloth fehlen noch.&lt;br /&gt;
* Der Static-Mesh-Pfad verarbeitet weiterhin LOD0-POSITION/NORMAL-Daten und Indices ohne UE-Materialien, Texturen, Beleuchtung, Schatten, Nanite, Lumen oder Frustum-/Occlusion-Culling. Mehrere Sections sind bislang nur im Skeletal-Mesh-Proof gezeigt. Für Cooked/Shipping muss der Zugriff auf benötigte Geometrie über einen eigenen Cache oder Build-Schritt abgesichert werden.&lt;br /&gt;
* Der SceneCapture-Output ist von 1×1 bis 4096×4096 konfigurierbar und sichtbar bis 3840×2160 getestet. RGBA8 ist fest; andere Formate, MSAA und produktive Resolution-Policies fehlen noch.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil des Engine-Commits &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Einen echten Nutzlast-Proof als CCTV, Spiegel oder Minimap aufbauen.&lt;br /&gt;
# Skeletal Skinning mit Bone-Matrizen und Skin Weights anbinden und Quinn von der Reference Pose zur laufenden Animation bringen.&lt;br /&gt;
# Mehrere Mesh-Sections, Material-/Textur-Bindings und anschließend Culling ergänzen.&lt;br /&gt;
# D3D12-Adapter-, Raster- und SceneCapture-Pfade auf Intel Arc A750/A380 und später mit RX 6900 XT als Primary gegenprüfen.&lt;br /&gt;
# Microbenchmarks und echte Workloads zu einem Autotuner für sinnvolle GPU-Paare und Jobzahlen ausbauen.&lt;br /&gt;
# Experimental-/Direct-Architektur mit State-Tracking, Residency, Hazards, Capability-Selftest und automatischem Fallback entwerfen.&lt;br /&gt;
# Mehrere Runtime-Slots beziehungsweise einen Ringbuffer erst bei echtem Workload-Bedarf ergänzen.&lt;br /&gt;
# Langfristig einen Engine-eigenen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM und RAM untersuchen; kein transparenter gemeinsamer Hardware-VRAM.&lt;br /&gt;
# Linux/Vulkan mit External Memory und externen Semaphoren/Fences untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der letzte Engine-Checkpoint &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; mit der Nachricht &amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt; folgt auf &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;. Er umfasst 13 Dateien mit 4443 Einfügungen und 11 Löschungen. Enthalten sind Raster3D, StaticMesh-, Multi-Mesh-, WorldScene- und Live-SceneCapture-Enginepfade. Die projektseitige Datei &amp;lt;code&amp;gt;UpscalerTest/Private/ExperimentalMultiGPUDisplayActor.cpp&amp;lt;/code&amp;gt; liegt außerhalb des Engine-Repositories und ist daher nicht Teil des Commits. Binaries, Intermediate-, Cache-, Saved- und Log-Dateien wurden nicht aufgenommen. Seit diesem Checkpoint wurden Dynamic Resolution, der SceneCapture-Scheduler-/Polling-Fix, der 4K60-Stresstest und der SkeletalMesh-ReferencePose-Proof weiterentwickelt; diese Änderungen sind zum Stand vom 12. September 2026 noch nicht als neuer Engine-Commit dokumentiert. Ein Push erfolgte nicht.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 12. September 2026; letzter Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; plus neuerer Working State. WorldStaticMeshScene, dynamische SceneCapture-Auflösung bis 4K60 und der SkeletalMesh-ReferencePose-Pfad sind sichtbar im PIE-Level getestet.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=185</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=185"/>
		<updated>2026-09-09T23:58:32Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Entwicklungsstand 10.09.2026: Live-World- und SceneCapture-Workerpfad, Commit 45d5c27&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 10. September 2026. Engine-Checkpoint: &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt;) auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; der Engine-Working-Tree war danach sauber, der Commit wurde noch nicht gepusht. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A380 als zusätzlicher dGPU-Worker-Gegencheck vorgesehen&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;; Engine-Working-Tree danach sauber, nicht gepusht&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Durchgängiger sichtbarer Worker-Rasterpfad von der laufenden UE-Welt über getaggte Static Meshes und eine echte SceneCapture2D-Kamera bis zur persistenten UE-Textur; Live-Stream mit 300/300 Ready-Frames nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden im Game Thread in reine POD-Strukturen und 4×4-Matrizen kopiert. D3D12RHI erhält keine &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer. Mehrere Instanzen desselben Meshes teilen den persistenten Worker-Mesh-Cache und unterscheiden sich nur durch Modelmatrix und Draw Call.&lt;br /&gt;
&lt;br /&gt;
Der Pfad wurde inzwischen sichtbar im PIE-Level verifiziert. Drei getaggte Static-Mesh-Actors erschienen mit ihren tatsächlichen relativen Positionen, Rotationen und Skalierungen im Worker-Bild. Die zentrale Koordinatenumrechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Worker (X, Y, Z) = (UE Y, UE X, -UE Z)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Transformation besitzt die Determinante +1 und ist damit keine Spiegelung. Das notwendige horizontale Spiegeln erfolgt ausschließlich auf der Presentation-Plane, nicht im Worker-Renderpfad.&lt;br /&gt;
&lt;br /&gt;
=== Kontinuierlicher WorldStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartWorldStaticMeshSceneStream&amp;lt;/code&amp;gt; erfasst die getaggte Szene fortlaufend im Game Thread. Reine Änderungen an Transform oder Kamera lösen keinen erneuten Mesh-Upload aus. Hinzugekommene, entfernte, unsichtbare oder umgetaggte Components werden im nächsten Snapshot berücksichtigt. Single-Slot-Backpressure verhindert einen wachsenden Rückstau.&lt;br /&gt;
&lt;br /&gt;
Ein verifizierter 30-Hz-Lauf endete nach 31,184 Sekunden mit 835 Ticks, 691 angenommenen Submits, 144 Busy, 0 Fehlern und 691 Ready-Frames. Die effektive Ready-Rate betrug 22,16 Hz. Dieser Test belegt die funktionale Live-Aktualisierung; die Rate war noch kein Optimierungsziel.&lt;br /&gt;
&lt;br /&gt;
=== SceneCapture2D als Worker-Kamera ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt; verwendet eine echte &amp;lt;code&amp;gt;ASceneCapture2D&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;USceneCaptureComponent2D&amp;lt;/code&amp;gt; aus der laufenden PIE-Welt als Kameraquelle. Der empfohlene Editor-Weg ist das Component Tag &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; auf der &amp;lt;code&amp;gt;CaptureComponent2D&amp;lt;/code&amp;gt;; ein gleichnamiges Actor-Tag bleibt nur als Legacy-Fallback.&lt;br /&gt;
&lt;br /&gt;
Ausgelesen werden World Location, Rotation, Forward/Right/Up, &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;ProjectionType&amp;lt;/code&amp;gt;. Orthografische Projektion wird derzeit sauber abgelehnt. Die SceneCapture2D liefert ausschließlich Kameradaten: Ihr UE-RenderTarget wird weder gelesen noch kopiert. Die Intel-Worker-GPU rendert die Geometrie selbst. Kamera und Actors werden gemeinsam mit &amp;lt;code&amp;gt;SceneScale = 0.01&amp;lt;/code&amp;gt; in Worker-Koordinaten überführt; Auto-Fit und Scene-Recentering sind in diesem Modus deaktiviert.&lt;br /&gt;
&lt;br /&gt;
Die 128×96-Worker-Projektion verwendet ein Seitenverhältnis von 4:3 und interpretiert &amp;lt;code&amp;gt;FOVAngle&amp;lt;/code&amp;gt; als horizontales FOV. Nach den Orientierungstests wird nur die Anzeige über &amp;lt;code&amp;gt;SetRelativeScale3D(FVector(-4.0f, -3.0f, 1.0f))&amp;lt;/code&amp;gt; korrigiert; dies entspricht &amp;lt;code&amp;gt;U&#039; = 1-U&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;V&#039; = 1-V&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Live SceneCaptureStaticMeshSceneStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StartSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt; liest Kamera-Transform, Kamerabasis, FOV und aktuelle Actor-Transforms pro Snapshot neu im Game Thread. Der Worker erhält weiterhin ausschließlich POD-Daten, verwendet den persistenten Mesh-Cache sowie ein gemeinsames Color- und D32-Depth-Target und führt pro akzeptiertem Frame genau einen Cross-Adapter-/Normal-SafeCopy-Transfer aus.&lt;br /&gt;
&lt;br /&gt;
Der Quiet-Test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream 30 300 quiet&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
lieferte in 10,084 Sekunden 301 Ticks, 300 Submits, 1 Busy, 0 Fehler und 300 Ready-Frames. Die effektive Ready-Rate betrug 29,75 Hz. Bewegungen der Kamera und Actors sowie FOV-Änderungen erschienen live auf der Display-Plane. Damit ist erstmals ein kleiner SceneCapture-/CCTV-artiger Worker-Kanal vollständig funktional nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen POD-Snapshot der sichtbaren, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten StaticMeshComponents aus der laufenden World. Der sichtbare PIE-Nachweis ist erfolgreich.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartWorldStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopWorldStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Stream der getaggten UE-Welt mit Live-Transforms und persistentem Mesh-Cache.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestSceneCaptureStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einen einmaligen Worker-Snapshot aus Sicht der mit &amp;lt;code&amp;gt;MultiGPUWorkerCamera&amp;lt;/code&amp;gt; markierten SceneCapture2D-Kamera.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartSceneCaptureStaticMeshSceneStream [Hz] [MaxSuccessfulSubmits] [quiet]&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;StopSceneCaptureStaticMeshSceneStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den Live-Worker-Kanal mit fortlaufend aktualisierten Kamera-, FOV- und Actor-Daten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der Live-SceneCapture-Kanal ist funktional nachgewiesen. Als nächstes soll die feste 128×96-Ausgabe durch eine konfigurierbare Capture-Auflösung ersetzt werden. Danach folgt ein erster echter Nutzlast-Proof als CCTV, Spiegel oder Minimap. Parallel bleiben mehrere Mesh-Sections, Material-/Textur-Bindings und späteres Culling offen. QueueProbe bleibt ein Diagnosewerkzeug; Experimental/Direct, Nanite, Lumen und automatische Workload-Verteilung sind spätere eigenständige Ausbaustufen.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der sichtbare Worker-Output ist derzeit auf 128×96 Pixel in &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1 begrenzt. Konfigurierbare Auflösung, weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Raster3D, einzelne UE-Static-Meshes, die Drei-Mesh-Szene sowie WorldStaticMeshScene sind sichtbar nachgewiesen. World- und SceneCapture-Pfade besitzen inzwischen laufende Streams; pro Snapshot werden weiterhin höchstens acht sichtbare StaticMeshComponents verarbeitet.&lt;br /&gt;
* Der Worker übernimmt weiterhin nur LOD0-POSITION/NORMAL-Daten und Indices. Materialien, Texturen, Mesh-Sections, Beleuchtung, Schatten, Skeletal Meshes, Nanite, Lumen sowie Frustum-/Occlusion-Culling fehlen. Für Cooked/Shipping muss der Zugriff auf benötigte Geometrie über einen eigenen Cache oder Build-Schritt abgesichert werden.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil von Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Worker-Target und Transport auf frei wählbare SceneCapture-Auflösungen erweitern.&lt;br /&gt;
# CCTV, Spiegel oder Minimap als ersten realen, unabhängigen Worker-Workload umsetzen.&lt;br /&gt;
# Mehrere Mesh-Sections, Material-/Textur-Bindings und später Culling ergänzen, ohne die POD-/Worker-Trennung aufzugeben.&lt;br /&gt;
# D3D12-Adapter-, Raster- und SceneCapture-Pfade auf der Intel Arc A380 und später mit RX 6900 XT als Primary gegenprüfen.&lt;br /&gt;
# Microbenchmarks und reale Workloads zu einem Benchmark-/Autotuner ausbauen, der den Netto-Nutzen pro GPU-Paar bewertet.&lt;br /&gt;
# Nach Portierung des eigentlichen Projekts schwere UE-Demos wie Electric Dreams und später Lumen in the Land of Nanite als Stresstest verwenden.&lt;br /&gt;
# Einen Multi-Tier Resource Manager für Primary-VRAM, Worker-VRAM und RAM mit Cache, Prefetch und Duplizierung untersuchen; dies ist keine transparente gemeinsame Hardware-VRAM-Lösung.&lt;br /&gt;
# Experimental-/Direct nur mit State-Tracking, Residency, Queue-Reihenfolge, Capability-Selbsttest und Session-Fallback auf Normal entwickeln.&lt;br /&gt;
# Weitere Runtime-Slots oder Ringbuffer erst bei echtem Bedarf und mit gelöstem Generation-, Fence-, Reuse- und Consumer-Hazard-Modell ergänzen.&lt;br /&gt;
# Capability-Matrix, Scheduler, manuelle Overrides und mehrere Worker-GPUs entwickeln.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Git-Checkpoint ==&lt;br /&gt;
&lt;br /&gt;
Der Engine-Checkpoint &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt; mit der Nachricht &amp;lt;code&amp;gt;Add live SceneCapture worker rendering pipeline&amp;lt;/code&amp;gt; folgt auf &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;. Er umfasst 13 Dateien mit 4443 Einfügungen und 11 Löschungen. Enthalten sind Raster3D, StaticMesh-, Multi-Mesh-, WorldScene- und Live-SceneCapture-Enginepfade. Die projektseitige Datei &amp;lt;code&amp;gt;UpscalerTest/Private/ExperimentalMultiGPUDisplayActor.cpp&amp;lt;/code&amp;gt; liegt außerhalb des Engine-Repositories und ist daher nicht Teil des Commits. Binaries, Intermediate-, Cache-, Saved- und Log-Dateien wurden nicht aufgenommen. Der Engine-Working-Tree war nach dem Commit sauber; ein Push erfolgte nicht.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 10. September 2026; Commit &amp;lt;code&amp;gt;45d5c27&amp;lt;/code&amp;gt;. WorldStaticMeshScene, WorldStaticMeshSceneStream und der SceneCaptureStaticMeshSceneStream sind sichtbar im PIE-Level getestet.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Seitliches_Rutschen_nach_dem_Sprint_beheben&amp;diff=184</id>
		<title>Seitliches Rutschen nach dem Sprint beheben</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Seitliches_Rutschen_nach_dem_Sprint_beheben&amp;diff=184"/>
		<updated>2026-09-09T23:49:49Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „Beim Wechsel vom Sprint zurück zur normalen Laufgeschwindigkeit kann ein Charakter in Kurven kurz seitlich über den Boden rutschen. Diese Anleitung zeigt, wie sich die Bewegungsrichtung während des Abbremsens korrigieren lässt, ohne Sprünge oder die Schwerkraft zu beeinflussen.  == Das Problem ==  Im beschriebenen Blueprint wird die Laufgeschwindigkeit mit einer Timeline weich verändert:  * normale Laufgeschwindigkeit: &amp;lt;code&amp;gt;500 cm/s&amp;lt;/code&amp;gt; * Sprint…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beim Wechsel vom Sprint zurück zur normalen Laufgeschwindigkeit kann ein Charakter in Kurven kurz seitlich über den Boden rutschen. Diese Anleitung zeigt, wie sich die Bewegungsrichtung während des Abbremsens korrigieren lässt, ohne Sprünge oder die Schwerkraft zu beeinflussen.&lt;br /&gt;
&lt;br /&gt;
== Das Problem ==&lt;br /&gt;
&lt;br /&gt;
Im beschriebenen Blueprint wird die Laufgeschwindigkeit mit einer Timeline weich verändert:&lt;br /&gt;
&lt;br /&gt;
* normale Laufgeschwindigkeit: &amp;lt;code&amp;gt;500 cm/s&amp;lt;/code&amp;gt;&lt;br /&gt;
* Sprintgeschwindigkeit: &amp;lt;code&amp;gt;820 cm/s&amp;lt;/code&amp;gt;&lt;br /&gt;
* Abbremszeit: &amp;lt;code&amp;gt;1 Sekunde&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Geradeaus fällt der Fehler kaum auf. Wird die Sprinttaste jedoch während einer Kurve losgelassen, zeigt der Character bereits in die neue Richtung, während seine tatsächliche [[Vector|Velocity]] noch einen seitlichen Anteil aus der alten Bewegungsrichtung besitzt. Dadurch entsteht ein sichtbarer Drift- oder „Eislauf“-Effekt.&lt;br /&gt;
&lt;br /&gt;
Die Timeline ist dabei nicht die eigentliche Ursache. Sie verlängert den Übergang lediglich und macht den Richtungsunterschied deutlicher sichtbar.&lt;br /&gt;
&lt;br /&gt;
== Ursache mit Debug-Pfeilen prüfen ==&lt;br /&gt;
&lt;br /&gt;
Zum Prüfen können zwei Debug-Pfeile gezeichnet werden:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Rot:&#039;&#039;&#039; &amp;lt;code&amp;gt;Get Velocity&amp;lt;/code&amp;gt; – die tatsächliche Bewegungsrichtung.&lt;br /&gt;
* &#039;&#039;&#039;Grün:&#039;&#039;&#039; &amp;lt;code&amp;gt;Get Actor Forward Vector&amp;lt;/code&amp;gt; – die Blick- beziehungsweise Vorwärtsrichtung des Characters.&lt;br /&gt;
&lt;br /&gt;
Tritt der Fehler auf, zeigt der grüne Pfeil bereits in die Kurve, während der rote Pfeil noch schräg in die vorherige Richtung weist. Damit lässt sich erkennen, dass es sich nicht nur um ein Animationsproblem handelt.&lt;br /&gt;
&lt;br /&gt;
== Lösung im Blueprint ==&lt;br /&gt;
&lt;br /&gt;
Die horizontale Geschwindigkeit bleibt erhalten, ihre Richtung wird während der Abbrems-Timeline jedoch auf die Vorwärtsrichtung des Characters ausgerichtet.&lt;br /&gt;
&lt;br /&gt;
=== 1. Horizontale Geschwindigkeit ermitteln ===&lt;br /&gt;
&lt;br /&gt;
# Eine Referenz auf den &#039;&#039;&#039;Character&#039;&#039;&#039; verwenden. Nicht die Velocity des Player Controllers abfragen.&lt;br /&gt;
# Am Character &amp;lt;code&amp;gt;Get Velocity&amp;lt;/code&amp;gt; aufrufen.&lt;br /&gt;
# Das Ergebnis mit &amp;lt;code&amp;gt;Vector Length XY&amp;lt;/code&amp;gt; verbinden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Vector Length XY&amp;lt;/code&amp;gt; liefert die aktuelle Geschwindigkeit auf der X/Y-Ebene als Float. Die vertikale Z-Bewegung wird dabei nicht in den Geschwindigkeitsbetrag eingerechnet.&lt;br /&gt;
&lt;br /&gt;
=== 2. Neue Bewegungsrichtung berechnen ===&lt;br /&gt;
&lt;br /&gt;
# Am Character &amp;lt;code&amp;gt;Get Actor Forward Vector&amp;lt;/code&amp;gt; aufrufen.&lt;br /&gt;
# Den von &amp;lt;code&amp;gt;Vector Length XY&amp;lt;/code&amp;gt; ausgegebenen Speed mit &amp;lt;code&amp;gt;Make Vector&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;(Speed, Speed, Speed)&amp;lt;/code&amp;gt; zusammensetzen.&lt;br /&gt;
# &amp;lt;code&amp;gt;Get Actor Forward Vector&amp;lt;/code&amp;gt; mit diesem Vector multiplizieren.&lt;br /&gt;
&lt;br /&gt;
Der beschriebene Blueprint verwendet dafür einen als &amp;lt;code&amp;gt;Vector × Vector&amp;lt;/code&amp;gt; typisierten Multiply-Node. Bei einem passend typisierten &amp;lt;code&amp;gt;Vector × Float&amp;lt;/code&amp;gt;-Node kann der Float auch direkt als Faktor verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Die Berechnung lautet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Neue Velocity = Actor Forward Vector × aktuelle XY-Geschwindigkeit&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Speed   = 735 cm/s&lt;br /&gt;
Forward = (0.80, 0.60, 0.00)&lt;br /&gt;
Velocity ≈ (588, 441, 0) cm/s&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Geschwindigkeit bleibt dadurch gleich, aber der seitliche Anteil relativ zur Charakterausrichtung verschwindet.&lt;br /&gt;
&lt;br /&gt;
=== 3. Velocity nur am Boden setzen ===&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Get Character Movement&amp;lt;/code&amp;gt; aufrufen.&lt;br /&gt;
# Vom Character Movement Component &amp;lt;code&amp;gt;Is Moving on Ground&amp;lt;/code&amp;gt; abfragen.&lt;br /&gt;
# Zwischen &amp;lt;code&amp;gt;Update&amp;lt;/code&amp;gt; der Abbrems-Timeline und &amp;lt;code&amp;gt;Set Velocity&amp;lt;/code&amp;gt; einen [[Boolean#Branch|Branch]] setzen.&lt;br /&gt;
# &amp;lt;code&amp;gt;Is Moving on Ground&amp;lt;/code&amp;gt; mit der &amp;lt;code&amp;gt;Condition&amp;lt;/code&amp;gt; des Branch verbinden.&lt;br /&gt;
# Nur den Ausgang &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; mit &amp;lt;code&amp;gt;Set Velocity&amp;lt;/code&amp;gt; verbinden. &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt; bleibt leer.&lt;br /&gt;
# Das Ergebnis der Richtungsberechnung an &amp;lt;code&amp;gt;New Velocity&amp;lt;/code&amp;gt; von &amp;lt;code&amp;gt;Set Velocity&amp;lt;/code&amp;gt; anschließen.&lt;br /&gt;
&lt;br /&gt;
Der vollständige Ablauf sieht vereinfacht so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;DATEN:&lt;br /&gt;
Get Velocity → Vector Length XY → Make Vector(Speed, Speed, Speed)&lt;br /&gt;
Get Actor Forward Vector ────────────────┐&lt;br /&gt;
                                        ├→ Multiply → Set Velocity (New Velocity)&lt;br /&gt;
Make Vector ─────────────────────────────┘&lt;br /&gt;
&lt;br /&gt;
AUSFÜHRUNG:&lt;br /&gt;
Timeline Update → Branch → True → Set Velocity&lt;br /&gt;
Is Moving on Ground ─────→ Condition&lt;br /&gt;
                           False → keine Aktion&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Warum die Bodenprüfung wichtig ist ==&lt;br /&gt;
&lt;br /&gt;
Der neu berechnete Forward Vector besitzt in diesem Fall einen Z-Wert von &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. Würde &amp;lt;code&amp;gt;Set Velocity&amp;lt;/code&amp;gt; auch in der Luft bei jedem Timeline-Update ausgeführt, würde die vertikale Geschwindigkeit ständig auf null gesetzt. Der Character könnte dann kurz schweben, weil Character Movement und Schwerkraft keine normale Fallgeschwindigkeit aufbauen können.&lt;br /&gt;
&lt;br /&gt;
Die Abfrage &amp;lt;code&amp;gt;Is Moving on Ground&amp;lt;/code&amp;gt; begrenzt den Fix deshalb auf das Laufen am Boden:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;: Richtungsanpassung ausführen.&lt;br /&gt;
* &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;: nichts setzen; Sprung, Fallbewegung und Schwerkraft bleiben vollständig beim Character Movement Component.&lt;br /&gt;
&lt;br /&gt;
== Einstellungen des getesteten Setups ==&lt;br /&gt;
&lt;br /&gt;
Der Fix wurde mit folgenden Ausgangswerten getestet:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Einstellung&lt;br /&gt;
! Wert&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Ground Friction&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;8.0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Max Acceleration&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;1500&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Braking Deceleration Walking&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;2000&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Braking Friction Factor&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Use Separate Braking Friction&amp;lt;/code&amp;gt;&lt;br /&gt;
| aktiviert&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Braking Friction&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Orient Rotation to Movement&amp;lt;/code&amp;gt;&lt;br /&gt;
| aktiviert&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Rotation Rate Z&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;360°/s&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Änderungen an &amp;lt;code&amp;gt;Braking Friction&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Braking Deceleration Walking&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Rotation Rate&amp;lt;/code&amp;gt; allein haben den Fehler im getesteten Projekt nicht beseitigt.&lt;br /&gt;
&lt;br /&gt;
== Testen ==&lt;br /&gt;
&lt;br /&gt;
Nach dem Umbau sollten diese Fälle einzeln geprüft werden:&lt;br /&gt;
&lt;br /&gt;
# Normal laufen und enge Kurven drehen.&lt;br /&gt;
# Sprint starten und bereits während des Sprints lenken.&lt;br /&gt;
# Die Sprinttaste in einem weiten und anschließend in einem engen Bogen loslassen. Der Character darf nicht mehr seitlich rutschen.&lt;br /&gt;
# Den roten Velocity-Pfeil mit dem grünen Forward-Pfeil vergleichen. Während der Korrektur am Boden sollten beide nahezu dieselbe Richtung anzeigen.&lt;br /&gt;
# Während des Abbremsens springen oder über ein Objekt laufen. Flugbahn und Schwerkraft müssen normal bleiben.&lt;br /&gt;
&lt;br /&gt;
Im dokumentierten Projekt wurden Kurvendrift und Schweben mit diesen Tests behoben.&lt;br /&gt;
&lt;br /&gt;
== Grenzen und mögliche Nebenwirkungen ==&lt;br /&gt;
&lt;br /&gt;
* Die Korrektur ist bewusst nur für Bodenbewegung gedacht. Sie sollte nicht ungeprüft für &amp;lt;code&amp;gt;Falling&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Swimming&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Flying&amp;lt;/code&amp;gt; übernommen werden.&lt;br /&gt;
* &amp;lt;code&amp;gt;Set Velocity&amp;lt;/code&amp;gt; kann gleichzeitig aktive Effekte wie Knockback, Dash, externe Kräfte oder Root Motion überschreiben.&lt;br /&gt;
* Für Multiplayer und Dedicated Server müssen Replikation und Movement Prediction gesondert auf Client und Server getestet werden.&lt;br /&gt;
* Bei größerer Spiellogik empfiehlt es sich, die Berechnung aus dem Player Controller in eine eigene Character-Funktion auszulagern.&lt;br /&gt;
* Nach erfolgreichem Test können die Debug-Pfeile entfernt oder über eine Debug-Variable ein- und ausgeschaltet werden.&lt;br /&gt;
&lt;br /&gt;
== Kurzfassung ==&lt;br /&gt;
&lt;br /&gt;
Während die Sprint-Timeline abbremst, wird die aktuelle horizontale Geschwindigkeit auf &amp;lt;code&amp;gt;Actor Forward&amp;lt;/code&amp;gt; ausgerichtet. Ein Branch mit &amp;lt;code&amp;gt;Is Moving on Ground&amp;lt;/code&amp;gt; verhindert, dass &amp;lt;code&amp;gt;Set Velocity&amp;lt;/code&amp;gt; in der Luft die Fallgeschwindigkeit löscht. So folgt der Character Kurven sauber, während Sprünge und Schwerkraft unverändert funktionieren.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Projektinterne Bugfix-Dokumentation: „UE5.8 Bugfix – Seitliches Rutschen beim Abbremsen in Kurven“, Stand 09.09.2026.&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/UCharacterMovementComponent UCharacterMovementComponent]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/BlueprintAPI/AI/Components/NavMovement/IsMovingonGround Is Moving on Ground]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/UMovementComponent UMovementComponent und Velocity]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/movement-components-in-unreal-engine Movement Components]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine Networked Character Movement]&lt;br /&gt;
&lt;br /&gt;
[[Category:Blueprint]]&lt;br /&gt;
[[Category:Character Movement]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
[[Category:Bugfix]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=182</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=182"/>
		<updated>2026-09-08T11:07:35Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 8. September 2026. Letzter Commit: &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;; RasterStream, Raster3D, StaticMeshWorker, StaticMeshScene und WorldStaticMeshScene liegen danach noch uncommitted im lokalen Working Tree. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Zusätzliche Testhardware&lt;br /&gt;
| Intel Arc A380 vorhanden; separater Worker-Test wartet auf das passende Stromkabel&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Basis-Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt; plus uncommitted Working Tree&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Sichtbarer 128×96-Worker-Texture-Stream, isolierte Queue-/Scheduling-Diagnose sowie kleiner Worker-Renderer mit Raster3D, Depth Buffer, echten UE-Static-Meshes und mehreren Draw Calls nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit der vorhandenen Intel Arc A380 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Worker-Rasterpfad und RasterStream ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden.&lt;br /&gt;
&lt;br /&gt;
Der einmalige Test wurde außerdem zu einem frei konfigurierbaren RasterStream ausgebaut. Ein sichtbarer Lauf mit 10 Hz und 50 erfolgreichen Submits endete mit 50 Ready-Ausgaben, 0 Busy und 0 Fehlern bei etwa 9,90 Ready/s. Primary-Textur und Materialbindung blieben dabei persistent.&lt;br /&gt;
&lt;br /&gt;
=== Raster3D mit echten Vertex- und Indexbuffern ===&lt;br /&gt;
&lt;br /&gt;
Der Worker besitzt inzwischen einen kleinen eigenständigen 3D-Rasterpfad mit perspektivischer Kamera, Model-View-Projection-Matrix als Root Constants, D32_FLOAT-Depth-Buffer und Depth-Test. Der finale Testwürfel verwendet 24 POSITION/COLOR-Vertices, 36 &amp;lt;code&amp;gt;uint16&amp;lt;/code&amp;gt;-Indices und &amp;lt;code&amp;gt;DrawIndexedInstanced(36,1,0,0,0)&amp;lt;/code&amp;gt;; sechs getrennte Seitenfarben machen Ausrichtung und Rotation sichtbar nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Die statischen Meshdaten werden einmalig über private Upload-Buffer in DEFAULT-Heaps übertragen. Der Init-Fence wird non-blocking über &amp;lt;code&amp;gt;GetCompletedValue()&amp;lt;/code&amp;gt; beobachtet. Der eigentliche Runtime-Renderpfad enthält weiterhin keine CPU-Waits und keine Maps.&lt;br /&gt;
&lt;br /&gt;
=== UE-Static-Meshes auf der Worker-GPU ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshWorker&amp;lt;/code&amp;gt; extrahiert echte LOD0-Geometrie aus &amp;lt;code&amp;gt;UStaticMesh&amp;lt;/code&amp;gt;-Assets. POSITION und NORMAL sowie &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt;-Indices werden in POD-Daten überführt, einmalig asynchron in eigene Worker-VB/IB hochgeladen und anschließend per &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt; gerendert. Assetpfade sind dynamisch; Auto-Fit richtet Kamera beziehungsweise Modellmaßstab an den Bounds aus.&lt;br /&gt;
&lt;br /&gt;
Sichtbar korrekt getestet wurden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Asset&lt;br /&gt;
! Vertices&lt;br /&gt;
! Indices&lt;br /&gt;
|-&lt;br /&gt;
| Sphere&lt;br /&gt;
| 559&lt;br /&gt;
| 2880&lt;br /&gt;
|-&lt;br /&gt;
| Cube&lt;br /&gt;
| 54&lt;br /&gt;
| 144&lt;br /&gt;
|-&lt;br /&gt;
| Cylinder&lt;br /&gt;
| 334&lt;br /&gt;
| 1536&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Multi-Mesh Worker-Szene ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;StaticMeshScene&amp;lt;/code&amp;gt; rendert Sphere, Cube und Cylinder gemeinsam in einen Color-/Depth-Frame. Der verifizierte Test umfasst insgesamt 947 Vertices und 4560 Indices, drei &amp;lt;code&amp;gt;DrawIndexedInstanced&amp;lt;/code&amp;gt;-Aufrufe und nur einen anschließenden Cross-Adapter-/Normal-SafeCopy-Transfer. Damit ist nicht mehr nur ein synthetisches Primitive, sondern mehrere echte UE-Meshes mit gemeinsamer Tiefenprüfung im Worker-Frame sichtbar nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== WorldStaticMeshScene ===&lt;br /&gt;
&lt;br /&gt;
Der nächste Integrationsschritt ist implementiert, aber noch nicht sichtbar im Level verifiziert. &amp;lt;code&amp;gt;ExperimentalMultiGPUWorldStaticMeshScene.cpp&amp;lt;/code&amp;gt; sammelt im Engine-Layer bis zu acht sichtbare &amp;lt;code&amp;gt;UStaticMeshComponent&amp;lt;/code&amp;gt;s von Actors mit dem Tag &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt;. Meshdaten und World-Transforms werden in POD-Strukturen beziehungsweise Matrizen kopiert und ohne &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;-Pointer über eine backend-neutrale RHI-Schnittstelle an D3D12RHI übergeben. Der Build ist erfolgreich; offen ist der sichtbare PIE-/Game-Test mit tatsächlich getaggten Actors.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRasterStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRasterStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen RGB-Dreieck-RasterStream mit frei wählbarer Zielrate, optionalem Submit-Limit und Quiet-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRaster3DWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert einmalig den perspektivischen 3D-Testwürfel mit Depth Buffer und echten Vertex-/Indexbuffern.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartRaster3DStream&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopRaster3DStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet beziehungsweise stoppt den kontinuierlichen Raster3D-Test.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshWorker [AssetPath]&amp;lt;/code&amp;gt;&lt;br /&gt;
| Extrahiert und rendert LOD0-Geometrie eines UE-Static-Mesh-Assets; ohne optionalen Pfad wird das konfigurierte Testasset verwendet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rendert Sphere, Cube und Cylinder gemeinsam mit drei Draw Calls und einem anschließenden Transfer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestWorldStaticMeshScene&amp;lt;/code&amp;gt;&lt;br /&gt;
| Sammelt sichtbare, mit &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggte StaticMeshComponents aus der laufenden World und reicht deren POD-Snapshot an den Worker weiter. Sichtbarer Level-Nachweis noch offen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der kleine 3D-Workload mit Geometrie, Kamera und Depth ist inzwischen umgesetzt und bis zur Multi-Mesh-Szene sichtbar nachgewiesen. Der nächste unmittelbare Nachweis ist der sichtbare PIE-/Game-Test des WorldStaticMeshScene-Snapshots mit tatsächlich als &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten Actors. Danach sollen SceneCapture-nahe Aufgaben wie CCTV, Spiegel oder Minimap folgen. Der robuste Normal-/SafeCopy-Pfad bleibt dabei der sichtbare Referenztransport. Die vorhandene Intel Arc A380 dient nach Eintreffen des Stromkabels als nächster Hardware-Gegencheck; ein privater Experimental-Fast-Path wird erst weiterverfolgt, wenn State-Tracking, Residency, Queue-Reihenfolge, Read-vs-Write-Hazards und automatischer Session-Fallback sauber gelöst sind.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Raster3D, einzelne echte UE-Static-Meshes und eine Drei-Mesh-Szene sind sichtbar nachgewiesen. Der WorldStaticMeshScene-POD-Snapshot ist implementiert und erfolgreich gebaut, sein sichtbarer Test mit getaggten Actors steht jedoch noch aus.&lt;br /&gt;
* Die aktuelle Worker-Szene übernimmt nur LOD0-POSITION/NORMAL-Daten und höchstens acht sichtbare StaticMeshComponents; vollständige Materialien, Texturen, Beleuchtung, Skeletal Meshes, Nanite und eine allgemeine SceneCapture-Pipeline fehlen.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil von Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# WorldStaticMeshScene mit tatsächlich als &amp;lt;code&amp;gt;MultiGPUWorker&amp;lt;/code&amp;gt; getaggten Actors im laufenden PIE-/Game-Level sichtbar testen und Snapshot-, Transform- und Auswahlverhalten verifizieren.&lt;br /&gt;
# Den Worker-Szenepfad schrittweise um weitere echte Szenendaten und robuste Cache-/Lifetime-Regeln erweitern.&lt;br /&gt;
# SceneCapture-nahe Workloads wie CCTV, Spiegel oder Minimap als erste praktisch nützliche unabhängige Raster-Aufgaben aufbauen.&lt;br /&gt;
# QueueProbe und &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt; auf der Intel Arc A380 wiederholen, um Laptop-iGPU-Sonderverhalten von der allgemeinen Architektur zu trennen.&lt;br /&gt;
# Experimental-Architektur nur mit Capability-Selbsttest, sauberem State-Tracking, Residency, Queue-Reihenfolge, Hazard-Modell und automatischem Session-Fallback definieren.&lt;br /&gt;
# Nur bei nachgewiesenem Workload-Bedarf einen zweiten Slot oder Ringbuffer mit Generation-, Fence-, Reuse- und Consumer-Hazard-Modell ergänzen.&lt;br /&gt;
# Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 8. September 2026; Basis-Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt; plus uncommitted Working Tree. WorldStaticMeshScene ist gebaut, aber noch nicht sichtbar getestet.&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=181</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=181"/>
		<updated>2026-09-07T10:20:32Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 7. September 2026, Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Sichtbarer 128×96-Worker-Texture-Stream, isolierte Queue-/Scheduling-Diagnose und erster echter Worker-Rasterpfad nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Neben &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; existieren inzwischen die Diagnosemodi &amp;lt;code&amp;gt;computeonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;. Als Queues stehen &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt; zur Verfügung. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Primary-Queues; die übrigen Varianten isolieren private beziehungsweise bereits vorhandene native D3D12-Queues.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics, signal-only, 30 FPS&lt;br /&gt;
| 33,319 ms PrimaryExecute bis Ready&lt;br /&gt;
| UE-verwaltete Graphics-Submission skaliert mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy, signal-only, 30 FPS&lt;br /&gt;
| 32,593 ms PrimaryExecute bis Ready&lt;br /&gt;
| Auch die UE-verwaltete Copy Queue ist framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private Primary-DIRECT-Queue, signal-only&lt;br /&gt;
| etwa 0,014 ms Queue/Fence-Latenz; nach Lifecycle-Fix rund 999 Ready/s bei 30 FPS&lt;br /&gt;
| Native Queue und Scheduler sind vollständig vom Frame entkoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker signal-only / leere Command List&lt;br /&gt;
| jeweils rund 1000 Ready/s bei 30 FPS&lt;br /&gt;
| Worker-Queue, Fence und reine Submission sind nicht framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Worker &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;, 30 / 60 / 120 FPS&lt;br /&gt;
| 29,41 / 58,25 / 113,08 Ready/s&lt;br /&gt;
| Bereits eine echte 256-Byte-GPU-Kopie folgt im UE-Prozess dem Frame-Raster&lt;br /&gt;
|-&lt;br /&gt;
| Worker COPY Queue / HIGH Priority, 30 FPS&lt;br /&gt;
| jeweils rund 29,42 Ready/s&lt;br /&gt;
| Queue-Typ und Priorität beseitigen die Kopplung nicht&lt;br /&gt;
|-&lt;br /&gt;
| Standalone-D3D12 auf derselben Intel UHD&lt;br /&gt;
| 92.956 Copy-Jobs/s; 0,007 ms durchschnittliche Fence-Latenz&lt;br /&gt;
| Die Kopplung ist UE-Prozess-/Scheduling-spezifisch, keine allgemeine Intel-, WDDM- oder D3D12-Grenze&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Die zunächst gemessene Verzögerung von rund 32 ms lag zwischen der In-Flight-Freigabe und dem nächsten Request auf dem Render Thread. Für &amp;lt;code&amp;gt;signalonly/native&amp;lt;/code&amp;gt; wurde der sichere Completion-/Submit-Lifecycle deshalb in den frameunabhängigen Scheduler verlegt. Danach erreichten zwei 100-Job-Läufe bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt; rund 999 bis 1029 Ready/s, ohne Busy oder Fehler.&lt;br /&gt;
&lt;br /&gt;
Der anschließende &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt;-Test lokalisierte die verbleibende Kopplung auf echte Worker-GPU-Arbeit: WorkerSubmit bis WorkerReady benötigte bei 30, 60 und 120 FPS ungefähr 33,29, 16,93 und 8,45 ms; WorkerReady bis PrimaryReady war danach praktisch sofort. Signal-only und eine leere Command List waren schnell, Resource Barriers und eine 256-Byte-Kopie dagegen framegebunden. Ein eigenständiger D3D12-Microbenchmark auf derselben Intel UHD erreichte außerhalb von Unreal bei derselben Kopie rund 92.956 Jobs/s mit 0,007 ms mittlerer Fence-Latenz. Die genaue Ursache im UE-Prozess beziehungsweise dessen GPU-Scheduling-Kontext bleibt offen und wird vorerst bis zum Gegencheck mit einer Intel Arc A750 geparkt.&lt;br /&gt;
&lt;br /&gt;
=== Erster Worker-Rasterpfad ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt; weist erstmals echte Rasterizer-Arbeit auf der Intel-Worker-GPU nach. &amp;lt;code&amp;gt;RasterWorkerVS&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;RasterWorkerPS&amp;lt;/code&amp;gt; werden über Unreals Global-Shader-Pfad kompiliert und für ein natives Worker-Graphics-PSO verwendet. Ein persistentes 128×96-RGBA8-RenderTarget besitzt RTV, leere Root Signature und eine DIRECT-Command-List. Der Vertex Shader erzeugt drei Vertices über &amp;lt;code&amp;gt;SV_VertexID&amp;lt;/code&amp;gt;; der Pixel Shader schreibt interpolierte RGB-Farben.&lt;br /&gt;
&lt;br /&gt;
Der Job wechselt das RenderTarget von &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt; nach &amp;lt;code&amp;gt;RENDER_TARGET&amp;lt;/code&amp;gt;, führt Clear und &amp;lt;code&amp;gt;DrawInstanced(3,1,0,0)&amp;lt;/code&amp;gt; aus und wechselt anschließend zurück nach &amp;lt;code&amp;gt;COPY_SOURCE&amp;lt;/code&amp;gt;. Danach verwendet er unverändert den robusten Normalpfad aus Cross-Adapter-Shared-Buffer, Primary SafeCopy, persistenter &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und DisplayActor. Der Runtime-Test meldete einen akzeptierten Submit und &amp;lt;code&amp;gt;RasterWorker READY&amp;lt;/code&amp;gt; für Generation 1; die 128×96-UTexture wurde erfolgreich gebunden. Ein eigener Screenshot des sichtbaren Dreiecks wurde noch nicht als Nachweis archiviert.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestRasterWorker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Rasterisiert auf der Worker-GPU ein echtes RGB-Dreieck per Vertex- und Pixel-Shader und transportiert das Ergebnis über den normalen SafeCopy-Pfad bis zum DisplayActor.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;commandonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Reicht eine leere echte Worker-Command-List ein und trennt Command-Submission von GPU-Arbeit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;barrieronly&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;barrierprivate&amp;lt;/code&amp;gt;&lt;br /&gt;
| Isoliert Resource-Barriers auf Worker-Ressourcen beziehungsweise einer privaten Testtextur.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copybuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt eine minimale echte &amp;lt;code&amp;gt;CopyBufferRegion&amp;lt;/code&amp;gt;-Operation über 256 Byte aus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary; reine Diagnose, kein fertiger Experimental-Modus.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene native Worker-DIRECT-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate native Worker-COPY-Queue.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;worker-high&amp;lt;/code&amp;gt;&lt;br /&gt;
| Separate Worker-DIRECT-Queue mit hoher Priorität.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Nach Abschluss der Queue-/Scheduling-Diagnose rückt wieder der eigentliche Workload in den Vordergrund. Der RasterWorker soll vom synthetischen Dreieck zu einem kleinen 3D-Workload mit Geometrie, Transformation, Kamera und später Depth erweitert werden. Darauf sollen SceneCapture-nahe Aufgaben wie CCTV, Spiegel oder Minimap folgen. Der robuste Normal-/SafeCopy-Pfad bleibt dabei der sichtbare Referenztransport. Die Arc A750 dient als nächster wichtiger Hardware-Gegencheck; ein privater Experimental-Fast-Path wird erst weiterverfolgt, wenn State-Tracking, Residency, Queue-Reihenfolge, Read-vs-Write-Hazards und automatischer Session-Fallback sauber gelöst sind.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Echte Intel-Worker-GPU-Arbeit skaliert im aktuellen UE-Prozess mit 30/60/120 FPS. Der Standalone-Test widerlegt eine allgemeine Intel-/WDDM-/D3D12-Grenze; die genaue UE-spezifische Ursache bleibt offen.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Private native Queues sind noch kein Experimental-/Direct-Modus und beschreiben keine UE-eigene sichtbare Textur.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Der RasterWorker zeichnet bislang nur ein synthetisches RGB-Dreieck. Eine echte 3D-Szene, SceneCapture2D, CCTV, Spiegel oder Minimap ist noch nicht umgesetzt.&lt;br /&gt;
* Ein explizites Read-vs-Write-Hazard-Modell für die persistente Primary-Textur fehlt noch und muss vor mehreren Slots oder einem nativen Experimental-Texturpfad gelöst werden.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil von Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# RasterWorker zu einem kleinen 3D-Workload mit Geometrie, Transformation, Kamera und später Depth erweitern.&lt;br /&gt;
# SceneCapture-nahe Workloads wie CCTV, Spiegel oder Minimap als erste praktisch nützliche unabhängige Raster-Aufgaben aufbauen.&lt;br /&gt;
# QueueProbe und &amp;lt;code&amp;gt;full native&amp;lt;/code&amp;gt; auf der Intel Arc A750 wiederholen, um Laptop-iGPU-Sonderverhalten von der allgemeinen Architektur zu trennen.&lt;br /&gt;
# Experimental-Architektur nur mit Capability-Selbsttest, sauberem State-Tracking, Residency, Queue-Reihenfolge, Hazard-Modell und automatischem Session-Fallback definieren.&lt;br /&gt;
# Nur bei nachgewiesenem Workload-Bedarf einen zweiten Slot oder Ringbuffer mit Generation-, Fence-, Reuse- und Consumer-Hazard-Modell ergänzen.&lt;br /&gt;
# Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 7. September 2026, Commit &amp;lt;code&amp;gt;0719998&amp;lt;/code&amp;gt;; vorheriger dokumentierter Checkpoint &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=180</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=180"/>
		<updated>2026-09-06T23:45:54Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 7. September 2026, Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Sichtbarer 128×96-Worker-Texture-Stream im TPS sowie isolierte Diagnose der Primary-Queue-/Submission-Latenz nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Der Probe besitzt die Modi &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; sowie die Queue-Auswahl &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Queues. Native verwendet derzeit ausschließlich im Signal-only-Modus eine eigene persistente D3D12-DIRECT-Queue auf dem Primary-Device.&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Signal-only-Test&lt;br /&gt;
! PrimaryExecute bis Ready&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics Queue, 30 FPS&lt;br /&gt;
| 33,319 ms&lt;br /&gt;
| skaliert praktisch mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics Queue, 60 FPS&lt;br /&gt;
| 16,377 ms&lt;br /&gt;
| skaliert praktisch mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics Queue, 120 FPS&lt;br /&gt;
| 8,712 ms&lt;br /&gt;
| skaliert praktisch mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy Queue, 30 / 120 FPS&lt;br /&gt;
| 32,593 / 8,206 ms&lt;br /&gt;
| Copy Queue ist ebenfalls framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private native DIRECT Queue, 30 FPS&lt;br /&gt;
| durchschnittlich 0,014 ms; 0,001–0,037 ms&lt;br /&gt;
| D3D12, Treiber und Primary-GPU sind nicht an die Frame-Dauer gebunden&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Er signalisiert nur einen privaten Fence und verwendet weder WorkerReady-Wait noch Cross-Adapter-Copy, UE-eigene Textur oder Engine-State-Tracking. Obwohl sein Fence nach rund 0,014 ms fertig ist, erreicht der gesamte Probe bei 30 FPS nur etwa 30,75 Ready/s; &amp;lt;code&amp;gt;Ready -&amp;gt; NextSubmit&amp;lt;/code&amp;gt; dauert im Mittel 32,403 ms. Damit ist als nächster Engpass der Lifecycle beziehungsweise die Freigabe des Single Slots isoliert.&lt;br /&gt;
&lt;br /&gt;
== Test- und Diagnosebefehle ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Befehl&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestComputeShader&amp;lt;/code&amp;gt;&lt;br /&gt;
| Führt den vollständigen Worker-Compute-Testpfad aus. Er enthält auch ältere Debug- und Regressionstests mit CPU-Readback und ist daher nicht mit dem reinen asynchronen Runtime-Pfad gleichzusetzen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureConsumer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Testet &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; auf der Primary-GPU. Die aktuelle Ready-Textur wird über UE-RHI gelesen und anhand ausgewählter Testpixel per Debug-Readback geprüft.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.TestTextureBridge&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prüft die Bridge von der fertigen &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; zu &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; und damit den UE- und materialtauglichen Texturpfad.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.SpawnDisplayActor&amp;lt;/code&amp;gt;&lt;br /&gt;
| Spawnt den Test-Actor mit Plane im Spiel. Das Material zeigt darauf die vom Worker erzeugte Textur an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den sichtbaren Normal-Pfad: Worker-Textur → Cross-Adapter-Transfer → SafeCopy → UE-Textur → Material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StopTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Verhindert weitere Submits des laufenden Streams. Ein bereits eingereichter GPU-Job darf noch sicher fertig werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartQueueProbe&amp;lt;/code&amp;gt;&lt;br /&gt;
| Startet den Diagnose-Benchmark für Primary-Queue-, Fence- und Submission-Verhalten. Der Probe verändert die sichtbare Textur nicht.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream [Hz] [MaxSuccessfulSubmits] [quiet]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Beispiel&lt;br /&gt;
! Wirkung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream&amp;lt;/code&amp;gt;&lt;br /&gt;
| Standardmäßig etwa 5 Hz, ohne Submit-Limit.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 37.5&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 37,5 Hz ohne Submit-Limit an. Sowohl &amp;lt;code&amp;gt;37.5&amp;lt;/code&amp;gt; als auch &amp;lt;code&amp;gt;37,5&amp;lt;/code&amp;gt; werden akzeptiert.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100&amp;lt;/code&amp;gt;&lt;br /&gt;
| Fordert 1000 Hz an und stoppt nach exakt 100 erfolgreichen Submits.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&amp;lt;/code&amp;gt;&lt;br /&gt;
| Wie zuvor, unterdrückt aber Per-Job- und Busy-Logspam.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die Hz-Angabe ist eine &#039;&#039;&#039;Ziel- beziehungsweise Request-Frequenz&#039;&#039;&#039;. &amp;lt;code&amp;gt;1000&amp;lt;/code&amp;gt; bedeutet daher nicht automatisch 1000 fertige Texturen pro Sekunde. Die tatsächliche Rate hängt unter anderem von Timer, Submission, Backpressure, Queue-Latenz und Slot-Lifecycle ab. &amp;lt;code&amp;gt;MaxSuccessfulSubmits&amp;lt;/code&amp;gt; zählt nur angenommene Submits; Busy- und Failed-Versuche verbrauchen das Limit nicht.&lt;br /&gt;
&lt;br /&gt;
=== QueueProbe ===&lt;br /&gt;
&lt;br /&gt;
Grundsyntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe &amp;lt;Hz&amp;gt; &amp;lt;MaxSubmits&amp;gt; [quiet] [Mode] [Queue]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Ausgeführter Pfad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary Wait → Copy → Completion Fence.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Worker Compute → Cross-Adapter-Transfer → Primary wartet auf WorkerReadyFence → Completion Fence. Es findet keine Texturkopie statt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt;&lt;br /&gt;
| Keine Textur, kein Worker-Wait und keine Kopie; nur Queue und Fence. Dieser Modus isoliert das Queue-Verhalten.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Queue&lt;br /&gt;
! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Graphics-/Direct-Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vorhandene UE Primary Copy Queue über &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;&lt;br /&gt;
| Vollständig private native D3D12-DIRECT-Queue auf der Primary. Derzeit nur für die Signal-only-Diagnose vorgesehen und kein fertiger Experimental-Modus.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typische Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet full graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet waitonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der letzte Befehl ist aktuell die wichtigste isolierte Gegenprobe. Mit der privaten nativen Queue wurde bei 30 FPS eine durchschnittliche Latenz &amp;lt;code&amp;gt;primaryExecuteToReadyAvgMs = 0.014 ms&amp;lt;/code&amp;gt; gemessen.&lt;br /&gt;
&lt;br /&gt;
=== Benchmark-CVars ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! CVar&lt;br /&gt;
! Zweck&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r.VSync 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Deaktiviert VSync, damit es die Messung nicht begrenzt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 60&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;t.MaxFPS 120&amp;lt;/code&amp;gt;&lt;br /&gt;
| Setzt die Engine-Framerate für reproduzierbare Frame-Coupling-Tests.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;t.MaxFPS 0&amp;lt;/code&amp;gt;&lt;br /&gt;
| Entfernt das normale &amp;lt;code&amp;gt;t.MaxFPS&amp;lt;/code&amp;gt;-Limit. Dieser Lauf ist als zusätzliche Diagnose-Gegenprobe vorgesehen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der nächste Schritt ist, den &#039;&#039;&#039;QueueProbe-Lifecycle nach der bereits abgeschlossenen nativen Fence-Operation&#039;&#039;&#039; zu entkoppeln: Warum bleibt der Slot nach einer etwa 0,014 ms schnellen Fence-Completion noch durchschnittlich rund 32,4 ms bis zum nächsten erfolgreichen Submit belegt? Danach soll eine private native Queue WorkerReady-Wait und Cross-Adapter-Copy zunächst ausschließlich mit privaten Ressourcen testen. Erst auf dieser Grundlage wird entschieden, wie ein sicherer Experimental-Modus mit Capability-Selbsttest und automatischem Fallback auf den robusten Normal-Pfad aussehen kann.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Der native Modus verwendet bisher nur QueueSignal und Fence, keine Textur oder Cross-Adapter-Ressource.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Der sichtbare TPS-Nachweis zeigt eine Worker-Compute-Textur, noch keine auf dem Worker gerenderte 3D-Szene. Echte UE-Szenen-Workloads, Benchmark-Wizard und Scheduler fehlen weiterhin.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil von Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# QueueProbe-Lifecycle entkoppeln und die verzögerte Slot-Freigabe nach schneller nativer Fence-Completion erklären.&lt;br /&gt;
# WorkerReady-Wait und Cross-Adapter-Copy auf einer privaten Primary-Ressource über die native Queue testen.&lt;br /&gt;
# Experimental-Architektur mit Capability-Selbsttest, Normal/Experimental-Einstellung und automatischem Session-Fallback definieren.&lt;br /&gt;
# Erst danach eine UE-sichtbare Experimental-Textur mit korrektem State-Tracking, Residency, Queue-Reihenfolge und Consumer-Synchronisation untersuchen.&lt;br /&gt;
# Nur bei nachgewiesenem Bedarf einen zweiten Slot oder Ringbuffer mit Generation-, Fence-, Reuse- und Consumer-Hazard-Modell ergänzen.&lt;br /&gt;
# Ersten echten UE-Offload wie SceneCapture2D, CCTV, Spiegel, Minimap, Niagara oder unabhängigen Compute integrieren.&lt;br /&gt;
# Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 7. September 2026, Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;; vorheriger Checkpoint &amp;lt;code&amp;gt;cbf56c2&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=179</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=179"/>
		<updated>2026-09-06T23:32:14Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 7. September 2026, Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Sichtbarer 128×96-Worker-Texture-Stream im TPS sowie isolierte Diagnose der Primary-Queue-/Submission-Latenz nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream 37,5&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream 37,5 25&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&lt;br /&gt;
ExperimentalMultiGPU.StopTextureStream&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
=== Queue-Submission-Diagnose ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MultiGPUD3D12QueueProbe&amp;lt;/code&amp;gt; untersucht die Submission unabhängig vom sichtbaren Texturpfad. Der Probe besitzt die Modi &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;waitonly&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;signalonly&amp;lt;/code&amp;gt; sowie die Queue-Auswahl &amp;lt;code&amp;gt;graphics&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;native&amp;lt;/code&amp;gt;. Graphics und Copy verwenden &amp;lt;code&amp;gt;RHIRunOnQueue(..., false)&amp;lt;/code&amp;gt; auf UE-verwalteten Queues. Native verwendet derzeit ausschließlich im Signal-only-Modus eine eigene persistente D3D12-DIRECT-Queue auf dem Primary-Device.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly graphics&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly copy&lt;br /&gt;
ExperimentalMultiGPU.StartQueueProbe 1000 100 quiet signalonly native&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Probe misst Request, Worker-Submit, &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Aufruf und -Callback, Primary-Execute, Fence-Completion sowie Ready bis zum nächsten akzeptierten Submit. Er fügt keine CPU-Waits, Readbacks, Maps oder &amp;lt;code&amp;gt;BlockUntilGPUIdle&amp;lt;/code&amp;gt; ein und beschreibt keine Textur des sichtbaren Normal-Pfads.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Signal-only-Test&lt;br /&gt;
! PrimaryExecute bis Ready&lt;br /&gt;
! Befund&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics Queue, 30 FPS&lt;br /&gt;
| 33,319 ms&lt;br /&gt;
| skaliert praktisch mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics Queue, 60 FPS&lt;br /&gt;
| 16,377 ms&lt;br /&gt;
| skaliert praktisch mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Graphics Queue, 120 FPS&lt;br /&gt;
| 8,712 ms&lt;br /&gt;
| skaliert praktisch mit der Frame-Dauer&lt;br /&gt;
|-&lt;br /&gt;
| UE Copy Queue, 30 / 120 FPS&lt;br /&gt;
| 32,593 / 8,206 ms&lt;br /&gt;
| Copy Queue ist ebenfalls framegekoppelt&lt;br /&gt;
|-&lt;br /&gt;
| Private native DIRECT Queue, 30 FPS&lt;br /&gt;
| durchschnittlich 0,014 ms; 0,001–0,037 ms&lt;br /&gt;
| D3D12, Treiber und Primary-GPU sind nicht an die Frame-Dauer gebunden&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;code&amp;gt;RHIRunOnQueue&amp;lt;/code&amp;gt;-Callback selbst erreicht den D3D12-Submission-Thread typischerweise bereits nach etwa 0,02–0,05 ms; die Verzögerung entsteht danach in der verwalteten Queue-/Submission-Reihenfolge. &amp;lt;code&amp;gt;SubmitCommandsHint()&amp;lt;/code&amp;gt; ist in UE 5.8 nur ein veralteter Alias für &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; und stellt daher keinen stärkeren Submission-Mechanismus dar.&lt;br /&gt;
&lt;br /&gt;
Der native Test ist ein &#039;&#039;&#039;Architekturbeweis, noch kein Experimental- oder Direct-Modus&#039;&#039;&#039;. Er signalisiert nur einen privaten Fence und verwendet weder WorkerReady-Wait noch Cross-Adapter-Copy, UE-eigene Textur oder Engine-State-Tracking. Obwohl sein Fence nach rund 0,014 ms fertig ist, erreicht der gesamte Probe bei 30 FPS nur etwa 30,75 Ready/s; &amp;lt;code&amp;gt;Ready -&amp;gt; NextSubmit&amp;lt;/code&amp;gt; dauert im Mittel 32,403 ms. Damit ist als nächster Engpass der Lifecycle beziehungsweise die Freigabe des Single Slots isoliert.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der nächste Schritt ist, den &#039;&#039;&#039;QueueProbe-Lifecycle nach der bereits abgeschlossenen nativen Fence-Operation&#039;&#039;&#039; zu entkoppeln: Warum bleibt der Slot nach einer etwa 0,014 ms schnellen Fence-Completion noch durchschnittlich rund 32,4 ms bis zum nächsten erfolgreichen Submit belegt? Danach soll eine private native Queue WorkerReady-Wait und Cross-Adapter-Copy zunächst ausschließlich mit privaten Ressourcen testen. Erst auf dieser Grundlage wird entschieden, wie ein sicherer Experimental-Modus mit Capability-Selbsttest und automatischem Fallback auf den robusten Normal-Pfad aussehen kann.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* QueueProbe ist reine Diagnose. Der native Modus verwendet bisher nur QueueSignal und Fence, keine Textur oder Cross-Adapter-Ressource.&lt;br /&gt;
* Es gibt noch keine Umschaltung zwischen Normal und Experimental sowie keinen automatischen Session-Fallback.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Der sichtbare TPS-Nachweis zeigt eine Worker-Compute-Textur, noch keine auf dem Worker gerenderte 3D-Szene. Echte UE-Szenen-Workloads, Benchmark-Wizard und Scheduler fehlen weiterhin.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil von Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# QueueProbe-Lifecycle entkoppeln und die verzögerte Slot-Freigabe nach schneller nativer Fence-Completion erklären.&lt;br /&gt;
# WorkerReady-Wait und Cross-Adapter-Copy auf einer privaten Primary-Ressource über die native Queue testen.&lt;br /&gt;
# Experimental-Architektur mit Capability-Selbsttest, Normal/Experimental-Einstellung und automatischem Session-Fallback definieren.&lt;br /&gt;
# Erst danach eine UE-sichtbare Experimental-Textur mit korrektem State-Tracking, Residency, Queue-Reihenfolge und Consumer-Synchronisation untersuchen.&lt;br /&gt;
# Nur bei nachgewiesenem Bedarf einen zweiten Slot oder Ringbuffer mit Generation-, Fence-, Reuse- und Consumer-Hazard-Modell ergänzen.&lt;br /&gt;
# Ersten echten UE-Offload wie SceneCapture2D, CCTV, Spiegel, Minimap, Niagara oder unabhängigen Compute integrieren.&lt;br /&gt;
# Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 7. September 2026, Commit &amp;lt;code&amp;gt;43a5c07&amp;lt;/code&amp;gt;; vorheriger Checkpoint &amp;lt;code&amp;gt;cbf56c2&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=178</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=178"/>
		<updated>2026-09-06T18:19:08Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 6. September 2026, Commit &amp;lt;code&amp;gt;cbf56c2&amp;lt;/code&amp;gt;. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;cbf56c2&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Sichtbarer 128×96-Worker-Texture-Stream im TPS, persistenter Single Runtime Slot, stabile UTexture-Bridge und Benchmark-Diagnostik nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS + PatternPhase&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; monotone Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; stabile UExperimentalMultiGPUTexture&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; TPS-Material zeigt das Worker-Ergebnis sichtbar an&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro Worker ist maximal ein Runtime-Job gleichzeitig in flight. Backpressure lehnt weitere Requests als &amp;lt;code&amp;gt;Busy&amp;lt;/code&amp;gt; ab, bis der Slot nach der Primary-Completion wieder sicher verwendbar ist.&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; erzeugt für jeden akzeptierten Submit deterministisch einen neuen sichtbaren Inhalt. Abgewiesene Busy-Requests erhöhen die Phase nicht und erzeugen daher keine Lücken.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein persistenter Shared Fence synchronisiert die Queues direkt von GPU zu GPU. Seine Werte steigen pro Job monoton: WorkerReady/PrimaryComplete verwenden die Paare 1/2, 3/4, 5/6 und so weiter.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; persistente Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; persistenter Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert WorkerReady (1, 3, 5, ...)&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf WorkerReady&lt;br /&gt;
  -&amp;gt; direkte Kopie in persistente UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert PrimaryComplete (2, 4, 6, ...)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Die Output Registry trennt Persistent-, Pending- und Ready-Zustände sowie Inhaltsgeneration und Texturidentität. Dadurch kann eine verspätete Completion keinen neueren Output zurückrollen.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion non-blocking über einen Runtime-Pump; &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; bleibt als Fallback erhalten.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach PrimaryComplete kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Eine backend-neutrale RHI-Provider-API reicht die Ready-Textur an die Engine weiter. &amp;lt;code&amp;gt;UExperimentalMultiGPUTexture&amp;lt;/code&amp;gt; hält eine stabile &amp;lt;code&amp;gt;UTexture&amp;lt;/code&amp;gt; samt TextureReference und bindet die persistente &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; ohne zusätzlichen Pixel-Copy. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Sichtbarer TPS-Consumer ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;AExperimentalMultiGPUDisplayActor&amp;lt;/code&amp;gt; zeigt die Worker-Ausgabe im Third-Person-Testlevel über den Materialparameter &amp;lt;code&amp;gt;MultiGPUTexture&amp;lt;/code&amp;gt; an. Damit ist der Output nicht mehr nur über Logs oder Readback nachgewiesen: Die Intel UHD erzeugt fortlaufend die Texturinhalte, während die RTX die Spielwelt und das Material rendert. &amp;lt;code&amp;gt;TextureConsumerCS&amp;lt;/code&amp;gt; kann Ready-Ausgaben auf der Primary zusätzlich als SRV lesen und fünf quantisierte Samples im Debugpfad prüfen.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Der Normal-Pfad verwendet pro Worker genau einen persistenten Runtime-Slot. Worker-Textur, Root Signature, PSO, Descriptor Heap, Command Allocator/List und Worker-Fence werden nach der ersten kompatiblen Initialisierung wiederverwendet. Dasselbe gilt für Shared Heap/Buffer/Fence und die Transport-Command-Objekte. Der In-Flight-Job trägt nur noch die nötigen Job-, Generation- und Fence-Metadaten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Runtime Request&lt;br /&gt;
  -&amp;gt; Completion non-blocking prüfen&lt;br /&gt;
  -&amp;gt; falls Slot frei: Worker Dispatch&lt;br /&gt;
  -&amp;gt; WorkerReady-Fence signalisieren&lt;br /&gt;
  -&amp;gt; Primary Wait, SafeCopy und PrimaryComplete-Signal&lt;br /&gt;
  -&amp;gt; Output Pending&lt;br /&gt;
  -&amp;gt; Runtime-Pump oder RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Output Ready publizieren&lt;br /&gt;
  -&amp;gt; Slot wiederverwendbar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Backpressure erlaubt maximal einen echten In-Flight-Job pro Worker. Ein Busy-Request setzt keine GPU-Arbeit ab, setzt keine Ressourcen zurück und erhöht &amp;lt;code&amp;gt;PatternPhase&amp;lt;/code&amp;gt; nicht. Worker-Fence-Werte steigen mit jedem akzeptierten Submit 1, 2, 3 und so weiter; der persistente Shared Fence verwendet fortlaufend die Paare 1/2, 3/4, 5/6. Fehler nach Übergabe von Ressourcen an die GPU führen zu sicherem Retire beziehungsweise Retention statt zu vorzeitigem Reuse.&lt;br /&gt;
&lt;br /&gt;
=== Texture Stream und Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
Der projektseitige Texture Stream akzeptiert eine beliebige positive, endliche Zielrate. Punkt und Komma sind als Dezimaltrenner möglich. Optional lässt sich die Zahl erfolgreicher Submits begrenzen; Busy- oder Failed-Versuche verbrauchen dieses Limit nicht. Der Quiet-Modus unterdrückt per-Job-Ausgaben, behält aber Start, echte Fehler und die Abschlussstatistik bei.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream 37,5&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream 37,5 25&lt;br /&gt;
ExperimentalMultiGPU.StartTextureStream 1000 100 quiet&lt;br /&gt;
ExperimentalMultiGPU.StopTextureStream&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Statistik unterscheidet Timer-Ticks, angenommene Submits, Busy/Failed, Ready, In-Flight und die jeweiligen effektiven Raten. Diagnosezeitpunkte erfassen unter anderem RequestAccepted, RenderCommandExecution, WorkerSubmit, NormalTransferQueued und ReadyObserved.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Test&lt;br /&gt;
! Ergebnis&lt;br /&gt;
! Aussage&lt;br /&gt;
|-&lt;br /&gt;
| 5 Hz, 20 Submits&lt;br /&gt;
| etwa 5 Ready/s, 20/20, kein Busy&lt;br /&gt;
| Entspannter Single-Slot-Betrieb&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz, 100 Submits, quiet&lt;br /&gt;
| 100/100 Ready, 0 Fehler, etwa 58 Ready/s&lt;br /&gt;
| Backpressure begrenzt den Durchsatz sicher&lt;br /&gt;
|-&lt;br /&gt;
| 1000 Hz bei &amp;lt;code&amp;gt;t.MaxFPS 30&amp;lt;/code&amp;gt;&lt;br /&gt;
| etwa 28–29 Ready/s trotz rund 982 Timer-Ticks/s&lt;br /&gt;
| Primary-/SafeCopy-/Ready-Kette ist effektiv framegekoppelt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein zusätzlicher non-blocking Aufruf von &amp;lt;code&amp;gt;ImmediateFlush(DispatchToRHIThread)&amp;lt;/code&amp;gt; erreicht hohe Render-Command-Raten, hebt die gemessene Frame-Kopplung aber nicht auf. Im 30-FPS-Test lag der RHIEndFrame-spezifische Completion-Takt praktisch exakt bei 30 Hz. Das aktuelle Problem ist damit eingegrenzt: Nicht der Stream-Timer, sondern die Primary-RHI-/D3D12-Submission der SafeCopy-Kette bestimmt die sichtbare Ready-Rate.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der nächste Schritt ist, die &#039;&#039;&#039;Frame-Kopplung der Primary-/SafeCopy-/Ready-Kette&#039;&#039;&#039; weiter zu zerlegen, ohne einen blockierenden Flush einzuführen. Erst danach sollte erneut gemessen werden, welche reale Worker- und Transferlatenz der Single Slot erreicht. Ein zweiter Slot oder Ringbuffer ist nur sinnvoll, wenn diese Messung echten Pipeline-Bedarf zeigt und der Read-vs-Write-Hazard zwischen Render-Consumer und erneut beschriebener Primary-Textur sauber modelliert ist.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Pro Worker existiert absichtlich nur ein persistenter Runtime-Slot. Mehrere parallele In-Flight-Jobs sowie Double-, Triple- oder Ring-Buffering fehlen noch.&lt;br /&gt;
* Die Primary-/SafeCopy-/Ready-Kette bleibt trotz zusätzlichem non-blocking &amp;lt;code&amp;gt;DispatchToRHIThread&amp;lt;/code&amp;gt; effektiv an den Frame-/Submission-Zyklus gekoppelt.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Der sichtbare TPS-Nachweis zeigt eine Worker-Compute-Textur, noch keine auf dem Worker gerenderte 3D-Szene. Echte UE-Szenen-Workloads, Benchmark-Wizard und Scheduler fehlen weiterhin.&lt;br /&gt;
* Die projektseitigen UpscalerTest-Dateien mit DisplayActor und Texture Stream liegen außerhalb des Engine-Git-Repositories und sind nicht Bestandteil von Commit &amp;lt;code&amp;gt;cbf56c2&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Primary-RHI-/D3D12-Submission untersuchen und die Frame-Kopplung ohne blockierende Flushes auflösen.&lt;br /&gt;
# Danach Quiet-Benchmarks wiederholen und die reale Single-Slot-Latenz bestimmen.&lt;br /&gt;
# Nur bei nachgewiesenem Bedarf einen zweiten Slot oder Ringbuffer mit Generation-, Fence-, Reuse- und Consumer-Hazard-Modell ergänzen.&lt;br /&gt;
# Ersten echten UE-Offload wie SceneCapture2D, CCTV, Spiegel, Minimap, Niagara oder unabhängigen Compute integrieren.&lt;br /&gt;
# Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 6. September 2026, Commit &amp;lt;code&amp;gt;cbf56c2&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Render_Hardware_Interface_(RHI)_in_Unreal_Engine_5&amp;diff=176</id>
		<title>Render Hardware Interface (RHI) in Unreal Engine 5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Render_Hardware_Interface_(RHI)_in_Unreal_Engine_5&amp;diff=176"/>
		<updated>2026-09-06T09:37:54Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Render Hardware Interface (RHI) in Unreal Engine 5 nach Render Hardware Interface (RHI): Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Render Hardware Interface (RHI)]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Render_Hardware_Interface_(RHI)&amp;diff=175</id>
		<title>Render Hardware Interface (RHI)</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Render_Hardware_Interface_(RHI)&amp;diff=175"/>
		<updated>2026-09-06T09:37:54Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Render Hardware Interface (RHI) in Unreal Engine 5 nach Render Hardware Interface (RHI): Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
Das &#039;&#039;&#039;Render Hardware Interface (RHI)&#039;&#039;&#039; ist die hardwarenahe Abstraktionsschicht des Unreal-Renderers. Rendering-Code arbeitet über ein gemeinsames Unreal-Interface, während das jeweils aktive Backend die Befehle auf eine konkrete Grafik-API wie Direct3D 12, Vulkan oder Metal abbildet.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Artikelstatus&lt;br /&gt;
|-&lt;br /&gt;
! Bezugsstand&lt;br /&gt;
| Unreal Engine 5.8&lt;br /&gt;
|-&lt;br /&gt;
! Letzte Aktualisierung&lt;br /&gt;
| 2. September 2026&lt;br /&gt;
|-&lt;br /&gt;
! Modul&lt;br /&gt;
| &amp;lt;code&amp;gt;RHI&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Zentrale Header&lt;br /&gt;
| &amp;lt;code&amp;gt;DynamicRHI.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RHICommandList.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RHIResources.h&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aufgabe des RHI ==&lt;br /&gt;
&lt;br /&gt;
Das RHI bildet eine gemeinsame Schnittstelle zwischen Unreals Renderer und den plattformspezifischen Grafik-APIs. Es abstrahiert unter anderem:&lt;br /&gt;
&lt;br /&gt;
* Grafik- und Compute-Pipelines&lt;br /&gt;
* Buffer und Texturen&lt;br /&gt;
* Shader und Shader-Parameter&lt;br /&gt;
* Render Passes&lt;br /&gt;
* Command Lists und Command Contexts&lt;br /&gt;
* Ressourcenübergänge und Synchronisation&lt;br /&gt;
* Queries, Fences und Readbacks&lt;br /&gt;
* Raytracing-Ressourcen und -Pipelines&lt;br /&gt;
&lt;br /&gt;
Die Abstraktion ist bewusst hardwarenah. Sie soll plattformunabhängigen Rendering-Code ermöglichen, ohne die Eigenschaften moderner Low-Level-APIs vollständig zu verbergen.&lt;br /&gt;
&lt;br /&gt;
== Grobe Einordnung im Renderer ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Spiel- und Engine-Systeme&lt;br /&gt;
        |&lt;br /&gt;
Renderer / Render Dependency Graph&lt;br /&gt;
        |&lt;br /&gt;
RHI-Befehle und RHI-Ressourcen&lt;br /&gt;
        |&lt;br /&gt;
plattformabhängiges RHI-Backend&lt;br /&gt;
        |&lt;br /&gt;
Direct3D 12 / Vulkan / Metal&lt;br /&gt;
        |&lt;br /&gt;
GPU und Treiber&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
High-Level-Rendering-Code wird in modernen UE-Versionen häufig über den [[Render Dependency Graph]] beschrieben. Bei der Ausführung werden daraus RHI-Befehle, die das aktive Backend anschließend in native API-Kommandos übersetzt.&lt;br /&gt;
&lt;br /&gt;
== Dynamisches RHI und Backends ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FDynamicRHI&amp;lt;/code&amp;gt; ist die zentrale Schnittstelle des zur Laufzeit gebundenen RHI-Backends. Konkrete Implementierungen stellen die Verbindung zur jeweiligen Grafik-API her. Dazu gehören beispielsweise Schnittstellen für Direct3D 12 und Vulkan.&lt;br /&gt;
&lt;br /&gt;
Das ausgewählte Backend wird während des Engine-Starts initialisiert. Welches RHI verwendet wird, hängt von Plattform, Projektkonfiguration und Startparametern ab. Das aktive Backend stellt die tatsächlichen Ressourcen, Command Contexts und Submit-Pfade bereit.&lt;br /&gt;
&lt;br /&gt;
Wichtig: RHI-Objekte sind Unreal-Abstraktionen. Ein &amp;lt;code&amp;gt;FRHIBuffer&amp;lt;/code&amp;gt; ist nicht selbst ein &amp;lt;code&amp;gt;ID3D12Resource&amp;lt;/code&amp;gt;; das D3D12-Backend verwaltet darunter das native Objekt.&lt;br /&gt;
&lt;br /&gt;
== RHI-Ressourcen ==&lt;br /&gt;
&lt;br /&gt;
Viele GPU-Objekte werden als von &amp;lt;code&amp;gt;FRHIResource&amp;lt;/code&amp;gt; abgeleitete Typen dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! RHI-Typ&lt;br /&gt;
! Aufgabe&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Allgemeiner GPU-Buffer mit Größe, Stride und Nutzungsflags&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHITexture&amp;lt;/code&amp;gt;&lt;br /&gt;
| Texturressource einschließlich Format, Ausdehnung und Mip-Struktur&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIShaderResourceView&amp;lt;/code&amp;gt; (SRV)&lt;br /&gt;
| Lesende Sicht auf eine Ressource für Shader&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIUnorderedAccessView&amp;lt;/code&amp;gt; (UAV)&lt;br /&gt;
| Schreibende beziehungsweise ungeordnet lesend-schreibende Sicht&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIUniformBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Gebündelte konstante Shader-Parameter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIGPUFence&amp;lt;/code&amp;gt;&lt;br /&gt;
| GPU-seitiger Synchronisationspunkt&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIGPUBufferReadback&amp;lt;/code&amp;gt;&lt;br /&gt;
| Hilfsobjekt für asynchrones Zurücklesen eines Buffers&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ressourcen besitzen Beschreibungen und Nutzungsflags. Diese Informationen sind wichtig, weil moderne APIs Speicher, Bindung und erlaubte Zugriffe explizit behandeln.&lt;br /&gt;
&lt;br /&gt;
== Command Lists ==&lt;br /&gt;
&lt;br /&gt;
Rendering- und Compute-Arbeit wird über RHI Command Lists aufgezeichnet. Sie enthalten keine beliebige Spiellogik, sondern eine geordnete Folge grafischer Befehle.&lt;br /&gt;
&lt;br /&gt;
=== Wichtige Typen ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIComputeCommandList&amp;lt;/code&amp;gt; stellt die gemeinsame Compute-Schnittstelle bereit.&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHICommandList&amp;lt;/code&amp;gt; erweitert diese um Grafikbefehle, beispielsweise Render Passes und Draw-Aufrufe.&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHICommandListImmediate&amp;lt;/code&amp;gt; ist die unmittelbare Haupt-Command-List. Sie sollte nicht ohne Not verwendet werden, wenn parallele Ausführung erhalten bleiben soll.&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHICommandListExecutor&amp;lt;/code&amp;gt; koordiniert Übersetzung und Übermittlung aufgezeichneter Command Lists.&lt;br /&gt;
&lt;br /&gt;
Typische Befehle umfassen:&lt;br /&gt;
&lt;br /&gt;
* Render Pass beginnen und beenden&lt;br /&gt;
* Grafik- oder Compute-PSO setzen&lt;br /&gt;
* Shader-Parameter binden&lt;br /&gt;
* Vertex- und Index-Buffer setzen&lt;br /&gt;
* Draw oder Dispatch auslösen&lt;br /&gt;
* Ressourcen kopieren&lt;br /&gt;
* Ressourcenübergänge einleiten&lt;br /&gt;
* GPU-Fences schreiben&lt;br /&gt;
&lt;br /&gt;
== Threads und Befehlsfluss ==&lt;br /&gt;
&lt;br /&gt;
Unreals Rendering arbeitet über mehrere Ebenen. Vereinfacht gilt:&lt;br /&gt;
&lt;br /&gt;
# Der &#039;&#039;&#039;Game Thread&#039;&#039;&#039; aktualisiert die Spielwelt und stößt Rendering-Arbeit an.&lt;br /&gt;
# Der &#039;&#039;&#039;Render Thread&#039;&#039;&#039; verarbeitet die Render-Szene und zeichnet plattformunabhängige RHI-Befehle auf.&lt;br /&gt;
# Der &#039;&#039;&#039;RHI Thread&#039;&#039;&#039; kann diese Befehle für das aktive Backend übersetzen und an die Grafik-API weitergeben.&lt;br /&gt;
# Das Backend übermittelt native Command Lists an die GPU-Queues.&lt;br /&gt;
&lt;br /&gt;
Diese Trennung erlaubt Parallelisierung. Renderer-Code sollte deshalb nicht unnötig blockieren oder voraussetzen, dass ein aufgezeichneter Befehl sofort auf der GPU ausgeführt wurde.&lt;br /&gt;
&lt;br /&gt;
== Pipeline State Objects ==&lt;br /&gt;
&lt;br /&gt;
Moderne Grafik-APIs bündeln viele Zustände in &#039;&#039;&#039;Pipeline State Objects&#039;&#039;&#039; (PSOs). Unreal unterscheidet unter anderem:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIGraphicsPipelineState&amp;lt;/code&amp;gt; für Grafik-Pipelines&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIComputePipelineState&amp;lt;/code&amp;gt; für Compute-Pipelines&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIRayTracingPipelineState&amp;lt;/code&amp;gt; für Raytracing&lt;br /&gt;
&lt;br /&gt;
Ein Grafik-PSO beschreibt beispielsweise Shader-Stufen, Blend-, Rasterizer- und Depth-Stencil-Zustand sowie Render-Target-Formate. Ein Compute-PSO benötigt vor allem den Compute Shader und die zum Backend gehörende Bindungsstruktur.&lt;br /&gt;
&lt;br /&gt;
Häufig wechselnde oder erst während des Spiels kompilierte PSOs können Ruckler verursachen. Deshalb sind PSO-Caching und eine frühzeitige Vorbereitung wichtiger Zustände für reale Projekte relevant.&lt;br /&gt;
&lt;br /&gt;
== Ressourcenstatus und Barriers ==&lt;br /&gt;
&lt;br /&gt;
In Direct3D 12 und Vulkan müssen Ressourcenzugriffe explizit synchronisiert werden. Eine Ressource kann beispielsweise als Kopierziel, Shader-Eingabe oder UAV-Ausgabe verwendet werden. Der Status muss vor der jeweiligen Nutzung passen.&lt;br /&gt;
&lt;br /&gt;
Das RHI beschreibt Zugriffe unter anderem über RHI-Zustände und Übergänge. Bei RDG-Ressourcen übernimmt der Render Dependency Graph einen großen Teil der Planung, sofern alle Ressourcen korrekt als Pass-Parameter angegeben wurden.&lt;br /&gt;
&lt;br /&gt;
Fehlerhafte Übergänge können zu Validierungsfehlern, beschädigten Ergebnissen oder GPU-Hängern führen. Besondere Vorsicht ist nötig, wenn Ressourcen außerhalb von RDG manuell verwaltet oder zwischen unabhängigen Queues ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
== Synchronisation und Readback ==&lt;br /&gt;
&lt;br /&gt;
CPU und GPU arbeiten asynchron. Ein Submit bedeutet deshalb nicht, dass die GPU-Arbeit bereits beendet ist.&lt;br /&gt;
&lt;br /&gt;
Typische Werkzeuge sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;GPU-Fence:&#039;&#039;&#039; signalisiert das Erreichen eines Punkts in einer GPU-Queue&lt;br /&gt;
* &#039;&#039;&#039;Queue- beziehungsweise Pipeline-Übergänge:&#039;&#039;&#039; koordinieren Graphics- und Async-Compute-Arbeit&lt;br /&gt;
* &#039;&#039;&#039;Readback-Ressourcen:&#039;&#039;&#039; übertragen Ergebnisse in CPU-lesbaren Speicher&lt;br /&gt;
* &#039;&#039;&#039;Staging-Buffer:&#039;&#039;&#039; dienen als Zwischenspeicher für Upload oder Readback&lt;br /&gt;
&lt;br /&gt;
Die CPU sollte nur dann auf Readback-Daten zugreifen, wenn der zugehörige Fence abgeschlossen ist. Häufige synchrone Wartezeiten zerstören die Parallelität und sollten im normalen Frame-Pfad vermieden werden.&lt;br /&gt;
&lt;br /&gt;
== RHI und Render Dependency Graph ==&lt;br /&gt;
&lt;br /&gt;
RHI und RDG erfüllen unterschiedliche Aufgaben:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Ebene&lt;br /&gt;
! Verantwortung&lt;br /&gt;
|-&lt;br /&gt;
| RDG&lt;br /&gt;
| Beschreibung von Passes und Abhängigkeiten, Ressourcenlebenszeiten, Culling, Planung und Parallelisierung&lt;br /&gt;
|-&lt;br /&gt;
| RHI&lt;br /&gt;
| Hardwarenahe Befehle, Ressourcen und Pipeline-Zustände für das aktive Grafik-Backend&lt;br /&gt;
|-&lt;br /&gt;
| Plattform-RHI&lt;br /&gt;
| Übersetzung in native Direct3D-12-, Vulkan- oder Metal-Objekte und -Kommandos&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für neuen High-Level-Rendering-Code ist RDG meist der bevorzugte Einstieg. Direkter RHI-Code bleibt wichtig, wenn hardwarenahe Kontrolle nötig ist oder ein System unterhalb beziehungsweise außerhalb des normalen Render Graphs arbeitet.&lt;br /&gt;
&lt;br /&gt;
== Debugging und Diagnose ==&lt;br /&gt;
&lt;br /&gt;
Bei RHI-Problemen helfen unter anderem:&lt;br /&gt;
&lt;br /&gt;
* aussagekräftige Namen für Ressourcen und Render-Passes&lt;br /&gt;
* Grafik-API-Debug-Layer und GPU-basierte Validierung in Entwicklungsumgebungen&lt;br /&gt;
* RHI- und RDG-Validierung&lt;br /&gt;
* Unreal Insights sowie RDG Insights&lt;br /&gt;
* GPU-Captures mit Werkzeugen wie RenderDoc oder PIX, sofern die Konfiguration dies unterstützt&lt;br /&gt;
* Prüfung von Nutzungsflags, Ressourcenstatus und Queue-Zugehörigkeit&lt;br /&gt;
* Kontrolle der Lebensdauer nativer und abstrahierter Ressourcen&lt;br /&gt;
* Fences und Readback-Zeitpunkte protokollieren&lt;br /&gt;
&lt;br /&gt;
== Bezug zum Heterogeneous-Multi-GPU-Projekt ==&lt;br /&gt;
&lt;br /&gt;
Das Projekt [[UE5 Heterogeneous Multi-GPU]] verwendet für die Primary GPU weiterhin Unreals regulären D3D12-RHI-Pfad. Die Intel-Worker-GPU wird dagegen aktuell über ein separat erzeugtes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt; mit eigener Direct Command Queue, eigenen Command Lists und eigener Fence-Synchronisation angesprochen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UE-Renderer&lt;br /&gt;
    |&lt;br /&gt;
    +-- reguläres D3D12-RHI --&amp;gt; RTX 5060 (Primary)&lt;br /&gt;
    |&lt;br /&gt;
    +-- ExperimentalMultiGPU --&amp;gt; separates ID3D12Device&lt;br /&gt;
                                  --&amp;gt; Intel UHD (Worker)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Worker-Pfad ist nicht automatisch Bestandteil von &amp;lt;code&amp;gt;GDynamicRHI&amp;lt;/code&amp;gt;. Dadurch ergeben sich besondere Aufgaben:&lt;br /&gt;
&lt;br /&gt;
* native Ressourcen des Worker-Devices dürfen nicht wie normale RHI-Ressourcen der Primary GPU behandelt werden&lt;br /&gt;
* Shader-Bytecode muss mit dem Zielgerät und dessen Fähigkeiten kompatibel sein&lt;br /&gt;
* Root Signature und PSO müssen für das Worker-Device erzeugt werden&lt;br /&gt;
* Command Allocator, Command List, Queue und Fence benötigen eine eigene Lebensdauerverwaltung&lt;br /&gt;
* Datenübertragung zwischen Primary und Worker muss ausdrücklich geplant werden&lt;br /&gt;
* Cross-Adapter-Ressourcen benötigen passende Heap- und Ressourcenflags; andernfalls ist ein Transfer über System-RAM erforderlich&lt;br /&gt;
* Fehler- und Device-Removal-Behandlung muss pro Device erfolgen&lt;br /&gt;
&lt;br /&gt;
Langfristig kann geprüft werden, welche Teile sinnvoll als eigene Unreal-Abstraktion oberhalb der nativen Devices modelliert werden. Eine direkte Erweiterung des regulären RHI um heterogene unabhängige Devices wäre dagegen ein erheblich größerer Eingriff in Engine-Annahmen, Ressourcenverwaltung und Scheduling.&lt;br /&gt;
&lt;br /&gt;
== Praktische Merksätze ==&lt;br /&gt;
&lt;br /&gt;
* RHI abstrahiert die Grafik-API, aber nicht die grundlegenden Regeln moderner GPUs.&lt;br /&gt;
* Command-Aufzeichnung und GPU-Ausführung finden zeitlich getrennt statt.&lt;br /&gt;
* Ressourcenstatus, Queue-Zugehörigkeit und Lebensdauer müssen immer eindeutig sein.&lt;br /&gt;
* RDG ist für neuen High-Level-Code meist geeigneter als manuelle Immediate-RHI-Befehle.&lt;br /&gt;
* Native Objekte verschiedener D3D12-Devices sind nicht beliebig austauschbar.&lt;br /&gt;
* Für einen unabhängigen Worker-Pfad müssen Synchronisation und Transfers ausdrücklich entworfen werden.&lt;br /&gt;
&lt;br /&gt;
== Quellen und weiterführende Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/graphics-programming-overview-for-unreal-engine Graphics Programming Overview] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI RHI API Reference] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FDynamicRHI FDynamicRHI] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI/FRHICommandList FRHICommandList] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI/FRHIBuffer FRHIBuffer] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI/FRHITexture FRHITexture] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/parallel-rendering-overview-for-unreal-engine Parallel Rendering Overview] – Epic Games, UE 5.8&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Dieser Artikel ist eine eigenständige deutschsprachige Zusammenfassung mit Projektbezug und keine vollständige Übersetzung der Epic-Dokumentation.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:RHI]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Grafikprogrammierung]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Render_Dependency_Graph_(RDG)_in_Unreal_Engine_5&amp;diff=174</id>
		<title>Render Dependency Graph (RDG) in Unreal Engine 5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Render_Dependency_Graph_(RDG)_in_Unreal_Engine_5&amp;diff=174"/>
		<updated>2026-09-06T09:37:44Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Render Dependency Graph (RDG) in Unreal Engine 5 nach Render Dependency Graph (RDG): Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Render Dependency Graph (RDG)]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Render_Dependency_Graph_(RDG)&amp;diff=173</id>
		<title>Render Dependency Graph (RDG)</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Render_Dependency_Graph_(RDG)&amp;diff=173"/>
		<updated>2026-09-06T09:37:43Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Render Dependency Graph (RDG) in Unreal Engine 5 nach Render Dependency Graph (RDG): Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;Render Dependency Graph&#039;&#039;&#039; (&#039;&#039;&#039;RDG&#039;&#039;&#039;, auch Render Graph) organisiert Renderarbeit als Graph aus &#039;&#039;Passes&#039;&#039; und Ressourcen. Ein Pass ist ein Arbeitsschritt auf CPU/GPU; Ressourcen sind vor allem Texturen und Buffer. Statt Übergänge, Lebensdauer und Synchronisation überall von Hand zu steuern, beschreibt der Code, welche Ressourcen ein Pass liest oder schreibt. RDG leitet daraus die Reihenfolge ab.&lt;br /&gt;
&lt;br /&gt;
== Warum RDG? ==&lt;br /&gt;
&lt;br /&gt;
RDG kann unbenutzte Passes entfernen, temporäre Ressourcen nur so lange wie nötig halten, Speicher zwischen nicht gleichzeitig lebenden Ressourcen wiederverwenden und Barrieren automatisch setzen. Es unterstützt außerdem Async Compute und paralleles Aufzeichnen von Command Lists. Das senkt Fehlergefahr und kann CPU-, GPU- und Speicherarbeit besser überlappen.&lt;br /&gt;
&lt;br /&gt;
== Das Grundmodell ==&lt;br /&gt;
&lt;br /&gt;
# Ein &amp;lt;code&amp;gt;FRDGBuilder&amp;lt;/code&amp;gt; sammelt Passes und Ressourcen für den Graphen.&lt;br /&gt;
# Texturen oder Buffer werden im Graphen erzeugt oder als externe Ressourcen registriert.&lt;br /&gt;
# Parameterstrukturen nennen die Eingaben und Ausgaben eines Passes. Daraus erkennt RDG echte Abhängigkeiten.&lt;br /&gt;
# &amp;lt;code&amp;gt;AddPass&amp;lt;/code&amp;gt; fügt die auszuführende Arbeit hinzu.&lt;br /&gt;
# &amp;lt;code&amp;gt;Execute()&amp;lt;/code&amp;gt; kompiliert den Graphen, entfernt tote Arbeit und führt die verbleibenden Passes aus.&lt;br /&gt;
&lt;br /&gt;
Ein RDG-Handle wie &amp;lt;code&amp;gt;FRDGTextureRef&amp;lt;/code&amp;gt; ist kein dauerhaft frei nutzbares RHI-Objekt. Seine Gültigkeit richtet sich nach dem Graphen. Soll ein Ergebnis außerhalb weiterleben, muss es über die dafür vorgesehenen Extract-/External-Mechanismen übergeben werden.&lt;br /&gt;
&lt;br /&gt;
== Kleines C++-Muster ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(&lt;br /&gt;
    Extent, PF_FloatRGBA, FClearValueBinding::Black,&lt;br /&gt;
    TexCreate_ShaderResource | TexCreate_UAV);&lt;br /&gt;
&lt;br /&gt;
FRDGTextureRef Output = GraphBuilder.CreateTexture(Desc, TEXT(&amp;quot;MyOutput&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
FMyShader::FParameters* Parameters =&lt;br /&gt;
    GraphBuilder.AllocParameters&amp;lt;FMyShader::FParameters&amp;gt;();&lt;br /&gt;
Parameters-&amp;gt;Output = GraphBuilder.CreateUAV(Output);&lt;br /&gt;
&lt;br /&gt;
FComputeShaderUtils::AddPass(&lt;br /&gt;
    GraphBuilder,&lt;br /&gt;
    RDG_EVENT_NAME(&amp;quot;MyComputePass&amp;quot;),&lt;br /&gt;
    ComputeShader,&lt;br /&gt;
    Parameters,&lt;br /&gt;
    GroupCount);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entscheidend ist nicht die genaue Shaderlogik, sondern dass &amp;lt;code&amp;gt;Parameters&amp;lt;/code&amp;gt; den Schreibzugriff auf &amp;lt;code&amp;gt;Output&amp;lt;/code&amp;gt; sichtbar macht. Versteckte Ressourcen-Zugriffe außerhalb der Parameterstruktur verhindern korrekte Planung und Validierung.&lt;br /&gt;
&lt;br /&gt;
== Praxisregeln ==&lt;br /&gt;
&lt;br /&gt;
* Ressourcen-Zugriffe vollständig in den Passparametern deklarieren.&lt;br /&gt;
* RDG-Ressourcen nicht über ihre vorgesehene Lebensdauer hinaus speichern.&lt;br /&gt;
* Pass-Lambdas nur mit Daten füttern, die bei ihrer späteren Ausführung noch gültig sind.&lt;br /&gt;
* Seiteneffekte vermeiden: Ein Pass ohne sichtbaren Beitrag kann entfernt werden. Notwendige Sonderfälle müssen bewusst mit passenden Pass-Flags modelliert werden.&lt;br /&gt;
* Ereignisnamen mit &amp;lt;code&amp;gt;RDG_EVENT_NAME&amp;lt;/code&amp;gt; vergeben; das macht Captures und RDG Insights lesbar.&lt;br /&gt;
* Erst messen, dann optimieren. RDG Insights visualisiert Graph, Abhängigkeiten und Ressourcenlebensdauer.&lt;br /&gt;
&lt;br /&gt;
== Bezug: UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Für Jans Projekt ist RDG die passende Ebene, um Abhängigkeiten zwischen GPU-Arbeit explizit zu machen. Das ist eine Voraussetzung für kontrollierte Überlappung und Synchronisation. RDG verteilt einen Pass jedoch &#039;&#039;&#039;nicht automatisch&#039;&#039;&#039; auf unterschiedliche oder heterogene GPUs.&lt;br /&gt;
&lt;br /&gt;
Die GPU-Auswahl liegt tiefer in RHI und Multi-GPU-Code, unter anderem über &amp;lt;code&amp;gt;FRHIGPUMask&amp;lt;/code&amp;gt;. Für einen Prototyp sollten deshalb drei Fragen getrennt geprüft werden:&lt;br /&gt;
&lt;br /&gt;
* Ist der RDG-Graph fachlich korrekt und frei von versteckten Abhängigkeiten?&lt;br /&gt;
* Welche Passes und Ressourcen dürfen auf welcher GPU liegen?&lt;br /&gt;
* Wo entstehen explizite Cross-GPU-Kopien und Synchronisationskosten?&lt;br /&gt;
&lt;br /&gt;
RDG Insights hilft bei der ersten Frage. Für GPU-Zuordnung, Transfers und Adapter-Fähigkeiten sind zusätzlich RHI-Quellcode, Plattform-RHI und GPU-Captures nötig.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/render-dependency-graph-in-unreal-engine?application_version=5.8 Epic: Render Dependency Graph (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RenderCore/FRDGBuilder?application_version=5.8 Epic API: FRDGBuilder (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RenderCore/FComputeShaderUtils__AddPass?application_version=5.8 Epic API: FComputeShaderUtils::AddPass (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FRHIGPUMask?application_version=5.8 Epic API: FRHIGPUMask (UE 5.8)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Paralleles_Rendering_und_RHI-Thread_in_Unreal_Engine_5&amp;diff=172</id>
		<title>Paralleles Rendering und RHI-Thread in Unreal Engine 5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Paralleles_Rendering_und_RHI-Thread_in_Unreal_Engine_5&amp;diff=172"/>
		<updated>2026-09-06T09:37:33Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Paralleles Rendering und RHI-Thread in Unreal Engine 5 nach Paralleles Rendering und RHI-Thread: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Paralleles Rendering und RHI-Thread]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Paralleles_Rendering_und_RHI-Thread&amp;diff=171</id>
		<title>Paralleles Rendering und RHI-Thread</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Paralleles_Rendering_und_RHI-Thread&amp;diff=171"/>
		<updated>2026-09-06T09:37:33Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Paralleles Rendering und RHI-Thread in Unreal Engine 5 nach Paralleles Rendering und RHI-Thread: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Paralleles Rendering&#039;&#039;&#039; verteilt die CPU-Arbeit des Renderers auf mehrere Threads. Der &#039;&#039;&#039;RHI Thread&#039;&#039;&#039; ist dabei der Thread, der Unreal-Befehle über das &#039;&#039;Render Hardware Interface&#039;&#039; (RHI) in Aufrufe der jeweiligen Grafik-API wie DirectX 12 oder Vulkan übersetzt. Das ist CPU-Parallelität und nicht automatisch Multi-GPU-Rendering.&lt;br /&gt;
&lt;br /&gt;
== Die beteiligten Stufen ==&lt;br /&gt;
&lt;br /&gt;
; Game Thread&lt;br /&gt;
: Aktualisiert Spielwelt, Actors und UObjects und übergibt Renderzustand asynchron an den Renderer.&lt;br /&gt;
; Render Thread&lt;br /&gt;
: Baut aus der Szene plattformunabhängige Renderbefehle und Command Lists auf. Eine Command List ist eine geordnete Liste von Grafikbefehlen.&lt;br /&gt;
; RHI Thread&lt;br /&gt;
: Übersetzt bzw. führt diese Listen im Backend für die konkrete Grafik-API aus.&lt;br /&gt;
; GPU&lt;br /&gt;
: Arbeitet die eingereichten Grafik- und Compute-Kommandos ab.&lt;br /&gt;
&lt;br /&gt;
Diese Stufen können an verschiedenen Frames arbeiten. Unreal bewahrt dabei die Einreichungsreihenfolge, die auch ein serieller Renderer hätte. Synchronisationspunkte und Fences sorgen dafür, dass ein Verbraucher nicht vor seinem Produzenten läuft.&lt;br /&gt;
&lt;br /&gt;
== Wo die Parallelität entsteht ==&lt;br /&gt;
&lt;br /&gt;
Der Render Thread kann Command Lists in parallelen Aufgaben vorbereiten. Auf geeigneten Plattformen kann auch das RHI-Backend mehrere Listen parallel übersetzen. Der getrennte RHI Thread verhindert, dass die Übersetzung aller API-Aufrufe den Render Thread direkt blockiert.&lt;br /&gt;
&lt;br /&gt;
Nicht jeder Vorgang passt in dieses Modell. Bestimmte Lock-/Unlock- oder Ressourcenoperationen können einen Flush erzwingen oder Daten kopieren und später einreihen. Häufige erzwungene Synchronisation nimmt den Threads den möglichen Zeitgewinn.&lt;br /&gt;
&lt;br /&gt;
== Thread-Sicherheit in eigenem Code ==&lt;br /&gt;
&lt;br /&gt;
Rendercode darf nicht einfach auf veränderliche &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;- oder Actor-Daten des Game Threads zugreifen. Sonst entsteht eine &#039;&#039;Race Condition&#039;&#039;: Das Ergebnis hängt vom zufälligen zeitlichen Ablauf der Threads ab.&lt;br /&gt;
&lt;br /&gt;
Das übliche Muster ist:&lt;br /&gt;
&lt;br /&gt;
# Der Game Thread besitzt Gameplay-Daten.&lt;br /&gt;
# Benötigte Werte werden in eine renderseitige Struktur oder einen Scene Proxy kopiert.&lt;br /&gt;
# Ein Render Command übergibt diese Kopie an den Render Thread.&lt;br /&gt;
# Ressourcen werden erst freigegeben, wenn Fence oder vorgesehener Cleanup-Mechanismus ihre Nutzung abgeschlossen meldet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FlushRenderingCommands&amp;lt;/code&amp;gt; blockiert den Game Thread bis der Renderer aufgeholt hat. Das kann für seltene Editor-/Offline-Operationen sinnvoll sein, sollte aber nicht zum normalen Gameplay-Pfad werden.&lt;br /&gt;
&lt;br /&gt;
== Prüfen und eingrenzen ==&lt;br /&gt;
&lt;br /&gt;
Unreal Insights zeigt Game-, Render- und RHI-Thread getrennt in Timing Insights. Verglichen werden sollten identische, reproduzierbare Szenen und mehrere Frames.&lt;br /&gt;
&lt;br /&gt;
Nützliche Diagnosevariablen aus der Epic-Dokumentation:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHIThread.Enable 0&amp;lt;/code&amp;gt; deaktiviert den separaten RHI Thread.&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHICmdUseDeferredContexts 0&amp;lt;/code&amp;gt; deaktiviert die Backend-Parallelisierung.&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHICmdUseParallelAlgorithms 0&amp;lt;/code&amp;gt; deaktiviert die Frontend-Parallelisierung.&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHICmdBypass 1&amp;lt;/code&amp;gt; umgeht Command Lists; dies wird nur berücksichtigt, wenn der RHI Thread deaktiviert ist.&lt;br /&gt;
&lt;br /&gt;
Diese Schalter sind Diagnosewerkzeuge, keine pauschalen Performance-Tipps. Wirkung und Standard können von Plattform und RHI abhängen. Für belastbare Aussagen immer in der Zielkonfiguration messen.&lt;br /&gt;
&lt;br /&gt;
== Typische Befunde ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Render Thread voll ausgelastet, RHI Thread wartet:&#039;&#039;&#039; Engpass eher beim Aufbau der Renderarbeit.&lt;br /&gt;
* &#039;&#039;&#039;RHI Thread voll ausgelastet:&#039;&#039;&#039; Übersetzung oder Treiberarbeit begrenzt die CPU-Seite.&lt;br /&gt;
* &#039;&#039;&#039;Viele Flushes/Fences:&#039;&#039;&#039; Zu enge Synchronisation oder ungeeignete Ressourcenpfade untersuchen.&lt;br /&gt;
* &#039;&#039;&#039;GPU voll ausgelastet, CPU-Threads mit Luft:&#039;&#039;&#039; Parallelisierung der CPU behebt den eigentlichen GPU-Engpass nicht.&lt;br /&gt;
&lt;br /&gt;
== Bezug: UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Für Jans Projekt müssen zwei Achsen getrennt betrachtet werden:&lt;br /&gt;
&lt;br /&gt;
* Parallel Rendering und RHI Thread verteilen hauptsächlich &#039;&#039;&#039;CPU-Arbeit&#039;&#039;&#039;.&lt;br /&gt;
* Heterogeneous Multi-GPU verteilt &#039;&#039;&#039;GPU-Arbeit und Ressourcen&#039;&#039;&#039; auf mehrere Adapter.&lt;br /&gt;
&lt;br /&gt;
Eine zweite GPU hilft daher nicht automatisch bei einem RHI-Thread-Limit. Umgekehrt kann ein langsamer serieller CPU-Pfad mehrere GPUs unterfüttern. Die offizielle RHI-API beschreibt Fähigkeiten wie Multithreading und parallele RHI-Ausführung; &amp;lt;code&amp;gt;FRHIGPUMask&amp;lt;/code&amp;gt; repräsentiert aktive GPU-Indizes. Ob heterogene Adapter einen konkreten Pfad unterstützen, muss jedoch für D3D12/Vulkan, Treiber, Speicherfreigabe und Kopierpfad separat validiert werden.&lt;br /&gt;
&lt;br /&gt;
Praktischer Messplan: zuerst Single-GPU-Baseline in Unreal Insights, dann RHI Thread und Parallelalgorithmen einzeln vergleichen, anschließend erst Multi-GPU aktivieren und CPU-Zeiten, GPU-Zeiten sowie Transferkosten getrennt erfassen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/parallel-rendering-overview-for-unreal-engine?application_version=5.8 Epic: Parallel Rendering Overview (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/threaded-rendering-in-unreal-engine?application_version=5.8 Epic: Threaded Rendering (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-insights-in-unreal-engine?application_version=5.8 Epic: Unreal Insights (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FRHIGlobals?application_version=5.8 Epic API: FRHIGlobals (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FRHIGPUMask?application_version=5.8 Epic API: FRHIGPUMask (UE 5.8)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Multi-Process_Rendering_und_Multi-GPU_in_Unreal_Engine_5&amp;diff=170</id>
		<title>Multi-Process Rendering und Multi-GPU in Unreal Engine 5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Multi-Process_Rendering_und_Multi-GPU_in_Unreal_Engine_5&amp;diff=170"/>
		<updated>2026-09-06T09:37:23Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Multi-Process Rendering und Multi-GPU in Unreal Engine 5 nach Multi-Process Rendering und Multi-GPU: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Multi-Process Rendering und Multi-GPU]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Multi-Process_Rendering_und_Multi-GPU&amp;diff=169</id>
		<title>Multi-Process Rendering und Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Multi-Process_Rendering_und_Multi-GPU&amp;diff=169"/>
		<updated>2026-09-06T09:37:23Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Multi-Process Rendering und Multi-GPU in Unreal Engine 5 nach Multi-Process Rendering und Multi-GPU: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel beschreibt Epics offiziell dokumentierte nDisplay-Verfahren.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multi-Process Rendering&#039;&#039;&#039; und &#039;&#039;&#039;Multi-GPU (mGPU)&#039;&#039;&#039; verteilen bei nDisplay Rendering-Arbeit auf mehrere Grafikkarten. Sie benutzen ähnliche Hardware, arbeiten intern aber unterschiedlich. Beide Verfahren sind auf virtuelle Produktion und große, synchronisierte Anzeigeflächen ausgerichtet.&lt;br /&gt;
&lt;br /&gt;
== Begriffe kurz erklärt ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;nDisplay&#039;&#039;&#039; verteilt Unreal-Ausgaben auf einen Verbund aus Rechnern, Displays und Render-Viewports.&lt;br /&gt;
* Ein &#039;&#039;&#039;Viewport&#039;&#039;&#039; ist der zu rendernde Bildausschnitt.&lt;br /&gt;
* Beim &#039;&#039;&#039;Inner Frustum&#039;&#039;&#039; rendert eine ICVFX-Kamera den für die reale Kamera sichtbaren Bereich; das &#039;&#039;&#039;Outer Frustum&#039;&#039;&#039; füllt den übrigen LED-Hintergrund.&lt;br /&gt;
* Ein &#039;&#039;&#039;Prozess&#039;&#039;&#039; ist eine laufende Instanz der Unreal-Anwendung.&lt;br /&gt;
&lt;br /&gt;
== Multi-Process Rendering ==&lt;br /&gt;
&lt;br /&gt;
Multi-Process startet pro Render-Rechner zwei getrennte Unreal-Prozesse:&lt;br /&gt;
&lt;br /&gt;
# Der &#039;&#039;&#039;Onscreen-Knoten&#039;&#039;&#039; läuft auf der primären GPU, rendert beispielsweise das Outer Frustum, setzt das Endbild zusammen und gibt es aus.&lt;br /&gt;
# Der &#039;&#039;&#039;Offscreen-Knoten&#039;&#039;&#039; läuft headless, also ohne sichtbares Fenster, auf der zweiten GPU und rendert beispielsweise das Inner Frustum.&lt;br /&gt;
# Zwischen den Prozessen wird nur die fertig gerenderte Textur über CPU und Mainboard übertragen. Der Onscreen-Knoten fügt sie in sein Bild ein.&lt;br /&gt;
&lt;br /&gt;
Epic bezeichnet Multi-Process für die meisten Szenen als schneller als das ältere mGPU-Verfahren. Es ist außerdem Epics empfohlener Weg für mehrere NVIDIA-Ada-Lovelace-GPUs, weil diese kein NVLink unterstützen.&lt;br /&gt;
&lt;br /&gt;
=== Voraussetzungen und Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Mindestens zwei GPUs; SLI muss deaktiviert sein. Premium Mosaic ist ungeeignet, weil es SLI aktiviert.&lt;br /&gt;
* Im nDisplay Config Asset erhält der Onscreen-Knoten typischerweise &#039;&#039;&#039;Graphics Adapter 0&#039;&#039;&#039;. Der zusätzliche Offscreen-Knoten erhält typischerweise &#039;&#039;&#039;Graphics Adapter 1&#039;&#039;&#039; und &#039;&#039;&#039;Headless Rendering&#039;&#039;&#039;. Die tatsächliche Nummerierung muss am Rechner geprüft werden.&lt;br /&gt;
* Für die ICVFX-Kamera werden Media Output und Media Input mit demselben eindeutigen, groß-/kleinschreibungssensitiven Namen verbunden.&lt;br /&gt;
* Der Eingang wird &#039;&#039;&#039;Framelocked&#039;&#039;&#039;, damit die Textur zum richtigen Frame gehört. Epic verwendet im Beispiel außerdem &#039;&#039;&#039;Zero Latency&#039;&#039;&#039;.&lt;br /&gt;
* Beide Knoten werden in Switchboard verbunden und gemeinsam gestartet; pro Rechner genügt ein Switchboard Listener.&lt;br /&gt;
&lt;br /&gt;
== Klassisches nDisplay Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Beim mGPU-Modus läuft grundsätzlich eine Unreal-Instanz auf dem Rechner. Ein Viewport oder Inner Frustum wird über seinen &#039;&#039;&#039;GPUIndex&#039;&#039;&#039; einer GPU zugewiesen. Das Ergebnis wird zur ausgebenden GPU kopiert und dort zusammengesetzt.&lt;br /&gt;
&lt;br /&gt;
Mit NVIDIA NVLink kann die Übertragung direkt von GPU zu GPU erfolgen. Ohne NVLink beschreibt Epic einen Peer-to-Peer-Transfer, der über CPU und PCIe langsamer sein kann. Zur Aktivierung:&lt;br /&gt;
&lt;br /&gt;
# Im nDisplay Config Asset &#039;&#039;&#039;Configuration &amp;gt; Render Frame Settings &amp;gt; Multi GPU Mode&#039;&#039;&#039; einschalten.&lt;br /&gt;
# Am Viewport oder an der ICVFX-Kamera den gewünschten &#039;&#039;&#039;GPUIndex&#039;&#039;&#039; setzen.&lt;br /&gt;
# In Switchboard &#039;&#039;&#039;Number of GPUs&#039;&#039;&#039; auf die vorhandene GPU-Anzahl setzen.&lt;br /&gt;
&lt;br /&gt;
== Direkter Vergleich ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Punkt !! Multi-Process !! nDisplay mGPU&lt;br /&gt;
|-&lt;br /&gt;
| Unreal-Instanzen pro Rechner || Zwei getrennte Prozesse || Eine Instanz&lt;br /&gt;
|-&lt;br /&gt;
| Typische Aufteilung || Onscreen- und Offscreen-Knoten || Viewport/Inner Frustum per GPUIndex&lt;br /&gt;
|-&lt;br /&gt;
| Austausch || Fertige Textur über CPU/Mainboard || GPU-Ressourcen bzw. Bildtransfer; NVLink ist vorteilhaft&lt;br /&gt;
|-&lt;br /&gt;
| Epics Einordnung || In den meisten Fällen empfohlen und schneller, abhängig von der Szene || Älteres Verfahren; sinnvoll, wenn die konkrete Anlage davon profitiert&lt;br /&gt;
|-&lt;br /&gt;
| Wichtig || SLI deaktivieren || Multi GPU Mode und GPU-Anzahl konfigurieren&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Abgrenzung zu UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Jans Projekt [[UE5 Heterogeneous Multi-GPU]] ist &#039;&#039;&#039;keines dieser nDisplay-Verfahren&#039;&#039;&#039;. Es verfolgt explizites Direct3D-12-Unlinked-Multiadapter-Compute mit unterschiedlichen GPUs, derzeit Intel UHD als Worker neben einer NVIDIA RTX 5060. Arbeit, Cross-Adapter-Ressourcen und Synchronisation werden im eigenen Code gesteuert.&lt;br /&gt;
&lt;br /&gt;
Die entscheidenden Unterschiede:&lt;br /&gt;
&lt;br /&gt;
* Epic verteilt bei nDisplay fertige Renderaufgaben wie Viewports oder Frustums. Jans Ansatz will einzelne Compute-Arbeiten innerhalb einer angepassten Engine-/RHI-Pipeline auslagern.&lt;br /&gt;
* Multi-Process benötigt zwei Unreal-Prozesse; Jans Ansatz arbeitet nicht nach dem Onscreen-/Offscreen-Muster.&lt;br /&gt;
* nDisplay mGPU ist nicht automatisch herstellerheterogen und nicht gleichbedeutend mit explizitem D3D12-Unlinked-Multiadapter.&lt;br /&gt;
* Aus Epics Empfehlung für Multi-Process folgt daher keine Aussage über die Leistung oder Machbarkeit von Jans Forschungsansatz. Beide lösen verschiedene Probleme.&lt;br /&gt;
&lt;br /&gt;
== Praxisentscheidung ==&lt;br /&gt;
&lt;br /&gt;
* Für LED-Wände und ICVFX mit klar trennbarem Inner/Outer Frustum zuerst Multi-Process testen.&lt;br /&gt;
* Wenn eine bestehende nDisplay-Anlage mit Viewport-Zuweisung und passender Transferhardware arbeitet, mGPU gezielt benchmarken.&lt;br /&gt;
* Für allgemeine Spiele- oder Compute-Lastverteilung auf unterschiedlichen GPUs ist keiner der beiden nDisplay-Wege ein fertiger Ersatz für Jans eigene Multiadapter-Implementierung.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/multi-process-rendering-with-unreal-engine?lang=en-US Epic: Multi-Process Rendering] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/getting-started-with-multi-process-rendering-in-unreal-engine Epic: Getting Started with Multi-Process Rendering] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/ndisplay-overview-for-unreal-engine?lang=en-US Epic: nDisplay Overview – Multi-GPU Support] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:nDisplay]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Global_Shaders_und_Compute_Shader_in_Unreal_Engine_5&amp;diff=168</id>
		<title>Global Shaders und Compute Shader in Unreal Engine 5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Global_Shaders_und_Compute_Shader_in_Unreal_Engine_5&amp;diff=168"/>
		<updated>2026-09-06T09:37:13Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Global Shaders und Compute Shader in Unreal Engine 5 nach Global Shaders und Compute Shader: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Global Shaders und Compute Shader]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Global_Shaders_und_Compute_Shader&amp;diff=167</id>
		<title>Global Shaders und Compute Shader</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Global_Shaders_und_Compute_Shader&amp;diff=167"/>
		<updated>2026-09-06T09:37:13Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Global Shaders und Compute Shader in Unreal Engine 5 nach Global Shaders und Compute Shader: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Global Shaders&#039;&#039;&#039; 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.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Artikelstatus&lt;br /&gt;
|-&lt;br /&gt;
! Bezugsstand&lt;br /&gt;
| Unreal Engine 5.8&lt;br /&gt;
|-&lt;br /&gt;
! Letzte Aktualisierung&lt;br /&gt;
| 2. September 2026&lt;br /&gt;
|-&lt;br /&gt;
! Zentrale Klassen und Hilfen&lt;br /&gt;
| &amp;lt;code&amp;gt;FGlobalShader&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FComputeShaderUtils&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FRDGBuilder&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Shader-Dateityp&lt;br /&gt;
| &amp;lt;code&amp;gt;.usf&amp;lt;/code&amp;gt; (Unreal Shader File)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Einsatzgebiete ==&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
* Compute-Berechnungen auf Buffern oder Texturen&lt;br /&gt;
* eigene Post-Processing-Schritte&lt;br /&gt;
* Fullscreen-Passes&lt;br /&gt;
* Erzeugen, Kopieren oder Umwandeln von GPU-Daten&lt;br /&gt;
* Debug- und Visualisierungs-Passes&lt;br /&gt;
* experimentelle Rendering-Pipelines&lt;br /&gt;
&lt;br /&gt;
Ein Compute Shader ist dabei ein möglicher Shader-Typ. Er verarbeitet Daten in frei definierbaren Thread-Gruppen und erzeugt nicht unmittelbar Rastergrafik.&lt;br /&gt;
&lt;br /&gt;
== Bausteine eines Global Shaders ==&lt;br /&gt;
&lt;br /&gt;
Ein Global Shader besteht in der Regel aus mehreren Teilen:&lt;br /&gt;
&lt;br /&gt;
# einer Shader-Datei mit HLSL-Code (&amp;lt;code&amp;gt;.usf&amp;lt;/code&amp;gt;)&lt;br /&gt;
# einer von &amp;lt;code&amp;gt;FGlobalShader&amp;lt;/code&amp;gt; abgeleiteten C++-Klasse&lt;br /&gt;
# einer Parameterstruktur für Eingaben und Ausgaben&lt;br /&gt;
# einem Registrierungs-Makro, das Klasse, Datei, Einstiegspunkt und Shader-Stufe verbindet&lt;br /&gt;
# Code, der den Shader auswählt, Parameter bindet und den Dispatch oder Draw-Aufruf ausführt&lt;br /&gt;
&lt;br /&gt;
=== Speicherort der Shader-Dateien ===&lt;br /&gt;
&lt;br /&gt;
Engine-eigene Shader liegen unter &amp;lt;code&amp;gt;Engine/Shaders&amp;lt;/code&amp;gt;. Shader eines Plugins gehören in dessen &amp;lt;code&amp;gt;Shaders&amp;lt;/code&amp;gt;-Verzeichnis. Die Trennung hält experimentellen Code von den Engine-Dateien fern und erleichtert Updates sowie Versionsverwaltung.&lt;br /&gt;
&lt;br /&gt;
== Minimaler Compute Shader ==&lt;br /&gt;
&lt;br /&gt;
Das folgende vereinfachte Beispiel verdoppelt jeden Wert eines Eingabebuffers. Es dient der Orientierung und muss an die konkrete Modul- und Ressourcenstruktur angepasst werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;hlsl&amp;quot;&amp;gt;&lt;br /&gt;
StructuredBuffer&amp;amp;lt;uint&amp;amp;gt; InputValues;&lt;br /&gt;
RWStructuredBuffer&amp;amp;lt;uint&amp;amp;gt; OutputValues;&lt;br /&gt;
uint ElementCount;&lt;br /&gt;
&lt;br /&gt;
[numthreads(64, 1, 1)]&lt;br /&gt;
void MainCS(uint3 DispatchThreadId : SV_DispatchThreadID)&lt;br /&gt;
{&lt;br /&gt;
    const uint Index = DispatchThreadId.x;&lt;br /&gt;
    if (Index &amp;amp;gt;= ElementCount)&lt;br /&gt;
    {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    OutputValues[Index] = InputValues[Index] * 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;numthreads(64, 1, 1)&amp;lt;/code&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
== C++-Repräsentation ==&lt;br /&gt;
&lt;br /&gt;
Die C++-Klasse beschreibt den Shader gegenüber Unreal und definiert seine Parameter. Ein typisches Grundmuster sieht so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class FExampleComputeShader : public FGlobalShader&lt;br /&gt;
{&lt;br /&gt;
    DECLARE_GLOBAL_SHADER(FExampleComputeShader);&lt;br /&gt;
    SHADER_USE_PARAMETER_STRUCT(FExampleComputeShader, FGlobalShader);&lt;br /&gt;
&lt;br /&gt;
    BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )&lt;br /&gt;
        SHADER_PARAMETER(uint32, ElementCount)&lt;br /&gt;
        SHADER_PARAMETER_SRV(StructuredBuffer&amp;amp;lt;uint32&amp;amp;gt;, InputValues)&lt;br /&gt;
        SHADER_PARAMETER_UAV(RWStructuredBuffer&amp;amp;lt;uint32&amp;amp;gt;, OutputValues)&lt;br /&gt;
    END_SHADER_PARAMETER_STRUCT()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
IMPLEMENT_GLOBAL_SHADER(&lt;br /&gt;
    FExampleComputeShader,&lt;br /&gt;
    &amp;quot;/Plugin/Example/Private/ExampleCompute.usf&amp;quot;,&lt;br /&gt;
    &amp;quot;MainCS&amp;quot;,&lt;br /&gt;
    SF_Compute&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wichtige Punkte:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;DECLARE_GLOBAL_SHADER&amp;lt;/code&amp;gt; deklariert den Shader-Typ.&lt;br /&gt;
* &amp;lt;code&amp;gt;SHADER_USE_PARAMETER_STRUCT&amp;lt;/code&amp;gt; aktiviert die strukturierte Parameterbindung.&lt;br /&gt;
* &amp;lt;code&amp;gt;BEGIN_SHADER_PARAMETER_STRUCT&amp;lt;/code&amp;gt; beschreibt Konstanten, SRVs und UAVs.&lt;br /&gt;
* &amp;lt;code&amp;gt;IMPLEMENT_GLOBAL_SHADER&amp;lt;/code&amp;gt; verbindet C++-Klasse, virtuellen Shader-Pfad, Einstiegspunkt und Shader-Stufe.&lt;br /&gt;
* &amp;lt;code&amp;gt;SF_Compute&amp;lt;/code&amp;gt; kennzeichnet den Shader als Compute Shader.&lt;br /&gt;
&lt;br /&gt;
Je nach Modulgrenze kann statt &amp;lt;code&amp;gt;DECLARE_GLOBAL_SHADER&amp;lt;/code&amp;gt; eine exportierte Shader-Deklaration nötig sein.&lt;br /&gt;
&lt;br /&gt;
== Kompilierungsbedingungen ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;code&amp;gt;PostConfigInit&amp;lt;/code&amp;gt; relevant.&lt;br /&gt;
&lt;br /&gt;
== Dispatch über das RHI ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FComputeShaderUtils::Dispatch&amp;lt;/code&amp;gt; sendet einen Compute Shader mit Parametern und Gruppenzahl an eine &amp;lt;code&amp;gt;FRHIComputeCommandList&amp;lt;/code&amp;gt;. Das ist die direkte Variante auf RHI-Ebene.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
const FIntVector GroupCount =&lt;br /&gt;
    FComputeShaderUtils::GetGroupCount(ElementCount, 64);&lt;br /&gt;
&lt;br /&gt;
FComputeShaderUtils::Dispatch(&lt;br /&gt;
    RHICmdList,&lt;br /&gt;
    ComputeShader,&lt;br /&gt;
    Parameters,&lt;br /&gt;
    GroupCount&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Hilfsfunktion &amp;lt;code&amp;gt;GetGroupCount&amp;lt;/code&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
== Dispatch über den Render Dependency Graph ==&lt;br /&gt;
&lt;br /&gt;
Für regulären High-Level-Rendering-Code empfiehlt Unreal den Render Dependency Graph (RDG). Ein Compute-Pass kann dort über &amp;lt;code&amp;gt;FComputeShaderUtils::AddPass&amp;lt;/code&amp;gt; registriert werden.&lt;br /&gt;
&lt;br /&gt;
RDG kennt dadurch die beteiligten Ressourcen und kann unter anderem:&lt;br /&gt;
&lt;br /&gt;
* Abhängigkeiten zwischen Passes bestimmen&lt;br /&gt;
* Ressourcenübergänge und Barriers verwalten&lt;br /&gt;
* ungenutzte Passes entfernen&lt;br /&gt;
* Lebenszeiten temporärer Ressourcen optimieren&lt;br /&gt;
* geeignete Arbeit parallelisieren&lt;br /&gt;
* Async-Compute-Passes synchronisieren&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Shader-Entwicklung und Fehlersuche ==&lt;br /&gt;
&lt;br /&gt;
Für die Entwicklung sind folgende Maßnahmen hilfreich:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;r.ShaderDevelopmentMode=1&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ConsoleVariables.ini&amp;lt;/code&amp;gt; aktivieren, um ausführlichere Shader-Compile-Logs zu erhalten.&lt;br /&gt;
* Einstiegspunkt, virtuellen Shader-Pfad und Shader-Stufe kontrollieren.&lt;br /&gt;
* Sicherstellen, dass das Plugin und alle benötigten Module als Abhängigkeiten eingetragen sind.&lt;br /&gt;
* Modul-Ladephase prüfen, wenn Unreal meldet, dass ein Shader-Typ zu spät registriert wurde.&lt;br /&gt;
* Parameterstruktur zwischen HLSL und C++ sorgfältig abgleichen.&lt;br /&gt;
* Thread-Gruppengröße und Bounds-Checks prüfen.&lt;br /&gt;
* Ressourcenstatus, SRV-/UAV-Bindung und Synchronisation kontrollieren.&lt;br /&gt;
* Bei RDG-Passes aussagekräftige Event-Namen verwenden und bei Bedarf RDG Insights einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Bezug zum Heterogeneous-Multi-GPU-Projekt ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Der geplante erste Test lässt sich in folgende Schritte zerlegen:&lt;br /&gt;
&lt;br /&gt;
# einfachen Global Compute Shader in einem früh geladenen Modul registrieren&lt;br /&gt;
# Shader über Unreals reguläre Shader-Pipeline kompilieren lassen&lt;br /&gt;
# kompilierten Bytecode für den gewählten Worker-Adapter prüfen&lt;br /&gt;
# passende Root Signature und Compute Pipeline State auf dem Worker-&amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt; erzeugen&lt;br /&gt;
# Input- und Output-Buffer auf dem Worker-Device bereitstellen&lt;br /&gt;
# Compute Dispatch auf der eigenen Worker-Command-Queue ausführen&lt;br /&gt;
# Ergebnis über Readback zurückholen und auf der CPU verifizieren&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Quellen und weiterführende Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/adding-global-shaders-to-unreal-engine Adding Global Shaders to Unreal Engine] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/overview-of-shaders-in-plugins-unreal-engine Overview of Shaders in Plugins] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/shader-development-in-unreal-engine Shader Development in Unreal Engine] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RenderCore/FComputeShaderUtils__Dispatch FComputeShaderUtils::Dispatch] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RenderCore/FComputeShaderUtils__AddPass FComputeShaderUtils::AddPass] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/render-dependency-graph-in-unreal-engine Render Dependency Graph] – Epic Games, UE 5.8&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Dieser Artikel ist eine eigenständige deutschsprachige Zusammenfassung mit Projektbezug und keine vollständige Übersetzung der Epic-Dokumentation.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Shader]]&lt;br /&gt;
[[Kategorie:Compute Shader]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Direct3D_12,_Shader_Model_6_und_Windows-RHI_in_Unreal_Engine_5&amp;diff=166</id>
		<title>Direct3D 12, Shader Model 6 und Windows-RHI in Unreal Engine 5</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Direct3D_12,_Shader_Model_6_und_Windows-RHI_in_Unreal_Engine_5&amp;diff=166"/>
		<updated>2026-09-06T09:37:03Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Direct3D 12, Shader Model 6 und Windows-RHI in Unreal Engine 5 nach Direct3D 12, Shader Model 6 und Windows-RHI: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#WEITERLEITUNG [[Direct3D 12, Shader Model 6 und Windows-RHI]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Direct3D_12,_Shader_Model_6_und_Windows-RHI&amp;diff=165</id>
		<title>Direct3D 12, Shader Model 6 und Windows-RHI</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Direct3D_12,_Shader_Model_6_und_Windows-RHI&amp;diff=165"/>
		<updated>2026-09-06T09:37:03Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Elaina verschob die Seite Direct3D 12, Shader Model 6 und Windows-RHI in Unreal Engine 5 nach Direct3D 12, Shader Model 6 und Windows-RHI: Redundanten Titelzusatz entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8 unter Windows. Bezeichnungen in der Oberfläche können bei lokalisierten Editor-Versionen leicht abweichen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Direct3D 12 (D3D12)&#039;&#039;&#039; ist Microsofts moderne Grafikschnittstelle. Unreal Engine greift nicht direkt aus jedem Spielsystem darauf zu, sondern über das &#039;&#039;&#039;Rendering Hardware Interface (RHI)&#039;&#039;&#039;. Das RHI vereinheitlicht verschiedene Grafik-APIs wie Direct3D 11, Direct3D 12 und Vulkan.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shader Model 6 (SM6)&#039;&#039;&#039; bezeichnet die neuere Shader-Funktionsstufe und den zugehörigen Compilerpfad. D3D12 und SM6 sind verschiedene Einstellungen: D3D12 wählt die Grafik-API, SM6 das Shader-Ziel innerhalb des D3D12-Pfads.&lt;br /&gt;
&lt;br /&gt;
== Warum D3D12 und SM6? ==&lt;br /&gt;
&lt;br /&gt;
Epic empfiehlt D3D12 für die meisten Spiele. In UE 5.8 benötigen mehrere moderne Rendering-Funktionen SM6:&lt;br /&gt;
&lt;br /&gt;
* Lumen und MegaLights unter Windows setzen D3D12 und aktiviertes SM6 voraus; Lumen Hardware Ray Tracing benötigt SM6.&lt;br /&gt;
* Nanite und Virtual Shadow Maps benötigen unter Windows D3D12 mit SM6; für Nanite nennt Epic D3D12 mit Shader-Model-6.6-Atomics sowie aktuelle Treiber.&lt;br /&gt;
* Temporal Super Resolution läuft grundsätzlich auch mit SM5, kann unter D3D12/SM6 aber 16-Bit-Typen nutzen. Der SM5-Pfad ist unter anderem durch acht UAVs pro Shader eingeschränkt. Ein UAV ist eine Shader-Ressource mit ungeordnetem Lese-/Schreibzugriff.&lt;br /&gt;
&lt;br /&gt;
SM6 macht eine GPU nicht automatisch schneller. Es schaltet Fähigkeiten frei; Nutzen und Kosten hängen von Renderer, Shadern, Treiber und Hardware ab.&lt;br /&gt;
&lt;br /&gt;
== Windows-RHI im Editor einstellen ==&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Edit &amp;gt; Project Settings &amp;gt; Platforms &amp;gt; Windows&#039;&#039;&#039; öffnen.&lt;br /&gt;
# Unter &#039;&#039;&#039;Targeted RHIs&#039;&#039;&#039; die benötigten Ziele aktivieren. Für den modernen Windows-Pfad &#039;&#039;&#039;DirectX 12 (SM6)&#039;&#039;&#039; einschalten.&lt;br /&gt;
# &#039;&#039;&#039;Default RHI&#039;&#039;&#039; auf &#039;&#039;&#039;DirectX 12&#039;&#039;&#039; setzen. Epic weist darauf hin, dass das ausgewählte Standard-RHI auch als Targeted RHI aktiviert sein muss.&lt;br /&gt;
# Den Editor neu starten. Eine RHI-Änderung wird erst danach wirksam; geänderte Shaderziele können eine längere Shader-Kompilierung auslösen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DirectX 11 &amp;amp; 12 (SM5)&#039;&#039;&#039; ist ein separater Kompatibilitätspfad. Wer SM5 zusätzlich aktiviert, erzeugt weitere Shader-Varianten und vergrößert damit typischerweise Cook- und Build-Aufwand. Für eine klar definierte D3D12-/SM6-Zielhardware sollte nur der tatsächlich benötigte Satz gepflegt werden; bei breiter Hardwareunterstützung muss der Fallback bewusst getestet werden.&lt;br /&gt;
&lt;br /&gt;
== Kurzzeitig über die Kommandozeile testen ==&lt;br /&gt;
&lt;br /&gt;
Die UE-5.8-Referenz dokumentiert folgende Startparameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-dx12&amp;lt;/code&amp;gt; erzwingt das D3D12-RHI.&lt;br /&gt;
* &amp;lt;code&amp;gt;-dx11&amp;lt;/code&amp;gt; erzwingt das D3D11-RHI.&lt;br /&gt;
* &amp;lt;code&amp;gt;-sm6&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;-sm5&amp;lt;/code&amp;gt; erzwingt das Shader Model.&lt;br /&gt;
* &amp;lt;code&amp;gt;-forcedisablesm6&amp;lt;/code&amp;gt; deaktiviert SM6 für einen Vergleichstest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
UnrealEditor.exe MeinProjekt.uproject -dx12 -sm6&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erzwungene Parameter eignen sich für Diagnose und A/B-Tests. Sie ersetzen keine korrekt gepflegten Targeted RHIs. Eine nicht unterstützte erzwungene Kombination kann den Start verhindern.&lt;br /&gt;
&lt;br /&gt;
== Praktische Prüfliste ==&lt;br /&gt;
&lt;br /&gt;
# Windows-Version, GPU-Funktionsumfang und aktuellen stabilen Herstellertreiber prüfen.&lt;br /&gt;
# D3D12 als Default RHI und D3D12 SM6 als Ziel aktivieren.&lt;br /&gt;
# Nach dem Neustart das Startprotokoll kontrollieren: verwendetes RHI, gewählter Adapter und Shader-Plattform müssen zur Erwartung passen.&lt;br /&gt;
# Benötigte Funktionen einzeln prüfen: Nanite, Virtual Shadow Maps, Lumen oder Hardware Ray Tracing.&lt;br /&gt;
# Einen Development- oder Test-Build auf der schwächsten unterstützten Ziel-GPU ausführen. Ein erfolgreicher Editorstart allein beweist keine vollständige Kompatibilität.&lt;br /&gt;
# D3D11/SM5 nur behalten, wenn dieser Pfad wirklich unterstützt, gekocht und getestet wird.&lt;br /&gt;
&lt;br /&gt;
== Typische Stolperfallen ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;D3D12 aktiviert, SM6 vergessen:&#039;&#039;&#039; Das RHI stimmt, moderne Funktionen bleiben dennoch nicht verfügbar.&lt;br /&gt;
* &#039;&#039;&#039;Default RHI ohne passendes Target:&#039;&#039;&#039; Epic verlangt, dass das Standard-RHI zugleich als Ziel ausgewählt ist.&lt;br /&gt;
* &#039;&#039;&#039;Altes Windows oder alter Treiber:&#039;&#039;&#039; Besonders Nanite und Virtual Shadow Maps benötigen geeignete Windows-Builds, D3D12 Agility SDK-Unterstützung und aktuelle Treiber.&lt;br /&gt;
* &#039;&#039;&#039;Shader-Neukompilierung unterschätzt:&#039;&#039;&#039; Ein Wechsel des Shaderziels kann viele Shader neu erzeugen.&lt;br /&gt;
* &#039;&#039;&#039;Nur auf einer GPU getestet:&#039;&#039;&#039; D3D12/SM6-Unterstützung und Stabilität sind Eigenschaften der gesamten Kombination aus Betriebssystem, Treiber und Hardware.&lt;br /&gt;
&lt;br /&gt;
== Bezug zu UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Für [[UE5 Heterogeneous Multi-GPU]] ist D3D12 nicht nur ein Renderer-Schalter, sondern die Grundlage des expliziten Unlinked-Multiadapter-Prototyps. Die Windows-RHI-Einstellungen bestimmen zunächst den regulären Unreal-D3D12-Pfad und die Shaderplattform. Sie aktivieren jedoch &#039;&#039;&#039;nicht automatisch&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* eine zweite, heterogene GPU,&lt;br /&gt;
* Cross-Adapter Heaps oder gemeinsam nutzbare Ressourcen,&lt;br /&gt;
* Shared Fences zur Synchronisation,&lt;br /&gt;
* die Auswahl eines Worker-Adapters oder die Verteilung von Compute-Arbeit.&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen müssen Jans Engine-Anpassungen ausdrücklich auf D3D12-Ebene implementieren. Ein sauberer D3D12-/SM6-Basiszustand ist trotzdem wichtig: Er trennt allgemeine RHI- oder Shaderprobleme von Fehlern im Multiadapter-Code.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/windows-settings-in-the-unreal-engine-project-settings?lang=en-US Epic: Windows Settings in Project Settings] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/hardware-and-software-specifications-for-unreal-engine?lang=en-US Epic: Hardware and Software Specifications] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/unreal-engine-command-line-arguments-reference?lang=en-US Epic: Command-Line Arguments Reference] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Shader]]&lt;br /&gt;
[[Kategorie:Windows]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Race_Condition&amp;diff=164</id>
		<title>Race Condition</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Race_Condition&amp;diff=164"/>
		<updated>2026-09-06T09:26:34Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „Eine &amp;#039;&amp;#039;&amp;#039;Race Condition&amp;#039;&amp;#039;&amp;#039; (deutsch etwa &amp;#039;&amp;#039;&amp;#039;Wettlaufsituation&amp;#039;&amp;#039;&amp;#039;) entsteht, wenn das Ergebnis eines Programms davon abhängt, in welcher zeitlichen Reihenfolge mehrere nebenläufige Vorgänge ausgeführt werden. Da Threads, Prozesse oder GPU-Queues nicht bei jedem Lauf exakt gleich geplant werden, kann derselbe Code scheinbar korrekt funktionieren und später sporadisch falsche Ergebnisse liefern.  Race Conditions treten besonders häufig auf, wenn mehrere…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Eine &#039;&#039;&#039;Race Condition&#039;&#039;&#039; (deutsch etwa &#039;&#039;&#039;Wettlaufsituation&#039;&#039;&#039;) entsteht, wenn das Ergebnis eines Programms davon abhängt, in welcher zeitlichen Reihenfolge mehrere nebenläufige Vorgänge ausgeführt werden. Da Threads, Prozesse oder GPU-Queues nicht bei jedem Lauf exakt gleich geplant werden, kann derselbe Code scheinbar korrekt funktionieren und später sporadisch falsche Ergebnisse liefern.&lt;br /&gt;
&lt;br /&gt;
Race Conditions treten besonders häufig auf, wenn mehrere Ausführungseinheiten gemeinsamen Zustand lesen und verändern, ohne den Zugriff ausreichend zu koordinieren.&amp;lt;ref name=&amp;quot;MSRace&amp;quot;&amp;gt;Microsoft: [https://learn.microsoft.com/en-us/archive/msdn-magazine/2008/june/tools-and-techniques-to-identify-concurrency-issues Tools and Techniques to Identify Concurrency Issues]. Abgerufen am 6. September 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Einfaches Beispiel ==&lt;br /&gt;
&lt;br /&gt;
Zwei Threads erhöhen denselben Zähler. Die scheinbar einzelne Operation &amp;lt;code&amp;gt;Zaehler++&amp;lt;/code&amp;gt; besteht intern aus mehreren Schritten:&lt;br /&gt;
&lt;br /&gt;
# aktuellen Wert lesen,&lt;br /&gt;
# Wert erhöhen,&lt;br /&gt;
# neuen Wert zurückschreiben.&lt;br /&gt;
&lt;br /&gt;
Lesen beide Threads gleichzeitig den Wert 10, berechnen beide 11 und schreiben anschließend 11 zurück. Erwartet wurde 12, tatsächlich ging jedoch eine Erhöhung verloren. Welcher Ablauf eintritt, hängt vom Timing ab.&lt;br /&gt;
&lt;br /&gt;
== Race Condition und Data Race ==&lt;br /&gt;
&lt;br /&gt;
Die Begriffe werden oft gleich verwendet, sind aber nicht vollständig identisch:&lt;br /&gt;
&lt;br /&gt;
* Eine &#039;&#039;&#039;Race Condition&#039;&#039;&#039; ist allgemein ein Fehler, bei dem das Verhalten von einer unerwünschten Reihenfolge nebenläufiger Ereignisse abhängt. Das kann auch Dateien, Netzwerkvorgänge oder GPU-Arbeit betreffen.&lt;br /&gt;
* Ein &#039;&#039;&#039;Data Race&#039;&#039;&#039; beziehungsweise &#039;&#039;&#039;Datenrennen&#039;&#039;&#039; bezeichnet enger gefasst unkoordinierte, gleichzeitig stattfindende Speicherzugriffe auf dieselben Daten, wobei mindestens ein Zugriff schreibt.&lt;br /&gt;
&lt;br /&gt;
Ein Data Race ist somit eine häufige Form der Race Condition. Nicht jede Race Condition muss jedoch durch denselben Speicherort verursacht werden.&lt;br /&gt;
&lt;br /&gt;
== Typische Ursachen ==&lt;br /&gt;
&lt;br /&gt;
* mehrere Threads verändern dieselbe Variable oder Datenstruktur;&lt;br /&gt;
* ein Objekt wird benutzt, bevor seine Initialisierung abgeschlossen ist;&lt;br /&gt;
* ein asynchroner Auftrag veröffentlicht ein Ergebnis zu früh;&lt;br /&gt;
* eine Ressource wird freigegeben, obwohl ein anderer Auftrag sie noch verwendet;&lt;br /&gt;
* zwei GPU-Queues oder Adapter greifen ohne passende Fence-Abhängigkeit auf zusammengehörige Daten zu;&lt;br /&gt;
* die Reihenfolge von Prüfung und anschließender Änderung ist nicht atomar, etwa bei „prüfen, ob frei“ und „reservieren“.&lt;br /&gt;
&lt;br /&gt;
== Vermeidung ==&lt;br /&gt;
&lt;br /&gt;
Race Conditions lassen sich unter anderem verhindern durch:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Mutexe, Critical Sections und Locks&#039;&#039;&#039;, die einen kritischen Abschnitt nur für einen Ausführungspfad gleichzeitig zugänglich machen;&lt;br /&gt;
* &#039;&#039;&#039;atomare Operationen&#039;&#039;&#039; für einfache, unteilbare Änderungen;&lt;br /&gt;
* &#039;&#039;&#039;Events, Semaphore und Condition Variables&#039;&#039;&#039; zur geregelten Reihenfolge von Arbeiten;&lt;br /&gt;
* &#039;&#039;&#039;Fences und Barriers&#039;&#039;&#039; zur Synchronisation von GPU-Queues, Ressourcenübergängen und Speicherzugriffen;&lt;br /&gt;
* unveränderliche Daten, getrennte Zuständigkeiten und Message Queues, wodurch gemeinsam beschreibbarer Zustand reduziert wird.&lt;br /&gt;
&lt;br /&gt;
Windows stellt dafür sowohl Synchronisationsobjekte als auch leichtgewichtige Primitive wie Critical Sections und SRW Locks bereit.&amp;lt;ref name=&amp;quot;MSSync&amp;quot;&amp;gt;Microsoft: [https://learn.microsoft.com/en-us/windows/win32/procthread/synchronizing-execution-of-multiple-threads Synchronizing Execution of Multiple Threads]. Abgerufen am 6. September 2026.&amp;lt;/ref&amp;gt; Synchronisation muss jedoch zur tatsächlich geschützten Ressource passen. Ein GPU-Fence ordnet beispielsweise GPU-Arbeit, ersetzt aber nicht automatisch den Schutz gemeinsam veränderter CPU-Daten.&lt;br /&gt;
&lt;br /&gt;
== Erkennung ==&lt;br /&gt;
&lt;br /&gt;
Race Conditions sind oft schwer reproduzierbar, weil Debug-Ausgaben, Breakpoints oder eine andere Auslastung bereits das Timing verändern können. Hinweise sind seltene falsche Werte, beschädigte Daten, flackernde Ausgaben, sporadische Abstürze oder Fehler, die nur auf Mehrkernsystemen auftreten.&lt;br /&gt;
&lt;br /&gt;
Hilfreich sind Stress- und Wiederholungstests, Thread- und GPU-Debugger, Race-Detector-Werkzeuge sowie klar protokollierte Zustandsübergänge. Die eigentliche Lösung besteht nicht darin, das Timing künstlich zu verändern, sondern die erforderliche Reihenfolge ausdrücklich zu synchronisieren. Auch Speicherreihenfolge und Sichtbarkeit zwischen Prozessorkernen müssen berücksichtigt werden.&amp;lt;ref name=&amp;quot;MSOrdering&amp;quot;&amp;gt;Microsoft: [https://learn.microsoft.com/en-us/windows/win32/sync/synchronization-and-multiprocessor-issues Synchronization and Multiprocessor Issues]. Abgerufen am 6. September 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Abgrenzung zum Deadlock ==&lt;br /&gt;
&lt;br /&gt;
Bei einer Race Condition laufen mehrere Vorgänge weiter, aber ihre unkontrollierte Reihenfolge erzeugt möglicherweise ein falsches Ergebnis. Bei einem &#039;&#039;&#039;Deadlock&#039;&#039;&#039; warten Vorgänge dagegen dauerhaft aufeinander und kommen nicht mehr voran. Übermäßig oder inkonsistent eingesetzte Locks können Race Conditions beseitigen, zugleich aber neue Deadlocks verursachen.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[UE5 Heterogeneous Multi-GPU]]&lt;br /&gt;
* [[Rendering Hardware Interface (RHI) in Unreal Engine 5]]&lt;br /&gt;
* [[Render Dependency Graph in Unreal Engine 5]]&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Programmierung]]&lt;br /&gt;
[[Kategorie:Parallelverarbeitung]]&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Subsurface_Scattering&amp;diff=163</id>
		<title>Subsurface Scattering</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Subsurface_Scattering&amp;diff=163"/>
		<updated>2026-09-05T15:17:49Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „&amp;#039;&amp;#039;&amp;#039;Subsurface Scattering&amp;#039;&amp;#039;&amp;#039; (kurz &amp;#039;&amp;#039;&amp;#039;SSS&amp;#039;&amp;#039;&amp;#039;, deutsch etwa &amp;#039;&amp;#039;&amp;#039;Streuung unterhalb der Oberfläche&amp;#039;&amp;#039;&amp;#039;) beschreibt, wie Licht in ein Material eindringt, im Inneren mehrfach gestreut und an einer anderen Stelle wieder austritt. Dadurch wirken Materialien wie Haut, Wachs, Marmor, Jade, Milch, Schnee oder Fruchtfleisch weich und leicht durchleuchtet. Ohne SSS sehen solche Oberflächen häufig zu hart, trocken oder plastikartig aus.  In der Computergrafik ist SSS…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Subsurface Scattering&#039;&#039;&#039; (kurz &#039;&#039;&#039;SSS&#039;&#039;&#039;, deutsch etwa &#039;&#039;&#039;Streuung unterhalb der Oberfläche&#039;&#039;&#039;) beschreibt, wie Licht in ein Material eindringt, im Inneren mehrfach gestreut und an einer anderen Stelle wieder austritt. Dadurch wirken Materialien wie Haut, Wachs, Marmor, Jade, Milch, Schnee oder Fruchtfleisch weich und leicht durchleuchtet. Ohne SSS sehen solche Oberflächen häufig zu hart, trocken oder plastikartig aus.&lt;br /&gt;
&lt;br /&gt;
In der Computergrafik ist SSS ein Teil der Lichttransportberechnung. Eine physikalisch genaue Simulation ist aufwendig, weshalb Echtzeit-Engines wie [[Unreal Engine 5]] spezialisierte Shading-Modelle und Näherungsverfahren verwenden.&lt;br /&gt;
&lt;br /&gt;
== Physikalisches Prinzip ==&lt;br /&gt;
&lt;br /&gt;
Bei einer ideal undurchsichtigen Oberfläche wird Licht vereinfacht am Auftreffpunkt reflektiert oder absorbiert. Bei einem streuenden Material läuft der Vorgang anders ab:&lt;br /&gt;
&lt;br /&gt;
# Licht trifft auf die Oberfläche und ein Teil davon wird direkt reflektiert.&lt;br /&gt;
# Ein weiterer Teil dringt durch die Materialgrenze ein.&lt;br /&gt;
# Im Inneren wird das Licht an mikroskopischen Strukturen mehrfach abgelenkt.&lt;br /&gt;
# Bestimmte Wellenlängen werden stärker absorbiert als andere.&lt;br /&gt;
# Das verbleibende Licht verlässt das Material an derselben oder an einer benachbarten Stelle.&lt;br /&gt;
&lt;br /&gt;
Deshalb sind Eintritts- und Austrittspunkt des Lichts nicht identisch. Diese räumliche Verteilung ist der entscheidende Unterschied zur gewöhnlichen diffusen Reflexion. In einer vollständigen Lichttransportbeschreibung wird sie mit einer &#039;&#039;&#039;BSSRDF&#039;&#039;&#039; (&#039;&#039;Bidirectional Surface Scattering Reflectance Distribution Function&#039;&#039;) modelliert. Eine BRDF beschreibt nur Reflexion an einem einzelnen Oberflächenpunkt; eine BSSRDF kann verschiedene Eintritts- und Austrittspunkte berücksichtigen.&amp;lt;ref name=&amp;quot;Jensen2001&amp;quot;&amp;gt;Henrik Wann Jensen u. a.: [https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf A Practical Model for Subsurface Light Transport]. SIGGRAPH 2001.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Streuung, Absorption und Farbe ==&lt;br /&gt;
&lt;br /&gt;
Das Erscheinungsbild hängt hauptsächlich von zwei Vorgängen ab:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Streuung&#039;&#039;&#039; ändert die Richtung des Lichts. Starke Streuung verteilt Beleuchtung über eine größere Fläche und macht harte Helligkeitsübergänge weicher.&lt;br /&gt;
* &#039;&#039;&#039;Absorption&#039;&#039;&#039; entfernt bestimmte Wellenlängen aus dem Licht. Dadurch verändert sich die Farbe auf dem Weg durch das Material.&lt;br /&gt;
&lt;br /&gt;
Die mittlere Weglänge eines Photons bis zur nächsten Wechselwirkung wird als &#039;&#039;&#039;Mean Free Path&#039;&#039;&#039; bezeichnet. Sie kann für Rot, Grün und Blau unterschiedlich sein. Bei menschlicher Haut dringt rotes Licht im Allgemeinen weiter ein als blaues oder grünes Licht. Das erzeugt unter anderem den warmen roten Schimmer an dünnen, von hinten beleuchteten Bereichen wie Ohren oder Nasenflügeln.&lt;br /&gt;
&lt;br /&gt;
Die sichtbare Wirkung hängt außerdem von Materialdicke, Beleuchtungsrichtung, Oberflächenform und Maßstab ab. Ein SSS-Radius, der bei einem Kopf glaubwürdig aussieht, ist bei einem kleinen Modell oder einem meterhohen Objekt nicht automatisch korrekt.&lt;br /&gt;
&lt;br /&gt;
== Abgrenzung zu ähnlichen Effekten ==&lt;br /&gt;
&lt;br /&gt;
SSS wird leicht mit Transparenz oder einfacher Lichtdurchlässigkeit verwechselt:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Effekt&lt;br /&gt;
! Kennzeichen&lt;br /&gt;
! Typische Beispiele&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Subsurface Scattering&#039;&#039;&#039;&lt;br /&gt;
| Licht dringt ein, wird im Material räumlich verteilt und tritt an anderer Stelle wieder aus.&lt;br /&gt;
| Haut, Wachs, Marmor, Jade&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Transparenz&#039;&#039;&#039;&lt;br /&gt;
| Hinter dem Material liegende Objekte bleiben direkt erkennbar.&lt;br /&gt;
| Klarglas, sauberes Wasser&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Transluzenz&#039;&#039;&#039;&lt;br /&gt;
| Licht gelangt hindurch, Details dahinter erscheinen jedoch unscharf oder gar nicht.&lt;br /&gt;
| Milchglas, dünnes Papier&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Transmission&#039;&#039;&#039;&lt;br /&gt;
| Oberbegriff für Licht, das ein Material durchquert; kann gerichtet oder gestreut sein.&lt;br /&gt;
| Blätter, Stoff, Hautränder&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Diffuse Reflexion&#039;&#039;&#039;&lt;br /&gt;
| Licht wird am betrachteten Oberflächenpunkt verteilt; kein räumlicher Transport unter der Oberfläche.&lt;br /&gt;
| Kreide, matte Farbe&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein Material kann mehrere dieser Eigenschaften gleichzeitig besitzen. Haut hat beispielsweise direkte Reflexion an der öligen Oberfläche, diffuse Anteile, Streuung in mehreren Gewebeschichten und sichtbare Transmission an dünnen Stellen.&lt;br /&gt;
&lt;br /&gt;
== Warum Echtzeit-SSS nur eine Näherung ist ==&lt;br /&gt;
&lt;br /&gt;
Physikalisch korrekter Untergrund-Lichttransport würde viele Lichtwege im Volumen verfolgen. Offline-Renderer und Path Tracer können dafür aufwendige Random-Walk-, Diffusions- oder BSSRDF-Verfahren einsetzen. In einem Echtzeit-Renderer müssen hingegen Millionen Pixel innerhalb weniger Millisekunden berechnet werden.&lt;br /&gt;
&lt;br /&gt;
Gebräuchliche Näherungen sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Screen-Space-Filterung:&#039;&#039;&#039; Bereits berechnete Beleuchtung wird in Abhängigkeit von Profil, Tiefe und Materialkennung über benachbarte Bildpunkte verteilt.&lt;br /&gt;
* &#039;&#039;&#039;Vorgefaltete oder vorintegrierte Modelle:&#039;&#039;&#039; Ein Teil der Lichtantwort wird vorab berechnet und während des Renderns günstig nachgeschlagen.&lt;br /&gt;
* &#039;&#039;&#039;Wrap Lighting und Backscattering:&#039;&#039;&#039; Beleuchtung wird um die Silhouette herum erweitert und bei Gegenlicht ergänzt, um den Eindruck innerer Streuung zu erzeugen.&lt;br /&gt;
* &#039;&#039;&#039;Dickenmasken:&#039;&#039;&#039; Dünne Bereiche erhalten stärkere Transmission als dicke Bereiche.&lt;br /&gt;
&lt;br /&gt;
Diese Methoden können sehr überzeugend aussehen, bilden aber nicht jeden Lichtweg geometrisch korrekt ab. Screen-Space-Verfahren kennen beispielsweise nur Informationen, die im aktuellen Kamerabild vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
== Subsurface Scattering in Unreal Engine 5 ==&lt;br /&gt;
&lt;br /&gt;
Unreal Engine stellt mehrere Shading-Modelle für unterschiedliche Materialklassen und Qualitätsziele bereit.&amp;lt;ref name=&amp;quot;EpicModels&amp;quot;&amp;gt;Epic Games: [https://dev.epicgames.com/documentation/en-us/unreal-engine/shading-models-in-unreal-engine Shading Models in Unreal Engine]. Abgerufen am 5. September 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subsurface ===&lt;br /&gt;
&lt;br /&gt;
Das Shading Model &#039;&#039;&#039;Subsurface&#039;&#039;&#039; ist eine vergleichsweise günstige Lösung für opake Materialien wie Wachs, Jade oder stilisierte Haut. Es kombiniert eine um die Oberfläche herumgreifende Beleuchtung mit einem Gegenlichtanteil. Epic beschreibt es als preiswerter, aber qualitativ schwächer als die speziell für Haut vorgesehene Lösung.&amp;lt;ref name=&amp;quot;EpicSubsurface&amp;quot;&amp;gt;Epic Games: [https://dev.epicgames.com/documentation/en-us/unreal-engine/subsurface-shading-model-in-unreal-engine Subsurface Shading Model in Unreal Engine]. Abgerufen am 5. September 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wichtige Materialeingänge sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Base Color:&#039;&#039;&#039; sichtbare Grundfarbe der Oberfläche.&lt;br /&gt;
* &#039;&#039;&#039;Subsurface Color:&#039;&#039;&#039; Farbe des unter der Oberfläche gestreuten Lichts.&lt;br /&gt;
* &#039;&#039;&#039;Opacity:&#039;&#039;&#039; steuert bei diesem opaken Shading-Modell nicht die gewöhnliche Durchsichtigkeit. Der Wert beeinflusst unter anderem Dichte, Streuweite, Normaleneinfluss und Schattenweichheit. Ein kleinerer Wert lässt Licht weiter durch das Material gelangen.&amp;lt;ref name=&amp;quot;EpicSubsurface&amp;quot; /&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Roughness, Specular und Normal:&#039;&#039;&#039; bestimmen die normale Oberflächenreflexion, die zusätzlich zum SSS-Eindruck erhalten bleibt.&lt;br /&gt;
&lt;br /&gt;
=== Subsurface Profile ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subsurface Profile&#039;&#039;&#039; ist Unreals hochwertigeres Shading-Modell für realistische Haut und ähnliche Materialien. Die Streueigenschaften werden in einem wiederverwendbaren &#039;&#039;&#039;Subsurface Profile Asset&#039;&#039;&#039; gespeichert und können bearbeitet werden, ohne das Material neu zu kompilieren. Die Berechnung arbeitet überwiegend im Screen Space und verteilt die Beleuchtung über benachbarte Pixel.&amp;lt;ref name=&amp;quot;EpicProfile&amp;quot;&amp;gt;Epic Games: [https://dev.epicgames.com/documentation/en-us/unreal-engine/subsurface-profile-shading-model-in-unreal-engine Subsurface Profile Shading Model in Unreal Engine]. Abgerufen am 5. September 2026.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu den wichtigsten Profilparametern gehören:&amp;lt;ref name=&amp;quot;EpicProfile&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Surface Albedo:&#039;&#039;&#039; diffuse Grundreflexion; sollte zur Base Color des Materials passen.&lt;br /&gt;
* &#039;&#039;&#039;Mean Free Path Color und Distance:&#039;&#039;&#039; legen fest, wie weit die roten, grünen und blauen Lichtanteile im Material gelangen.&lt;br /&gt;
* &#039;&#039;&#039;World Unit Scale:&#039;&#039;&#039; verbindet die Streuweite mit dem Maßstab in Unreal Units beziehungsweise Zentimetern.&lt;br /&gt;
* &#039;&#039;&#039;Transmission:&#039;&#039;&#039; steuert durch das Material gelangendes Licht, einschließlich Extinktion, Brechungsindex und Farbtönung.&lt;br /&gt;
* &#039;&#039;&#039;Dual Specular:&#039;&#039;&#039; kombiniert zwei Glanzkeulen unterschiedlicher Rauheit und kann dadurch die mehrschichtige, mikrostrukturierte Reflexion von Haut glaubwürdiger darstellen.&lt;br /&gt;
&lt;br /&gt;
Beim Subsurface-Profile-Modell maskiert der Materialeingang &#039;&#039;&#039;Opacity&#039;&#039;&#039; den SSS-Anteil: 0 bedeutet keine Streuung, 1 die volle Wirkung. Das Material bleibt dabei opak. Der Metallic-Eingang steht im klassischen Deferred-Pfad nicht normal zur Verfügung, weil der entsprechende GBuffer-Speicher für Profildaten verwendet wird.&amp;lt;ref name=&amp;quot;EpicProfile&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Preintegrated Skin ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Preintegrated Skin&#039;&#039;&#039; ist eine ältere beziehungsweise günstigere, speziell auf Haut zugeschnittene Näherung. Sie verwendet ebenfalls den Eingang Subsurface Color, bietet aber weniger Kontrolle und physikalische Tiefe als Subsurface Profile. Für hochwertige menschliche Haut empfiehlt sich in der Regel Subsurface Profile; Preintegrated Skin kann bei einfacheren Figuren oder knapperem Leistungsbudget sinnvoll sein.&amp;lt;ref name=&amp;quot;EpicModels&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Two Sided Foliage ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Two Sided Foliage&#039;&#039;&#039; ist für dünne, beidseitig sichtbare Flächen wie Blätter gedacht. Hier repräsentiert Subsurface Color vor allem das Licht, das durch das Blatt gelangt. Masken können Adern, Stiele und unterschiedlich dicke Bereiche voneinander trennen. Das ist keine vollständige Volumensimulation, sondern eine auf dünne Vegetation zugeschnittene Transmission-Näherung.&amp;lt;ref name=&amp;quot;EpicModels&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Substrate ===&lt;br /&gt;
&lt;br /&gt;
Bei Verwendung von &#039;&#039;&#039;Substrate&#039;&#039;&#039; werden Materialien aus Schichten beziehungsweise sogenannten Slabs aufgebaut. Für streuende Materialien existieren eigene interne Subsurface-Varianten, unter anderem auf Basis der Mean Free Path. Das Grundprinzip bleibt gleich: Farbe und Weglänge der Streuung müssen zur realen Größe und zum Aufbau des Materials passen. Da sich Substrate und der klassische Materialpfad in Bedienung und Funktionsumfang unterscheiden, sollten konkrete Einstellungen immer für die eingesetzte UE-Version geprüft werden.&lt;br /&gt;
&lt;br /&gt;
== Praktischer Aufbau eines Hautmaterials in UE5 ==&lt;br /&gt;
&lt;br /&gt;
Ein typischer Arbeitsablauf für hochwertige Haut sieht so aus:&lt;br /&gt;
&lt;br /&gt;
# Material anlegen und &#039;&#039;&#039;Shading Model = Subsurface Profile&#039;&#039;&#039; wählen.&lt;br /&gt;
# Ein Subsurface-Profile-Asset erstellen und dem Material zuweisen.&lt;br /&gt;
# Physikalisch plausible Base-Color-, Roughness- und Normal-Maps anschließen.&lt;br /&gt;
# Eine SSS-Maske über &#039;&#039;&#039;Opacity&#039;&#039;&#039; einspeisen. Lippen, Ohren und weiche Wangenbereiche dürfen meist stärker streuen; Augenbrauen, Bartstoppeln oder stark verhornte Bereiche schwächer.&lt;br /&gt;
# Mean Free Path und World Unit Scale bei neutraler Beleuchtung auf den tatsächlichen Modellmaßstab abstimmen.&lt;br /&gt;
# Gegenlicht testen, um Ohren und dünne Partien zu beurteilen.&lt;br /&gt;
# Verschiedene Kameradistanzen, Hauttöne und Lichtgrößen prüfen. SSS darf Details weichzeichnen, aber nicht das ganze Gesicht wie selbstleuchtendes Gummi erscheinen lassen.&lt;br /&gt;
&lt;br /&gt;
Epic weist darauf hin, dass das Profil nur ein Bestandteil glaubwürdiger Haut ist. Geometrie, Texturen, Mikronormalen, Rauheit, Spiegelreflexion und Beleuchtung bleiben ebenso wichtig.&amp;lt;ref name=&amp;quot;EpicProfile&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typische Fehler ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Zu große Streuweite:&#039;&#039;&#039; Das Gesicht verliert Poren und Formen und wirkt wie Wachs.&lt;br /&gt;
* &#039;&#039;&#039;Falscher Maßstab:&#039;&#039;&#039; Ein in Zentimetern gedachtes Profil wird auf ein falsch skaliertes Mesh angewendet.&lt;br /&gt;
* &#039;&#039;&#039;Zu gesättigte Streufarbe:&#039;&#039;&#039; Haut wird unnatürlich rot oder Wachs leuchtet farbig statt Licht nur zu verteilen.&lt;br /&gt;
* &#039;&#039;&#039;SSS als Transparenzersatz:&#039;&#039;&#039; Subsurface-Materialien zeigen nicht automatisch klar erkennbare Objekte hinter der Oberfläche.&lt;br /&gt;
* &#039;&#039;&#039;Gleiche Stärke auf dem ganzen Modell:&#039;&#039;&#039; Zähne, Lippen, Ohren, Bart, Nägel und Hornschichten benötigen unterschiedliche Maskierung oder eigene Materialien.&lt;br /&gt;
* &#039;&#039;&#039;Nur Frontlicht beurteilt:&#039;&#039;&#039; Viele Probleme werden erst in Seiten- und Gegenlicht sichtbar.&lt;br /&gt;
* &#039;&#039;&#039;Diffuse Textur mit eingebranntem Licht:&#039;&#039;&#039; Schatten oder Glanz in der Base Color konkurrieren mit der dynamischen Beleuchtung und verfälschen das Profil.&lt;br /&gt;
* &#039;&#039;&#039;Fehlende Qualitätsprüfung:&#039;&#039;&#039; Screen-Space-SSS kann abhängig von Auflösung, Anti-Aliasing, Sichtbarkeit und Plattform anders wirken.&lt;br /&gt;
&lt;br /&gt;
== Leistung und Grenzen ==&lt;br /&gt;
&lt;br /&gt;
SSS ist teurer als gewöhnliches Default-Lit-Shading, weil zusätzliche Materialdaten gespeichert und Beleuchtung räumlich gefiltert oder separat ausgewertet werden muss. Die tatsächlichen Kosten hängen von Auflösung, Bildschirmfläche der SSS-Objekte, Qualitätsstufe, Plattform und Shading-Pfad ab.&lt;br /&gt;
&lt;br /&gt;
Für die Optimierung helfen typischerweise:&lt;br /&gt;
&lt;br /&gt;
* SSS nur auf Materialien verwenden, die sichtbar davon profitieren.&lt;br /&gt;
* Hochwertiges Subsurface Profile auf wichtige Figuren beschränken.&lt;br /&gt;
* Masken nutzen, statt die gesamte Oberfläche maximal streuen zu lassen.&lt;br /&gt;
* GPU-Profiler und verschiedene Zielauflösungen verwenden.&lt;br /&gt;
* Auf Zielhardware testen; Editor-Ansicht und finale Laufzeit können sich unterscheiden.&lt;br /&gt;
&lt;br /&gt;
Screen-Space-Methoden besitzen prinzipbedingte Grenzen an Bildrändern und bei verdeckten Geometriedetails. Außerdem ersetzt SSS keine echte volumetrische Darstellung großer, durchsichtiger Körper. Für Glas, klare Flüssigkeiten oder tief einsehbare Medien sind Translucency-, Refraction- oder Volumenverfahren geeigneter.&lt;br /&gt;
&lt;br /&gt;
== Bedeutung für realistisches Rendering ==&lt;br /&gt;
&lt;br /&gt;
SSS liefert nicht einfach einen dekorativen „Glow“. Es verändert die räumliche Lichtantwort eines Materials und ist deshalb für organische oder mineralische Stoffe oft entscheidend. Besonders bei Haut sorgt die Mischung aus scharfer Oberflächenreflexion und weicher Streuung darunter dafür, dass Form, Feuchtigkeit und Gewebetiefe gleichzeitig erkennbar bleiben.&lt;br /&gt;
&lt;br /&gt;
Für ein glaubwürdiges Ergebnis ist nicht die maximal sichtbare Wirkung das Ziel, sondern ein zum Materialmaßstab passender, meist subtiler Lichttransport. Gutes SSS fällt häufig erst dann deutlich auf, wenn es abgeschaltet wird.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[Unreal Engine 5]]&lt;br /&gt;
* [[Rendering Hardware Interface (RHI) in Unreal Engine 5]]&lt;br /&gt;
* [[Render Dependency Graph in Unreal Engine 5]]&lt;br /&gt;
* [[Shader Model 6 und Direct3D 12 in Unreal Engine 5]]&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Computergrafik]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Materialien]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=162</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=162"/>
		<updated>2026-09-05T14:53:56Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Projektstand 05.09.2026: asynchroner 128x96-Texture-Job, Pending/Ready und persistentes Target&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 5. September 2026. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;30202f7&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Asynchroner 128×96-Worker-Texture-Job, GPU-Transfer, Pending/Ready-Ausgabe und persistente UE-Textur nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS&lt;br /&gt;
  -&amp;gt; lokale Worker-Textur&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; UE-eigene FTextureRHIRef auf der Primary&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; übernimmt und verwendet das Worker-Ergebnis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der synchrone Debugtest erzeugt eine 64 × 64 Pixel große RGBA8-Textur; &#039;&#039;&#039;alle 4096 shader-generierten Pixel wurden korrekt verifiziert&#039;&#039;&#039;. Der normale Runtime-Pfad verwendet inzwischen einen asynchronen 128×96-Test. Der Shader liest seine Dimensionen mit &amp;lt;code&amp;gt;GetDimensions()&amp;lt;/code&amp;gt;, schützt überhängende Threads durch einen Bounds-Check und wird mit &amp;lt;code&amp;gt;Dispatch(16,12,1)&amp;lt;/code&amp;gt; ausgeführt. Ein fester 64×64-Divisor ist damit aus dem produktiven Testpfad entfernt.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein Shared Fence synchronisiert die Queues direkt von GPU zu GPU.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert Shared Fence 1&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf Fence 1&lt;br /&gt;
  -&amp;gt; direkte Kopie in UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert Completion Fence 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Breite, Höhe und Row Pitch werden dynamisch aus Worker-Ressource und Transport-Metadaten übernommen. Der erfolgreiche 128×96-RGBA8-Test verwendet 512 Byte Row Pitch und 49.152 Byte Transfergröße. Das Ergebnis wird pro Worker in einer Output Registry veröffentlicht und kann über &amp;lt;code&amp;gt;GetNormalTextureOutputForWorker()&amp;lt;/code&amp;gt; abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;SubmitWorkerTextureComputeJob()&amp;lt;/code&amp;gt; reicht den Worker-Dispatch ohne CPU-Wait ein. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Der normale MainTextureCS-Pfad enthält weder CPU-Fence-Waits noch Readback, &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; oder Pixelvergleich. Erst &amp;lt;code&amp;gt;TickNormalTextureTransfers()&amp;lt;/code&amp;gt; prüft die Primary-Completion in &amp;lt;code&amp;gt;RHIEndFrame()&amp;lt;/code&amp;gt; non-blocking.&lt;br /&gt;
&lt;br /&gt;
Eine passende Primary-&amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt; wird pro Worker und Konfiguration persistent gehalten. Nach Fence 2 kann der nächste Job dieselbe Resource erneut verwenden; dabei führt Unreal die Übergänge &amp;lt;code&amp;gt;SRVMask -&amp;gt; CopyDest -&amp;gt; SRVMask&amp;lt;/code&amp;gt; aus. Pending- und Ready-Zustand hängen von Inhaltsgeneration und Fence ab, nicht von der Pointer-Identität. Eine native D3D12-Resource wird weiterhin nicht blind als UE-Textur gewrappt, weil Unreals Resource-State-Buchhaltung den tatsächlichen nativen Zustand sonst nicht sicher kennt.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Da die CPU nicht blockierend wartet, hält der Normal-Pfad einen vollständigen In-Flight-Job: Worker-Textur, Root Signature, PSO, Descriptor Heap, Allocator, Command List, Worker-Fence, Cross-Adapter-Transport, Shared-Ressourcen und Primary-Textur bleiben bis zum sicheren Abschluss erhalten. Die Completion wird automatisch in &amp;lt;code&amp;gt;FD3D12DynamicRHI::RHIEndFrame()&amp;lt;/code&amp;gt; geprüft:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Fence vor dem Submit erzeugen&lt;br /&gt;
  -&amp;gt; Dispatch und UAV-&amp;gt;COPY_SOURCE auf Worker-Queue&lt;br /&gt;
  -&amp;gt; Worker-Kopie in Shared Buffer&lt;br /&gt;
  -&amp;gt; Fence 1: Shared Buffer fertig&lt;br /&gt;
  -&amp;gt; Primary Wait, Copy und Signal Fence 2&lt;br /&gt;
  -&amp;gt; Output ist Pending&lt;br /&gt;
  -&amp;gt; RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; Fence 2 erreicht: aktuelle Generation wird Ready&lt;br /&gt;
  -&amp;gt; Job sicher freigeben; persistentes Target bleibt erhalten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehrere Jobs können lifetime-sicher gleichzeitig in flight sein. Im aktuellen Stand besitzt jeder Transport eine eigene Shared Fence sowie eigene Shared Heaps und Buffer; die Werte 1 und 2 sind daher transportlokal. Generationen verhindern, dass ein älterer Job einen neueren Pending- oder Ready-Output zurückrollt. Ein persistentes Target wird nicht erneut beschrieben, solange es noch in flight ist; dann wird vorläufig eine neue Textur erzeugt. Backpressure und ein echter Ressourcenpool fehlen noch.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der nächste qualitative Schritt ist ein &#039;&#039;&#039;erster sichtbarer Consumer&#039;&#039;&#039;: Das Worker-Ergebnis soll kontrolliert in einem UE-Material oder Compositing-Pfad erscheinen. Dabei muss insbesondere die Synchronisation stimmen, wenn dieselbe persistente Textur gelesen und später mit einer neuen Generation beschrieben wird. Danach folgen Backpressure, Ressourcenpooling, Messungen und echte Offload-Workloads.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der asynchrone 128×96-End-to-End-Pfad ist über Dimensionen, Dispatch, Transfer, Fences, Pending/Ready und Reuse verifiziert; ein eigener 128×96-Pixel-Readback fehlt noch. Der synchrone 64×64-Debugtest prüft weiterhin alle 4096 Pixel.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Shared Heaps, Buffer, Fences und Worker-Command-Objekte werden noch pro Job erzeugt. Backpressure, Pooling sowie Double-, Triple- oder Ring-Buffering fehlen.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Ein sichtbarer Material-/Renderer-Consumer, echte UE-Szenen-Workloads, Benchmark-Wizard und Scheduler fehlen weiterhin.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# Worker-Ergebnis als ersten sichtbaren Consumer in Material, Compositing oder Render Graph einbinden.&lt;br /&gt;
# Consumer-Synchronisation für Updates derselben persistenten Textur absichern.&lt;br /&gt;
# Backpressure sowie Pools für Shared Heaps, Buffer, Fences und Command Objects einführen.&lt;br /&gt;
# Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Latenz, Bandbreite, Größen, Update-Raten und Synchronisationskosten messen.&lt;br /&gt;
# Ersten echten UE-Offload wie SceneCapture2D, CCTV, Spiegel, Minimap, Niagara oder unabhängigen Compute integrieren.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 5. September 2026, Commit &amp;lt;code&amp;gt;30202f7&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=DirectX_12_Multiadapter_%E2%80%93_UE4_Elemental_Demo&amp;diff=156</id>
		<title>DirectX 12 Multiadapter – UE4 Elemental Demo</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=DirectX_12_Multiadapter_%E2%80%93_UE4_Elemental_Demo&amp;diff=156"/>
		<updated>2026-09-05T05:46:42Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|Historische Technikdemonstration: Microsoft zeigte diesen Prototyp am 30. April 2015 auf der Entwicklerkonferenz Build 2015. Die Demonstration war kein allgemein aktivierbarer Unreal-Engine-Modus und keine serienreife Produktfunktion.}}  Die &amp;#039;&amp;#039;&amp;#039;DirectX-12-Multiadapter-Demonstration mit Unreal Engine 4&amp;#039;&amp;#039;&amp;#039; war ein gemeinsamer Technikversuch von Microsoft und Epic Games aus dem Jahr 2015. Eine angepasste DirectX-12-Version der &amp;#039;&amp;#039;&amp;#039;UE4 Elemental Demo…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Historische Technikdemonstration: Microsoft zeigte diesen Prototyp am 30. April 2015 auf der Entwicklerkonferenz Build 2015. Die Demonstration war kein allgemein aktivierbarer Unreal-Engine-Modus und keine serienreife Produktfunktion.}}&lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;DirectX-12-Multiadapter-Demonstration mit Unreal Engine 4&#039;&#039;&#039; war ein gemeinsamer Technikversuch von Microsoft und Epic Games aus dem Jahr 2015. Eine angepasste DirectX-12-Version der &#039;&#039;&#039;UE4 Elemental Demo&#039;&#039;&#039; nutzte gleichzeitig eine diskrete NVIDIA-Grafikkarte und eine integrierte Intel-GPU. Microsoft wollte damit zeigen, dass Direct3D 12 auch sehr unterschiedliche Grafikprozessoren desselben PCs gezielt zusammenarbeiten lassen kann.&lt;br /&gt;
&lt;br /&gt;
Anders als bei klassischem NVIDIA SLI oder AMD CrossFire verteilte nicht der Grafikkartentreiber vollständige Frames auf ähnliche GPUs. Die Anwendung verwaltete beide Adapter ausdrücklich selbst und gab der schwächeren Intel-iGPU eine klar abgegrenzte Post-Processing-Aufgabe. Dadurch wurde die NVIDIA-GPU früher frei und konnte bereits mit dem nächsten Frame beginnen.&lt;br /&gt;
&lt;br /&gt;
Im gezeigten Test stieg die durchschnittliche Bildrate von &#039;&#039;&#039;35,9 FPS auf 39,7 FPS&#039;&#039;&#039;. Das entspricht rund &#039;&#039;&#039;10,6 Prozent Mehrleistung&#039;&#039;&#039;. Der Prototyp war ein wichtiger Machbarkeitsnachweis für heterogene Multi-GPU-Systeme, entwickelte sich jedoch nicht zu einer allgemeinen Funktion von Unreal Engine 4 oder späteren Engine-Versionen.&lt;br /&gt;
&lt;br /&gt;
== Hintergrund ==&lt;br /&gt;
&lt;br /&gt;
Viele PCs und Notebooks besaßen 2015 gleichzeitig eine integrierte GPU im Prozessor und eine deutlich leistungsfähigere diskrete Grafikkarte. Beim Spielen arbeitete normalerweise nur die dGPU; die iGPU blieb weitgehend ungenutzt oder diente lediglich als Display-Ausgabe. Microsoft bezeichnete diese brachliegende Rechenleistung als &#039;&#039;&#039;dormant silicon&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Direct3D 11 konnte mehrere GPUs nur eingeschränkt und meist über herstellerspezifische Treiberlösungen verwenden. SLI und CrossFire erwarteten typischerweise ähnliche Grafikkarten desselben Herstellers. Wie Frames oder Bildbereiche verteilt wurden, bestimmte weitgehend der Treiber.&lt;br /&gt;
&lt;br /&gt;
Direct3D 12 verlagerte mehr Verantwortung in die Anwendung. Mit &#039;&#039;&#039;Explicit Multiadapter&#039;&#039;&#039; konnte eine Engine:&lt;br /&gt;
&lt;br /&gt;
* verfügbare Adapter selbst erkennen,&lt;br /&gt;
* für jede GPU eigene Geräte, Queues und Ressourcen verwalten,&lt;br /&gt;
* verschiedene Aufgaben passend zur Leistungsfähigkeit verteilen,&lt;br /&gt;
* Daten ausdrücklich zwischen Adaptern austauschen,&lt;br /&gt;
* die Ausführung mit Fences und Queue-Abhängigkeiten synchronisieren.&lt;br /&gt;
&lt;br /&gt;
Damit wurde eine Kombination aus Intel-iGPU und NVIDIA-dGPU technisch möglich, obwohl beide Geräte unterschiedliche Leistung, Speicherbereiche und Treiber besaßen.&lt;br /&gt;
&lt;br /&gt;
== Die UE4 Elemental Demo ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Elemental&#039;&#039;&#039; ist eine von Epic Games entwickelte Echtzeitdemonstration für Unreal Engine 4. Die Szene zeigt eine große, aus Lava und Gestein bestehende Figur in einer aufwendig beleuchteten Umgebung. Epic hatte sie ursprünglich zur Präsentation der damaligen UE4-Renderingtechnik erstellt.&lt;br /&gt;
&lt;br /&gt;
Microsoft verwendete eine angepasste DirectX-12-Fassung dieser Demo als realistische Testlast. Die beiden verglichenen Konfigurationen sollten jeweils genau &#039;&#039;&#039;635 Frames&#039;&#039;&#039; so schnell wie möglich rendern:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Konfiguration&lt;br /&gt;
! Durchschnittliche Bildrate&lt;br /&gt;
! Ergebnis&lt;br /&gt;
|-&lt;br /&gt;
| NVIDIA-dGPU allein&lt;br /&gt;
| 35,9 FPS&lt;br /&gt;
| Ausgangswert&lt;br /&gt;
|-&lt;br /&gt;
| NVIDIA-dGPU + Intel-iGPU&lt;br /&gt;
| 39,7 FPS&lt;br /&gt;
| rund 10,6 % schneller&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die genauen Modelle der NVIDIA- und Intel-GPU wurden in Microsofts veröffentlichtem Beitrag nicht genannt. Die Messung war deshalb kein allgemein übertragbarer Hardwarebenchmark, sondern ein Nachweis, dass eine zusätzliche, deutlich schwächere und herstellerfremde GPU einen realen Leistungsgewinn erzielen konnte.&lt;br /&gt;
&lt;br /&gt;
== Aufteilung der Arbeit ==&lt;br /&gt;
&lt;br /&gt;
Die Demo verteilte nicht die gesamte Szene oder abwechselnde Frames auf beide GPUs. Stattdessen wurde ein &#039;&#039;&#039;separierbarer Post-Processing-Abschnitt&#039;&#039;&#039; auf die Intel-iGPU ausgelagert.&lt;br /&gt;
&lt;br /&gt;
Vereinfacht sah die Pipeline so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
NVIDIA-dGPU&lt;br /&gt;
  -&amp;gt; Hauptszene rendern&lt;br /&gt;
  -&amp;gt; benötigte Bilddaten für den zweiten Adapter bereitstellen&lt;br /&gt;
&lt;br /&gt;
Intel-iGPU&lt;br /&gt;
  -&amp;gt; ausgelagertes Post-Processing ausführen&lt;br /&gt;
  -&amp;gt; bearbeitetes Ergebnis zurückgeben&lt;br /&gt;
&lt;br /&gt;
NVIDIA-dGPU&lt;br /&gt;
  -&amp;gt; währenddessen früher mit dem nächsten Frame beginnen&lt;br /&gt;
  -&amp;gt; Ergebnisse zusammenführen und ausgeben&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Gewinn entstand durch &#039;&#039;&#039;Überlappung&#039;&#039;&#039;: Arbeit, die zuvor auf der NVIDIA-GPU lag, lief nun parallel auf der Intel-GPU. Die dGPU musste nicht bis zum Abschluss dieses Post-Processing-Schritts warten, bevor sie die nächste geeignete Aufgabe beginnen konnte.&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine zeitlich maßstäbliche GPU-Timeline. Darin liefen Kopieroperationen auf einer eigenen Copy Engine der NVIDIA-GPU parallel zu Arbeit auf deren 3D-Engine. Der Prototyp kombinierte somit zwei Direct3D-12-Konzepte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Multiadapter:&#039;&#039;&#039; parallele Arbeit auf verschiedenen GPUs,&lt;br /&gt;
* &#039;&#039;&#039;Multiengine:&#039;&#039;&#039; parallele Nutzung verschiedener Engines beziehungsweise Queues innerhalb einer GPU.&lt;br /&gt;
&lt;br /&gt;
== Ressourcenübertragung und Synchronisation ==&lt;br /&gt;
&lt;br /&gt;
Unabhängige GPUs besitzen normalerweise getrennte Speicherbereiche. Eine Ressource im lokalen VRAM der NVIDIA-GPU kann nicht ohne Weiteres von der Intel-GPU gelesen werden. Die Anwendung muss deshalb einen ausdrücklich unterstützten Austauschpfad verwenden.&lt;br /&gt;
&lt;br /&gt;
Direct3D 12 stellt dafür &#039;&#039;&#039;Cross-Adapter Shared Heaps&#039;&#039;&#039; und &#039;&#039;&#039;Cross-Adapter-Ressourcen&#039;&#039;&#039; bereit. Beide Geräte können einen gemeinsam freigegebenen Speicherbereich öffnen. Die CPU muss die Bilddaten dadurch nicht selbst lesen und erneut hochladen. GPU-Kopien, Resource Barriers und gemeinsam nutzbare Fences koordinieren Besitz, Sichtbarkeit und Ausführungsreihenfolge.&lt;br /&gt;
&lt;br /&gt;
Ein typischer Ablauf besteht aus:&lt;br /&gt;
&lt;br /&gt;
# Haupt-GPU rendert das benötigte Zwischenbild.&lt;br /&gt;
# Die Daten werden in eine Cross-Adapter-Ressource kopiert.&lt;br /&gt;
# Ein Fence signalisiert, dass die zweite GPU darauf zugreifen darf.&lt;br /&gt;
# Die Worker-GPU führt ihren Effekt aus.&lt;br /&gt;
# Das Ergebnis wird über einen geeigneten Austauschpuffer zurückgegeben.&lt;br /&gt;
# Die Ausgabe-GPU wartet nur dort, wo das Ergebnis tatsächlich benötigt wird.&lt;br /&gt;
&lt;br /&gt;
Die 2015 veröffentlichte Beschreibung nennt nicht jede konkrete Ressource und jeden einzelnen API-Aufruf des internen UE4-Prototyps. Der Ablauf darf daher nicht mit Microsofts später veröffentlichtem, eigenständigem D3D12-Heterogeneous-Multiadapter-Sample gleichgesetzt werden. Beide beruhen aber auf derselben technischen Familie aus getrennten Adaptern, geteilten Ressourcen, GPU-Kopien und expliziter Synchronisation.&lt;br /&gt;
&lt;br /&gt;
== Gemessene Auslastung ==&lt;br /&gt;
&lt;br /&gt;
Microsoft veröffentlichte für den Test folgende durchschnittliche GPU-Auslastungen:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;NVIDIA-GPU:&#039;&#039;&#039; ungefähr 100 Prozent,&lt;br /&gt;
* &#039;&#039;&#039;Intel-GPU:&#039;&#039;&#039; ungefähr 70 Prozent.&lt;br /&gt;
&lt;br /&gt;
Die dGPU blieb damit der vollständig ausgelastete Hauptprozessor. Die iGPU ersetzte sie nicht, sondern arbeitete als zusätzlicher Worker. Microsoft deutete die nur etwa 70-prozentige iGPU-Auslastung als Hinweis auf weiteres Optimierungspotenzial.&lt;br /&gt;
&lt;br /&gt;
Eine höhere Auslastung hätte allerdings nicht automatisch proportional mehr Bildrate bedeutet. Der Nutzen wird durch Abhängigkeiten, Übertragungskosten, Synchronisation und die Frage begrenzt, ob weitere Aufgaben unabhängig genug für eine parallele Ausführung sind.&lt;br /&gt;
&lt;br /&gt;
== Warum Post-Processing geeignet war ==&lt;br /&gt;
&lt;br /&gt;
Post-Processing ist für einen frühen Multiadapter-Versuch vergleichsweise attraktiv:&lt;br /&gt;
&lt;br /&gt;
* Der Arbeitsschritt besitzt einen klaren Anfang und ein klar definiertes Ergebnis.&lt;br /&gt;
* Er kann nach dem eigentlichen Szenenrendering ausgeführt werden.&lt;br /&gt;
* Viele Effekte arbeiten bildschirmraumbezogen und benötigen weniger komplexe Szenendaten.&lt;br /&gt;
* Das Ergebnis ist eine Textur beziehungsweise ein begrenzter Satz von Bildressourcen.&lt;br /&gt;
* Die Haupt-GPU kann parallel bereits Arbeit für den nächsten Frame vorbereiten.&lt;br /&gt;
&lt;br /&gt;
Schlechter geeignet wären eng gekoppelte Renderpässe, die ständig auf große Mengen lokaler Geometrie-, Material-, Tiefen- und Beleuchtungsdaten der Haupt-GPU zugreifen. Werden zu viele Ressourcen übertragen, kann die Kommunikation den Rechengewinn vollständig aufzehren.&lt;br /&gt;
&lt;br /&gt;
== Abgrenzung zu SLI und CrossFire ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Merkmal&lt;br /&gt;
! SLI / CrossFire&lt;br /&gt;
! DX12 Explicit Multiadapter der Demo&lt;br /&gt;
|-&lt;br /&gt;
| Steuerung&lt;br /&gt;
| überwiegend Treiber&lt;br /&gt;
| Anwendung beziehungsweise Engine&lt;br /&gt;
|-&lt;br /&gt;
| GPU-Kombination&lt;br /&gt;
| typischerweise ähnliche GPUs desselben Herstellers&lt;br /&gt;
| Intel-iGPU und NVIDIA-dGPU&lt;br /&gt;
|-&lt;br /&gt;
| Arbeitsverteilung&lt;br /&gt;
| häufig ganze Frames oder Bildbereiche&lt;br /&gt;
| gezielte Auslagerung eines Post-Processing-Workloads&lt;br /&gt;
|-&lt;br /&gt;
| Ressourcenverwaltung&lt;br /&gt;
| weitgehend durch Treiber abstrahiert&lt;br /&gt;
| getrennte Geräte und expliziter Datenaustausch&lt;br /&gt;
|-&lt;br /&gt;
| Entwicklungsaufwand&lt;br /&gt;
| geringerer Eingriff in die Engine&lt;br /&gt;
| deutlich höher; Engine muss alle Abhängigkeiten selbst verwalten&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der Vorteil des expliziten Ansatzes ist die freie Aufgabenwahl. Sein Nachteil ist, dass die Engine Hardwareunterschiede, Speicher, Zustände, Fences, Fehlerpfade und Performanceentscheidungen selbst beherrschen muss.&lt;br /&gt;
&lt;br /&gt;
== Warum daraus keine allgemeine UE4-Funktion wurde ==&lt;br /&gt;
&lt;br /&gt;
Microsoft beschrieb die Demo ausdrücklich als frühen Prototyp und als Einladung an Entwickler, neue Möglichkeiten zu erforschen. Eine universelle Funktion entstand daraus nicht. Wesentliche Hürden waren:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Integrationsaufwand:&#039;&#039;&#039; Jeder ausgelagerte Renderpass benötigt passende Ressourcen- und Synchronisationspfade.&lt;br /&gt;
* &#039;&#039;&#039;Stark unterschiedliche Hardware:&#039;&#039;&#039; Leistung, Speicherarchitektur, unterstützte Formate und Übertragungswege variieren zwischen Systemen.&lt;br /&gt;
* &#039;&#039;&#039;Transferkosten:&#039;&#039;&#039; Cross-Adapter-Ressourcen liegen nicht automatisch im schnellen lokalen VRAM der dGPU und können ungünstige Layouts erfordern.&lt;br /&gt;
* &#039;&#039;&#039;Begrenzte Parallelisierbarkeit:&#039;&#039;&#039; Viele moderne Renderpässe hängen eng voneinander und von Daten der Haupt-GPU ab.&lt;br /&gt;
* &#039;&#039;&#039;Schwierige Skalierung:&#039;&#039;&#039; Ein sinnvoller Scheduler muss pro System entscheiden, ob eine Auslagerung tatsächlich schneller ist.&lt;br /&gt;
* &#039;&#039;&#039;Test- und Wartungsaufwand:&#039;&#039;&#039; Kombinationen verschiedener Hersteller, Treiber und Leistungsstufen vervielfachen die Fehlerfälle.&lt;br /&gt;
* &#039;&#039;&#039;Andere Optimierungswege:&#039;&#039;&#039; Asynchronous Compute, leistungsfähigere Einzel-GPUs und später neue Rekonstruktionsverfahren boten oft ein besseres Verhältnis aus Aufwand und Nutzen.&lt;br /&gt;
&lt;br /&gt;
Direct3D 12 behielt seine Multiadapter-Fähigkeiten. Einzelne Anwendungen wie &#039;&#039;Ashes of the Singularity&#039;&#039; bewiesen 2015 sogar die gemeinsame Nutzung von AMD- und NVIDIA-GPUs. In der breiten Spieleentwicklung blieb heterogenes Explicit Multiadapter dennoch eine Ausnahme.&lt;br /&gt;
&lt;br /&gt;
== Bedeutung für UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Microsofts Elemental-Demo ist ein direkter historischer Vorläufer des Projekts [[UE5 Heterogeneous Multi-GPU]]. Beide Ansätze verfolgen dieselbe Grundidee: Eine leistungsfähige GPU rendert die Hauptansicht, während ein anderer Adapter eine klar abgegrenzte Aufgabe übernimmt.&lt;br /&gt;
&lt;br /&gt;
Die Projekte unterscheiden sich jedoch im Ziel und Entwicklungsstand:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Punkt&lt;br /&gt;
! Microsoft/Epic 2015&lt;br /&gt;
! UE5 Heterogeneous Multi-GPU&lt;br /&gt;
|-&lt;br /&gt;
| Engine&lt;br /&gt;
| angepasste Unreal Engine 4&lt;br /&gt;
| Unreal Engine 5.8 Source Build&lt;br /&gt;
|-&lt;br /&gt;
| Gezeigte Aufgabe&lt;br /&gt;
| Post-Processing&lt;br /&gt;
| zunächst Compute- und Texturtransport-Proofs; später frei wählbare Worker-Aufgaben&lt;br /&gt;
|-&lt;br /&gt;
| Hardwarebeispiel&lt;br /&gt;
| nicht benannte NVIDIA-dGPU + Intel-iGPU&lt;br /&gt;
| RTX 5060 Laptop GPU + Intel UHD&lt;br /&gt;
|-&lt;br /&gt;
| Hauptziel&lt;br /&gt;
| DX12-Fähigkeit und messbaren FPS-Gewinn demonstrieren&lt;br /&gt;
| allgemeine UE5-RHI-Integration, Scheduler, Fallbacks und mehrere Workload-Typen&lt;br /&gt;
|-&lt;br /&gt;
| Veröffentlichung&lt;br /&gt;
| Technikdemo, kein allgemeines UE4-Feature&lt;br /&gt;
| experimentelles Entwicklungsprojekt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die wichtigste Lehre aus dem Versuch von 2015 bleibt aktuell: Eine zweite GPU ist nur dann nützlich, wenn der Rechengewinn größer ist als Vorbereitung, Datentransfer, Synchronisation und Rückintegration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Nutzen des Worker-Workloads&lt;br /&gt;
  &amp;gt; Übertragung + Synchronisation + Integrationskosten&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fazit ==&lt;br /&gt;
&lt;br /&gt;
Die UE4-Elemental-Multiadapter-Demo zeigte 2015 glaubhaft, dass eine Intel-iGPU und eine NVIDIA-dGPU gemeinsam an aufeinanderfolgenden Bildern arbeiten können. Durch das Auslagern von Post-Processing stieg die Bildrate im konkreten Prototyp um gut zehn Prozent. Das war weder SLI noch CrossFire und auch kein automatisches Zusammenlegen zweier Grafikkarten. Es war ein ausdrücklich programmierter, workload-basierter Multi-GPU-Pfad.&lt;br /&gt;
&lt;br /&gt;
Technisch war der Versuch erfolgreich. Als allgemeines Produktmodell scheiterte er am hohen Engine-Aufwand, an Hardwareunterschieden und an den Kosten des Datenaustauschs. Gerade deshalb ist er für heutige heterogene Multi-GPU-Experimente wertvoll: Er zeigt sowohl das mögliche Leistungsplus als auch die Notwendigkeit, kleine, unabhängige und transferarme Aufgaben auszuwählen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft DirectX Developer Blog: DirectX 12 Multiadapter – UE4 Elemental Demo, Messwerte, Auslastung und Ablauf]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft DirectX Developer Blog: früher Prototyp, Leistungsplus über zehn Prozent und späterer Spieleinsatz]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft Learn: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft Learn: Cross-Adapter Shared Heaps, Ressourcen und Einschränkungen]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://github.com/microsoft/DirectX-Graphics-Samples Microsoft: DirectX Graphics Samples]&lt;br /&gt;
* [https://www.pcgameshardware.de/DirectX-Software-255525/News/Windows-10-iGPU-und-Grafikarte-arbeiten-an-einem-Frame-1157931/ PC Games Hardware: dokumentierte Benchmarkwerte 35,9 und 39,7 FPS]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 4]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Microsoft]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Microsoft_Talisman&amp;diff=155</id>
		<title>Microsoft Talisman</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Microsoft_Talisman&amp;diff=155"/>
		<updated>2026-09-05T05:38:42Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|Historisches Projekt: Microsoft Talisman wurde 1996 öffentlich vorgestellt, erreichte jedoch nie den Markt. Der Begriff „Hybrid“ bezeichnet hier die Verbindung aus klassischer 3D-Berechnung, wiederverwendeten 2D-Bildebenen und Multimedia-Verarbeitung – nicht ein heutiges Notebook-System aus iGPU und dGPU.}}  &amp;#039;&amp;#039;&amp;#039;Microsoft Talisman&amp;#039;&amp;#039;&amp;#039; war der Codename einer experimentellen 3D-Grafik- und Multimedia-Architektur von Microsoft Research aus der…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Historisches Projekt: Microsoft Talisman wurde 1996 öffentlich vorgestellt, erreichte jedoch nie den Markt. Der Begriff „Hybrid“ bezeichnet hier die Verbindung aus klassischer 3D-Berechnung, wiederverwendeten 2D-Bildebenen und Multimedia-Verarbeitung – nicht ein heutiges Notebook-System aus iGPU und dGPU.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Microsoft Talisman&#039;&#039;&#039; war der Codename einer experimentellen 3D-Grafik- und Multimedia-Architektur von Microsoft Research aus der Mitte der 1990er-Jahre. Microsoft wollte hochwertige Echtzeitgrafik auf bezahlbaren PCs ermöglichen, obwohl damalige Prozessoren, Grafikspeicher und Speicherbusse für komplexe 3D-Szenen noch sehr begrenzt waren.&lt;br /&gt;
&lt;br /&gt;
Talisman sollte dieses Problem nicht allein mit mehr Rechenleistung lösen. Statt eine vollständige Szene in jedem Bild neu zu rendern, zerlegte das System sie in unabhängig aktualisierbare &#039;&#039;&#039;Bildebenen&#039;&#039;&#039; – vergleichbar mit Sprites oder Folien. Bereits berechnete Objektbilder konnten über mehrere Frames gespeichert, verschoben, skaliert, gedreht, verzerrt und anschließend wieder zur fertigen Szene zusammengesetzt werden. Nur sichtbar veränderte Inhalte mussten erneut als echte 3D-Geometrie gerendert werden.&lt;br /&gt;
&lt;br /&gt;
Damit war Talisman ein ungewöhnlicher Hybrid aus 3D-Rendering, bildbasierter Darstellung, 2D-Compositing und programmierbarer Medienverarbeitung. Das Projekt beeinflusste Forschung und Diskussionen über bandbreiteneffiziente Grafik, setzte sich gegen die schnell besser werdenden konventionellen 3D-Beschleuniger jedoch nicht durch.&lt;br /&gt;
&lt;br /&gt;
== Ausgangslage und Ziel ==&lt;br /&gt;
&lt;br /&gt;
Mitte der 1990er-Jahre waren Echtzeit-3D-Grafik und Multimedia auf dem PC teuer. Ein konventioneller Renderer musste Geometrie transformieren, Polygone rasterisieren, Texturen lesen, Tiefentests ausführen und ein vollständiges Framebuffer-Bild schreiben. Speicherbandbreite war knapp, dedizierter Grafikspeicher teuer und viele Arbeitsschritte lagen noch auf der CPU.&lt;br /&gt;
&lt;br /&gt;
Microsofts Ziel war deshalb eine Grafiklösung im Bereich von ungefähr &#039;&#039;&#039;200 bis 300 US-Dollar&#039;&#039;&#039;, deren wahrgenommene Bildqualität und Komplexität an damalige 3D-Workstations heranreichen sollte. Die Architektur sollte außerdem nicht nur Spiele beschleunigen, sondern mehrere zuvor getrennte PC-Komponenten zusammenführen: 2D- und 3D-Grafik, Audio, MPEG-Wiedergabe, Videokonferenzen und sogar Modemfunktionen.&lt;br /&gt;
&lt;br /&gt;
Die grundlegende Idee lautete:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
3D-Objekte nur bei Bedarf neu rendern&lt;br /&gt;
             ↓&lt;br /&gt;
Objektbilder als komprimierte Ebenen speichern&lt;br /&gt;
             ↓&lt;br /&gt;
Ebenen pro Bild günstig transformieren&lt;br /&gt;
             ↓&lt;br /&gt;
Ebenen mit Transparenz zum Ausgabebild zusammensetzen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Talisman nutzte damit sowohl &#039;&#039;&#039;räumliche Kohärenz&#039;&#039;&#039; – benachbarte Bildbereiche ähneln sich – als auch &#039;&#039;&#039;zeitliche Kohärenz&#039;&#039;&#039; – viele Inhalte verändern sich zwischen zwei Frames nur wenig.&lt;br /&gt;
&lt;br /&gt;
== Das Ebenenprinzip ==&lt;br /&gt;
&lt;br /&gt;
Bei Talisman wurde ein bewegliches Objekt zunächst aus Polygonen in eine eigene zweidimensionale Bildebene gerendert. Zu dieser Ebene gehörten Farb-, Transparenz- und Tiefeninformationen. Solange sich Form, Beleuchtung oder Blickwinkel nicht zu stark änderten, konnte das gespeicherte Bild weiterverwendet werden.&lt;br /&gt;
&lt;br /&gt;
Der Image Layer Compositor setzte die Ebenen mit hoher Rate zum sichtbaren Bild zusammen. Eine affine Transformation erlaubte dabei:&lt;br /&gt;
&lt;br /&gt;
* Verschieben,&lt;br /&gt;
* Skalieren,&lt;br /&gt;
* Rotation innerhalb der Bildebene,&lt;br /&gt;
* Spiegeln und Scheren,&lt;br /&gt;
* Filtern und Alpha-Compositing.&lt;br /&gt;
&lt;br /&gt;
Eine solche Transformation kann bestimmte Bewegungen überzeugend vortäuschen, ohne alle Polygone erneut zu berechnen. Dreht sich ein dreidimensionales Objekt stark, werden zuvor verdeckte Flächen sichtbar oder verändert sich seine Beleuchtung, muss seine Ebene dagegen neu gerendert werden.&lt;br /&gt;
&lt;br /&gt;
Microsofts Forschungsarbeiten ergänzten das Konzept um Qualitätsmaße, sogenannte &#039;&#039;&#039;Fiducials&#039;&#039;&#039;. Sie sollten abschätzen, wann eine wiederverwendete Ebene sichtbar vom korrekten Ergebnis abweicht. Auf dieser Grundlage konnten Aktualisierungsrate, Auflösung und andere Qualitätsparameter je Ebene angepasst werden. Wichtige Objekte ließen sich häufiger oder höher aufgelöst aktualisieren als kleine Hintergrundelements.&lt;br /&gt;
&lt;br /&gt;
== Chunking, Kompression und Mehrfachdurchläufe ==&lt;br /&gt;
&lt;br /&gt;
Talisman verarbeitete Ebenen nicht nur als große rechteckige Bilder. Sie wurden in kleinere Bereiche oder &#039;&#039;&#039;Chunks&#039;&#039;&#039; zerlegt. Dadurch musste das System nur jene Teile lesen und bearbeiten, die für den aktuellen Bildausschnitt tatsächlich benötigt wurden.&lt;br /&gt;
&lt;br /&gt;
Bild- und Texturdaten sollten breit komprimiert werden, um Speicherbedarf und Bandbreite zu senken. Die geplante Hardware konnte diese Daten während der Ausgabe wieder entpacken. Das war entscheidend, weil Talisman zwischen gespeicherten Ebenen, Texturen und dem Compositor große Datenmengen bewegen musste.&lt;br /&gt;
&lt;br /&gt;
Außerdem setzte die Architektur auf &#039;&#039;&#039;Multi-Pass-Rendering&#039;&#039;&#039;. Komplexe Material- und Beleuchtungseffekte konnten in mehreren Durchläufen berechnet und anschließend kombiniert werden. Dieser Ansatz war für die damalige PC-Hardware ungewöhnlich ambitioniert, erhöhte allerdings auch die Anforderungen an Software, Speicherverwaltung und Synchronisation.&lt;br /&gt;
&lt;br /&gt;
== Geplante Referenzhardware ==&lt;br /&gt;
&lt;br /&gt;
Microsoft entwickelte Talisman als Architektur und Referenzentwurf, nicht als eigene serienreife Microsoft-Grafikkarte. Mehrere Halbleiterhersteller sollten Komponenten oder kompatible Umsetzungen liefern.&lt;br /&gt;
&lt;br /&gt;
Eine frühe Referenzimplementierung war als PCI-Erweiterungskarte vorgesehen. Dokumentiert sind unter anderem:&lt;br /&gt;
&lt;br /&gt;
* ein &#039;&#039;&#039;Media Signal Processor&#039;&#039;&#039; von Samsung mit einem ARM-RISC-Kern und einem programmierbaren Vektor-Coprozessor,&lt;br /&gt;
* spezialisierte Logik für Polygon- beziehungsweise Bildverarbeitung,&lt;br /&gt;
* ein &#039;&#039;&#039;Image Layer Compositor&#039;&#039;&#039; für Transformation, Filterung und Zusammensetzen der Ebenen,&lt;br /&gt;
* lokaler Speicher für Grafik- und Mediendaten,&lt;br /&gt;
* ein kleines Betriebssystem auf der Karte, das Module und Treiber vom Windows-PC laden konnte.&lt;br /&gt;
&lt;br /&gt;
Der ARM-Kern übernahm Steuerungs- und Betriebssystemaufgaben. Der SIMD-artige Vektorprozessor war für rechenintensive Medienoperationen vorgesehen. Microsoft Research untersuchte sogar ein asymmetrisches Scheduling: Der ARM-Kern konnte normal präemptiv zwischen Threads wechseln, während der große Zustand des Vektorprozessors nur an vorbereiteten Kontrollpunkten gewechselt wurde.&lt;br /&gt;
&lt;br /&gt;
Die geplante Karte war daher mehr als ein reiner 3D-Beschleuniger. In heutiger Sprache ähnelte sie teilweise einer Mischung aus GPU, programmierbarem Medienprozessor, Audio-DSP und eigenständigem Subsystem.&lt;br /&gt;
&lt;br /&gt;
== Software und DirectX ==&lt;br /&gt;
&lt;br /&gt;
Talisman benötigte eine enge Zusammenarbeit zwischen Anwendung, Grafiktreiber und Hardware. Eine Engine musste Objekte sinnvoll in Ebenen zerlegen, deren Gültigkeit bewerten und entscheiden, wann echtes Neurendern erforderlich war. Ohne diese Informationen konnte die Hardware ihren wichtigsten Vorteil – die Wiederverwendung bereits berechneter Bilder – nur eingeschränkt ausspielen.&lt;br /&gt;
&lt;br /&gt;
Microsoft wollte Talisman-Funktionen über seine Windows-Grafikschnittstellen zugänglich machen und verband dabei Ideen aus DirectDraw und Direct3D. Für bestehende Spiele blieb jedoch ein Kompatibilitätspfad nötig. Wenn eine Anwendung nur eine gewöhnliche unmittelbare 3D-Pipeline erwartete, konnte sie die spezielle Layer-Architektur nicht automatisch optimal nutzen.&lt;br /&gt;
&lt;br /&gt;
Genau darin lag ein strategisches Problem: Talisman versprach den größten Gewinn bei speziell angepassten Anwendungen, während Entwickler gleichzeitig bereits Direct3D, OpenGL und herstellerspezifische APIs bedienen mussten.&lt;br /&gt;
&lt;br /&gt;
== Demonstration „Chicken Crossing“ ==&lt;br /&gt;
&lt;br /&gt;
Auf der SIGGRAPH 1996 zeigte Microsoft den animierten Kurzfilm &#039;&#039;&#039;Chicken Crossing&#039;&#039;&#039;. Er demonstrierte Talisman-Techniken in einer für damalige PCs aufwendigen Szene und sollte zeigen, dass die Kombination aus Ebenen, Wiederverwendung und Compositing workstationähnliche Darstellung zu deutlich geringeren Kosten ermöglichen könnte.&lt;br /&gt;
&lt;br /&gt;
Die Vorführung belegte, dass das Grundprinzip funktionierte. Sie war jedoch kein Nachweis für eine allgemein verfügbare Grafikkarte oder dafür, dass beliebige Spiele ohne Anpassung gleich gut profitiert hätten.&lt;br /&gt;
&lt;br /&gt;
== Warum Talisman scheiterte ==&lt;br /&gt;
&lt;br /&gt;
Talisman wurde nie als Endkundenprodukt veröffentlicht. Dafür kamen mehrere technische und wirtschaftliche Gründe zusammen:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Der Markt entwickelte sich schneller als erwartet:&#039;&#039;&#039; 3dfx, NVIDIA, ATI, S3 und weitere Anbieter steigerten Rasterleistung und Speicherbandbreite konventioneller 3D-Beschleuniger sehr schnell.&lt;br /&gt;
* &#039;&#039;&#039;Spezialbehandlung in Anwendungen:&#039;&#039;&#039; Die besten Ergebnisse erforderten eine bewusste Zerlegung der Szene in wiederverwendbare Ebenen.&lt;br /&gt;
* &#039;&#039;&#039;Begrenzte Wiederverwendbarkeit:&#039;&#039;&#039; Starke Perspektivänderungen, Verdeckungen, dynamische Beleuchtung, Schatten und komplexe Überschneidungen konnten ein Neurendern erzwingen oder sichtbare Näherungsfehler erzeugen.&lt;br /&gt;
* &#039;&#039;&#039;Komplexe Gesamtarchitektur:&#039;&#039;&#039; Programmierbarer Medienprozessor, Spezialchips, Kompression, eigenes Scheduling und neue Softwarepfade mussten gemeinsam zuverlässig funktionieren.&lt;br /&gt;
* &#039;&#039;&#039;Schwieriger Kompatibilitätspfad:&#039;&#039;&#039; Ein gewöhnliches Direct3D-Spiel konnte auf Talisman laufen, nutzte die besonderen Fähigkeiten aber nicht automatisch vollständig aus.&lt;br /&gt;
* &#039;&#039;&#039;Sinkende Preise klassischer GPUs:&#039;&#039;&#039; Als entsprechende Referenzdesigns produktionsnah wurden, boten konventionelle Beschleuniger eine einfachere und zunehmend günstigere Lösung.&lt;br /&gt;
&lt;br /&gt;
Das Scheitern bedeutet daher nicht, dass die technischen Ideen wirkungslos waren. Vielmehr verlor eine stark spezialisierte Architektur ihr wirtschaftliches Zeitfenster, bevor Hardware, Werkzeuge und ein breites Software-Ökosystem gleichzeitig bereitstanden.&lt;br /&gt;
&lt;br /&gt;
== Abgrenzung zu heutigen Hybrid-Grafiksystemen ==&lt;br /&gt;
&lt;br /&gt;
Talisman darf nicht mit modernen &#039;&#039;&#039;Hybrid-GPU-Systemen&#039;&#039;&#039; wie NVIDIA Optimus oder einer Windows-Konfiguration aus integrierter und diskreter GPU verwechselt werden. Dort rendern zwei weitgehend vollständige Grafikprozessoren je nach Leistungs- oder Energiebedarf; häufig erzeugt die dGPU ein Bild, das über die iGPU ausgegeben wird.&lt;br /&gt;
&lt;br /&gt;
Talisman kombinierte dagegen verschiedene Arten der Bildberechnung innerhalb einer neuen Architektur:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! System&lt;br /&gt;
! Grundidee&lt;br /&gt;
! Ziel&lt;br /&gt;
|-&lt;br /&gt;
| Microsoft Talisman&lt;br /&gt;
| 3D-Objekte in wiederverwendbare 2D-Bildebenen rendern und per Compositor zusammensetzen&lt;br /&gt;
| Rechen- und Speicheraufwand hochwertiger Grafik senken&lt;br /&gt;
|-&lt;br /&gt;
| Modernes iGPU/dGPU-Hybridsystem&lt;br /&gt;
| Zwischen vollständigen GPUs umschalten oder das fertige Bild zwischen ihnen übertragen&lt;br /&gt;
| Akkulaufzeit und Leistung ausbalancieren&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D-12-Explicit-Multiadapter&lt;br /&gt;
| Eine Anwendung verteilt eigene Aufgaben auf mehrere unabhängige GPUs&lt;br /&gt;
| Mehrere vorhandene Adapter parallel nutzen&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bedeutung aus heutiger Sicht ==&lt;br /&gt;
&lt;br /&gt;
Talisman war keine Vorstufe moderner GPUs im geradlinigen Sinn. Heutige Grafikprozessoren folgen weiterhin überwiegend einer konventionellen, massiv parallelen Raster- und Compute-Architektur. Mehrere Talisman-Gedanken wirken aus heutiger Sicht dennoch erstaunlich vertraut:&lt;br /&gt;
&lt;br /&gt;
* temporale Wiederverwendung statt vollständiger Neuberechnung,&lt;br /&gt;
* unterschiedliche Aktualisierungsraten für Bildbestandteile,&lt;br /&gt;
* Rekonstruktion und Transformation bereits gerenderter Informationen,&lt;br /&gt;
* Kachelung und Verarbeitung kleiner Bildbereiche,&lt;br /&gt;
* Kompression zur Verringerung von Speicherbandbreite,&lt;br /&gt;
* Trennung von 3D-Rendering und späterem Compositing,&lt;br /&gt;
* programmierbare Prozessoren für Grafik-, Audio- und Videoaufgaben.&lt;br /&gt;
&lt;br /&gt;
Moderne temporale Upscaler, Frame Generation, reprojizierte VR-Bilder, variable Shading-Raten und komprimierte Renderziele sind keine direkten Talisman-Nachfolger. Sie beruhen jedoch auf einem ähnlichen Grundgedanken: Ein glaubwürdiges neues Bild muss nicht in jedem Teil vollständig von Grund auf neu berechnet werden.&lt;br /&gt;
&lt;br /&gt;
== Fazit ==&lt;br /&gt;
&lt;br /&gt;
Microsoft Talisman war der Versuch, die Grenzen damaliger PC-Hardware mit einer radikal anderen Aufteilung der Grafikarbeit zu umgehen. Echte 3D-Berechnung erzeugte Objektbilder; ein schneller 2D-Compositor verwandelte und kombinierte sie über mehrere Frames hinweg. Ergänzt um Kompression und programmierbare Multimedia-Verarbeitung sollte daraus eine günstige Allzweckkarte für Grafik, Ton und Video entstehen.&lt;br /&gt;
&lt;br /&gt;
Technisch war das Konzept vorausschauend, praktisch aber zu spezialisiert und vom schnellen Fortschritt klassischer 3D-Grafikkarten überholt. Talisman blieb deshalb ein Forschungs- und Referenzprojekt – ein faszinierender Seitenweg der GPU-Geschichte, dessen zentrale Idee der zeitlichen Wiederverwendung heute aktueller wirkt als in den 1990er-Jahren.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.microsoft.com/en-us/research/publication/talisman-commodity-realtime-3d-graphics-for-the-pc/ Microsoft Research: Jay Torborg und Jim Kajiya – Talisman: Commodity Realtime 3D Graphics for the PC (1996)]&lt;br /&gt;
* [https://news.microsoft.com/source/1996/08/06/microsoft-research-displays-latest-innovations-at-siggraph-96/ Microsoft: Vorstellung von Talisman und „Chicken Crossing“ auf der SIGGRAPH 1996]&lt;br /&gt;
* [https://www.microsoft.com/en-us/research/people/johnsny/other-research/ Microsoft Research: Rendering with Coherent Layers und verwandte Arbeiten]&lt;br /&gt;
* [https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-98-09.pdf Microsoft Research: Asymmetric Real Time Scheduling on a Multimedia Processor – Referenzhardware, MSP und Scheduling]&lt;br /&gt;
* [https://history.siggraph.org/wp-content/uploads/2022/11/SIGGRAPH-1997-Visual-Proceedings.pdf SIGGRAPH 1997 Visual Proceedings: Delivering High Quality 3D to Every Desk]&lt;br /&gt;
* [https://www.electronicdesign.com/technologies/embedded/article/21131674/jon-peddie-research-microsofts-talisman-the-graphics-chip-that-never-was Electronic Design / Jon Peddie Research: Microsoft’s Talisman – The Graphics Chip That Never Was]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grafik]]&lt;br /&gt;
[[Kategorie:Microsoft]]&lt;br /&gt;
[[Kategorie:Hardware]]&lt;br /&gt;
[[Kategorie:Historische Technik]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=XeSS_Intel_Xe_Super_Sampling&amp;diff=153</id>
		<title>XeSS Intel Xe Super Sampling</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=XeSS_Intel_Xe_Super_Sampling&amp;diff=153"/>
		<updated>2026-09-05T00:18:26Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: 5. September 2026. Aktuell ist das XeSS 3 SDK 3.0.2. Das offizielle Unreal-Engine-Plugin 3.1.0 unterstützt Unreal Engine bis Version 5.8; bei UE 5.8.0 und 5.8.1 besteht eine bekannte Einschränkung für Xe Low Latency.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Intel Xe Super Sampling&#039;&#039;&#039; (&#039;&#039;&#039;XeSS&#039;&#039;&#039;) ist eine Familie KI-gestützter Grafikverfahren für Spiele. XeSS kann ein intern niedriger aufgelöstes Bild rekonstruieren, zusätzliche Zwischenbilder erzeugen und die Eingabelatenz begrenzen. Die einzelnen Funktionen heißen &#039;&#039;&#039;XeSS Super Resolution&#039;&#039;&#039; (XeSS-SR), &#039;&#039;&#039;XeSS Frame Generation&#039;&#039;&#039; (XeSS-FG) und &#039;&#039;&#039;Xe Low Latency&#039;&#039;&#039; (XeLL).&lt;br /&gt;
&lt;br /&gt;
XeSS wurde zusammen mit Intel Arc eingeführt, ist aber nicht grundsätzlich auf Intel-GPUs beschränkt. Für kompatible Grafikkarten anderer Hersteller existieren herstellerübergreifende Ausführungspfade. Funktionsumfang und Leistung unterscheiden sich jedoch je nach GPU und Grafikschnittstelle.&lt;br /&gt;
&lt;br /&gt;
== Die Bestandteile von XeSS 3 ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;XeSS Super Resolution (XeSS-SR):&#039;&#039;&#039; rekonstruiert aus einem niedriger aufgelösten, zeitlich versetzten Eingabebild ein höher aufgelöstes und geglättetes Ausgabebild.&lt;br /&gt;
* &#039;&#039;&#039;XeSS Frame Generation (XeSS-FG):&#039;&#039;&#039; berechnet zusätzliche Zwischenbilder zwischen regulär gerenderten Frames.&lt;br /&gt;
* &#039;&#039;&#039;Xe Low Latency (XeLL):&#039;&#039;&#039; steuert das CPU-Timing anhand von Markierungen aus der Engine, um die Eingabe-zu-Anzeige-Latenz zu verringern. XeSS-FG setzt eine XeLL-Integration voraus.&lt;br /&gt;
&lt;br /&gt;
Die drei Komponenten können passend zum Spiel kombiniert werden. Super Resolution und XeLL lassen sich auch ohne Frame Generation verwenden. Die Bezeichnung &#039;&#039;&#039;XeSS 3&#039;&#039;&#039; steht für das gemeinsame Paket dieser Technologien einschließlich Multi Frame Generation.&lt;br /&gt;
&lt;br /&gt;
== Entwicklung der XeSS-Versionen ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;XeSS 1.0:&#039;&#039;&#039; erste Version von XeSS-SR mit einem für Intel XMX optimierten Pfad und einer herstellerübergreifenden DP4a-Variante.&lt;br /&gt;
* &#039;&#039;&#039;XeSS 1.1 und 1.2:&#039;&#039;&#039; Verbesserungen an zeitlicher Stabilität, automatischer Belichtung, Leistung und Fehlerbehandlung.&lt;br /&gt;
* &#039;&#039;&#039;XeSS 1.3:&#039;&#039;&#039; neue Modelle und Qualitätsmodi. Hinzu kamen Native Anti-Aliasing, Ultra Quality Plus und Ultra Performance; außerdem änderten sich mehrere Skalierungsfaktoren.&lt;br /&gt;
* &#039;&#039;&#039;XeSS 2:&#039;&#039;&#039; ergänzte XeSS-FG und XeLL. Spätere 2.x-Versionen erweiterten Frame Generation auf kompatible Nicht-Intel-GPUs und fügten XeSS-SR-Unterstützung für Vulkan sowie auf Intel Arc für DirectX 11 hinzu.&lt;br /&gt;
* &#039;&#039;&#039;XeSS 3:&#039;&#039;&#039; führte Multi Frame Generation mit zwei oder drei erzeugten Zwischenbildern auf unterstützter Intel-Arc-Hardware ein. Verbesserte Frame-Generation-Modelle sollen außerdem die Darstellung von Benutzeroberflächen stabilisieren.&lt;br /&gt;
* &#039;&#039;&#039;XeSS 3.0.2:&#039;&#039;&#039; aktueller SDK-Stand. Diese Wartungsversion aktualisiert XeLL, behebt unter anderem einen Speicherverlust auf Nicht-Intel-GPUs und verbessert die Zusammenarbeit mit Streamline-Proxys.&lt;br /&gt;
&lt;br /&gt;
== Super Resolution ==&lt;br /&gt;
&lt;br /&gt;
XeSS-SR ist ein temporales Upscaling- und Anti-Aliasing-Verfahren. Es wird als Folge von Compute-Shader-Durchläufen vor späteren Post-Processing-Schritten ausgeführt. Typische Eingaben sind:&lt;br /&gt;
&lt;br /&gt;
* ein niedrig aufgelöstes Farbbild,&lt;br /&gt;
* Bewegungsvektoren von Kamera und Objekten,&lt;br /&gt;
* ein Tiefenpuffer,&lt;br /&gt;
* Kamerajitter,&lt;br /&gt;
* Belichtungsinformationen,&lt;br /&gt;
* optional eine Responsive Mask für schwer rekonstruierbare Bereiche.&lt;br /&gt;
&lt;br /&gt;
Aus diesen Daten rekonstruiert XeSS-SR ein Bild in der Zielauflösung. Fehlerhafte Bewegungsvektoren, falsche Jitter-Skalierung, ungeeignete Masken oder unpassende Farbräume können Ghosting, Flimmern, Schlieren und Detailverlust verursachen. Die Qualität hängt deshalb stark von der Integration im jeweiligen Spiel ab.&lt;br /&gt;
&lt;br /&gt;
Auf Intel Arc und Intel Iris Xe kann eine für Intel-Hardware optimierte Implementierung verwendet werden. Der herstellerübergreifende HLSL-Pfad setzt Shader Model 6.4 voraus; DP4a oder eine gleichwertige Beschleunigung wird empfohlen.&lt;br /&gt;
&lt;br /&gt;
== Qualitätsmodi von XeSS-SR ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Skalierungsfaktor pro Bilddimension&lt;br /&gt;
! Beispiel für 4K-Ausgabe&lt;br /&gt;
|-&lt;br /&gt;
| Native Anti-Aliasing&lt;br /&gt;
| 1,0×&lt;br /&gt;
| 3840 × 2160&lt;br /&gt;
|-&lt;br /&gt;
| Ultra Quality Plus&lt;br /&gt;
| 1,3×&lt;br /&gt;
| ungefähr 2954 × 1662&lt;br /&gt;
|-&lt;br /&gt;
| Ultra Quality&lt;br /&gt;
| 1,5×&lt;br /&gt;
| 2560 × 1440&lt;br /&gt;
|-&lt;br /&gt;
| Quality&lt;br /&gt;
| 1,7×&lt;br /&gt;
| ungefähr 2259 × 1271&lt;br /&gt;
|-&lt;br /&gt;
| Balanced&lt;br /&gt;
| 2,0×&lt;br /&gt;
| 1920 × 1080&lt;br /&gt;
|-&lt;br /&gt;
| Performance&lt;br /&gt;
| 2,3×&lt;br /&gt;
| ungefähr 1670 × 939&lt;br /&gt;
|-&lt;br /&gt;
| Ultra Performance&lt;br /&gt;
| 3,0×&lt;br /&gt;
| 1280 × 720&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein größerer Faktor bedeutet eine niedrigere interne Renderauflösung und normalerweise mehr Leistung. Gleichzeitig stehen dem Rekonstruktionsverfahren weniger Ausgangsinformationen zur Verfügung. Native Anti-Aliasing arbeitet dagegen bei nativer Auflösung und nutzt XeSS nur zur Kantenglättung und zeitlichen Stabilisierung.&lt;br /&gt;
&lt;br /&gt;
== Frame Generation und Multi Frame Generation ==&lt;br /&gt;
&lt;br /&gt;
XeSS-FG interpoliert zusätzliche Bilder zwischen zwei regulär gerenderten Frames. Dafür verwendet es unter anderem Bewegungsinformationen, Tiefendaten und Bilddaten aus der Engine. Eine Proxy-Swapchain übernimmt die zusätzlichen Present-Aufrufe und das Frame Pacing.&lt;br /&gt;
&lt;br /&gt;
XeSS 3 unterstützt auf geeigneter Intel-Arc-Hardware folgende Multiplikatoren:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;2×:&#039;&#039;&#039; ein regulär gerenderter und ein erzeugter Frame,&lt;br /&gt;
* &#039;&#039;&#039;3×:&#039;&#039;&#039; ein regulär gerenderter und zwei erzeugte Frames,&lt;br /&gt;
* &#039;&#039;&#039;4×:&#039;&#039;&#039; ein regulär gerenderter und drei erzeugte Frames.&lt;br /&gt;
&lt;br /&gt;
Auf kompatiblen Nicht-Intel-GPUs ist höchstens ein erzeugtes Zwischenbild vorgesehen. Die Funktion steigert die angezeigte Bildrate, verkürzt aber nicht automatisch die Renderzeit eines echten Frames. Für eine gute Reaktionsfähigkeit ist deshalb XeLL vorgeschrieben. Intel empfiehlt mindestens ungefähr 40 regulär gerenderte FPS als Eingang und etwa 60 FPS für das beste Latenz- und Bewegungsgefühl.&lt;br /&gt;
&lt;br /&gt;
Benutzeroberflächen benötigen besondere Behandlung: Idealerweise liefert die Engine ein Bild ohne HUD und eine separate UI-Textur. Andernfalls können Schrift, Fadenkreuz oder halbtransparente Elemente in erzeugten Frames flimmern oder verzerrt erscheinen.&lt;br /&gt;
&lt;br /&gt;
== Xe Low Latency ==&lt;br /&gt;
&lt;br /&gt;
XeLL verringert Warteschlangen zwischen CPU und GPU. Die Engine markiert wichtige Zeitpunkte eines Frames; XeLL berechnet daraus, wann die CPU mit dem nächsten Frame beginnen sollte. Dadurch soll nicht unnötig früh gerendert und zusätzliche Eingabelatenz aufgebaut werden.&lt;br /&gt;
&lt;br /&gt;
XeLL kann auf unterstützter Intel-Hardware eigenständig eingesetzt werden. Auf Nicht-Intel-GPUs wird es im XeSS-SDK im Zusammenhang mit XeSS-FG verwendet. Andere Latenzlösungen sollen laut Intel nicht gleichzeitig mit XeSS-FG verwendet werden, weil unerwartetes Verhalten möglich ist.&lt;br /&gt;
&lt;br /&gt;
== Hardware- und API-Kompatibilität ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Funktion&lt;br /&gt;
! Intel-Hardware&lt;br /&gt;
! Andere Hersteller&lt;br /&gt;
! Schnittstellen&lt;br /&gt;
|-&lt;br /&gt;
| XeSS-SR&lt;br /&gt;
| Intel Arc A/B, integrierte Arc-Grafik und unterstützte Iris-Xe-GPUs; optimierter Intel-Pfad&lt;br /&gt;
| GPUs mit Shader Model 6.4 und geeignetem DP4a- oder vergleichbarem Pfad&lt;br /&gt;
| DirectX 12; Vulkan; DirectX 11 auf Intel Arc&lt;br /&gt;
|-&lt;br /&gt;
| XeSS-FG&lt;br /&gt;
| diskrete und integrierte Intel-Arc-Grafik; auf geeigneter Hardware bis zu drei erzeugte Frames&lt;br /&gt;
| GPUs mit Shader Model 6.4; höchstens ein erzeugter Frame&lt;br /&gt;
| DirectX 12&lt;br /&gt;
|-&lt;br /&gt;
| XeLL&lt;br /&gt;
| unterstützte Intel Arc und Core-Ultra-Plattformen&lt;br /&gt;
| zusammen mit XeSS-FG auf kompatibler Hardware&lt;br /&gt;
| DirectX 12 im aktuellen FG-Pfad&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die genaue Unterstützung hängt zusätzlich von Treiber, SDK-Version, Spielintegration und Betriebssystem ab. Für XeSS-FG nennt Intel Windows 10 oder 11, DirectX 12, eine aktuelle Laufzeitbibliothek und auf Intel-GPUs einen ausreichend neuen Grafiktreiber.&lt;br /&gt;
&lt;br /&gt;
== Unreal Engine 5 ==&lt;br /&gt;
&lt;br /&gt;
Intel stellt ein offizielles XeSS-Plugin für Unreal Engine bereit. Das Plugin &#039;&#039;&#039;3.1.0&#039;&#039;&#039; basiert auf dem XeSS SDK 3.0.2 und integriert:&lt;br /&gt;
&lt;br /&gt;
* XeSS-SR,&lt;br /&gt;
* XeSS-FG einschließlich Multi Frame Generation,&lt;br /&gt;
* XeLL,&lt;br /&gt;
* Konsolenbefehle sowie Blueprint- und C++-Schnittstellen,&lt;br /&gt;
* vorgefertigte Pakete für mehrere Versionen von UE 4 und UE 5 bis einschließlich &#039;&#039;&#039;UE 5.8&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Für UE 5.8.0 und 5.8.1 nennt Intel eine bekannte Einschränkung: XeLL funktioniert dort ohne eine entsprechende Unreal-Engine-Korrektur nicht. Entwickler sollen auf ein Engine-Update warten oder den von Intel verlinkten Epic-Patch in einen Source Build übernehmen. XeSS-SR und die übrige Plugin-Funktionalität müssen davon getrennt bewertet werden.&lt;br /&gt;
&lt;br /&gt;
Für UE 5.1 und neuer muss bei direkter Steuerung über Konsolenvariablen auch die Screen Percentage zum gewählten Qualitätsmodus passen. Die Blueprint-Schnittstelle übernimmt diese Anpassung automatisch.&lt;br /&gt;
&lt;br /&gt;
== Offenheit und Verteilung ==&lt;br /&gt;
&lt;br /&gt;
Intel stellt das XeSS SDK, Dokumentation, Header, Beispiele und Unreal-Plugin öffentlich auf GitHub bereit. Die optimierten Laufzeitkomponenten werden jedoch teilweise als vorgefertigte Bibliotheken ausgeliefert. Deshalb ist „vollständig Open Source“ als pauschale Beschreibung ungenau. Entwickler müssen außerdem die jeweiligen Lizenz- und Verteilungsbedingungen der SDK-Bestandteile beachten.&lt;br /&gt;
&lt;br /&gt;
== Vorteile ==&lt;br /&gt;
&lt;br /&gt;
* Super Resolution, Frame Generation und Latenzsteuerung in einem gemeinsamen SDK.&lt;br /&gt;
* Herstellerübergreifender XeSS-SR-Pfad für kompatible GPUs.&lt;br /&gt;
* Frame Generation unterstützt inzwischen auch kompatible Nicht-Intel-GPUs.&lt;br /&gt;
* Multi Frame Generation mit bis zu drei Zwischenbildern auf unterstützter Intel-Hardware.&lt;br /&gt;
* Native-AA-Modus sowie viele Qualitätsstufen.&lt;br /&gt;
* DirectX-12- und Vulkan-Unterstützung für XeSS-SR; zusätzlicher DirectX-11-Pfad auf Intel Arc.&lt;br /&gt;
* Offizielles Unreal-Engine-Plugin bis UE 5.8 und ein XeSS Inspector zur Integrationsprüfung.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und Grenzen ==&lt;br /&gt;
&lt;br /&gt;
* Funktionsumfang und maximaler Frame-Multiplikator unterscheiden sich zwischen Intel- und Nicht-Intel-GPUs.&lt;br /&gt;
* XeSS-FG und XeLL besitzen strengere Plattformanforderungen als XeSS-SR.&lt;br /&gt;
* Frame Generation erhöht die angezeigte Bildrate, aber nicht im gleichen Maß die Reaktionsfähigkeit.&lt;br /&gt;
* Fehlerhafte Bewegungsvektoren, Masken oder UI-Trennung können sichtbare Artefakte verursachen.&lt;br /&gt;
* Sehr niedrige Eingangsbildraten verschlechtern Bewegungsqualität und Latenz von Frame Generation.&lt;br /&gt;
* Nicht alle Laufzeitbestandteile liegen als vollständig offener Quellcode vor.&lt;br /&gt;
* XeLL benötigt in UE 5.8.0 und 5.8.1 derzeit eine Engine-Korrektur.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.intel.com/content/www/us/en/developer/topic-technology/gamedev/xess.html Intel: XeSS 3 für Entwickler]&lt;br /&gt;
* [https://github.com/intel/xess Intel: offizielles XeSS SDK]&lt;br /&gt;
* [https://github.com/intel/xess/releases Intel: XeSS-SDK-Versionen und Änderungsprotokoll]&lt;br /&gt;
* [https://github.com/intel/xess/blob/main/doc/xess_sr_developer_guide_english.md Intel: XeSS-SR Developer Guide]&lt;br /&gt;
* [https://github.com/intel/xess/blob/main/doc/xess_fg_developer_guide_english.md Intel: XeSS-FG Developer Guide]&lt;br /&gt;
* [https://github.com/intel/xess/blob/main/doc/xell_developer_guide_english.md Intel: XeLL Developer Guide]&lt;br /&gt;
* [https://github.com/GameTechDev/XeSSUnrealPlugin Intel: XeSS-Plugin für Unreal Engine]&lt;br /&gt;
* [https://github.com/GameTechDev/XeSSUnrealPlugin/releases Intel: Releases des Unreal-Engine-Plugins]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Grafik]]&lt;br /&gt;
[[Kategorie:Intel]]&lt;br /&gt;
[[Kategorie:Künstliche Intelligenz]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=FidelityFX%E2%84%A2_Super_Resolution&amp;diff=152</id>
		<title>FidelityFX™ Super Resolution</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=FidelityFX%E2%84%A2_Super_Resolution&amp;diff=152"/>
		<updated>2026-09-04T23:42:25Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: 4. September 2026. AMD hat FSR 4 inzwischen in „FSR Upscaling“ umbenannt. Aktuell ist FSR Upscaling 4.1.1 im FSR SDK 2.3.0.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;AMD FidelityFX Super Resolution&#039;&#039;&#039; (&#039;&#039;&#039;FSR&#039;&#039;&#039;) ist eine Familie von Verfahren zur Bildrekonstruktion und Leistungssteigerung in Spielen. Je nach Version skaliert FSR ein intern niedriger aufgelöstes Bild hoch, glättet Kanten oder erzeugt zusätzliche Zwischenbilder. Dadurch kann die Bildrate steigen, ohne dass das Spiel vollständig in der Ausgabeauflösung gerendert werden muss.&lt;br /&gt;
&lt;br /&gt;
FSR ist nicht mit &#039;&#039;&#039;Radeon Super Resolution&#039;&#039;&#039; (RSR) zu verwechseln: FSR wird in ein Spiel integriert und kann Bewegungsvektoren, Tiefeninformationen und weitere Engine-Daten verwenden. RSR arbeitet als Treiberfunktion ohne eine solche Spielintegration.&lt;br /&gt;
&lt;br /&gt;
== Entwicklung der FSR-Versionen ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FSR 1:&#039;&#039;&#039; räumliches Upscaling eines einzelnen Frames. Es benötigt keine Bewegungsvektoren, kann feine Details aber schlechter rekonstruieren.&lt;br /&gt;
* &#039;&#039;&#039;FSR 2:&#039;&#039;&#039; temporales Upscaling. Informationen aus mehreren Frames, Bewegungsvektoren, Tiefe und Kamerajitter verbessern Detailrekonstruktion und zeitliche Stabilität.&lt;br /&gt;
* &#039;&#039;&#039;FSR 3:&#039;&#039;&#039; erweitert das temporale Upscaling um optionale &#039;&#039;&#039;Frame Generation&#039;&#039;&#039;. Upscaling und Zwischenbilder sind getrennte Funktionen und können unabhängig voneinander verwendet werden.&lt;br /&gt;
* &#039;&#039;&#039;FSR 3.1:&#039;&#039;&#039; trennt Upscaling und Frame Generation technisch deutlicher, verbessert die Bildqualität und erleichtert den Austausch einzelner Komponenten.&lt;br /&gt;
* &#039;&#039;&#039;FSR Upscaling 4 / 4.1:&#039;&#039;&#039; nutzt ein Machine-Learning-Modell zur temporalen Bildrekonstruktion. Der ursprüngliche Name &#039;&#039;&#039;FSR 4&#039;&#039;&#039; wurde später in &#039;&#039;&#039;FSR Upscaling&#039;&#039;&#039; geändert, um die Funktion von den übrigen Bestandteilen der Redstone-Suite abzugrenzen.&lt;br /&gt;
&lt;br /&gt;
== FSR Upscaling 4 und 4.1 ==&lt;br /&gt;
&lt;br /&gt;
FSR Upscaling 4 analysiert räumliche und zeitliche Informationen mehrerer Frames mit einem Machine-Learning-Modell. Es rekonstruiert daraus ein höher aufgelöstes Ausgabebild. Gegenüber FSR 3.1 zielt das Verfahren insbesondere auf bessere Detailerhaltung, weniger Ghosting und stabilere Darstellung in Bewegung.&lt;br /&gt;
&lt;br /&gt;
FSR Upscaling 4.1 verbessert unter anderem die Schärfe in Bewegung, den Ultra-Performance-Modus und die dynamische Auflösung. Die aktuelle Version 4.1.1 erweitert das ML-Upscaling auf diskrete Radeon-RX-7000-Grafikkarten.&lt;br /&gt;
&lt;br /&gt;
Das ML-Upscaling ist nicht dasselbe wie Frame Generation: Upscaling rekonstruiert einen bereits gerenderten Frame in höherer Auflösung. Frame Generation erzeugt zusätzliche Zwischenbilder zwischen regulär gerenderten Frames.&lt;br /&gt;
&lt;br /&gt;
== FSR „Redstone“ ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FSR „Redstone“&#039;&#039;&#039; bezeichnet eine Suite aus mehreren Funktionen:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FSR Upscaling:&#039;&#039;&#039; ML-gestützte Rekonstruktion eines höher aufgelösten Frames; früher FSR 4 genannt.&lt;br /&gt;
* &#039;&#039;&#039;FSR Frame Generation:&#039;&#039;&#039; erzeugt Zwischenbilder zur Erhöhung der angezeigten Bildrate.&lt;br /&gt;
* &#039;&#039;&#039;FSR Ray Regeneration:&#039;&#039;&#039; rekonstruiert und entrauscht Raytracing-Ergebnisse aus einer kleineren Zahl berechneter Strahlen.&lt;br /&gt;
* &#039;&#039;&#039;FSR Radiance Caching:&#039;&#039;&#039; ML-gestützte Vorhersage der Lichtausbreitung für globale Beleuchtung; derzeit als Vorschau geführt.&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen sind eigenständige Bausteine. Ein Spiel kann deshalb beispielsweise FSR Upscaling verwenden, ohne Frame Generation oder Ray Regeneration einzusetzen.&lt;br /&gt;
&lt;br /&gt;
== Benötigte Engine-Daten ==&lt;br /&gt;
&lt;br /&gt;
Für eine hochwertige temporale Rekonstruktion muss die Spiel-Engine korrekte Eingaben bereitstellen. Dazu gehören insbesondere:&lt;br /&gt;
&lt;br /&gt;
* das niedrig aufgelöste Farbbild,&lt;br /&gt;
* Bewegungsvektoren von Kamera und Objekten,&lt;br /&gt;
* ein Tiefenpuffer,&lt;br /&gt;
* Kamerajitter für die zeitlich versetzten Abtastpositionen,&lt;br /&gt;
* Belichtungsinformationen,&lt;br /&gt;
* bei Bedarf eine Reactive Mask für transparente oder schwer rekonstruierbare Bildbereiche.&lt;br /&gt;
&lt;br /&gt;
Fehlerhafte Bewegungsvektoren, ungeeignete Masken oder falsche Farbräume können Ghosting, Flimmern, Schlieren und Detailverlust verursachen. Die Qualität hängt daher nicht nur vom Algorithmus, sondern stark von der Integration im jeweiligen Spiel ab.&lt;br /&gt;
&lt;br /&gt;
== Qualitätsmodi ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modus&lt;br /&gt;
! Skalierungsfaktor pro Bilddimension&lt;br /&gt;
! Beispiel für 4K-Ausgabe&lt;br /&gt;
|-&lt;br /&gt;
| Native AA&lt;br /&gt;
| 1,0×&lt;br /&gt;
| 3840 × 2160&lt;br /&gt;
|-&lt;br /&gt;
| Quality&lt;br /&gt;
| 1,5×&lt;br /&gt;
| 2560 × 1440&lt;br /&gt;
|-&lt;br /&gt;
| Balanced&lt;br /&gt;
| 1,7×&lt;br /&gt;
| ungefähr 2259 × 1271&lt;br /&gt;
|-&lt;br /&gt;
| Performance&lt;br /&gt;
| 2,0×&lt;br /&gt;
| 1920 × 1080&lt;br /&gt;
|-&lt;br /&gt;
| Ultra Performance&lt;br /&gt;
| 3,0×&lt;br /&gt;
| 1280 × 720&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ein größerer Faktor bedeutet eine niedrigere interne Renderauflösung und normalerweise mehr Leistung, stellt die Rekonstruktion aber vor eine schwierigere Aufgabe. Native AA verwendet keine niedrigere Renderauflösung und setzt das Verfahren nur zur Kantenglättung und Bildstabilisierung ein.&lt;br /&gt;
&lt;br /&gt;
== Hardware und Plattformen ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FSR Upscaling 4.1.1:&#039;&#039;&#039; diskrete Radeon RX 7000 sowie Radeon RX 9000 und neuer.&lt;br /&gt;
* &#039;&#039;&#039;Weitere ML-Funktionen von Redstone:&#039;&#039;&#039; FSR Frame Generation 4, Ray Regeneration und Radiance Caching sind auf Radeon RX 9000 und neuer ausgerichtet.&lt;br /&gt;
* &#039;&#039;&#039;Fallback:&#039;&#039;&#039; Auf nicht unterstützter Hardware können Anwendungen analytische FSR-2-/FSR-3-Verfahren anbieten. Welche Funktion tatsächlich verfügbar ist, hängt von SDK-Version, Spiel und Hardware ab.&lt;br /&gt;
* &#039;&#039;&#039;Grafikschnittstellen:&#039;&#039;&#039; Das FSR SDK 2.3.0 dokumentiert DirectX 12 und Vulkan. Einzelne Effekte und Plugins können strengere Anforderungen besitzen.&lt;br /&gt;
* &#039;&#039;&#039;Betriebssystem:&#039;&#039;&#039; Die PC-Integration richtet sich primär an Windows 10 und Windows 11; bestimmte Redstone-Funktionen setzen Windows 11 voraus.&lt;br /&gt;
&lt;br /&gt;
Die früher oft genannte Aussage „FSR funktioniert auf praktisch jeder GPU“ gilt damit weiterhin für ältere, analytische FSR-Versionen, aber nicht pauschal für die ML-Funktionen von FSR Upscaling 4 und Redstone.&lt;br /&gt;
&lt;br /&gt;
== Unreal Engine 5 ==&lt;br /&gt;
&lt;br /&gt;
AMD stellt ein offizielles FSR-Plugin für Unreal Engine 5 bereit. Das Plugin in Version 4.1.1 unterstützt &#039;&#039;&#039;Unreal Engine 5.3 bis 5.8&#039;&#039;&#039; und basiert auf dem &#039;&#039;&#039;FSR SDK 2.3.0&#039;&#039;&#039;. Es enthält FSR Upscaling 4.1.1 sowie FSR Frame Generation 4.0.1.&lt;br /&gt;
&lt;br /&gt;
Auf passender Hardware wählt das Plugin die ML-Varianten. Für ältere oder nicht unterstützte Hardware stehen analytische Fallbacks bereit. Eine produktive Integration sollte außerdem Bewegungsvektoren, transparente Materialien, World Position Offset, Kameraschnitte, dynamische Auflösung und die Zusammenarbeit mit anderen Upscalern testen.&lt;br /&gt;
&lt;br /&gt;
== Treiber-Upgrade und native Integration ==&lt;br /&gt;
&lt;br /&gt;
FSR Upscaling kann auf zwei Arten verfügbar sein:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Native Integration:&#039;&#039;&#039; Das Spiel bindet die passende FSR-Version direkt ein und bietet sie im Grafikmenü an.&lt;br /&gt;
* &#039;&#039;&#039;Treiber-Upgrade:&#039;&#039;&#039; Bei ausgewählten DirectX-12-Spielen mit geeigneter FSR-3.1-Integration kann AMD Software die verwendete Upscaling-Komponente durch eine ML-Version ersetzen. Für Frame Generation gelten eigene Mindestversionen und Voraussetzungen.&lt;br /&gt;
&lt;br /&gt;
Die Kompatibilität ist nicht für jedes FSR-Spiel automatisch gegeben. AMD führt deshalb eine eigene, laufend aktualisierte Liste unterstützter Titel.&lt;br /&gt;
&lt;br /&gt;
== Offenheit und Lizenzierung ==&lt;br /&gt;
&lt;br /&gt;
„FSR ist Open Source“ lässt sich nicht mehr unterschiedslos auf alle Generationen und Komponenten übertragen. Teile des SDK, Beispiele und ältere Verfahren sind mit offenem Quellcode verfügbar. Die ML-basierten FSR-Komponenten werden dagegen als vorgefertigte und signierte Binärdateien ausgeliefert. Entwickler binden sie über die FSR-API ein. Diese Trennung ermöglicht AMD, Modelle und Implementierungen zu aktualisieren, ohne dass jedes Spiel den vollständigen Algorithmus selbst mitliefern muss.&lt;br /&gt;
&lt;br /&gt;
== Vorteile ==&lt;br /&gt;
&lt;br /&gt;
* Höhere Bildrate durch niedrigere interne Renderauflösung.&lt;br /&gt;
* ML-Upscaling bietet bessere Detailrekonstruktion und zeitliche Stabilität als frühere FSR-Generationen.&lt;br /&gt;
* Native-AA-Modus ohne Verringerung der Renderauflösung.&lt;br /&gt;
* Getrennte Module für Upscaling, Frame Generation und weitere Redstone-Funktionen.&lt;br /&gt;
* Offizielle Integration für Unreal Engine 5.3 bis 5.8.&lt;br /&gt;
* Analytische Fallbacks ermöglichen eine breitere Hardwareabdeckung als die ML-Funktionen allein.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und Grenzen ==&lt;br /&gt;
&lt;br /&gt;
* Die ML-Varianten unterstützen nicht alle GPUs, auf denen ältere FSR-Versionen laufen.&lt;br /&gt;
* Die Bildqualität hängt stark von Bewegungsvektoren, Masken und der Integration des Spiels ab.&lt;br /&gt;
* Niedrige interne Auflösungen können feine Geometrie, Partikel, Transparenzen und UI-Elemente schwieriger rekonstruierbar machen.&lt;br /&gt;
* Frame Generation erhöht die angezeigte Bildrate, verbessert aber nicht im gleichen Maß die Eingabelatenz und kann eigene Artefakte erzeugen.&lt;br /&gt;
* Nicht alle Redstone-Funktionen stehen auf RX-7000-Grafikkarten zur Verfügung.&lt;br /&gt;
* Die ML-Laufzeit wird als signierte Binärkomponente und nicht vollständig als Quellcode verteilt.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.amd.com/en/products/graphics/technologies/fidelityfx/super-resolution.html AMD: FSR-Technologien, Redstone, Hardware und Umbenennung von FSR 4]&lt;br /&gt;
* [https://gpuopen.com/manuals/fsr_sdk/ AMD GPUOpen: FSR SDK 2.3.0]&lt;br /&gt;
* [https://gpuopen.com/manuals/fsr_sdk/techniques/super-resolution-ml/ AMD GPUOpen: FSR Upscaling 4.1.1 – Integration, Qualitätsmodi und Voraussetzungen]&lt;br /&gt;
* [https://gpuopen.com/learn/ue-fsr/ AMD GPUOpen: Unreal Engine FSR Plugin]&lt;br /&gt;
* [https://gpuopen.com/manuals/fsr_sdk/samples/getting-started/ AMD GPUOpen: SDK-Inhalt, Plattformen und Open-Source-Hinweise]&lt;br /&gt;
* [https://www.amd.com/en/products/graphics/technologies/fidelityfx/supported-games.html AMD: laufend aktualisierte Liste unterstützter Spiele]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Grafik]]&lt;br /&gt;
[[Kategorie:AMD]]&lt;br /&gt;
[[Kategorie:Künstliche Intelligenz]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=151</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=151"/>
		<updated>2026-09-04T20:28:33Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 4. September 2026. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Git-Stand&lt;br /&gt;
| Commit &amp;lt;code&amp;gt;4808b5b&amp;lt;/code&amp;gt; auf Branch &amp;lt;code&amp;gt;mgpu-experimental&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| Worker-Compute, Texturtransport und non-blocking UE-Runtime-Ausgabe grundsätzlich nachgewiesen&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; MainTextureCS&lt;br /&gt;
  -&amp;gt; lokale Worker-Textur&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Shared Fence / Queue Wait&lt;br /&gt;
  -&amp;gt; UE-eigene FTextureRHIRef auf der Primary&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; übernimmt und verwendet das Worker-Ergebnis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich läuft inzwischen &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Intel-GPU. Der Shader erzeugt selbstständig eine 64 × 64 Pixel große RGBA8-Textur mit einem aus den Pixelkoordinaten berechneten Farbmuster. &#039;&#039;&#039;Alle 4096 shader-generierten Pixel wurden gegen das erwartete Ergebnis geprüft.&#039;&#039;&#039; Das frühere Zwischenziel, eine Textur direkt auf dem Worker zu erzeugen, ist damit erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein Shared Fence synchronisiert die Queues direkt von GPU zu GPU.&lt;br /&gt;
* Die CPU vermittelt die GPU-Abhängigkeit nicht; Worker- und Primary-Queue verwenden &amp;lt;code&amp;gt;Signal&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;Wait&amp;lt;/code&amp;gt; direkt auf der GPU.&lt;br /&gt;
* Der separate Readback-Verifikationstest darf weiterhin blockieren. Der normale Runtime-Pfad wartet dagegen nicht auf GPU-Leerlauf.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel MainTextureCS&lt;br /&gt;
  -&amp;gt; Worker-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Worker signalisiert Shared Fence 1&lt;br /&gt;
  -&amp;gt; UE-Primary-Queue wartet auf Fence 1&lt;br /&gt;
  -&amp;gt; direkte Kopie in UE-eigene FTextureRHIRef&lt;br /&gt;
  -&amp;gt; Primary signalisiert Completion Fence 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der robuste Normal-Pfad kopiert die Worker-Textur über den Shared Buffer direkt in eine von Unreal erzeugte &amp;lt;code&amp;gt;FTextureRHIRef&amp;lt;/code&amp;gt;. Der ältere Umweg über eine zusätzliche native RTX-Zwischentextur ist im Normal-Runtime-Test entfallen. Das Ergebnis wird pro Worker in einer Output Registry veröffentlicht und kann über &amp;lt;code&amp;gt;GetNormalTextureOutputForWorker()&amp;lt;/code&amp;gt; abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
=== Non-blocking Runtime-Pfad ===&lt;br /&gt;
&lt;br /&gt;
Die produktive Testlogik ist aus dem Konsolenkommando in eine gekapselte NormalPath-API verschoben. &amp;lt;code&amp;gt;QueueNormalTextureTransfer()&amp;lt;/code&amp;gt; reiht Wait, Kopie und Completion-Signal in Unreals D3D12-Kontext ein. Ein &amp;lt;code&amp;gt;SubmitAndBlockUntilGPUIdle&amp;lt;/code&amp;gt; ist im normalen Ablauf nicht mehr erforderlich.&lt;br /&gt;
&lt;br /&gt;
Eine native D3D12-Resource wird dabei bewusst nicht blind als UE-Textur gewrappt. Unreal könnte sonst einen anderen Ressourcenstatus annehmen als den tatsächlich vorhandenen. Ein späterer direkter Fast Path bleibt experimentell und muss auf den sicheren Normal-Pfad zurückfallen können.&lt;br /&gt;
&lt;br /&gt;
=== Lebensdauer und automatisches Cleanup ===&lt;br /&gt;
&lt;br /&gt;
Da die CPU nicht mehr blockierend auf das Ergebnis wartet, müssen Heap, Buffer und Fence bis zum tatsächlichen Abschluss der Primary-Kopie am Leben bleiben. Eine In-Flight Registry hält deshalb jeden Transport über mehrere Frames und prüft ihn automatisch in &amp;lt;code&amp;gt;FD3D12DynamicRHI::RHIEndFrame()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Transport anlegen und registrieren&lt;br /&gt;
  -&amp;gt; Worker Fence 1: Worker-Kopie abgeschlossen&lt;br /&gt;
  -&amp;gt; Primary Fence 2: UE-Zieltextur fertig beschrieben&lt;br /&gt;
  -&amp;gt; RHIEndFrame prüft GetCompletedValue()&lt;br /&gt;
  -&amp;gt; erst ab Fence 2 Ressourcen freigeben&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehrere Transporte können gleichzeitig in flight sein. Im aktuellen Stand besitzt jeder Transport eine eigene Shared Fence sowie eigene Shared Heaps und Buffer; die Werte 1 und 2 sind daher transportlokal. Bei einem späteren Fence-Pool müssen Fence-Werte pro Fence monoton steigen. Ein gepoolter Buffer-Slot darf erst nach Abschluss der Primary-Kopie wiederverwendet werden, nicht bereits nach der Worker-Kopie.&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Breite und Höhe werden am Cross-Adapter-Transport bereits aus &amp;lt;code&amp;gt;WorkerTexture-&amp;amp;gt;GetDesc()&amp;lt;/code&amp;gt; gelesen. Der SafeCopy-Zielpfad enthält jedoch noch Annahmen des verifizierten 64×64-Falls. Als nächster Test ist deshalb bewusst eine &#039;&#039;&#039;nicht quadratische 128×96-RGBA8-Textur&#039;&#039;&#039; vorgesehen. Sie deckt vertauschte Dimensionen und ungewollte Quadratannahmen früh auf.&lt;br /&gt;
&lt;br /&gt;
Erst nach dieser Dimensions-Generalierung folgen weitere Formate, Mips, Arrays oder Slices sowie persistente Ressourcenpools, belastbare Benchmarks und ein erster echter UE-Szenen-Workload.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Grenzen des Proof of Concepts ==&lt;br /&gt;
&lt;br /&gt;
* Der SafeCopy-Zielpfad ist trotz dynamisch gelesener Worker-Dimensionen noch auf den verifizierten 64×64-Testfall zugeschnitten.&lt;br /&gt;
* Der Normal-Transport unterstützt derzeit &amp;lt;code&amp;gt;DXGI_FORMAT_R8G8B8A8_UNORM&amp;lt;/code&amp;gt; mit Sample Count 1; weitere Formate, Mips, Arrays, Slices und MSAA sind offen.&lt;br /&gt;
* Shared Heaps, Buffer, Fences, Worker Allocators und Command Lists werden noch pro Transfer erzeugt. Für Produktion braucht es Pooling sowie Double-, Triple- oder Ring-Buffering.&lt;br /&gt;
* Raw-D3D12-Shared-Ressourcen sind noch nicht vollständig in Unreals Residency-Management eingebunden.&lt;br /&gt;
* Praktisch getestet ist Primary plus ein Worker. Die Architektur ist auf mehrere Worker ausgelegt, N-GPU ist aber noch nicht praktisch validiert.&lt;br /&gt;
* Ein echter UE-Szenen-Workload, Benchmark-Wizard und Scheduler fehlen weiterhin.&lt;br /&gt;
* Device Lost, Timeouts, Speicherdruck und die vollständige Fallback-Matrix müssen vor produktiver Nutzung gehärtet werden.&lt;br /&gt;
* Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation ist noch nicht implementiert.&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# SafeCopy-Dimensionen vollständig generalisieren und 128×96 RGBA8 testen.&lt;br /&gt;
# Danach Formate, Mips, Arrays/Slices und gegebenenfalls MSAA capability-basiert erweitern.&lt;br /&gt;
# Shared Heaps, Buffer, Fences und Command Objects persistent halten; Ring- beziehungsweise Mehrfachpuffer einführen.&lt;br /&gt;
# Latenz, Bandbreite, Größen, Update-Raten und Synchronisationskosten messen.&lt;br /&gt;
# Ersten echten UE-Offload integrieren und das Worker-Ergebnis in Material, Compositing oder Render Graph verwenden.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback-Matrix aus Normal Shared Buffer, System-RAM/Staging und einem späteren Experimental Fast Path ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 4. September 2026, Commit &amp;lt;code&amp;gt;4808b5b&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Direct3D_12,_Shader_Model_6_und_Windows-RHI&amp;diff=150</id>
		<title>Direct3D 12, Shader Model 6 und Windows-RHI</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Direct3D_12,_Shader_Model_6_und_Windows-RHI&amp;diff=150"/>
		<updated>2026-09-04T13:03:14Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|Stand: Unreal Engine 5.8 unter Windows. Bezeichnungen in der Oberfläche können bei lokalisierten Editor-Versionen leicht abweichen.}}  &amp;#039;&amp;#039;&amp;#039;Direct3D 12 (D3D12)&amp;#039;&amp;#039;&amp;#039; ist Microsofts moderne Grafikschnittstelle. Unreal Engine greift nicht direkt aus jedem Spielsystem darauf zu, sondern über das &amp;#039;&amp;#039;&amp;#039;Rendering Hardware Interface (RHI)&amp;#039;&amp;#039;&amp;#039;. Das RHI vereinheitlicht verschiedene Grafik-APIs wie Direct3D 11, Direct3D 12 und Vulkan.  &amp;#039;&amp;#039;&amp;#039;Shader Model 6 (SM6)&amp;#039;…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8 unter Windows. Bezeichnungen in der Oberfläche können bei lokalisierten Editor-Versionen leicht abweichen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Direct3D 12 (D3D12)&#039;&#039;&#039; ist Microsofts moderne Grafikschnittstelle. Unreal Engine greift nicht direkt aus jedem Spielsystem darauf zu, sondern über das &#039;&#039;&#039;Rendering Hardware Interface (RHI)&#039;&#039;&#039;. Das RHI vereinheitlicht verschiedene Grafik-APIs wie Direct3D 11, Direct3D 12 und Vulkan.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Shader Model 6 (SM6)&#039;&#039;&#039; bezeichnet die neuere Shader-Funktionsstufe und den zugehörigen Compilerpfad. D3D12 und SM6 sind verschiedene Einstellungen: D3D12 wählt die Grafik-API, SM6 das Shader-Ziel innerhalb des D3D12-Pfads.&lt;br /&gt;
&lt;br /&gt;
== Warum D3D12 und SM6? ==&lt;br /&gt;
&lt;br /&gt;
Epic empfiehlt D3D12 für die meisten Spiele. In UE 5.8 benötigen mehrere moderne Rendering-Funktionen SM6:&lt;br /&gt;
&lt;br /&gt;
* Lumen und MegaLights unter Windows setzen D3D12 und aktiviertes SM6 voraus; Lumen Hardware Ray Tracing benötigt SM6.&lt;br /&gt;
* Nanite und Virtual Shadow Maps benötigen unter Windows D3D12 mit SM6; für Nanite nennt Epic D3D12 mit Shader-Model-6.6-Atomics sowie aktuelle Treiber.&lt;br /&gt;
* Temporal Super Resolution läuft grundsätzlich auch mit SM5, kann unter D3D12/SM6 aber 16-Bit-Typen nutzen. Der SM5-Pfad ist unter anderem durch acht UAVs pro Shader eingeschränkt. Ein UAV ist eine Shader-Ressource mit ungeordnetem Lese-/Schreibzugriff.&lt;br /&gt;
&lt;br /&gt;
SM6 macht eine GPU nicht automatisch schneller. Es schaltet Fähigkeiten frei; Nutzen und Kosten hängen von Renderer, Shadern, Treiber und Hardware ab.&lt;br /&gt;
&lt;br /&gt;
== Windows-RHI im Editor einstellen ==&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Edit &amp;gt; Project Settings &amp;gt; Platforms &amp;gt; Windows&#039;&#039;&#039; öffnen.&lt;br /&gt;
# Unter &#039;&#039;&#039;Targeted RHIs&#039;&#039;&#039; die benötigten Ziele aktivieren. Für den modernen Windows-Pfad &#039;&#039;&#039;DirectX 12 (SM6)&#039;&#039;&#039; einschalten.&lt;br /&gt;
# &#039;&#039;&#039;Default RHI&#039;&#039;&#039; auf &#039;&#039;&#039;DirectX 12&#039;&#039;&#039; setzen. Epic weist darauf hin, dass das ausgewählte Standard-RHI auch als Targeted RHI aktiviert sein muss.&lt;br /&gt;
# Den Editor neu starten. Eine RHI-Änderung wird erst danach wirksam; geänderte Shaderziele können eine längere Shader-Kompilierung auslösen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DirectX 11 &amp;amp; 12 (SM5)&#039;&#039;&#039; ist ein separater Kompatibilitätspfad. Wer SM5 zusätzlich aktiviert, erzeugt weitere Shader-Varianten und vergrößert damit typischerweise Cook- und Build-Aufwand. Für eine klar definierte D3D12-/SM6-Zielhardware sollte nur der tatsächlich benötigte Satz gepflegt werden; bei breiter Hardwareunterstützung muss der Fallback bewusst getestet werden.&lt;br /&gt;
&lt;br /&gt;
== Kurzzeitig über die Kommandozeile testen ==&lt;br /&gt;
&lt;br /&gt;
Die UE-5.8-Referenz dokumentiert folgende Startparameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-dx12&amp;lt;/code&amp;gt; erzwingt das D3D12-RHI.&lt;br /&gt;
* &amp;lt;code&amp;gt;-dx11&amp;lt;/code&amp;gt; erzwingt das D3D11-RHI.&lt;br /&gt;
* &amp;lt;code&amp;gt;-sm6&amp;lt;/code&amp;gt; beziehungsweise &amp;lt;code&amp;gt;-sm5&amp;lt;/code&amp;gt; erzwingt das Shader Model.&lt;br /&gt;
* &amp;lt;code&amp;gt;-forcedisablesm6&amp;lt;/code&amp;gt; deaktiviert SM6 für einen Vergleichstest.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;powershell&amp;quot;&amp;gt;&lt;br /&gt;
UnrealEditor.exe MeinProjekt.uproject -dx12 -sm6&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erzwungene Parameter eignen sich für Diagnose und A/B-Tests. Sie ersetzen keine korrekt gepflegten Targeted RHIs. Eine nicht unterstützte erzwungene Kombination kann den Start verhindern.&lt;br /&gt;
&lt;br /&gt;
== Praktische Prüfliste ==&lt;br /&gt;
&lt;br /&gt;
# Windows-Version, GPU-Funktionsumfang und aktuellen stabilen Herstellertreiber prüfen.&lt;br /&gt;
# D3D12 als Default RHI und D3D12 SM6 als Ziel aktivieren.&lt;br /&gt;
# Nach dem Neustart das Startprotokoll kontrollieren: verwendetes RHI, gewählter Adapter und Shader-Plattform müssen zur Erwartung passen.&lt;br /&gt;
# Benötigte Funktionen einzeln prüfen: Nanite, Virtual Shadow Maps, Lumen oder Hardware Ray Tracing.&lt;br /&gt;
# Einen Development- oder Test-Build auf der schwächsten unterstützten Ziel-GPU ausführen. Ein erfolgreicher Editorstart allein beweist keine vollständige Kompatibilität.&lt;br /&gt;
# D3D11/SM5 nur behalten, wenn dieser Pfad wirklich unterstützt, gekocht und getestet wird.&lt;br /&gt;
&lt;br /&gt;
== Typische Stolperfallen ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;D3D12 aktiviert, SM6 vergessen:&#039;&#039;&#039; Das RHI stimmt, moderne Funktionen bleiben dennoch nicht verfügbar.&lt;br /&gt;
* &#039;&#039;&#039;Default RHI ohne passendes Target:&#039;&#039;&#039; Epic verlangt, dass das Standard-RHI zugleich als Ziel ausgewählt ist.&lt;br /&gt;
* &#039;&#039;&#039;Altes Windows oder alter Treiber:&#039;&#039;&#039; Besonders Nanite und Virtual Shadow Maps benötigen geeignete Windows-Builds, D3D12 Agility SDK-Unterstützung und aktuelle Treiber.&lt;br /&gt;
* &#039;&#039;&#039;Shader-Neukompilierung unterschätzt:&#039;&#039;&#039; Ein Wechsel des Shaderziels kann viele Shader neu erzeugen.&lt;br /&gt;
* &#039;&#039;&#039;Nur auf einer GPU getestet:&#039;&#039;&#039; D3D12/SM6-Unterstützung und Stabilität sind Eigenschaften der gesamten Kombination aus Betriebssystem, Treiber und Hardware.&lt;br /&gt;
&lt;br /&gt;
== Bezug zu UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Für [[UE5 Heterogeneous Multi-GPU]] ist D3D12 nicht nur ein Renderer-Schalter, sondern die Grundlage des expliziten Unlinked-Multiadapter-Prototyps. Die Windows-RHI-Einstellungen bestimmen zunächst den regulären Unreal-D3D12-Pfad und die Shaderplattform. Sie aktivieren jedoch &#039;&#039;&#039;nicht automatisch&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* eine zweite, heterogene GPU,&lt;br /&gt;
* Cross-Adapter Heaps oder gemeinsam nutzbare Ressourcen,&lt;br /&gt;
* Shared Fences zur Synchronisation,&lt;br /&gt;
* die Auswahl eines Worker-Adapters oder die Verteilung von Compute-Arbeit.&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen müssen Jans Engine-Anpassungen ausdrücklich auf D3D12-Ebene implementieren. Ein sauberer D3D12-/SM6-Basiszustand ist trotzdem wichtig: Er trennt allgemeine RHI- oder Shaderprobleme von Fehlern im Multiadapter-Code.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/windows-settings-in-the-unreal-engine-project-settings?lang=en-US Epic: Windows Settings in Project Settings] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/hardware-and-software-specifications-for-unreal-engine?lang=en-US Epic: Hardware and Software Specifications] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/unreal-engine-command-line-arguments-reference?lang=en-US Epic: Command-Line Arguments Reference] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Shader]]&lt;br /&gt;
[[Kategorie:Windows]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Multi-Process_Rendering_und_Multi-GPU&amp;diff=149</id>
		<title>Multi-Process Rendering und Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Multi-Process_Rendering_und_Multi-GPU&amp;diff=149"/>
		<updated>2026-09-04T13:02:56Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel beschreibt Epics offiziell dokumentierte nDisplay-Verfahren.}}  &amp;#039;&amp;#039;&amp;#039;Multi-Process Rendering&amp;#039;&amp;#039;&amp;#039; und &amp;#039;&amp;#039;&amp;#039;Multi-GPU (mGPU)&amp;#039;&amp;#039;&amp;#039; verteilen bei nDisplay Rendering-Arbeit auf mehrere Grafikkarten. Sie benutzen ähnliche Hardware, arbeiten intern aber unterschiedlich. Beide Verfahren sind auf virtuelle Produktion und große, synchronisierte Anzeigeflächen ausgerichtet.  == Begriffe kurz erklärt ==  * &amp;#039;&amp;#039;&amp;#039;nDisplay&amp;#039;&amp;#039;…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel beschreibt Epics offiziell dokumentierte nDisplay-Verfahren.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Multi-Process Rendering&#039;&#039;&#039; und &#039;&#039;&#039;Multi-GPU (mGPU)&#039;&#039;&#039; verteilen bei nDisplay Rendering-Arbeit auf mehrere Grafikkarten. Sie benutzen ähnliche Hardware, arbeiten intern aber unterschiedlich. Beide Verfahren sind auf virtuelle Produktion und große, synchronisierte Anzeigeflächen ausgerichtet.&lt;br /&gt;
&lt;br /&gt;
== Begriffe kurz erklärt ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;nDisplay&#039;&#039;&#039; verteilt Unreal-Ausgaben auf einen Verbund aus Rechnern, Displays und Render-Viewports.&lt;br /&gt;
* Ein &#039;&#039;&#039;Viewport&#039;&#039;&#039; ist der zu rendernde Bildausschnitt.&lt;br /&gt;
* Beim &#039;&#039;&#039;Inner Frustum&#039;&#039;&#039; rendert eine ICVFX-Kamera den für die reale Kamera sichtbaren Bereich; das &#039;&#039;&#039;Outer Frustum&#039;&#039;&#039; füllt den übrigen LED-Hintergrund.&lt;br /&gt;
* Ein &#039;&#039;&#039;Prozess&#039;&#039;&#039; ist eine laufende Instanz der Unreal-Anwendung.&lt;br /&gt;
&lt;br /&gt;
== Multi-Process Rendering ==&lt;br /&gt;
&lt;br /&gt;
Multi-Process startet pro Render-Rechner zwei getrennte Unreal-Prozesse:&lt;br /&gt;
&lt;br /&gt;
# Der &#039;&#039;&#039;Onscreen-Knoten&#039;&#039;&#039; läuft auf der primären GPU, rendert beispielsweise das Outer Frustum, setzt das Endbild zusammen und gibt es aus.&lt;br /&gt;
# Der &#039;&#039;&#039;Offscreen-Knoten&#039;&#039;&#039; läuft headless, also ohne sichtbares Fenster, auf der zweiten GPU und rendert beispielsweise das Inner Frustum.&lt;br /&gt;
# Zwischen den Prozessen wird nur die fertig gerenderte Textur über CPU und Mainboard übertragen. Der Onscreen-Knoten fügt sie in sein Bild ein.&lt;br /&gt;
&lt;br /&gt;
Epic bezeichnet Multi-Process für die meisten Szenen als schneller als das ältere mGPU-Verfahren. Es ist außerdem Epics empfohlener Weg für mehrere NVIDIA-Ada-Lovelace-GPUs, weil diese kein NVLink unterstützen.&lt;br /&gt;
&lt;br /&gt;
=== Voraussetzungen und Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Mindestens zwei GPUs; SLI muss deaktiviert sein. Premium Mosaic ist ungeeignet, weil es SLI aktiviert.&lt;br /&gt;
* Im nDisplay Config Asset erhält der Onscreen-Knoten typischerweise &#039;&#039;&#039;Graphics Adapter 0&#039;&#039;&#039;. Der zusätzliche Offscreen-Knoten erhält typischerweise &#039;&#039;&#039;Graphics Adapter 1&#039;&#039;&#039; und &#039;&#039;&#039;Headless Rendering&#039;&#039;&#039;. Die tatsächliche Nummerierung muss am Rechner geprüft werden.&lt;br /&gt;
* Für die ICVFX-Kamera werden Media Output und Media Input mit demselben eindeutigen, groß-/kleinschreibungssensitiven Namen verbunden.&lt;br /&gt;
* Der Eingang wird &#039;&#039;&#039;Framelocked&#039;&#039;&#039;, damit die Textur zum richtigen Frame gehört. Epic verwendet im Beispiel außerdem &#039;&#039;&#039;Zero Latency&#039;&#039;&#039;.&lt;br /&gt;
* Beide Knoten werden in Switchboard verbunden und gemeinsam gestartet; pro Rechner genügt ein Switchboard Listener.&lt;br /&gt;
&lt;br /&gt;
== Klassisches nDisplay Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Beim mGPU-Modus läuft grundsätzlich eine Unreal-Instanz auf dem Rechner. Ein Viewport oder Inner Frustum wird über seinen &#039;&#039;&#039;GPUIndex&#039;&#039;&#039; einer GPU zugewiesen. Das Ergebnis wird zur ausgebenden GPU kopiert und dort zusammengesetzt.&lt;br /&gt;
&lt;br /&gt;
Mit NVIDIA NVLink kann die Übertragung direkt von GPU zu GPU erfolgen. Ohne NVLink beschreibt Epic einen Peer-to-Peer-Transfer, der über CPU und PCIe langsamer sein kann. Zur Aktivierung:&lt;br /&gt;
&lt;br /&gt;
# Im nDisplay Config Asset &#039;&#039;&#039;Configuration &amp;gt; Render Frame Settings &amp;gt; Multi GPU Mode&#039;&#039;&#039; einschalten.&lt;br /&gt;
# Am Viewport oder an der ICVFX-Kamera den gewünschten &#039;&#039;&#039;GPUIndex&#039;&#039;&#039; setzen.&lt;br /&gt;
# In Switchboard &#039;&#039;&#039;Number of GPUs&#039;&#039;&#039; auf die vorhandene GPU-Anzahl setzen.&lt;br /&gt;
&lt;br /&gt;
== Direkter Vergleich ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Punkt !! Multi-Process !! nDisplay mGPU&lt;br /&gt;
|-&lt;br /&gt;
| Unreal-Instanzen pro Rechner || Zwei getrennte Prozesse || Eine Instanz&lt;br /&gt;
|-&lt;br /&gt;
| Typische Aufteilung || Onscreen- und Offscreen-Knoten || Viewport/Inner Frustum per GPUIndex&lt;br /&gt;
|-&lt;br /&gt;
| Austausch || Fertige Textur über CPU/Mainboard || GPU-Ressourcen bzw. Bildtransfer; NVLink ist vorteilhaft&lt;br /&gt;
|-&lt;br /&gt;
| Epics Einordnung || In den meisten Fällen empfohlen und schneller, abhängig von der Szene || Älteres Verfahren; sinnvoll, wenn die konkrete Anlage davon profitiert&lt;br /&gt;
|-&lt;br /&gt;
| Wichtig || SLI deaktivieren || Multi GPU Mode und GPU-Anzahl konfigurieren&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Abgrenzung zu UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Jans Projekt [[UE5 Heterogeneous Multi-GPU]] ist &#039;&#039;&#039;keines dieser nDisplay-Verfahren&#039;&#039;&#039;. Es verfolgt explizites Direct3D-12-Unlinked-Multiadapter-Compute mit unterschiedlichen GPUs, derzeit Intel UHD als Worker neben einer NVIDIA RTX 5060. Arbeit, Cross-Adapter-Ressourcen und Synchronisation werden im eigenen Code gesteuert.&lt;br /&gt;
&lt;br /&gt;
Die entscheidenden Unterschiede:&lt;br /&gt;
&lt;br /&gt;
* Epic verteilt bei nDisplay fertige Renderaufgaben wie Viewports oder Frustums. Jans Ansatz will einzelne Compute-Arbeiten innerhalb einer angepassten Engine-/RHI-Pipeline auslagern.&lt;br /&gt;
* Multi-Process benötigt zwei Unreal-Prozesse; Jans Ansatz arbeitet nicht nach dem Onscreen-/Offscreen-Muster.&lt;br /&gt;
* nDisplay mGPU ist nicht automatisch herstellerheterogen und nicht gleichbedeutend mit explizitem D3D12-Unlinked-Multiadapter.&lt;br /&gt;
* Aus Epics Empfehlung für Multi-Process folgt daher keine Aussage über die Leistung oder Machbarkeit von Jans Forschungsansatz. Beide lösen verschiedene Probleme.&lt;br /&gt;
&lt;br /&gt;
== Praxisentscheidung ==&lt;br /&gt;
&lt;br /&gt;
* Für LED-Wände und ICVFX mit klar trennbarem Inner/Outer Frustum zuerst Multi-Process testen.&lt;br /&gt;
* Wenn eine bestehende nDisplay-Anlage mit Viewport-Zuweisung und passender Transferhardware arbeitet, mGPU gezielt benchmarken.&lt;br /&gt;
* Für allgemeine Spiele- oder Compute-Lastverteilung auf unterschiedlichen GPUs ist keiner der beiden nDisplay-Wege ein fertiger Ersatz für Jans eigene Multiadapter-Implementierung.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/multi-process-rendering-with-unreal-engine?lang=en-US Epic: Multi-Process Rendering] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/getting-started-with-multi-process-rendering-in-unreal-engine Epic: Getting Started with Multi-Process Rendering] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/ndisplay-overview-for-unreal-engine?lang=en-US Epic: nDisplay Overview – Multi-GPU Support] (UE 5.8, abgerufen am 4. September 2026)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:nDisplay]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=148</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=148"/>
		<updated>2026-09-04T00:47:46Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 4. September 2026. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| etwa 75–80 % (grobe Projekteinschätzung)&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; eigener UE-Compute-Shader / später eigenständiger Workload&lt;br /&gt;
  -&amp;gt; lokale Worker-Ressource&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Shared Fence&lt;br /&gt;
  -&amp;gt; lokale RTX-Ressource&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; übernimmt und verwendet das Worker-Ergebnis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein Shared Fence synchronisiert die Queues direkt von GPU zu GPU.&lt;br /&gt;
* Die CPU wartet im Test nur noch für die abschließende Ergebnisprüfung, nicht als Vermittler der GPU-Abhängigkeit.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Shared Fence / RTX Queue Wait&lt;br /&gt;
  -&amp;gt; lokale RTX-Textur&lt;br /&gt;
  -&amp;gt; Readback und Prüfung&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine 64 × 64 Pixel große RGBA8-Testtextur wurde auf diesem Weg vollständig übertragen und auf der RTX als echte lokale Textur rekonstruiert. &#039;&#039;&#039;4096 von 4096 Pixeln waren korrekt.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der zweite Global Shader &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; ist registriert und wird bereits als RHI-Shader erzeugt. Als Nächstes soll er die Testtextur direkt auf der Intel-GPU erzeugen. Danach folgt der bereits verifizierte Transportweg zur RTX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MainTextureCS -&amp;gt; Intel-Textur -&amp;gt; Shared Buffer -&amp;gt; Shared Fence -&amp;gt; RTX-Textur&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erst danach folgen persistente Ressourcenpools, Double- oder Triple-Buffering, belastbare Benchmarks und ein erster echter UE-Szenen-Workload.&lt;br /&gt;
&lt;br /&gt;
== Historische Vorläufer ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee heterogener Multi-GPU-Nutzung ist nicht neu. Bereits mit der Einführung von Direct3D 12 entstanden mehrere Versuche, integrierte und dedizierte GPUs gemeinsam zu verwenden. Eine allgemein einsetzbare Lösung für moderne UE5-Spiele hat sich daraus jedoch nicht entwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Microsoft und Epic: UE4 Elemental Demo (2015) ===&lt;br /&gt;
&lt;br /&gt;
Microsoft zeigte eine angepasste Unreal-Engine-4-Version der Elemental-Demo, bei der eine NVIDIA-GPU und eine Intel-iGPU gemeinsam arbeiteten. Das erklärte Ziel war, ansonsten ungenutzte Grafikleistung in Hybrid-Systemen zu verwenden. Dieser Versuch ist der Grundidee des Projekts besonders ähnlich, blieb aber eine technische Demonstration.&lt;br /&gt;
&lt;br /&gt;
=== Intel: D3D12 Multi-Adapter Sample (2015) ===&lt;br /&gt;
&lt;br /&gt;
Intels Beispiel kombinierte eine GeForce 840M mit Intel HD Graphics 5500. Beide GPUs berechneten getrennte Teile einer einfach parallelisierbaren Raytracing-Szene. Cross-Adapter-Ressourcen und Shared Fences führten die Ergebnisse anschließend zusammen. Intel berichtete in diesem Test von nahezu halbierter Framezeit, warnte jedoch ausdrücklich davor, das Ergebnis unmittelbar auf reale Spiele zu übertragen.&lt;br /&gt;
&lt;br /&gt;
=== Ashes of the Singularity ===&lt;br /&gt;
&lt;br /&gt;
Die Nitrous Engine von &#039;&#039;Ashes of the Singularity&#039;&#039; setzte Direct3D-12-Explicit-Multiadapter in einem veröffentlichten Spiel ein. Dabei konnten auch unterschiedliche GPU-Modelle und Hersteller zusammenarbeiten. Das war ein wichtiger Praxisnachweis, blieb in der Spielebranche aber eine seltene Ausnahme.&lt;br /&gt;
&lt;br /&gt;
=== Weitere verwandte Ansätze ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Rise of the Tomb Raider&#039;&#039; erhielt explizite Direct3D-12-Multi-GPU-Unterstützung, vor allem für klassische Kombinationen ähnlicher GPUs.&lt;br /&gt;
* NVIDIA VR SLI wies bei Virtual Reality jeder GPU ein Auge zu. Das verteilt unabhängige Ansichten, bleibt jedoch NVIDIA-spezifisch.&lt;br /&gt;
* Unreal nDisplay kann Viewports oder Frustums auf weitere GPUs beziehungsweise Prozesse auslagern und das fertige Bild zur Ausgabe-GPU zurückführen. Der Einsatzbereich ist hauptsächlich Virtual Production.&lt;br /&gt;
* Forschung und High-Performance Computing verwenden seit Jahren Scheduler für heterogene GPUs, allerdings überwiegend für Compute- und Datenverarbeitungsaufgaben statt für einen allgemeinen UE5-Echtzeitrenderer.&lt;br /&gt;
&lt;br /&gt;
=== Abgrenzung dieses Projekts ===&lt;br /&gt;
&lt;br /&gt;
Das Projekt erfindet Direct3D-12-Explicit-Multiadapter nicht neu. Sein eigener Ansatz liegt in der Kombination aus tiefer UE5.8-RHI-Integration, UE-kompilierten Shadern auf unabhängigen Worker-Devices, frei wählbaren Spiel- und Compute-Workloads, Capability- und Performance-Scheduler, mehreren Fallback-Pfaden sowie dem langfristigen Ziel beliebiger Hersteller und mehrerer Worker.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Worker-GPU ausführen und Ergebnis übertragen.&lt;br /&gt;
# Shared Heaps, Buffer und Fences persistent halten; Ring- beziehungsweise Mehrfachpuffer einführen.&lt;br /&gt;
# Latenz und Bandbreite für verschiedene Größen und Update-Raten messen.&lt;br /&gt;
# Ersten echten UE-Offload integrieren und als Primary-RHI-Textur bereitstellen.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback über System-RAM ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 4. September 2026&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/directx-12-multiadapter-lighting-up-dormant-silicon-and-making-it-work-for-you/ Microsoft: UE4 Elemental Demo mit heterogenem Multiadapter]&lt;br /&gt;
* [https://www.intel.com/content/dam/develop/external/us/en/documents/multi-adapter-support-in-directx-12-594015.pdf Intel: Multi-Adapter Support in DirectX 12]&lt;br /&gt;
* [https://devblogs.microsoft.com/directx/ashes-of-the-singularity-makes-gaming-history-with-directx-12/ Microsoft: Ashes of the Singularity und heterogene Adapter]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=147</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=147"/>
		<updated>2026-09-04T00:38:48Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Projektstand: 4. September 2026. Die beschriebenen Ergebnisse sind ein experimenteller Proof of Concept für Unreal Engine 5.8 unter Windows und Direct3D 12.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur gemeinsamen Nutzung unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. Eine leistungsfähige GPU übernimmt das normale Rendering. Weitere NVIDIA-, AMD- oder Intel-GPUs sollen als unabhängige Worker klar abgegrenzte Aufgaben bearbeiten.&lt;br /&gt;
&lt;br /&gt;
Das Ziel ist ausdrücklich &#039;&#039;&#039;kein klassisches SLI oder CrossFire&#039;&#039;&#039;. Die Anwendung verteilt Arbeit selbst und tauscht nur benötigte Ergebnisse zwischen den GPUs aus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Engine / Plattform&lt;br /&gt;
| Unreal Engine 5.8 Source Build / Windows / Direct3D 12&lt;br /&gt;
|-&lt;br /&gt;
! Testsystem&lt;br /&gt;
| Lenovo LOQ 17IRX10&lt;br /&gt;
|-&lt;br /&gt;
! Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker&lt;br /&gt;
| Intel UHD Graphics&lt;br /&gt;
|-&lt;br /&gt;
! Windows/D3D12-Proof-of-Concept&lt;br /&gt;
| etwa 75–80 % (grobe Projekteinschätzung)&lt;br /&gt;
|-&lt;br /&gt;
! Gesamtvision&lt;br /&gt;
| etwa 30–35 % (Scheduler, echte Workloads, N-GPU und Vulkan noch offen)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel Worker GPU&lt;br /&gt;
  -&amp;gt; eigener UE-Compute-Shader / später eigenständiger Workload&lt;br /&gt;
  -&amp;gt; lokale Worker-Ressource&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Shared Fence&lt;br /&gt;
  -&amp;gt; lokale RTX-Ressource&lt;br /&gt;
&lt;br /&gt;
RTX Primary GPU&lt;br /&gt;
  -&amp;gt; normales UE5-Rendering&lt;br /&gt;
  -&amp;gt; übernimmt und verwendet das Worker-Ergebnis&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jeder Worker besitzt ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt;, eigene Queues, Command Lists und Ressourcen. Ein späterer Scheduler soll Rechenleistung, Fähigkeiten, Transferkosten und gewünschte Aktualisierungsrate bewerten. Vorgesehene Aufgaben sind beispielsweise SceneCapture2D, Spiegel, CCTV, Minimap, Compute oder Niagara.&lt;br /&gt;
&lt;br /&gt;
== Verifizierter Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
=== Worker-Compute ===&lt;br /&gt;
&lt;br /&gt;
Ein echter, von Unreal kompilierter Global Compute Shader läuft auf der Intel UHD, während Unreal regulär über die RTX rendert. Der Test verdoppelt 64 Ganzzahlen auf dem Worker; &#039;&#039;&#039;64 von 64 Ergebnissen wurden korrekt verifiziert&#039;&#039;&#039;. Damit ist echte GPU-Arbeit auf einem zweiten, herstellerfremden Device nachgewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Cross-Adapter-Speicher und Synchronisation ===&lt;br /&gt;
&lt;br /&gt;
* RTX und Intel öffnen denselben D3D12 Cross-Adapter Heap.&lt;br /&gt;
* Ein gemeinsamer Buffer wurde mit 64 Testwerten erfolgreich geprüft.&lt;br /&gt;
* Ein Shared Fence synchronisiert die Queues direkt von GPU zu GPU.&lt;br /&gt;
* Die CPU wartet im Test nur noch für die abschließende Ergebnisprüfung, nicht als Vermittler der GPU-Abhängigkeit.&lt;br /&gt;
&lt;br /&gt;
=== Texturtransport ===&lt;br /&gt;
&lt;br /&gt;
Direkte Cross-Adapter-Texturen sind auf dem Testsystem nicht beidseitig verfügbar: Die Intel UHD meldet Unterstützung für Row-Major Cross-Adapter Textures, die RTX 5060 Laptop GPU nicht. Deshalb verwendet das Projekt einen allgemeineren Buffer-Fallback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Intel-Textur&lt;br /&gt;
  -&amp;gt; CopyTextureRegion&lt;br /&gt;
  -&amp;gt; Shared Cross-Adapter Buffer&lt;br /&gt;
  -&amp;gt; Shared Fence / RTX Queue Wait&lt;br /&gt;
  -&amp;gt; lokale RTX-Textur&lt;br /&gt;
  -&amp;gt; Readback und Prüfung&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine 64 × 64 Pixel große RGBA8-Testtextur wurde auf diesem Weg vollständig übertragen und auf der RTX als echte lokale Textur rekonstruiert. &#039;&#039;&#039;4096 von 4096 Pixeln waren korrekt.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Aktueller nächster Schritt ==&lt;br /&gt;
&lt;br /&gt;
Der zweite Global Shader &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; ist registriert und wird bereits als RHI-Shader erzeugt. Als Nächstes soll er die Testtextur direkt auf der Intel-GPU erzeugen. Danach folgt der bereits verifizierte Transportweg zur RTX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MainTextureCS -&amp;gt; Intel-Textur -&amp;gt; Shared Buffer -&amp;gt; Shared Fence -&amp;gt; RTX-Textur&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erst danach folgen persistente Ressourcenpools, Double- oder Triple-Buffering, belastbare Benchmarks und ein erster echter UE-Szenen-Workload.&lt;br /&gt;
&lt;br /&gt;
== Vergleich mit anderen Multi-GPU-Verfahren ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Verfahren&lt;br /&gt;
! Arbeitsweise&lt;br /&gt;
! Verhältnis zu diesem Projekt&lt;br /&gt;
|-&lt;br /&gt;
| SLI / CrossFire&lt;br /&gt;
| Treiber- beziehungsweise Verbundlösung für meist ähnliche GPUs; häufig wird die Bildarbeit verteilt.&lt;br /&gt;
| Dieses Projekt benötigt keinen herstellerspezifischen GPU-Verbund und weist Aufgaben ausdrücklich selbst zu.&lt;br /&gt;
|-&lt;br /&gt;
| AFR (Alternate Frame Rendering)&lt;br /&gt;
| GPU 1 rendert einen Frame, GPU 2 den nächsten.&lt;br /&gt;
| Das Projekt verteilt unabhängige Aufgaben statt aufeinanderfolgender Frames. Dadurch werden Frame-Abhängigkeiten und typisches AFR-Pacing vermieden.&lt;br /&gt;
|-&lt;br /&gt;
| SFR (Split Frame Rendering)&lt;br /&gt;
| Mehrere GPUs bearbeiten Bereiche desselben Frames.&lt;br /&gt;
| Erfordert enge Lastverteilung und viel Datenaustausch. Das Projekt bevorzugt vollständig abgrenzbare Workloads und überträgt deren Ergebnis.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Linked Multiadapter&lt;br /&gt;
| Mehrere vom Treiber verbundene GPUs erscheinen als Knoten eines logischen Adapters.&lt;br /&gt;
| Eignet sich eher für eng kompatible GPUs. Das Projekt verwendet unabhängige Devices (Unlinked/Explicit Multiadapter) und unterstützt dadurch heterogene Herstellerkombinationen.&lt;br /&gt;
|-&lt;br /&gt;
| Direct3D 12 Unlinked / Explicit Multiadapter&lt;br /&gt;
| Die Anwendung verwaltet getrennte Adapter, Ressourcen und Synchronisation selbst.&lt;br /&gt;
| Das ist die technische Familie des Projekts. Hinzu kommen die eigene UE5-RHI-Integration, Workload-Ziele, Fallbacks und der geplante Scheduler.&lt;br /&gt;
|-&lt;br /&gt;
| UE nDisplay mGPU / Multi-Process&lt;br /&gt;
| Separate GPUs rendern bestimmte Viewports oder Frustums, vor allem für Virtual Production; Ergebnisse werden zur Ausgabe-GPU kopiert.&lt;br /&gt;
| Ähnliche Idee der aufgabenweisen Trennung, aber für einen anderen Einsatzbereich. Dieses Projekt zielt auf allgemeine Spiel- und Compute-Workloads innerhalb der Engine.&lt;br /&gt;
|-&lt;br /&gt;
| Vulkan Device Groups&lt;br /&gt;
| Ähnliche physische GPUs können ein gemeinsames logisches Device bilden.&lt;br /&gt;
| Für beliebige heterogene GPUs meist ungeeignet, da Geräte einer Gruppe nahezu gleiche Eigenschaften besitzen müssen. Eine spätere Vulkan-Portierung benötigt daher wahrscheinlich getrennte Devices und External Memory/Semaphores.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SLI und CrossFire bezeichnen den Verbund; AFR und SFR beschreiben mögliche Verteilungsmethoden innerhalb solcher Systeme. Sie sind deshalb nicht vollständig getrennte Kategorien.&lt;br /&gt;
&lt;br /&gt;
== Vorteile der geplanten Variante ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Herstellerunabhängig:&#039;&#039;&#039; NVIDIA, AMD und Intel können grundsätzlich kombiniert werden.&lt;br /&gt;
* &#039;&#039;&#039;Vorhandene Hardware nutzen:&#039;&#039;&#039; Auch eine sonst wenig genutzte integrierte GPU kann geeignete Nebenaufgaben übernehmen.&lt;br /&gt;
* &#039;&#039;&#039;Aufgaben statt Frames verteilen:&#039;&#039;&#039; Spiegel, Minimap oder Compute können mit eigener Auflösung und Aktualisierungsrate laufen.&lt;br /&gt;
* &#039;&#039;&#039;Keine identischen GPUs erforderlich:&#039;&#039;&#039; Unterschiedliche Fähigkeiten können gezielt genutzt werden.&lt;br /&gt;
* &#039;&#039;&#039;Kontrollierter Datenaustausch:&#039;&#039;&#039; Nur das benötigte Ergebnis muss zurück zur Primary-GPU.&lt;br /&gt;
* &#039;&#039;&#039;Robuste Fallback-Idee:&#039;&#039;&#039; Wenn direkte Texturen nicht gemeinsam nutzbar sind, bleibt der Shared-Buffer-Pfad.&lt;br /&gt;
* &#039;&#039;&#039;Erweiterbar:&#039;&#039;&#039; Scheduler, manuelles Mapping und mehrere Worker sind als spätere Stufen vorgesehen.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und technische Risiken ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Hoher Entwicklungsaufwand:&#039;&#039;&#039; Geräte, Ressourcen, Zustände, Fences, Fehlerfälle und UE-Lebenszyklen müssen selbst verwaltet werden.&lt;br /&gt;
* &#039;&#039;&#039;Transfer kann den Gewinn aufzehren:&#039;&#039;&#039; Cross-Adapter Heaps liegen laut D3D12 nicht automatisch im schnellen lokalen VRAM. Bandbreite und Latenz müssen für jeden Workload gemessen werden.&lt;br /&gt;
* &#039;&#039;&#039;VRAM wird nicht einfach addiert:&#039;&#039;&#039; Benötigte Ressourcen können auf mehreren GPUs vorliegen und zusätzlichen Speicher verbrauchen.&lt;br /&gt;
* &#039;&#039;&#039;Langsame Worker können bremsen:&#039;&#039;&#039; Eine Aufgabe lohnt sich nur, wenn Rechengewinn größer als Übergabe-, Warte- und Kopierkosten ist.&lt;br /&gt;
* &#039;&#039;&#039;Nicht jeder Workload ist unabhängig:&#039;&#039;&#039; Hauptansicht, Lumen, Nanite und stark gekoppelte Renderpässe besitzen viele Abhängigkeiten und sind schwieriger auszulagern.&lt;br /&gt;
* &#039;&#039;&#039;Hardwareunterschiede:&#039;&#039;&#039; Formate, Shader-Funktionen, Queue-Fähigkeiten und Cross-Adapter-Support müssen pro GPU geprüft werden.&lt;br /&gt;
* &#039;&#039;&#039;Wartungsrisiko:&#039;&#039;&#039; Eingriffe in private D3D12RHI-Dateien können bei Engine-Updates angepasst werden müssen.&lt;br /&gt;
* &#039;&#039;&#039;Produktionsreife fehlt noch:&#039;&#039;&#039; Ressourcenpools, Timeouts, Device-Lost-Wiederherstellung, Scheduler und echte Szenentests sind offen.&lt;br /&gt;
&lt;br /&gt;
== Wann die Variante sinnvoll ist ==&lt;br /&gt;
&lt;br /&gt;
Am aussichtsreichsten sind Aufgaben mit viel eigener Rechenarbeit, einem relativ kleinen Endergebnis und wenigen Abhängigkeiten zur Hauptszene. Gute frühe Kandidaten sind unabhängige Compute-Aufgaben sowie Scene Captures, die nicht in jedem Frame aktualisiert werden müssen. Weniger geeignet sind winzige Aufgaben mit großem Transfer oder Renderpässe, die ständig auf Ressourcen der Primary-GPU zugreifen.&lt;br /&gt;
&lt;br /&gt;
Die entscheidende Regel für den späteren Scheduler lautet daher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Worker-Gewinn &amp;gt; Vorbereitung + Datentransfer + Synchronisation + Rückintegration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Roadmap ==&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;MainTextureCS&amp;lt;/code&amp;gt; auf der Worker-GPU ausführen und Ergebnis übertragen.&lt;br /&gt;
# Shared Heaps, Buffer und Fences persistent halten; Ring- beziehungsweise Mehrfachpuffer einführen.&lt;br /&gt;
# Latenz und Bandbreite für verschiedene Größen und Update-Raten messen.&lt;br /&gt;
# Ersten echten UE-Offload integrieren und als Primary-RHI-Textur bereitstellen.&lt;br /&gt;
# Capability-Matrix, Benchmark-Wizard, Scheduler und manuelle Overrides entwickeln.&lt;br /&gt;
# Mehrere Worker-GPUs unterstützen.&lt;br /&gt;
# Fallback über System-RAM ergänzen.&lt;br /&gt;
# Linux/Vulkan mit getrennten Devices, External Memory und externer Synchronisation untersuchen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* Interner Entwicklungsstand und verifizierte Testprotokolle vom 4. September 2026&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/multi-engine Microsoft: Direct3D 12 Multi-adapter systems]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/windows/win32/direct3d12/shared-heaps Microsoft: Shared heaps]&lt;br /&gt;
* [https://learn.microsoft.com/en-us/samples/microsoft/directx-graphics-samples/d3d12-heterogeneous-multiadapter-sample-win32/ Microsoft: D3D12 Heterogeneous Multiadapter Sample]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/nvidia-sli-alternative-frame-rendering-in-unreal-engine Epic: NVIDIA SLI Alternate Frame Rendering]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/multi-process-rendering-with-unreal-engine Epic: Multi-Process Rendering]&lt;br /&gt;
* [https://registry.khronos.org/vulkan/specs/latest/pdf/vkspec.pdf Khronos: Vulkan Specification – Device Groups]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Deep_Learning_Super_Sampling&amp;diff=146</id>
		<title>Deep Learning Super Sampling</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Deep_Learning_Super_Sampling&amp;diff=146"/>
		<updated>2026-09-04T00:38:39Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: 4. September 2026. DLSS 5 ist neu; unabhängige Praxistests und unterstützte Spiele sind noch begrenzt.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deep Learning Super Sampling&#039;&#039;&#039; (&#039;&#039;&#039;DLSS&#039;&#039;&#039;) ist eine Sammlung KI-gestützter Grafikverfahren von NVIDIA. Je nach Funktion rekonstruiert DLSS ein höher aufgelöstes Bild, verbessert Raytracing-Ergebnisse, erzeugt zusätzliche Frames oder ergänzt mit DLSS 5 das endgültige Erscheinungsbild eines Frames.&lt;br /&gt;
&lt;br /&gt;
== Die wichtigsten Bestandteile ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Super Resolution:&#039;&#039;&#039; rekonstruiert aus einer niedrigeren Renderauflösung ein höher aufgelöstes Bild.&lt;br /&gt;
* &#039;&#039;&#039;DLAA:&#039;&#039;&#039; nutzt das Modell zur Kantenglättung bei nativer Auflösung.&lt;br /&gt;
* &#039;&#039;&#039;Ray Reconstruction:&#039;&#039;&#039; ersetzt mehrere klassische Denoiser für Ray- und Pathtracing.&lt;br /&gt;
* &#039;&#039;&#039;Frame Generation:&#039;&#039;&#039; erzeugt Zwischenbilder; NVIDIA Reflex soll die zusätzliche Latenz begrenzen.&lt;br /&gt;
* &#039;&#039;&#039;Multi Frame Generation:&#039;&#039;&#039; erzeugt mehrere Zwischenbilder pro regulär gerendertem Frame.&lt;br /&gt;
* &#039;&#039;&#039;3D-Guided Neural Rendering:&#039;&#039;&#039; ergänzt mit DLSS 5 Beleuchtung und Materialwirkung im finalen Bild.&lt;br /&gt;
&lt;br /&gt;
== DLSS 4 und 4.5 ==&lt;br /&gt;
&lt;br /&gt;
DLSS 4 führte Transformer-Modelle für Super Resolution, DLAA und Ray Reconstruction ein. Transformer können Bildbereiche und zeitliche Zusammenhänge umfangreicher auswerten als die zuvor verwendeten Netze. Auf RTX-50-Grafikkarten kam außerdem Multi Frame Generation hinzu: DLSS 4 kann bis zu drei zusätzliche Frames zwischen zwei regulär gerenderten Frames erzeugen.&lt;br /&gt;
&lt;br /&gt;
DLSS 4.5 erweitert dies um ein leistungsfähigeres Transformer-Modell und &#039;&#039;&#039;Dynamic Multi Frame Generation&#039;&#039;&#039;. Dabei kann der Multiplikator automatisch angepasst werden. Maximal werden fünf zusätzliche Frames pro regulär gerendertem Frame erzeugt (6X-Anzeigeausgabe).&lt;br /&gt;
&lt;br /&gt;
== Was DLSS 5 verändert ==&lt;br /&gt;
&lt;br /&gt;
DLSS 5 ist kein bloßer Nachfolger des Upscalers. Die neue Funktion heißt &#039;&#039;&#039;3D-Guided Neural Rendering&#039;&#039;&#039; und arbeitet als zusätzliche Stufe am Ende der Renderpipeline. Ein einstufiges Diffusionsmodell erhält unter anderem das gerenderte Ausgangsbild, Bewegungsvektoren, zeitlichen Zustand und Engine-Informationen. Daraus ergänzt es schwer in Echtzeit darstellbare Erscheinungsdetails, beispielsweise:&lt;br /&gt;
&lt;br /&gt;
* Lichtstreuung in Haut,&lt;br /&gt;
* Lichtdurchlässigkeit bei Haaren und Blättern,&lt;br /&gt;
* Materialreaktionen und Reflexionen,&lt;br /&gt;
* Kontakt- und Umgebungsschatten,&lt;br /&gt;
* Teile der globalen Beleuchtungswirkung.&lt;br /&gt;
&lt;br /&gt;
Geometrie, grundlegende Szene und künstlerische Gestaltung stammen weiterhin aus dem Spiel. Das Modell soll deterministisch arbeiten und von Frame zu Frame stabil bleiben. Entwickler können Modellvarianten wählen, Struktur- und Tonwirkung einstellen und Objekte über semantische oder Engine-Masken von der Bearbeitung ausnehmen.&lt;br /&gt;
&lt;br /&gt;
== Vergleich: DLSS 4/4.5 und DLSS 5 ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Punkt&lt;br /&gt;
! DLSS 4 / 4.5&lt;br /&gt;
! DLSS 5&lt;br /&gt;
|-&lt;br /&gt;
| Hauptziel&lt;br /&gt;
| Mehr Bildqualität und Bildrate aus vorhandenen Renderdaten&lt;br /&gt;
| Realistischere Beleuchtung und Materialwirkung erzeugen&lt;br /&gt;
|-&lt;br /&gt;
| Arbeitsweise&lt;br /&gt;
| Rekonstruktion, Denoising und Frame-Interpolation&lt;br /&gt;
| Generative, durch 3D- und Engine-Daten geführte Bildveredelung&lt;br /&gt;
|-&lt;br /&gt;
| Erzeugt zusätzliche Frames?&lt;br /&gt;
| Ja, über Frame beziehungsweise Multi Frame Generation&lt;br /&gt;
| Nicht selbst; kann mit Multi Frame Generation kombiniert werden&lt;br /&gt;
|-&lt;br /&gt;
| Verändert die Erscheinung?&lt;br /&gt;
| Überwiegend Rekonstruktion bereits vorhandener Informationen&lt;br /&gt;
| Ergänzt sichtbar neue Erscheinungsdetails im finalen Frame&lt;br /&gt;
|-&lt;br /&gt;
| Hardware&lt;br /&gt;
| Funktionsabhängig; viele Teile laufen auf älteren RTX-Generationen, Multi Frame Generation auf RTX 50&lt;br /&gt;
| Zum Start nur GeForce RTX 50 und entsprechende Laptop-GPUs&lt;br /&gt;
|-&lt;br /&gt;
| Unreal Engine&lt;br /&gt;
| Offizielles NVIDIA-DLSS-Plugin&lt;br /&gt;
| Integration über NVIDIA Streamline oder ein UE5-Plugin&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
DLSS 5 ersetzt DLSS 4/4.5 daher nicht vollständig. Ein Spiel kann Super Resolution, Ray Reconstruction, Multi Frame Generation und DLSS 5 gemeinsam verwenden.&lt;br /&gt;
&lt;br /&gt;
== Vorteile von DLSS 5 ==&lt;br /&gt;
&lt;br /&gt;
* Komplexe Licht- und Materialeffekte können mit geringerem klassischen Renderaufwand sichtbar werden.&lt;br /&gt;
* Künstler können Intensität, Ton und Masken steuern.&lt;br /&gt;
* Rasterisierung, Raytracing und Pathtracing können als Ausgangsbasis dienen.&lt;br /&gt;
* Die Berechnung läuft lokal auf der GPU und ist an die vom Spiel vorgegebene Szene gebunden.&lt;br /&gt;
&lt;br /&gt;
== Nachteile und offene Fragen ==&lt;br /&gt;
&lt;br /&gt;
* Zum Start ist eine RTX-50-GPU erforderlich.&lt;br /&gt;
* Das Verfahren kann den beabsichtigten Grafikstil verändern, wenn Modelle und Regler unpassend gewählt werden.&lt;br /&gt;
* Kleine Fehler können als erfundene Materialdetails, instabile Kanten oder zeitliche Artefakte sichtbar werden.&lt;br /&gt;
* Die Qualität hängt stark vom Ausgangsbild und den gelieferten Engine-Daten ab.&lt;br /&gt;
* Die zusätzliche Renderstufe kostet Rechenzeit; hohe beworbene FPS entstehen meist erst zusammen mit Super Resolution und Multi Frame Generation.&lt;br /&gt;
* SDK, Modelle und Laufzeit sind proprietär.&lt;br /&gt;
* Kurz nach Veröffentlichung fehlen noch breite unabhängige Vergleiche in unterschiedlichen Spielszenen.&lt;br /&gt;
&lt;br /&gt;
== Verfügbarkeit ==&lt;br /&gt;
&lt;br /&gt;
Der erste angekündigte Titel ist &#039;&#039;NBA 2K27&#039;&#039;. Weitere genannte Spiele sind unter anderem &#039;&#039;Starfield&#039;&#039;, &#039;&#039;Hogwarts Legacy&#039;&#039;, &#039;&#039;Assassin’s Creed Shadows&#039;&#039;, &#039;&#039;Resident Evil Requiem&#039;&#039; und &#039;&#039;The Elder Scrolls IV: Oblivion Remastered&#039;&#039;. Unterstützung muss vom jeweiligen Spielentwickler integriert und abgestimmt werden.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://research.nvidia.com/labs/adlr/DLSS5/ NVIDIA Research: DLSS 5 – Generative Neural Rendering]&lt;br /&gt;
* [https://www.nvidia.com/en-us/geforce/news/dlss-5-3d-guided-neural-rendering/ NVIDIA: DLSS 5 und 3D-Guided Neural Rendering]&lt;br /&gt;
* [https://research.nvidia.com/labs/adlr/DLSS4/ NVIDIA Research: DLSS 4]&lt;br /&gt;
* [https://developer.nvidia.com/rtx/dlss NVIDIA Developer: DLSS-Technologien und Unreal-Plugin]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Grafik]]&lt;br /&gt;
[[Kategorie:NVIDIA]]&lt;br /&gt;
[[Kategorie:Künstliche Intelligenz]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Render_Hardware_Interface_(RHI)&amp;diff=145</id>
		<title>Render Hardware Interface (RHI)</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Render_Hardware_Interface_(RHI)&amp;diff=145"/>
		<updated>2026-09-03T14:19:45Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
Das &#039;&#039;&#039;Render Hardware Interface (RHI)&#039;&#039;&#039; ist die hardwarenahe Abstraktionsschicht des Unreal-Renderers. Rendering-Code arbeitet über ein gemeinsames Unreal-Interface, während das jeweils aktive Backend die Befehle auf eine konkrete Grafik-API wie Direct3D 12, Vulkan oder Metal abbildet.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Artikelstatus&lt;br /&gt;
|-&lt;br /&gt;
! Bezugsstand&lt;br /&gt;
| Unreal Engine 5.8&lt;br /&gt;
|-&lt;br /&gt;
! Letzte Aktualisierung&lt;br /&gt;
| 2. September 2026&lt;br /&gt;
|-&lt;br /&gt;
! Modul&lt;br /&gt;
| &amp;lt;code&amp;gt;RHI&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Zentrale Header&lt;br /&gt;
| &amp;lt;code&amp;gt;DynamicRHI.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RHICommandList.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RHIResources.h&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aufgabe des RHI ==&lt;br /&gt;
&lt;br /&gt;
Das RHI bildet eine gemeinsame Schnittstelle zwischen Unreals Renderer und den plattformspezifischen Grafik-APIs. Es abstrahiert unter anderem:&lt;br /&gt;
&lt;br /&gt;
* Grafik- und Compute-Pipelines&lt;br /&gt;
* Buffer und Texturen&lt;br /&gt;
* Shader und Shader-Parameter&lt;br /&gt;
* Render Passes&lt;br /&gt;
* Command Lists und Command Contexts&lt;br /&gt;
* Ressourcenübergänge und Synchronisation&lt;br /&gt;
* Queries, Fences und Readbacks&lt;br /&gt;
* Raytracing-Ressourcen und -Pipelines&lt;br /&gt;
&lt;br /&gt;
Die Abstraktion ist bewusst hardwarenah. Sie soll plattformunabhängigen Rendering-Code ermöglichen, ohne die Eigenschaften moderner Low-Level-APIs vollständig zu verbergen.&lt;br /&gt;
&lt;br /&gt;
== Grobe Einordnung im Renderer ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Spiel- und Engine-Systeme&lt;br /&gt;
        |&lt;br /&gt;
Renderer / Render Dependency Graph&lt;br /&gt;
        |&lt;br /&gt;
RHI-Befehle und RHI-Ressourcen&lt;br /&gt;
        |&lt;br /&gt;
plattformabhängiges RHI-Backend&lt;br /&gt;
        |&lt;br /&gt;
Direct3D 12 / Vulkan / Metal&lt;br /&gt;
        |&lt;br /&gt;
GPU und Treiber&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
High-Level-Rendering-Code wird in modernen UE-Versionen häufig über den [[Render Dependency Graph]] beschrieben. Bei der Ausführung werden daraus RHI-Befehle, die das aktive Backend anschließend in native API-Kommandos übersetzt.&lt;br /&gt;
&lt;br /&gt;
== Dynamisches RHI und Backends ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FDynamicRHI&amp;lt;/code&amp;gt; ist die zentrale Schnittstelle des zur Laufzeit gebundenen RHI-Backends. Konkrete Implementierungen stellen die Verbindung zur jeweiligen Grafik-API her. Dazu gehören beispielsweise Schnittstellen für Direct3D 12 und Vulkan.&lt;br /&gt;
&lt;br /&gt;
Das ausgewählte Backend wird während des Engine-Starts initialisiert. Welches RHI verwendet wird, hängt von Plattform, Projektkonfiguration und Startparametern ab. Das aktive Backend stellt die tatsächlichen Ressourcen, Command Contexts und Submit-Pfade bereit.&lt;br /&gt;
&lt;br /&gt;
Wichtig: RHI-Objekte sind Unreal-Abstraktionen. Ein &amp;lt;code&amp;gt;FRHIBuffer&amp;lt;/code&amp;gt; ist nicht selbst ein &amp;lt;code&amp;gt;ID3D12Resource&amp;lt;/code&amp;gt;; das D3D12-Backend verwaltet darunter das native Objekt.&lt;br /&gt;
&lt;br /&gt;
== RHI-Ressourcen ==&lt;br /&gt;
&lt;br /&gt;
Viele GPU-Objekte werden als von &amp;lt;code&amp;gt;FRHIResource&amp;lt;/code&amp;gt; abgeleitete Typen dargestellt.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! RHI-Typ&lt;br /&gt;
! Aufgabe&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Allgemeiner GPU-Buffer mit Größe, Stride und Nutzungsflags&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHITexture&amp;lt;/code&amp;gt;&lt;br /&gt;
| Texturressource einschließlich Format, Ausdehnung und Mip-Struktur&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIShaderResourceView&amp;lt;/code&amp;gt; (SRV)&lt;br /&gt;
| Lesende Sicht auf eine Ressource für Shader&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIUnorderedAccessView&amp;lt;/code&amp;gt; (UAV)&lt;br /&gt;
| Schreibende beziehungsweise ungeordnet lesend-schreibende Sicht&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIUniformBuffer&amp;lt;/code&amp;gt;&lt;br /&gt;
| Gebündelte konstante Shader-Parameter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIGPUFence&amp;lt;/code&amp;gt;&lt;br /&gt;
| GPU-seitiger Synchronisationspunkt&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FRHIGPUBufferReadback&amp;lt;/code&amp;gt;&lt;br /&gt;
| Hilfsobjekt für asynchrones Zurücklesen eines Buffers&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Ressourcen besitzen Beschreibungen und Nutzungsflags. Diese Informationen sind wichtig, weil moderne APIs Speicher, Bindung und erlaubte Zugriffe explizit behandeln.&lt;br /&gt;
&lt;br /&gt;
== Command Lists ==&lt;br /&gt;
&lt;br /&gt;
Rendering- und Compute-Arbeit wird über RHI Command Lists aufgezeichnet. Sie enthalten keine beliebige Spiellogik, sondern eine geordnete Folge grafischer Befehle.&lt;br /&gt;
&lt;br /&gt;
=== Wichtige Typen ===&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIComputeCommandList&amp;lt;/code&amp;gt; stellt die gemeinsame Compute-Schnittstelle bereit.&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHICommandList&amp;lt;/code&amp;gt; erweitert diese um Grafikbefehle, beispielsweise Render Passes und Draw-Aufrufe.&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHICommandListImmediate&amp;lt;/code&amp;gt; ist die unmittelbare Haupt-Command-List. Sie sollte nicht ohne Not verwendet werden, wenn parallele Ausführung erhalten bleiben soll.&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHICommandListExecutor&amp;lt;/code&amp;gt; koordiniert Übersetzung und Übermittlung aufgezeichneter Command Lists.&lt;br /&gt;
&lt;br /&gt;
Typische Befehle umfassen:&lt;br /&gt;
&lt;br /&gt;
* Render Pass beginnen und beenden&lt;br /&gt;
* Grafik- oder Compute-PSO setzen&lt;br /&gt;
* Shader-Parameter binden&lt;br /&gt;
* Vertex- und Index-Buffer setzen&lt;br /&gt;
* Draw oder Dispatch auslösen&lt;br /&gt;
* Ressourcen kopieren&lt;br /&gt;
* Ressourcenübergänge einleiten&lt;br /&gt;
* GPU-Fences schreiben&lt;br /&gt;
&lt;br /&gt;
== Threads und Befehlsfluss ==&lt;br /&gt;
&lt;br /&gt;
Unreals Rendering arbeitet über mehrere Ebenen. Vereinfacht gilt:&lt;br /&gt;
&lt;br /&gt;
# Der &#039;&#039;&#039;Game Thread&#039;&#039;&#039; aktualisiert die Spielwelt und stößt Rendering-Arbeit an.&lt;br /&gt;
# Der &#039;&#039;&#039;Render Thread&#039;&#039;&#039; verarbeitet die Render-Szene und zeichnet plattformunabhängige RHI-Befehle auf.&lt;br /&gt;
# Der &#039;&#039;&#039;RHI Thread&#039;&#039;&#039; kann diese Befehle für das aktive Backend übersetzen und an die Grafik-API weitergeben.&lt;br /&gt;
# Das Backend übermittelt native Command Lists an die GPU-Queues.&lt;br /&gt;
&lt;br /&gt;
Diese Trennung erlaubt Parallelisierung. Renderer-Code sollte deshalb nicht unnötig blockieren oder voraussetzen, dass ein aufgezeichneter Befehl sofort auf der GPU ausgeführt wurde.&lt;br /&gt;
&lt;br /&gt;
== Pipeline State Objects ==&lt;br /&gt;
&lt;br /&gt;
Moderne Grafik-APIs bündeln viele Zustände in &#039;&#039;&#039;Pipeline State Objects&#039;&#039;&#039; (PSOs). Unreal unterscheidet unter anderem:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIGraphicsPipelineState&amp;lt;/code&amp;gt; für Grafik-Pipelines&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIComputePipelineState&amp;lt;/code&amp;gt; für Compute-Pipelines&lt;br /&gt;
* &amp;lt;code&amp;gt;FRHIRayTracingPipelineState&amp;lt;/code&amp;gt; für Raytracing&lt;br /&gt;
&lt;br /&gt;
Ein Grafik-PSO beschreibt beispielsweise Shader-Stufen, Blend-, Rasterizer- und Depth-Stencil-Zustand sowie Render-Target-Formate. Ein Compute-PSO benötigt vor allem den Compute Shader und die zum Backend gehörende Bindungsstruktur.&lt;br /&gt;
&lt;br /&gt;
Häufig wechselnde oder erst während des Spiels kompilierte PSOs können Ruckler verursachen. Deshalb sind PSO-Caching und eine frühzeitige Vorbereitung wichtiger Zustände für reale Projekte relevant.&lt;br /&gt;
&lt;br /&gt;
== Ressourcenstatus und Barriers ==&lt;br /&gt;
&lt;br /&gt;
In Direct3D 12 und Vulkan müssen Ressourcenzugriffe explizit synchronisiert werden. Eine Ressource kann beispielsweise als Kopierziel, Shader-Eingabe oder UAV-Ausgabe verwendet werden. Der Status muss vor der jeweiligen Nutzung passen.&lt;br /&gt;
&lt;br /&gt;
Das RHI beschreibt Zugriffe unter anderem über RHI-Zustände und Übergänge. Bei RDG-Ressourcen übernimmt der Render Dependency Graph einen großen Teil der Planung, sofern alle Ressourcen korrekt als Pass-Parameter angegeben wurden.&lt;br /&gt;
&lt;br /&gt;
Fehlerhafte Übergänge können zu Validierungsfehlern, beschädigten Ergebnissen oder GPU-Hängern führen. Besondere Vorsicht ist nötig, wenn Ressourcen außerhalb von RDG manuell verwaltet oder zwischen unabhängigen Queues ausgetauscht werden.&lt;br /&gt;
&lt;br /&gt;
== Synchronisation und Readback ==&lt;br /&gt;
&lt;br /&gt;
CPU und GPU arbeiten asynchron. Ein Submit bedeutet deshalb nicht, dass die GPU-Arbeit bereits beendet ist.&lt;br /&gt;
&lt;br /&gt;
Typische Werkzeuge sind:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;GPU-Fence:&#039;&#039;&#039; signalisiert das Erreichen eines Punkts in einer GPU-Queue&lt;br /&gt;
* &#039;&#039;&#039;Queue- beziehungsweise Pipeline-Übergänge:&#039;&#039;&#039; koordinieren Graphics- und Async-Compute-Arbeit&lt;br /&gt;
* &#039;&#039;&#039;Readback-Ressourcen:&#039;&#039;&#039; übertragen Ergebnisse in CPU-lesbaren Speicher&lt;br /&gt;
* &#039;&#039;&#039;Staging-Buffer:&#039;&#039;&#039; dienen als Zwischenspeicher für Upload oder Readback&lt;br /&gt;
&lt;br /&gt;
Die CPU sollte nur dann auf Readback-Daten zugreifen, wenn der zugehörige Fence abgeschlossen ist. Häufige synchrone Wartezeiten zerstören die Parallelität und sollten im normalen Frame-Pfad vermieden werden.&lt;br /&gt;
&lt;br /&gt;
== RHI und Render Dependency Graph ==&lt;br /&gt;
&lt;br /&gt;
RHI und RDG erfüllen unterschiedliche Aufgaben:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Ebene&lt;br /&gt;
! Verantwortung&lt;br /&gt;
|-&lt;br /&gt;
| RDG&lt;br /&gt;
| Beschreibung von Passes und Abhängigkeiten, Ressourcenlebenszeiten, Culling, Planung und Parallelisierung&lt;br /&gt;
|-&lt;br /&gt;
| RHI&lt;br /&gt;
| Hardwarenahe Befehle, Ressourcen und Pipeline-Zustände für das aktive Grafik-Backend&lt;br /&gt;
|-&lt;br /&gt;
| Plattform-RHI&lt;br /&gt;
| Übersetzung in native Direct3D-12-, Vulkan- oder Metal-Objekte und -Kommandos&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für neuen High-Level-Rendering-Code ist RDG meist der bevorzugte Einstieg. Direkter RHI-Code bleibt wichtig, wenn hardwarenahe Kontrolle nötig ist oder ein System unterhalb beziehungsweise außerhalb des normalen Render Graphs arbeitet.&lt;br /&gt;
&lt;br /&gt;
== Debugging und Diagnose ==&lt;br /&gt;
&lt;br /&gt;
Bei RHI-Problemen helfen unter anderem:&lt;br /&gt;
&lt;br /&gt;
* aussagekräftige Namen für Ressourcen und Render-Passes&lt;br /&gt;
* Grafik-API-Debug-Layer und GPU-basierte Validierung in Entwicklungsumgebungen&lt;br /&gt;
* RHI- und RDG-Validierung&lt;br /&gt;
* Unreal Insights sowie RDG Insights&lt;br /&gt;
* GPU-Captures mit Werkzeugen wie RenderDoc oder PIX, sofern die Konfiguration dies unterstützt&lt;br /&gt;
* Prüfung von Nutzungsflags, Ressourcenstatus und Queue-Zugehörigkeit&lt;br /&gt;
* Kontrolle der Lebensdauer nativer und abstrahierter Ressourcen&lt;br /&gt;
* Fences und Readback-Zeitpunkte protokollieren&lt;br /&gt;
&lt;br /&gt;
== Bezug zum Heterogeneous-Multi-GPU-Projekt ==&lt;br /&gt;
&lt;br /&gt;
Das Projekt [[UE5 Heterogeneous Multi-GPU]] verwendet für die Primary GPU weiterhin Unreals regulären D3D12-RHI-Pfad. Die Intel-Worker-GPU wird dagegen aktuell über ein separat erzeugtes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt; mit eigener Direct Command Queue, eigenen Command Lists und eigener Fence-Synchronisation angesprochen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UE-Renderer&lt;br /&gt;
    |&lt;br /&gt;
    +-- reguläres D3D12-RHI --&amp;gt; RTX 5060 (Primary)&lt;br /&gt;
    |&lt;br /&gt;
    +-- ExperimentalMultiGPU --&amp;gt; separates ID3D12Device&lt;br /&gt;
                                  --&amp;gt; Intel UHD (Worker)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Worker-Pfad ist nicht automatisch Bestandteil von &amp;lt;code&amp;gt;GDynamicRHI&amp;lt;/code&amp;gt;. Dadurch ergeben sich besondere Aufgaben:&lt;br /&gt;
&lt;br /&gt;
* native Ressourcen des Worker-Devices dürfen nicht wie normale RHI-Ressourcen der Primary GPU behandelt werden&lt;br /&gt;
* Shader-Bytecode muss mit dem Zielgerät und dessen Fähigkeiten kompatibel sein&lt;br /&gt;
* Root Signature und PSO müssen für das Worker-Device erzeugt werden&lt;br /&gt;
* Command Allocator, Command List, Queue und Fence benötigen eine eigene Lebensdauerverwaltung&lt;br /&gt;
* Datenübertragung zwischen Primary und Worker muss ausdrücklich geplant werden&lt;br /&gt;
* Cross-Adapter-Ressourcen benötigen passende Heap- und Ressourcenflags; andernfalls ist ein Transfer über System-RAM erforderlich&lt;br /&gt;
* Fehler- und Device-Removal-Behandlung muss pro Device erfolgen&lt;br /&gt;
&lt;br /&gt;
Langfristig kann geprüft werden, welche Teile sinnvoll als eigene Unreal-Abstraktion oberhalb der nativen Devices modelliert werden. Eine direkte Erweiterung des regulären RHI um heterogene unabhängige Devices wäre dagegen ein erheblich größerer Eingriff in Engine-Annahmen, Ressourcenverwaltung und Scheduling.&lt;br /&gt;
&lt;br /&gt;
== Praktische Merksätze ==&lt;br /&gt;
&lt;br /&gt;
* RHI abstrahiert die Grafik-API, aber nicht die grundlegenden Regeln moderner GPUs.&lt;br /&gt;
* Command-Aufzeichnung und GPU-Ausführung finden zeitlich getrennt statt.&lt;br /&gt;
* Ressourcenstatus, Queue-Zugehörigkeit und Lebensdauer müssen immer eindeutig sein.&lt;br /&gt;
* RDG ist für neuen High-Level-Code meist geeigneter als manuelle Immediate-RHI-Befehle.&lt;br /&gt;
* Native Objekte verschiedener D3D12-Devices sind nicht beliebig austauschbar.&lt;br /&gt;
* Für einen unabhängigen Worker-Pfad müssen Synchronisation und Transfers ausdrücklich entworfen werden.&lt;br /&gt;
&lt;br /&gt;
== Quellen und weiterführende Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/graphics-programming-overview-for-unreal-engine Graphics Programming Overview] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI RHI API Reference] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FDynamicRHI FDynamicRHI] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI/FRHICommandList FRHICommandList] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI/FRHIBuffer FRHIBuffer] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RHI/FRHITexture FRHITexture] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/parallel-rendering-overview-for-unreal-engine Parallel Rendering Overview] – Epic Games, UE 5.8&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Dieser Artikel ist eine eigenständige deutschsprachige Zusammenfassung mit Projektbezug und keine vollständige Übersetzung der Epic-Dokumentation.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:RHI]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Grafikprogrammierung]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Global_Shaders_und_Compute_Shader&amp;diff=144</id>
		<title>Global Shaders und Compute Shader</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Global_Shaders_und_Compute_Shader&amp;diff=144"/>
		<updated>2026-09-03T14:19:36Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Global Shaders&#039;&#039;&#039; 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.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Artikelstatus&lt;br /&gt;
|-&lt;br /&gt;
! Bezugsstand&lt;br /&gt;
| Unreal Engine 5.8&lt;br /&gt;
|-&lt;br /&gt;
! Letzte Aktualisierung&lt;br /&gt;
| 2. September 2026&lt;br /&gt;
|-&lt;br /&gt;
! Zentrale Klassen und Hilfen&lt;br /&gt;
| &amp;lt;code&amp;gt;FGlobalShader&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FComputeShaderUtils&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FRDGBuilder&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! Shader-Dateityp&lt;br /&gt;
| &amp;lt;code&amp;gt;.usf&amp;lt;/code&amp;gt; (Unreal Shader File)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Einsatzgebiete ==&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
* Compute-Berechnungen auf Buffern oder Texturen&lt;br /&gt;
* eigene Post-Processing-Schritte&lt;br /&gt;
* Fullscreen-Passes&lt;br /&gt;
* Erzeugen, Kopieren oder Umwandeln von GPU-Daten&lt;br /&gt;
* Debug- und Visualisierungs-Passes&lt;br /&gt;
* experimentelle Rendering-Pipelines&lt;br /&gt;
&lt;br /&gt;
Ein Compute Shader ist dabei ein möglicher Shader-Typ. Er verarbeitet Daten in frei definierbaren Thread-Gruppen und erzeugt nicht unmittelbar Rastergrafik.&lt;br /&gt;
&lt;br /&gt;
== Bausteine eines Global Shaders ==&lt;br /&gt;
&lt;br /&gt;
Ein Global Shader besteht in der Regel aus mehreren Teilen:&lt;br /&gt;
&lt;br /&gt;
# einer Shader-Datei mit HLSL-Code (&amp;lt;code&amp;gt;.usf&amp;lt;/code&amp;gt;)&lt;br /&gt;
# einer von &amp;lt;code&amp;gt;FGlobalShader&amp;lt;/code&amp;gt; abgeleiteten C++-Klasse&lt;br /&gt;
# einer Parameterstruktur für Eingaben und Ausgaben&lt;br /&gt;
# einem Registrierungs-Makro, das Klasse, Datei, Einstiegspunkt und Shader-Stufe verbindet&lt;br /&gt;
# Code, der den Shader auswählt, Parameter bindet und den Dispatch oder Draw-Aufruf ausführt&lt;br /&gt;
&lt;br /&gt;
=== Speicherort der Shader-Dateien ===&lt;br /&gt;
&lt;br /&gt;
Engine-eigene Shader liegen unter &amp;lt;code&amp;gt;Engine/Shaders&amp;lt;/code&amp;gt;. Shader eines Plugins gehören in dessen &amp;lt;code&amp;gt;Shaders&amp;lt;/code&amp;gt;-Verzeichnis. Die Trennung hält experimentellen Code von den Engine-Dateien fern und erleichtert Updates sowie Versionsverwaltung.&lt;br /&gt;
&lt;br /&gt;
== Minimaler Compute Shader ==&lt;br /&gt;
&lt;br /&gt;
Das folgende vereinfachte Beispiel verdoppelt jeden Wert eines Eingabebuffers. Es dient der Orientierung und muss an die konkrete Modul- und Ressourcenstruktur angepasst werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;hlsl&amp;quot;&amp;gt;&lt;br /&gt;
StructuredBuffer&amp;amp;lt;uint&amp;amp;gt; InputValues;&lt;br /&gt;
RWStructuredBuffer&amp;amp;lt;uint&amp;amp;gt; OutputValues;&lt;br /&gt;
uint ElementCount;&lt;br /&gt;
&lt;br /&gt;
[numthreads(64, 1, 1)]&lt;br /&gt;
void MainCS(uint3 DispatchThreadId : SV_DispatchThreadID)&lt;br /&gt;
{&lt;br /&gt;
    const uint Index = DispatchThreadId.x;&lt;br /&gt;
    if (Index &amp;amp;gt;= ElementCount)&lt;br /&gt;
    {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    OutputValues[Index] = InputValues[Index] * 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;numthreads(64, 1, 1)&amp;lt;/code&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
== C++-Repräsentation ==&lt;br /&gt;
&lt;br /&gt;
Die C++-Klasse beschreibt den Shader gegenüber Unreal und definiert seine Parameter. Ein typisches Grundmuster sieht so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class FExampleComputeShader : public FGlobalShader&lt;br /&gt;
{&lt;br /&gt;
    DECLARE_GLOBAL_SHADER(FExampleComputeShader);&lt;br /&gt;
    SHADER_USE_PARAMETER_STRUCT(FExampleComputeShader, FGlobalShader);&lt;br /&gt;
&lt;br /&gt;
    BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )&lt;br /&gt;
        SHADER_PARAMETER(uint32, ElementCount)&lt;br /&gt;
        SHADER_PARAMETER_SRV(StructuredBuffer&amp;amp;lt;uint32&amp;amp;gt;, InputValues)&lt;br /&gt;
        SHADER_PARAMETER_UAV(RWStructuredBuffer&amp;amp;lt;uint32&amp;amp;gt;, OutputValues)&lt;br /&gt;
    END_SHADER_PARAMETER_STRUCT()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
IMPLEMENT_GLOBAL_SHADER(&lt;br /&gt;
    FExampleComputeShader,&lt;br /&gt;
    &amp;quot;/Plugin/Example/Private/ExampleCompute.usf&amp;quot;,&lt;br /&gt;
    &amp;quot;MainCS&amp;quot;,&lt;br /&gt;
    SF_Compute&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wichtige Punkte:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;DECLARE_GLOBAL_SHADER&amp;lt;/code&amp;gt; deklariert den Shader-Typ.&lt;br /&gt;
* &amp;lt;code&amp;gt;SHADER_USE_PARAMETER_STRUCT&amp;lt;/code&amp;gt; aktiviert die strukturierte Parameterbindung.&lt;br /&gt;
* &amp;lt;code&amp;gt;BEGIN_SHADER_PARAMETER_STRUCT&amp;lt;/code&amp;gt; beschreibt Konstanten, SRVs und UAVs.&lt;br /&gt;
* &amp;lt;code&amp;gt;IMPLEMENT_GLOBAL_SHADER&amp;lt;/code&amp;gt; verbindet C++-Klasse, virtuellen Shader-Pfad, Einstiegspunkt und Shader-Stufe.&lt;br /&gt;
* &amp;lt;code&amp;gt;SF_Compute&amp;lt;/code&amp;gt; kennzeichnet den Shader als Compute Shader.&lt;br /&gt;
&lt;br /&gt;
Je nach Modulgrenze kann statt &amp;lt;code&amp;gt;DECLARE_GLOBAL_SHADER&amp;lt;/code&amp;gt; eine exportierte Shader-Deklaration nötig sein.&lt;br /&gt;
&lt;br /&gt;
== Kompilierungsbedingungen ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;lt;code&amp;gt;PostConfigInit&amp;lt;/code&amp;gt; relevant.&lt;br /&gt;
&lt;br /&gt;
== Dispatch über das RHI ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FComputeShaderUtils::Dispatch&amp;lt;/code&amp;gt; sendet einen Compute Shader mit Parametern und Gruppenzahl an eine &amp;lt;code&amp;gt;FRHIComputeCommandList&amp;lt;/code&amp;gt;. Das ist die direkte Variante auf RHI-Ebene.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
const FIntVector GroupCount =&lt;br /&gt;
    FComputeShaderUtils::GetGroupCount(ElementCount, 64);&lt;br /&gt;
&lt;br /&gt;
FComputeShaderUtils::Dispatch(&lt;br /&gt;
    RHICmdList,&lt;br /&gt;
    ComputeShader,&lt;br /&gt;
    Parameters,&lt;br /&gt;
    GroupCount&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Hilfsfunktion &amp;lt;code&amp;gt;GetGroupCount&amp;lt;/code&amp;gt; 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.&lt;br /&gt;
&lt;br /&gt;
== Dispatch über den Render Dependency Graph ==&lt;br /&gt;
&lt;br /&gt;
Für regulären High-Level-Rendering-Code empfiehlt Unreal den Render Dependency Graph (RDG). Ein Compute-Pass kann dort über &amp;lt;code&amp;gt;FComputeShaderUtils::AddPass&amp;lt;/code&amp;gt; registriert werden.&lt;br /&gt;
&lt;br /&gt;
RDG kennt dadurch die beteiligten Ressourcen und kann unter anderem:&lt;br /&gt;
&lt;br /&gt;
* Abhängigkeiten zwischen Passes bestimmen&lt;br /&gt;
* Ressourcenübergänge und Barriers verwalten&lt;br /&gt;
* ungenutzte Passes entfernen&lt;br /&gt;
* Lebenszeiten temporärer Ressourcen optimieren&lt;br /&gt;
* geeignete Arbeit parallelisieren&lt;br /&gt;
* Async-Compute-Passes synchronisieren&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Shader-Entwicklung und Fehlersuche ==&lt;br /&gt;
&lt;br /&gt;
Für die Entwicklung sind folgende Maßnahmen hilfreich:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;r.ShaderDevelopmentMode=1&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ConsoleVariables.ini&amp;lt;/code&amp;gt; aktivieren, um ausführlichere Shader-Compile-Logs zu erhalten.&lt;br /&gt;
* Einstiegspunkt, virtuellen Shader-Pfad und Shader-Stufe kontrollieren.&lt;br /&gt;
* Sicherstellen, dass das Plugin und alle benötigten Module als Abhängigkeiten eingetragen sind.&lt;br /&gt;
* Modul-Ladephase prüfen, wenn Unreal meldet, dass ein Shader-Typ zu spät registriert wurde.&lt;br /&gt;
* Parameterstruktur zwischen HLSL und C++ sorgfältig abgleichen.&lt;br /&gt;
* Thread-Gruppengröße und Bounds-Checks prüfen.&lt;br /&gt;
* Ressourcenstatus, SRV-/UAV-Bindung und Synchronisation kontrollieren.&lt;br /&gt;
* Bei RDG-Passes aussagekräftige Event-Namen verwenden und bei Bedarf RDG Insights einsetzen.&lt;br /&gt;
&lt;br /&gt;
== Bezug zum Heterogeneous-Multi-GPU-Projekt ==&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Der geplante erste Test lässt sich in folgende Schritte zerlegen:&lt;br /&gt;
&lt;br /&gt;
# einfachen Global Compute Shader in einem früh geladenen Modul registrieren&lt;br /&gt;
# Shader über Unreals reguläre Shader-Pipeline kompilieren lassen&lt;br /&gt;
# kompilierten Bytecode für den gewählten Worker-Adapter prüfen&lt;br /&gt;
# passende Root Signature und Compute Pipeline State auf dem Worker-&amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt; erzeugen&lt;br /&gt;
# Input- und Output-Buffer auf dem Worker-Device bereitstellen&lt;br /&gt;
# Compute Dispatch auf der eigenen Worker-Command-Queue ausführen&lt;br /&gt;
# Ergebnis über Readback zurückholen und auf der CPU verifizieren&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Quellen und weiterführende Dokumentation ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/adding-global-shaders-to-unreal-engine Adding Global Shaders to Unreal Engine] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/overview-of-shaders-in-plugins-unreal-engine Overview of Shaders in Plugins] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/shader-development-in-unreal-engine Shader Development in Unreal Engine] – Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/RenderCore/FComputeShaderUtils__Dispatch FComputeShaderUtils::Dispatch] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RenderCore/FComputeShaderUtils__AddPass FComputeShaderUtils::AddPass] – API-Referenz, Epic Games, UE 5.8&lt;br /&gt;
* [https://dev.epicgames.com/documentation/unreal-engine/render-dependency-graph-in-unreal-engine Render Dependency Graph] – Epic Games, UE 5.8&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Dieser Artikel ist eine eigenständige deutschsprachige Zusammenfassung mit Projektbezug und keine vollständige Übersetzung der Epic-Dokumentation.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Shader]]&lt;br /&gt;
[[Kategorie:Compute Shader]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=143</id>
		<title>UE5 Heterogeneous Multi-GPU</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=UE5_Heterogeneous_Multi-GPU&amp;diff=143"/>
		<updated>2026-09-03T14:19:28Z</updated>

		<summary type="html">&lt;p&gt;Elaina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UE5 Heterogeneous Multi-GPU&#039;&#039;&#039; ist ein experimentelles Projekt zur herstellerunabhängigen Nutzung mehrerer unterschiedlicher Grafikkarten in [[Unreal Engine 5]]. NVIDIA-, AMD- und Intel-GPUs sollen gleichzeitig verschiedene, voneinander unabhängige Aufgaben übernehmen können.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Projektstatus&lt;br /&gt;
|-&lt;br /&gt;
! Stand&lt;br /&gt;
| 2. September 2026&lt;br /&gt;
|-&lt;br /&gt;
! Engine-Version&lt;br /&gt;
| Unreal Engine 5.8&lt;br /&gt;
|-&lt;br /&gt;
! Status&lt;br /&gt;
| &#039;&#039;&#039;Proof of Concept erfolgreich&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! Primary GPU&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
! Worker GPU&lt;br /&gt;
| Intel(R) UHD Graphics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Projektziel ==&lt;br /&gt;
&lt;br /&gt;
Ziel ist eine Multi-GPU-Erweiterung für Unreal Engine 5, die weder identische GPUs noch einen Linked-Adapter-Verbund voraussetzt. Vorgesehen sind unter anderem Kombinationen wie:&lt;br /&gt;
&lt;br /&gt;
* NVIDIA + Intel&lt;br /&gt;
* NVIDIA + AMD&lt;br /&gt;
* langfristig NVIDIA + AMD + Intel&lt;br /&gt;
&lt;br /&gt;
Die Architektur soll grundsätzlich &#039;&#039;&#039;N GPUs&#039;&#039;&#039; unterstützen und nicht fest auf zwei Grafikkarten beschränkt sein.&lt;br /&gt;
&lt;br /&gt;
== Grundprinzip ==&lt;br /&gt;
&lt;br /&gt;
Unreal Engine verwendet weiterhin eine normale Grafikkarte als &#039;&#039;&#039;Primary GPU&#039;&#039;&#039; für das reguläre Rendering. Weitere erkannte Grafikkarten werden als &#039;&#039;&#039;Worker GPUs&#039;&#039;&#039; registriert. Jeder Worker erhält ein unabhängiges Grafik-Device und eigene Arbeitswarteschlangen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Primary GPU:&#039;&#039;&#039; normales Unreal-Rendering über das reguläre D3D12-RHI&lt;br /&gt;
* &#039;&#039;&#039;Worker GPUs:&#039;&#039;&#039; separate Devices für gezielt ausgelagerte Aufgaben&lt;br /&gt;
* &#039;&#039;&#039;Geplante Workloads:&#039;&#039;&#039; Scene Captures, Spiegel, CCTV-Kameras, Minimap-Rendering, Compute-Aufgaben und weitere unabhängige Render-Workloads&lt;br /&gt;
* &#039;&#039;&#039;Automatische Verteilung:&#039;&#039;&#039; Ein späterer Benchmark soll GPUs und Transferwege bewerten und eine sinnvolle Aufgabenverteilung empfehlen.&lt;br /&gt;
* &#039;&#039;&#039;Manuelle Kontrolle:&#039;&#039;&#039; Konfiguration und Overrides sollen weiterhin möglich bleiben.&lt;br /&gt;
&lt;br /&gt;
== Aktuelles Testsystem ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Rolle&lt;br /&gt;
! GPU&lt;br /&gt;
|-&lt;br /&gt;
| Primary&lt;br /&gt;
| NVIDIA GeForce RTX 5060 Laptop GPU&lt;br /&gt;
|-&lt;br /&gt;
| Worker&lt;br /&gt;
| Intel(R) UHD Graphics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Aktueller Entwicklungsstand ==&lt;br /&gt;
&lt;br /&gt;
* Unreal erkennt beide physischen D3D12-Adapter und filtert den Microsoft Basic Render Driver heraus.&lt;br /&gt;
* Die RTX 5060 wird als Primary GPU und die Intel UHD als Worker GPU erkannt.&lt;br /&gt;
* Für die Intel-GPU wird unabhängig vom normalen Unreal-RHI ein eigenes &amp;lt;code&amp;gt;ID3D12Device&amp;lt;/code&amp;gt; erzeugt.&lt;br /&gt;
* Für das Worker-Device wird eine eigene D3D12 Direct Command Queue erstellt.&lt;br /&gt;
* Eigene Command Lists können auf der Intel-GPU ausgeführt und über einen Fence erfolgreich bestätigt werden.&lt;br /&gt;
* Ein realer Datentest kopiert 256 Byte Testdaten über den Pfad Upload → GPU Buffer → Readback.&lt;br /&gt;
* Die zurückgelesenen Daten stimmen vollständig mit dem ursprünglichen Testmuster überein. Der Worker-Buffer-Copy-Test meldet &#039;&#039;&#039;PASSED&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Damit läuft UE5.8 regulär auf der RTX 5060, während die Intel UHD gleichzeitig über einen vollständig separaten D3D12-Ausführungspfad angesprochen und tatsächlich für GPU-Arbeit verwendet wird.&lt;br /&gt;
&lt;br /&gt;
== Aktuelle Architektur ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UE5.8&lt;br /&gt;
|&lt;br /&gt;
+-- normales UE-D3D12-RHI&lt;br /&gt;
|   +-- RTX 5060 (Primary)&lt;br /&gt;
|&lt;br /&gt;
+-- ExperimentalMultiGPU&lt;br /&gt;
    +-- Intel UHD (Worker)&lt;br /&gt;
        +-- eigenes ID3D12Device&lt;br /&gt;
        +-- eigene Direct Command Queue&lt;br /&gt;
        +-- eigene Command Lists&lt;br /&gt;
        +-- Fence-Synchronisation&lt;br /&gt;
        +-- Buffer-Copy / Readback&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modulare Code-Struktur ==&lt;br /&gt;
&lt;br /&gt;
Der experimentelle Code ist bewusst in kleine, klar abgegrenzte Komponenten aufgeteilt. Das erleichtert die Weiterentwicklung, Fehlersuche und spätere Portierung.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ExperimentalMultiGPU/&lt;br /&gt;
+-- MultiGPUAdapterRegistry.*&lt;br /&gt;
+-- MultiGPUD3D12Device.*&lt;br /&gt;
+-- MultiGPUD3D12Queue.*&lt;br /&gt;
+-- MultiGPUD3D12Command.*&lt;br /&gt;
+-- MultiGPUD3D12Transfer.*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nächste Entwicklungsstufe ==&lt;br /&gt;
&lt;br /&gt;
Als nächster Meilenstein soll die Worker-GPU erstmals eine echte Compute-Berechnung durchführen. Dafür soll ein von Unreals normaler Shader-Pipeline kompilierter Compute Shader auf dem unabhängigen Worker-Device ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
# UE-Shader-Blob verwenden, statt einen separaten DXC-Hack einzubauen&lt;br /&gt;
# Root Signature für das Worker-Device erzeugen&lt;br /&gt;
# Compute Pipeline State auf der Worker-GPU erstellen&lt;br /&gt;
# Testdaten verarbeiten, zurücklesen und auf der CPU verifizieren&lt;br /&gt;
# Ressourcen- und Transfer-Benchmarks durchführen&lt;br /&gt;
# Cross-Adapter-Datenaustausch erproben&lt;br /&gt;
&lt;br /&gt;
== Langfristige Ziele ==&lt;br /&gt;
&lt;br /&gt;
* Automatische Erkennung und Bewertung beliebiger GPU-Kombinationen&lt;br /&gt;
* Benchmarks für Raster-, Compute-, Raytracing- und Transferleistung&lt;br /&gt;
* Automatische Empfehlung für Primary- und Worker-Rollen&lt;br /&gt;
* Manuelle Zuweisung einzelner Workloads zu bestimmten GPUs&lt;br /&gt;
* Unterstützung mehrerer Worker mit unterschiedlichen Update-Raten&lt;br /&gt;
* Direkte Cross-Adapter-Transfers, sofern möglich, mit Fallback über den System-RAM&lt;br /&gt;
* Vulkan-Implementierung für Linux&lt;br /&gt;
* Gleichzeitiger Betrieb von NVIDIA-, AMD- und Intel-GPUs in einem UE-Projekt&lt;br /&gt;
&lt;br /&gt;
== Versionsverwaltung und Backup ==&lt;br /&gt;
&lt;br /&gt;
Die Änderungen werden separat in einem kleinen Git-Repository dokumentiert. Zusätzlich existiert ein vollständiges NAS-Backup der gebauten UE5.8-Engine als Rücksprungpunkt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Z:\03 Development\UE\UE5.8-MGPU\&lt;br /&gt;
+-- Git\&lt;br /&gt;
+-- FullBackup\&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Zusammenfassung:&#039;&#039;&#039; Der Proof of Concept ist erfolgreich. Eine heterogene Worker-GPU führt bereits echte D3D12-Datenarbeit über ein vom regulären Unreal-RHI unabhängiges Device aus.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;br /&gt;
[[Kategorie:Direct3D 12]]&lt;br /&gt;
[[Kategorie:Experimentell]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Vorlage:Hinweis&amp;diff=142</id>
		<title>Vorlage:Hinweis</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Vorlage:Hinweis&amp;diff=142"/>
		<updated>2026-09-03T14:19:19Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „&amp;lt;div style=&amp;quot;border-left: 4px solid #36c; background: #f8f9fa; padding: 0.7em 1em; margin: 0 0 1em 0;&amp;quot;&amp;gt; &amp;#039;&amp;#039;&amp;#039;Hinweis:&amp;#039;&amp;#039;&amp;#039; {{{1|}}} &amp;lt;/div&amp;gt;&amp;lt;noinclude&amp;gt; Diese Vorlage stellt einen kurzen Hinweis optisch hervorgehoben dar.  == Verwendung == &amp;lt;pre&amp;gt;{{Hinweis|Text des Hinweises}}&amp;lt;/pre&amp;gt; &amp;lt;/noinclude&amp;gt;“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;border-left: 4px solid #36c; background: #f8f9fa; padding: 0.7em 1em; margin: 0 0 1em 0;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; {{{1|}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
Diese Vorlage stellt einen kurzen Hinweis optisch hervorgehoben dar.&lt;br /&gt;
&lt;br /&gt;
== Verwendung ==&lt;br /&gt;
&amp;lt;pre&amp;gt;{{Hinweis|Text des Hinweises}}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Paralleles_Rendering_und_RHI-Thread&amp;diff=141</id>
		<title>Paralleles Rendering und RHI-Thread</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Paralleles_Rendering_und_RHI-Thread&amp;diff=141"/>
		<updated>2026-09-03T13:02:55Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}  &amp;#039;&amp;#039;&amp;#039;Paralleles Rendering&amp;#039;&amp;#039;&amp;#039; verteilt die CPU-Arbeit des Renderers auf mehrere Threads. Der &amp;#039;&amp;#039;&amp;#039;RHI Thread&amp;#039;&amp;#039;&amp;#039; ist dabei der Thread, der Unreal-Befehle über das &amp;#039;&amp;#039;Render Hardware Interface&amp;#039;&amp;#039; (RHI) in Aufrufe der jeweiligen Grafik-API wie DirectX 12 oder Vulkan übersetzt. Das ist CPU-Parallelität und nicht automatisch Multi-GPU-Rendering.  == Die…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Paralleles Rendering&#039;&#039;&#039; verteilt die CPU-Arbeit des Renderers auf mehrere Threads. Der &#039;&#039;&#039;RHI Thread&#039;&#039;&#039; ist dabei der Thread, der Unreal-Befehle über das &#039;&#039;Render Hardware Interface&#039;&#039; (RHI) in Aufrufe der jeweiligen Grafik-API wie DirectX 12 oder Vulkan übersetzt. Das ist CPU-Parallelität und nicht automatisch Multi-GPU-Rendering.&lt;br /&gt;
&lt;br /&gt;
== Die beteiligten Stufen ==&lt;br /&gt;
&lt;br /&gt;
; Game Thread&lt;br /&gt;
: Aktualisiert Spielwelt, Actors und UObjects und übergibt Renderzustand asynchron an den Renderer.&lt;br /&gt;
; Render Thread&lt;br /&gt;
: Baut aus der Szene plattformunabhängige Renderbefehle und Command Lists auf. Eine Command List ist eine geordnete Liste von Grafikbefehlen.&lt;br /&gt;
; RHI Thread&lt;br /&gt;
: Übersetzt bzw. führt diese Listen im Backend für die konkrete Grafik-API aus.&lt;br /&gt;
; GPU&lt;br /&gt;
: Arbeitet die eingereichten Grafik- und Compute-Kommandos ab.&lt;br /&gt;
&lt;br /&gt;
Diese Stufen können an verschiedenen Frames arbeiten. Unreal bewahrt dabei die Einreichungsreihenfolge, die auch ein serieller Renderer hätte. Synchronisationspunkte und Fences sorgen dafür, dass ein Verbraucher nicht vor seinem Produzenten läuft.&lt;br /&gt;
&lt;br /&gt;
== Wo die Parallelität entsteht ==&lt;br /&gt;
&lt;br /&gt;
Der Render Thread kann Command Lists in parallelen Aufgaben vorbereiten. Auf geeigneten Plattformen kann auch das RHI-Backend mehrere Listen parallel übersetzen. Der getrennte RHI Thread verhindert, dass die Übersetzung aller API-Aufrufe den Render Thread direkt blockiert.&lt;br /&gt;
&lt;br /&gt;
Nicht jeder Vorgang passt in dieses Modell. Bestimmte Lock-/Unlock- oder Ressourcenoperationen können einen Flush erzwingen oder Daten kopieren und später einreihen. Häufige erzwungene Synchronisation nimmt den Threads den möglichen Zeitgewinn.&lt;br /&gt;
&lt;br /&gt;
== Thread-Sicherheit in eigenem Code ==&lt;br /&gt;
&lt;br /&gt;
Rendercode darf nicht einfach auf veränderliche &amp;lt;code&amp;gt;UObject&amp;lt;/code&amp;gt;- oder Actor-Daten des Game Threads zugreifen. Sonst entsteht eine &#039;&#039;Race Condition&#039;&#039;: Das Ergebnis hängt vom zufälligen zeitlichen Ablauf der Threads ab.&lt;br /&gt;
&lt;br /&gt;
Das übliche Muster ist:&lt;br /&gt;
&lt;br /&gt;
# Der Game Thread besitzt Gameplay-Daten.&lt;br /&gt;
# Benötigte Werte werden in eine renderseitige Struktur oder einen Scene Proxy kopiert.&lt;br /&gt;
# Ein Render Command übergibt diese Kopie an den Render Thread.&lt;br /&gt;
# Ressourcen werden erst freigegeben, wenn Fence oder vorgesehener Cleanup-Mechanismus ihre Nutzung abgeschlossen meldet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;FlushRenderingCommands&amp;lt;/code&amp;gt; blockiert den Game Thread bis der Renderer aufgeholt hat. Das kann für seltene Editor-/Offline-Operationen sinnvoll sein, sollte aber nicht zum normalen Gameplay-Pfad werden.&lt;br /&gt;
&lt;br /&gt;
== Prüfen und eingrenzen ==&lt;br /&gt;
&lt;br /&gt;
Unreal Insights zeigt Game-, Render- und RHI-Thread getrennt in Timing Insights. Verglichen werden sollten identische, reproduzierbare Szenen und mehrere Frames.&lt;br /&gt;
&lt;br /&gt;
Nützliche Diagnosevariablen aus der Epic-Dokumentation:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHIThread.Enable 0&amp;lt;/code&amp;gt; deaktiviert den separaten RHI Thread.&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHICmdUseDeferredContexts 0&amp;lt;/code&amp;gt; deaktiviert die Backend-Parallelisierung.&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHICmdUseParallelAlgorithms 0&amp;lt;/code&amp;gt; deaktiviert die Frontend-Parallelisierung.&lt;br /&gt;
* &amp;lt;code&amp;gt;r.RHICmdBypass 1&amp;lt;/code&amp;gt; umgeht Command Lists; dies wird nur berücksichtigt, wenn der RHI Thread deaktiviert ist.&lt;br /&gt;
&lt;br /&gt;
Diese Schalter sind Diagnosewerkzeuge, keine pauschalen Performance-Tipps. Wirkung und Standard können von Plattform und RHI abhängen. Für belastbare Aussagen immer in der Zielkonfiguration messen.&lt;br /&gt;
&lt;br /&gt;
== Typische Befunde ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Render Thread voll ausgelastet, RHI Thread wartet:&#039;&#039;&#039; Engpass eher beim Aufbau der Renderarbeit.&lt;br /&gt;
* &#039;&#039;&#039;RHI Thread voll ausgelastet:&#039;&#039;&#039; Übersetzung oder Treiberarbeit begrenzt die CPU-Seite.&lt;br /&gt;
* &#039;&#039;&#039;Viele Flushes/Fences:&#039;&#039;&#039; Zu enge Synchronisation oder ungeeignete Ressourcenpfade untersuchen.&lt;br /&gt;
* &#039;&#039;&#039;GPU voll ausgelastet, CPU-Threads mit Luft:&#039;&#039;&#039; Parallelisierung der CPU behebt den eigentlichen GPU-Engpass nicht.&lt;br /&gt;
&lt;br /&gt;
== Bezug: UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Für Jans Projekt müssen zwei Achsen getrennt betrachtet werden:&lt;br /&gt;
&lt;br /&gt;
* Parallel Rendering und RHI Thread verteilen hauptsächlich &#039;&#039;&#039;CPU-Arbeit&#039;&#039;&#039;.&lt;br /&gt;
* Heterogeneous Multi-GPU verteilt &#039;&#039;&#039;GPU-Arbeit und Ressourcen&#039;&#039;&#039; auf mehrere Adapter.&lt;br /&gt;
&lt;br /&gt;
Eine zweite GPU hilft daher nicht automatisch bei einem RHI-Thread-Limit. Umgekehrt kann ein langsamer serieller CPU-Pfad mehrere GPUs unterfüttern. Die offizielle RHI-API beschreibt Fähigkeiten wie Multithreading und parallele RHI-Ausführung; &amp;lt;code&amp;gt;FRHIGPUMask&amp;lt;/code&amp;gt; repräsentiert aktive GPU-Indizes. Ob heterogene Adapter einen konkreten Pfad unterstützen, muss jedoch für D3D12/Vulkan, Treiber, Speicherfreigabe und Kopierpfad separat validiert werden.&lt;br /&gt;
&lt;br /&gt;
Praktischer Messplan: zuerst Single-GPU-Baseline in Unreal Insights, dann RHI Thread und Parallelalgorithmen einzeln vergleichen, anschließend erst Multi-GPU aktivieren und CPU-Zeiten, GPU-Zeiten sowie Transferkosten getrennt erfassen.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/parallel-rendering-overview-for-unreal-engine?application_version=5.8 Epic: Parallel Rendering Overview (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/threaded-rendering-in-unreal-engine?application_version=5.8 Epic: Threaded Rendering (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-insights-in-unreal-engine?application_version=5.8 Epic: Unreal Insights (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FRHIGlobals?application_version=5.8 Epic API: FRHIGlobals (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FRHIGPUMask?application_version=5.8 Epic API: FRHIGPUMask (UE 5.8)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
	<entry>
		<id>https://wiki.janvolkland.de/index.php?title=Render_Dependency_Graph_(RDG)&amp;diff=140</id>
		<title>Render Dependency Graph (RDG)</title>
		<link rel="alternate" type="text/html" href="https://wiki.janvolkland.de/index.php?title=Render_Dependency_Graph_(RDG)&amp;diff=140"/>
		<updated>2026-09-03T13:02:37Z</updated>

		<summary type="html">&lt;p&gt;Elaina: Die Seite wurde neu angelegt: „{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}  Der &amp;#039;&amp;#039;&amp;#039;Render Dependency Graph&amp;#039;&amp;#039;&amp;#039; (&amp;#039;&amp;#039;&amp;#039;RDG&amp;#039;&amp;#039;&amp;#039;, auch Render Graph) organisiert Renderarbeit als Graph aus &amp;#039;&amp;#039;Passes&amp;#039;&amp;#039; und Ressourcen. Ein Pass ist ein Arbeitsschritt auf CPU/GPU; Ressourcen sind vor allem Texturen und Buffer. Statt Übergänge, Lebensdauer und Synchronisation überall von Hand zu steuern, beschreibt der Code, welche Ressourcen ein…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Stand: Unreal Engine 5.8. Dieser Artikel fasst die aktuelle offizielle Epic-Dokumentation zusammen.}}&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;Render Dependency Graph&#039;&#039;&#039; (&#039;&#039;&#039;RDG&#039;&#039;&#039;, auch Render Graph) organisiert Renderarbeit als Graph aus &#039;&#039;Passes&#039;&#039; und Ressourcen. Ein Pass ist ein Arbeitsschritt auf CPU/GPU; Ressourcen sind vor allem Texturen und Buffer. Statt Übergänge, Lebensdauer und Synchronisation überall von Hand zu steuern, beschreibt der Code, welche Ressourcen ein Pass liest oder schreibt. RDG leitet daraus die Reihenfolge ab.&lt;br /&gt;
&lt;br /&gt;
== Warum RDG? ==&lt;br /&gt;
&lt;br /&gt;
RDG kann unbenutzte Passes entfernen, temporäre Ressourcen nur so lange wie nötig halten, Speicher zwischen nicht gleichzeitig lebenden Ressourcen wiederverwenden und Barrieren automatisch setzen. Es unterstützt außerdem Async Compute und paralleles Aufzeichnen von Command Lists. Das senkt Fehlergefahr und kann CPU-, GPU- und Speicherarbeit besser überlappen.&lt;br /&gt;
&lt;br /&gt;
== Das Grundmodell ==&lt;br /&gt;
&lt;br /&gt;
# Ein &amp;lt;code&amp;gt;FRDGBuilder&amp;lt;/code&amp;gt; sammelt Passes und Ressourcen für den Graphen.&lt;br /&gt;
# Texturen oder Buffer werden im Graphen erzeugt oder als externe Ressourcen registriert.&lt;br /&gt;
# Parameterstrukturen nennen die Eingaben und Ausgaben eines Passes. Daraus erkennt RDG echte Abhängigkeiten.&lt;br /&gt;
# &amp;lt;code&amp;gt;AddPass&amp;lt;/code&amp;gt; fügt die auszuführende Arbeit hinzu.&lt;br /&gt;
# &amp;lt;code&amp;gt;Execute()&amp;lt;/code&amp;gt; kompiliert den Graphen, entfernt tote Arbeit und führt die verbleibenden Passes aus.&lt;br /&gt;
&lt;br /&gt;
Ein RDG-Handle wie &amp;lt;code&amp;gt;FRDGTextureRef&amp;lt;/code&amp;gt; ist kein dauerhaft frei nutzbares RHI-Objekt. Seine Gültigkeit richtet sich nach dem Graphen. Soll ein Ergebnis außerhalb weiterleben, muss es über die dafür vorgesehenen Extract-/External-Mechanismen übergeben werden.&lt;br /&gt;
&lt;br /&gt;
== Kleines C++-Muster ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(&lt;br /&gt;
    Extent, PF_FloatRGBA, FClearValueBinding::Black,&lt;br /&gt;
    TexCreate_ShaderResource | TexCreate_UAV);&lt;br /&gt;
&lt;br /&gt;
FRDGTextureRef Output = GraphBuilder.CreateTexture(Desc, TEXT(&amp;quot;MyOutput&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
FMyShader::FParameters* Parameters =&lt;br /&gt;
    GraphBuilder.AllocParameters&amp;lt;FMyShader::FParameters&amp;gt;();&lt;br /&gt;
Parameters-&amp;gt;Output = GraphBuilder.CreateUAV(Output);&lt;br /&gt;
&lt;br /&gt;
FComputeShaderUtils::AddPass(&lt;br /&gt;
    GraphBuilder,&lt;br /&gt;
    RDG_EVENT_NAME(&amp;quot;MyComputePass&amp;quot;),&lt;br /&gt;
    ComputeShader,&lt;br /&gt;
    Parameters,&lt;br /&gt;
    GroupCount);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entscheidend ist nicht die genaue Shaderlogik, sondern dass &amp;lt;code&amp;gt;Parameters&amp;lt;/code&amp;gt; den Schreibzugriff auf &amp;lt;code&amp;gt;Output&amp;lt;/code&amp;gt; sichtbar macht. Versteckte Ressourcen-Zugriffe außerhalb der Parameterstruktur verhindern korrekte Planung und Validierung.&lt;br /&gt;
&lt;br /&gt;
== Praxisregeln ==&lt;br /&gt;
&lt;br /&gt;
* Ressourcen-Zugriffe vollständig in den Passparametern deklarieren.&lt;br /&gt;
* RDG-Ressourcen nicht über ihre vorgesehene Lebensdauer hinaus speichern.&lt;br /&gt;
* Pass-Lambdas nur mit Daten füttern, die bei ihrer späteren Ausführung noch gültig sind.&lt;br /&gt;
* Seiteneffekte vermeiden: Ein Pass ohne sichtbaren Beitrag kann entfernt werden. Notwendige Sonderfälle müssen bewusst mit passenden Pass-Flags modelliert werden.&lt;br /&gt;
* Ereignisnamen mit &amp;lt;code&amp;gt;RDG_EVENT_NAME&amp;lt;/code&amp;gt; vergeben; das macht Captures und RDG Insights lesbar.&lt;br /&gt;
* Erst messen, dann optimieren. RDG Insights visualisiert Graph, Abhängigkeiten und Ressourcenlebensdauer.&lt;br /&gt;
&lt;br /&gt;
== Bezug: UE5 Heterogeneous Multi-GPU ==&lt;br /&gt;
&lt;br /&gt;
Für Jans Projekt ist RDG die passende Ebene, um Abhängigkeiten zwischen GPU-Arbeit explizit zu machen. Das ist eine Voraussetzung für kontrollierte Überlappung und Synchronisation. RDG verteilt einen Pass jedoch &#039;&#039;&#039;nicht automatisch&#039;&#039;&#039; auf unterschiedliche oder heterogene GPUs.&lt;br /&gt;
&lt;br /&gt;
Die GPU-Auswahl liegt tiefer in RHI und Multi-GPU-Code, unter anderem über &amp;lt;code&amp;gt;FRHIGPUMask&amp;lt;/code&amp;gt;. Für einen Prototyp sollten deshalb drei Fragen getrennt geprüft werden:&lt;br /&gt;
&lt;br /&gt;
* Ist der RDG-Graph fachlich korrekt und frei von versteckten Abhängigkeiten?&lt;br /&gt;
* Welche Passes und Ressourcen dürfen auf welcher GPU liegen?&lt;br /&gt;
* Wo entstehen explizite Cross-GPU-Kopien und Synchronisationskosten?&lt;br /&gt;
&lt;br /&gt;
RDG Insights hilft bei der ersten Frage. Für GPU-Zuordnung, Transfers und Adapter-Fähigkeiten sind zusätzlich RHI-Quellcode, Plattform-RHI und GPU-Captures nötig.&lt;br /&gt;
&lt;br /&gt;
== Quellen ==&lt;br /&gt;
&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/render-dependency-graph-in-unreal-engine?application_version=5.8 Epic: Render Dependency Graph (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RenderCore/FRDGBuilder?application_version=5.8 Epic API: FRDGBuilder (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RenderCore/FComputeShaderUtils__AddPass?application_version=5.8 Epic API: FComputeShaderUtils::AddPass (UE 5.8)]&lt;br /&gt;
* [https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/RHI/FRHIGPUMask?application_version=5.8 Epic API: FRHIGPUMask (UE 5.8)]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Unreal Engine 5]]&lt;br /&gt;
[[Kategorie:Rendering]]&lt;br /&gt;
[[Kategorie:Multi-GPU]]&lt;/div&gt;</summary>
		<author><name>Elaina</name></author>
	</entry>
</feed>