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:
+346
-28
@@ -1,29 +1,347 @@
|
||||
export const GRAPH_ID = "demo_forward";
|
||||
export const CATALOG_VERSION = 1;
|
||||
|
||||
export const socketTypes = {
|
||||
surface: { title: "Surface", color: "#62b0ff", acceptsFrom: ["surface"] },
|
||||
depth: { title: "Depth", color: "#b58cff", acceptsFrom: ["depth"] },
|
||||
};
|
||||
export const theme = {
|
||||
background:"#151820",grid:"#292e3a",frame:"#30343a80",frameHeader:"#59616c",body:"#292e39",control:"#191d26",controlFill:"#4775b8",controlEditing:"#101218",textSelection:"#4775b8",outline:"#0b0d12",text:"#edf1f7",muted:"#969eaa",shadow:"#00000088",nodeSelected:"#ff9f43",nodeActive:"#ffffff",unknownHeader:"#555b64",unknownSocket:"#999999",linkMuted:"#d94b4b",knifeMuted:"#e85b5b",emphasis:"#ffffff",focus:"#f5a623",editOutline:"#666a70",resize:"#8b8e95",muteOverlay:"#14141459",boxSelectionFill:"#f5a6231f",checkerLight:"#aaaaaa",checkerDark:"#777777",widgetBorder:"#111216",rampBorder:"#111111",resourceBackground:"#202228"
|
||||
};
|
||||
export const styles = { resource:{header:"#3977a8"}, pass:{header:"#426b43"}, output:{header:"#a75d37"} };
|
||||
const socket = (title, direction, type) => ({ title,direction,type,maxIncomingLinks:direction === "input" ? 1 : 0,visible:true,value:null,showValue:false });
|
||||
const node = (title, style, sockets, parameters = {}) => ({ version:1,title,behavior:"standard",style,parameters,sockets,ui:[...Object.keys(parameters).map(parameter=>({kind:"parameter",parameter})),...Object.keys(sockets).map(socket=>({kind:"socket",socket}))],muteBypass:[],migrations:[] });
|
||||
export const nodeDefinitions = {
|
||||
surface_color: node("Surface Color", "resource", { surface:socket("Surface","output","surface") }),
|
||||
depth32: node("Depth 32", "resource", { depth:socket("Depth","output","depth") }),
|
||||
scene_forward: node("Scene Forward", "pass", { color:socket("Color","input","surface"),depth:socket("Depth","input","depth"),result:socket("Result","output","surface") }, {
|
||||
clearColor:{type:"color",default:{kind:"color",value:[0,0,0,1]},minimum:0,maximum:1},
|
||||
clearDepth:{type:"number",default:{kind:"number",value:1},minimum:0,maximum:1,step:0.01},
|
||||
}),
|
||||
present: node("Present", "output", { surface:socket("Surface","input","surface") }),
|
||||
};
|
||||
|
||||
export const descriptors = Object.freeze({
|
||||
surface_color:{version:1,sockets:{surface:["output","surface"]},parameters:[]},
|
||||
depth32:{version:1,sockets:{depth:["output","depth"]},parameters:[]},
|
||||
scene_forward:{version:1,sockets:{color:["input","surface"],depth:["input","depth"],result:["output","surface"]},parameters:["clearColor","clearDepth"]},
|
||||
present:{version:1,sockets:{surface:["input","surface"]},parameters:[]},
|
||||
export const GRAPH_ID = "authored_gpu_culling";
|
||||
export const CATALOG_VERSION = 2;
|
||||
const exact = (type) => ({ kind: "exact", types: [type] });
|
||||
const oneOf = (...types) => ({ kind: "one_of", types });
|
||||
const i = (type, required = true, authoringType) => ({
|
||||
accepted: typeof type === "string" ? exact(type) : type,
|
||||
required,
|
||||
...(authoringType ? { authoringType } : {}),
|
||||
});
|
||||
const o = (type) => ({ type });
|
||||
const texture = {
|
||||
residency: "transient",
|
||||
texture: {
|
||||
dimension: "d2",
|
||||
format: "rgba16_float",
|
||||
extent: {
|
||||
kind: "surface_relative",
|
||||
width: { numerator: 1, denominator: 1 },
|
||||
height: { numerator: 1, denominator: 1 },
|
||||
depthOrArrayLayers: 1,
|
||||
},
|
||||
mipLevelCount: 1,
|
||||
sampleCount: 1,
|
||||
viewFormats: [],
|
||||
},
|
||||
};
|
||||
export const semanticCatalog = Object.freeze({
|
||||
surface_target: {
|
||||
execution: "source",
|
||||
inputs: {},
|
||||
outputs: { surface: o("surface_target") },
|
||||
parameters: {},
|
||||
},
|
||||
texture_spec: {
|
||||
execution: "source",
|
||||
inputs: {},
|
||||
outputs: { spec: o("texture_spec") },
|
||||
parameters: structuredClone(texture),
|
||||
},
|
||||
scene_table: {
|
||||
execution: "source",
|
||||
inputs: {},
|
||||
outputs: { scene: o("scene_table") },
|
||||
parameters: {},
|
||||
},
|
||||
local_aabb_buffer: {
|
||||
execution: "source",
|
||||
inputs: { scene: i("scene_table") },
|
||||
outputs: { localAabbs: o("local_aabb_buffer") },
|
||||
parameters: {},
|
||||
},
|
||||
camera_frustum: {
|
||||
execution: "source",
|
||||
inputs: {},
|
||||
outputs: { frustum: o("camera_frustum") },
|
||||
parameters: {},
|
||||
},
|
||||
visibility_flags: {
|
||||
execution: "source",
|
||||
inputs: { scene: i("scene_table") },
|
||||
outputs: {
|
||||
flags: {
|
||||
...o("boolean_flag_buffer"),
|
||||
authoringType: "visibility_flag_buffer",
|
||||
},
|
||||
},
|
||||
parameters: {},
|
||||
},
|
||||
frustum_cull: {
|
||||
execution: "compute",
|
||||
inputs: {
|
||||
scene: i("scene_table"),
|
||||
localAabbs: i("local_aabb_buffer"),
|
||||
frustum: i("camera_frustum"),
|
||||
},
|
||||
outputs: {
|
||||
flags: {
|
||||
...o("boolean_flag_buffer"),
|
||||
authoringType: "frustum_flag_buffer",
|
||||
},
|
||||
},
|
||||
parameters: {},
|
||||
},
|
||||
mesh_query: {
|
||||
execution: "compute",
|
||||
inputs: {
|
||||
scene: i("scene_table"),
|
||||
isVisible: i("boolean_flag_buffer", false, "visibility_flag_buffer"),
|
||||
isFrustumCulled: i("boolean_flag_buffer", false, "frustum_flag_buffer"),
|
||||
},
|
||||
outputs: { draws: o("draw_stream") },
|
||||
parameters: {
|
||||
filters: [
|
||||
{ flag: "isVisible", predicate: "required_true" },
|
||||
{ flag: "isFrustumCulled", predicate: "required_false" },
|
||||
],
|
||||
},
|
||||
},
|
||||
depth_stencil_config: {
|
||||
execution: "source",
|
||||
inputs: {},
|
||||
outputs: { config: o("depth_stencil_config") },
|
||||
parameters: {
|
||||
depthCompare: "less_equal",
|
||||
depthWriteEnabled: true,
|
||||
clearDepth: 1,
|
||||
},
|
||||
},
|
||||
legacy_forward: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
scene: i("scene_table"),
|
||||
draws: i("draw_stream"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
depthTarget: i(oneOf("texture_spec", "texture")),
|
||||
depthStencil: i("depth_stencil_config"),
|
||||
},
|
||||
outputs: { color: o("texture"), depth: o("texture") },
|
||||
parameters: { clearColor: [0.015, 0.02, 0.03, 1] },
|
||||
},
|
||||
fullscreen_copy: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
source: i("texture"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
},
|
||||
outputs: { color: o("texture") },
|
||||
parameters: {},
|
||||
},
|
||||
tone_map: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
source: i("texture"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
},
|
||||
outputs: { color: o("texture") },
|
||||
parameters: { exposure: 1 },
|
||||
},
|
||||
bloom_extract: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
source: i("texture"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
},
|
||||
outputs: { color: o("texture") },
|
||||
parameters: { threshold: 1, knee: 0.5 },
|
||||
},
|
||||
bloom_blur: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
source: i("texture"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
},
|
||||
outputs: { color: o("texture") },
|
||||
parameters: { direction: [1, 0], radius: 1 },
|
||||
},
|
||||
bloom_composite: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
source: i("texture"),
|
||||
bloom: i("texture"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
},
|
||||
outputs: { color: o("texture") },
|
||||
parameters: { intensity: 1 },
|
||||
},
|
||||
luminance_edge: {
|
||||
execution: "render",
|
||||
inputs: {
|
||||
source: i("texture"),
|
||||
colorTarget: i(oneOf("surface_target", "texture_spec", "texture")),
|
||||
},
|
||||
outputs: { color: o("texture") },
|
||||
parameters: { strength: 2 },
|
||||
},
|
||||
present: {
|
||||
execution: "present",
|
||||
inputs: { surface: i("texture") },
|
||||
outputs: {},
|
||||
parameters: {},
|
||||
},
|
||||
});
|
||||
const socketColors = [
|
||||
"#d17c7c",
|
||||
"#d19e7c",
|
||||
"#d1c77c",
|
||||
"#9ed17c",
|
||||
"#7cd1a5",
|
||||
"#7ccbd1",
|
||||
"#7c98d1",
|
||||
"#a27cd1",
|
||||
"#d17cb8",
|
||||
];
|
||||
export const socketTypes = Object.fromEntries(
|
||||
[
|
||||
"surface_target",
|
||||
"texture_spec",
|
||||
"texture",
|
||||
"scene_table",
|
||||
"local_aabb_buffer",
|
||||
"camera_frustum",
|
||||
"boolean_flag_buffer",
|
||||
"draw_stream",
|
||||
"depth_stencil_config",
|
||||
"visibility_flag_buffer",
|
||||
"frustum_flag_buffer",
|
||||
].map((type, index) => [
|
||||
type,
|
||||
{
|
||||
title: type.replaceAll("_", " "),
|
||||
color: socketColors[index % socketColors.length],
|
||||
acceptsFrom: [type],
|
||||
},
|
||||
]),
|
||||
);
|
||||
socketTypes.surface_target.acceptsFrom = [
|
||||
"surface_target",
|
||||
"texture_spec",
|
||||
"texture",
|
||||
];
|
||||
socketTypes.texture_spec.acceptsFrom = ["texture_spec", "texture"];
|
||||
socketTypes.boolean_flag_buffer.acceptsFrom = [
|
||||
"boolean_flag_buffer",
|
||||
"visibility_flag_buffer",
|
||||
"frustum_flag_buffer",
|
||||
];
|
||||
export const theme = {
|
||||
background: "#151820",
|
||||
grid: "#292e3a",
|
||||
frame: "#30343a80",
|
||||
frameHeader: "#59616c",
|
||||
body: "#292e39",
|
||||
control: "#24272b",
|
||||
controlFill: "#4775b8",
|
||||
controlEditing: "#181a1d",
|
||||
textSelection: "#4775b8",
|
||||
outline: "#0b0d12",
|
||||
text: "#edf1f7",
|
||||
muted: "#969eaa",
|
||||
shadow: "#00000088",
|
||||
nodeSelected: "#ff9f43",
|
||||
nodeActive: "#ffffff",
|
||||
unknownHeader: "#555b64",
|
||||
unknownSocket: "#999999",
|
||||
linkMuted: "#d94b4b",
|
||||
knifeMuted: "#e85b5b",
|
||||
emphasis: "#ffffff",
|
||||
focus: "#f5a623",
|
||||
editOutline: "#666a70",
|
||||
resize: "#8b8e95",
|
||||
muteOverlay: "#14141459",
|
||||
boxSelectionFill: "#f5a6231f",
|
||||
checkerLight: "#aaaaaa",
|
||||
checkerDark: "#777777",
|
||||
widgetBorder: "#111216",
|
||||
rampBorder: "#111111",
|
||||
resourceBackground: "#202228",
|
||||
};
|
||||
export const styles = {
|
||||
source: { header: "#3977a8" },
|
||||
compute: { header: "#725a9b" },
|
||||
render: { header: "#426b43" },
|
||||
present: { header: "#a75d37" },
|
||||
};
|
||||
const socket = (title, direction, type) => ({
|
||||
title,
|
||||
direction,
|
||||
type,
|
||||
maxIncomingLinks: direction === "input" ? 1 : 0,
|
||||
visible: true,
|
||||
value: null,
|
||||
showValue: false,
|
||||
});
|
||||
const parameterSchema = (value) =>
|
||||
typeof value === "number"
|
||||
? { type: "number", default: { kind: "number", value } }
|
||||
: typeof value === "string"
|
||||
? { type: "string", default: { kind: "string", value } }
|
||||
: typeof value === "boolean"
|
||||
? { type: "boolean", default: { kind: "boolean", value } }
|
||||
: { type: "json", default: { kind: "json", value } };
|
||||
export const nodeDefinitions = Object.fromEntries(
|
||||
Object.entries(semanticCatalog).map(([key, c]) => {
|
||||
const sockets = {
|
||||
...Object.fromEntries(
|
||||
Object.entries(c.inputs).map(([n, v]) => [
|
||||
n,
|
||||
socket(n, "input", v.authoringType ?? v.accepted.types[0]),
|
||||
]),
|
||||
),
|
||||
...Object.fromEntries(
|
||||
Object.entries(c.outputs).map(([n, v]) => [
|
||||
n,
|
||||
socket(n, "output", v.authoringType ?? v.type),
|
||||
]),
|
||||
),
|
||||
},
|
||||
parameters = Object.fromEntries(
|
||||
Object.entries(c.parameters).map(([name, value]) => [
|
||||
name,
|
||||
parameterSchema(value),
|
||||
]),
|
||||
);
|
||||
return [
|
||||
key,
|
||||
{
|
||||
version: 1,
|
||||
title: key.replaceAll("_", " "),
|
||||
behavior: "standard",
|
||||
style: c.execution,
|
||||
parameters,
|
||||
sockets,
|
||||
ui: [
|
||||
...Object.keys(parameters).map((parameter) => ({
|
||||
kind: "parameter",
|
||||
parameter,
|
||||
})),
|
||||
...Object.keys(sockets).map((socket) => ({ kind: "socket", socket })),
|
||||
],
|
||||
muteBypass: [],
|
||||
migrations: [],
|
||||
},
|
||||
];
|
||||
}),
|
||||
);
|
||||
export const fxNodeComposition = Object.freeze({
|
||||
schemaVersion: 2,
|
||||
id: "yawn.render-graph",
|
||||
version: CATALOG_VERSION,
|
||||
compatibility: { wildcardInputTypes: [] },
|
||||
socketTypes,
|
||||
nodeStyles: styles,
|
||||
resources: {},
|
||||
theme,
|
||||
nodes: nodeDefinitions,
|
||||
});
|
||||
export const descriptors = Object.fromEntries(
|
||||
Object.entries(semanticCatalog).map(([key, c]) => [
|
||||
key,
|
||||
{
|
||||
version: 1,
|
||||
inputs: c.inputs,
|
||||
outputs: c.outputs,
|
||||
parameters: c.parameters,
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user