Optimize render graph and add GPU profiling

Amp-Thread-ID: https://ampcode.com/threads/T-01a01380-b478-77d0-84a0-102880a5c5ae
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-08-20 11:48:06 +00:00
co-authored by heaust
parent ded70a3cb4
commit 000bfd63bf
22 changed files with 1622 additions and 203 deletions
+31 -2
View File
@@ -1,6 +1,7 @@
import { Mesh } from "../Mesh";
import type { Scene } from "../Scene";
import { PBRMaterial } from "../materials/PBRMaterial";
import { Texture } from "../materials/Texture";
let worker: Worker | undefined;
let nextRequest = 1;
@@ -42,9 +43,31 @@ export async function importGltf(scene: Scene, url: string | URL) {
nodes: result.primitives.length,
materials: result.materials.length,
});
return scene.batchGraphUpdates(async () => {
let textures: Texture[] = [];
const imported = await scene.batchGraphUpdates(async () => {
const srgb = new Set<number>();
for (const material of result.materials) {
if (material.baseColorTexture >= 0) srgb.add(material.baseColorTexture);
if (material.emissiveTexture >= 0) srgb.add(material.emissiveTexture);
}
textures = result.textures.map(
({ image }: { image: ImageBitmap }, index: number) =>
new Texture(scene, {
source: image,
format: srgb.has(index) ? "rgba8unorm-srgb" : "rgba8unorm",
}),
);
await Promise.all(textures.map((texture: Texture) => texture.ready));
const materials = result.materials.map(
(options: any) => new PBRMaterial(scene, options),
(options: any) =>
new PBRMaterial(scene, {
...options,
baseColorTexture: textures[options.baseColorTexture],
metallicRoughnessTexture:
textures[options.metallicRoughnessTexture],
normalTexture: textures[options.normalTexture],
emissiveTexture: textures[options.emissiveTexture],
}),
);
await Promise.all(materials.map((material: PBRMaterial) => material.ready));
const meshes: Mesh[] = result.primitives.map(
@@ -67,4 +90,10 @@ export async function importGltf(scene: Scene, url: string | URL) {
await Promise.all(meshes.map((mesh) => mesh.ready));
return meshes;
});
await Promise.all(
result.textures.map((_: unknown, index: number) =>
scene.core.deleteTexture(textures[index].resource),
),
);
return imported;
}
+26 -1
View File
@@ -144,6 +144,26 @@ async function load(url: string) {
return new Uint8Array(await result.arrayBuffer());
}),
);
const imageBlobs = await Promise.all(
(document.images ?? []).map(async (image: any) => {
if (image.bufferView !== undefined) {
const view = document.bufferViews[image.bufferView];
const bytes = buffers[view.buffer];
const start = view.byteOffset ?? 0;
return new Blob([bytes.slice(start, start + view.byteLength)], {
type: image.mimeType,
});
}
const result = await fetch(new URL(image.uri, url));
if (!result.ok) throw new Error(`HTTP_${result.status}`);
return result.blob();
}),
);
const textures = await Promise.all(
(document.textures ?? []).map(async (texture: any) => ({
image: await createImageBitmap(imageBlobs[texture.source]),
})),
);
const accessor = (id: number, integer = false) => {
const source = document.accessors[id];
@@ -199,6 +219,10 @@ async function load(url: string) {
roughness: pbr.roughnessFactor ?? 0.7,
emissive: material.emissiveFactor ?? [0, 0, 0],
alphaCutoff: material.alphaCutoff ?? 0.5,
baseColorTexture: pbr.baseColorTexture?.index ?? -1,
metallicRoughnessTexture: pbr.metallicRoughnessTexture?.index ?? -1,
normalTexture: material.normalTexture?.index ?? -1,
emissiveTexture: material.emissiveTexture?.index ?? -1,
};
});
const primitives: any[] = [];
@@ -264,7 +288,7 @@ async function load(url: string) {
if (!nodes.length)
for (let id = 0; id < (document.meshes ?? []).length; id++)
emitMesh(id, {});
return { materials, primitives };
return { materials, primitives, textures };
}
addEventListener("message", async ({ data }) => {
@@ -275,6 +299,7 @@ addEventListener("message", async ({ data }) => {
.map((name) => primitive[name]?.buffer)
.filter(Boolean),
);
transfers.push(...result.textures.map((texture: any) => texture.image));
(postMessage as any)({ request: data.request, result }, transfers);
} catch (error) {
postMessage({