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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user