feat: add gpu driven render graph pipeline

Amp-Thread-ID: https://ampcode.com/threads/T-019f9d91-77c1-7206-a60f-ed6554ce92ab

Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-07-27 20:26:31 +00:00
co-authored by heaust
parent d4e8634f67
commit 05311e564c
51 changed files with 13262 additions and 743 deletions
+199 -4
View File
@@ -1,5 +1,200 @@
<!doctype html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Yawn Render Graph Demo</title>
<style>
*{box-sizing:border-box}html,body{height:100%;margin:0;overflow:hidden;background:#0b0e14;color:#eef2f8;font:14px Inter,system-ui,sans-serif}main{display:grid;grid-template-columns:minmax(0,3fr) minmax(380px,2fr);height:100%}.viewport,.editor{min-width:0;min-height:0;position:relative}canvas{display:block;width:100%;height:100%}#canvas0{background:#090d16}.toolbar{position:absolute;z-index:2;inset:18px 18px auto;display:flex;align-items:end;gap:14px;padding:13px 16px;border:1px solid #ffffff18;border-radius:10px;background:#111722e8;box-shadow:0 12px 30px #0008}.brand{margin-right:auto}.brand strong{display:block;font-size:17px;letter-spacing:.08em}.brand small{color:#8d9bb1}.field{display:grid;gap:5px;color:#9da9ba;font-size:11px;text-transform:uppercase;letter-spacing:.08em}select,button{font:inherit;color:#eef;background:#202938;border:1px solid #3a4659;border-radius:6px;padding:7px 10px}button{background:#ba5c2e;border-color:#d77949;font-weight:650;cursor:pointer}button:disabled,select:disabled{opacity:.48;cursor:wait}#demo-status{position:absolute;z-index:2;left:18px;bottom:18px;padding:9px 12px;border-radius:7px;background:#0b1019dc;color:#bac6d8;box-shadow:0 5px 20px #0008}.editor{display:grid;grid-template-rows:58px minmax(0,1fr);border-left:1px solid #2d3542;background:#151820}.editor-bar{display:flex;align-items:center;gap:12px;padding:0 14px;border-bottom:1px solid #303745}.editor-bar strong{font-size:15px}.editor-bar span{color:#9ba7b9}@media(max-width:820px){main{grid-template-columns:1fr;grid-template-rows:52% 48%}.editor{border-left:0;border-top:1px solid #2d3542}.toolbar{flex-wrap:wrap}.brand{width:100%}}
</style></head><body><main><section class="viewport" aria-label="Rendered scene"><div class="toolbar"><div class="brand"><strong>YAWN</strong><small>Render Graph Studio</small></div><label class="field" for="loadout-select">Scene loadout<select id="loadout-select"><option value="cubes">Cubes</option><option value="spheres">UV spheres</option><option value="manor">The Manor</option><option value="sponza">Sponza</option></select></label><label class="field" for="graph-select">Graph preset<select id="graph-select"><option value="authored">Authored</option><option value="midnight">Midnight</option><option value="ember">Ember</option></select></label></div><canvas id="canvas0"></canvas><output id="demo-status" aria-live="polite">Starting Phase 8…</output></section><section class="editor" aria-label="Render graph editor"><div class="editor-bar"><strong>Authored Graph</strong><button id="apply-graph" disabled>Apply</button><span id="graph-status">Loading editor…</span></div><canvas id="graph-editor"></canvas></section></main><script type="module" src="./index.js"></script></body></html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Yawn Render Graph Demo</title>
<style>
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
overflow: hidden;
background: #0b0e14;
color: #eef2f8;
font:
14px Inter,
system-ui,
sans-serif;
}
main {
display: grid;
grid-template-columns: minmax(0, 3fr) minmax(380px, 2fr);
height: 100%;
}
.viewport,
.editor {
min-width: 0;
min-height: 0;
position: relative;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
#canvas0 {
background: #090d16;
}
.toolbar {
position: absolute;
z-index: 2;
inset: 18px 18px auto;
display: flex;
align-items: end;
gap: 14px;
padding: 13px 16px;
border: 1px solid #ffffff18;
border-radius: 10px;
background: #111722e8;
box-shadow: 0 12px 30px #0008;
}
.brand {
margin-right: auto;
}
.brand strong {
display: block;
font-size: 17px;
letter-spacing: 0.08em;
}
.brand small {
color: #8d9bb1;
}
.field {
display: grid;
gap: 5px;
color: #9da9ba;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.08em;
}
#profile-menu { min-width: 210px; color: #9da9ba; }
#profile-menu summary { cursor: pointer; color: #eef2f8; }
#profile-menu table { width: 100%; font-size: 11px; }
#profile-menu th { text-align: left; font-weight: 500; }
#profile-menu td { text-align: right; font-variant-numeric: tabular-nums; }
select,
button {
font: inherit;
color: #eef;
background: #202938;
border: 1px solid #3a4659;
border-radius: 6px;
padding: 7px 10px;
}
button {
background: #ba5c2e;
border-color: #d77949;
font-weight: 650;
cursor: pointer;
}
button:disabled,
select:disabled {
opacity: 0.48;
cursor: wait;
}
#demo-status {
position: absolute;
z-index: 2;
left: 18px;
bottom: 18px;
padding: 9px 12px;
border-radius: 7px;
background: #0b1019dc;
color: #bac6d8;
box-shadow: 0 5px 20px #0008;
}
.editor {
display: grid;
grid-template-rows: 58px minmax(0, 1fr);
border-left: 1px solid #2d3542;
background: #151820;
}
.editor-bar {
display: flex;
align-items: center;
gap: 12px;
padding: 0 14px;
border-bottom: 1px solid #303745;
}
.editor-bar strong {
font-size: 15px;
}
.editor-bar span {
color: #9ba7b9;
}
.fxnode-add-menu {
position: fixed; z-index: 20; width: min(280px, calc(100vw - 16px)); max-height: min(440px, calc(100vh - 16px));
padding: 8px; overflow: hidden; border: 1px solid #495568; border-radius: 8px; background: #171d27; box-shadow: 0 14px 40px #000b;
}
.fxnode-add-menu[hidden] { display: none; }
.fxnode-add-menu input { width: 100%; padding: 8px; color: #eef2f8; background: #0f141c; border: 1px solid #3a4659; border-radius: 5px; }
.fxnode-add-menu__list { max-height: 360px; margin-top: 6px; overflow: auto; }
.fxnode-add-menu__group { padding: 8px 7px 3px; color: #8491a5; font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.fxnode-add-menu .fxnode-add-menu__option { display: block; width: 100%; padding: 7px 9px; border: 0; text-align: left; text-transform: capitalize; background: transparent; }
.fxnode-add-menu__option[aria-selected="true"] { background: #394a64; outline: 1px solid #6883aa; }
@media (max-width: 820px) {
main {
grid-template-columns: 1fr;
grid-template-rows: 52% 48%;
}
.editor {
border-left: 0;
border-top: 1px solid #2d3542;
}
.toolbar {
flex-wrap: wrap;
}
.brand {
width: 100%;
}
}
</style>
</head>
<body>
<main>
<section class="viewport" aria-label="Rendered scene">
<div class="toolbar">
<div class="brand">
<strong>YAWN</strong><small>Render Graph Studio</small>
</div>
<label class="field" for="loadout-select"
>Scene loadout<select id="loadout-select">
<option value="cubes">Cubes</option>
<option value="spheres">UV spheres</option>
<option value="materials">Phase 6 PBR gallery</option>
<option value="manor">The Manor</option>
<option value="sponza">Sponza</option>
</select></label
><label class="field" for="graph-select"
>Graph preset<select id="graph-select">
<option value="authored">Authored</option>
<option value="midnight">Midnight</option>
<option value="ember">Ember</option>
<option value="hdr">HDR Fullscreen</option>
<option value="culling">GPU frustum culling</option>
<option value="tone">Tone map</option>
<option value="edges">Edges</option>
<option value="bloom">Bloom</option>
<option value="combined">Combined</option>
</select></label
>
</div>
<canvas id="canvas0"></canvas
><output id="demo-status" aria-live="polite">Starting Phase 8…</output>
</section>
<section class="editor" aria-label="Render graph editor">
<div class="editor-bar">
<strong>Authored Graph</strong
><button id="apply-graph" disabled>Apply</button
><span id="graph-status">Loading editor…</span>
</div>
<canvas id="graph-editor"></canvas>
</section>
</main>
<script type="module" src="./index.js"></script>
</body>
</html>