update: add agent.md + skills
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# Skill — GPU Memory Management
|
||||
|
||||
## Principle
|
||||
|
||||
Dispose only what you own. Never blindly traverse and dispose shared or cached assets.
|
||||
|
||||
## What to dispose
|
||||
|
||||
| Resource | When to dispose |
|
||||
| ---------------------------------- | ------------------------------------ |
|
||||
| Custom `THREE.ShaderMaterial` | When the component using it unmounts |
|
||||
| `THREE.WebGLRenderTarget` | When the pass or effect is destroyed |
|
||||
| Manually created `THREE.Geometry` | When no longer needed |
|
||||
| Manually created `THREE.Texture` | When no longer needed |
|
||||
| Cloned scenes with owned materials | When the clone is removed |
|
||||
|
||||
## What NOT to dispose
|
||||
|
||||
| Resource | Why |
|
||||
| -------------------------------- | ----------------------------------------------- |
|
||||
| GLTF scenes loaded via `useGLTF` | drei caches them — disposing breaks other users |
|
||||
| Textures loaded via `useTexture` | drei caches them — same reason |
|
||||
| Shared materials from a GLTF | Other instances may reference them |
|
||||
|
||||
## Dispose utility
|
||||
|
||||
```ts
|
||||
// src/utils/Dispose.ts
|
||||
import * as THREE from "three";
|
||||
|
||||
export class Dispose {
|
||||
static material(material: THREE.Material): void {
|
||||
for (const value of Object.values(material)) {
|
||||
if (value instanceof THREE.Texture) {
|
||||
value.dispose();
|
||||
}
|
||||
}
|
||||
material.dispose();
|
||||
}
|
||||
|
||||
static mesh(mesh: THREE.Mesh): void {
|
||||
mesh.geometry?.dispose();
|
||||
const materials = Array.isArray(mesh.material)
|
||||
? mesh.material
|
||||
: [mesh.material];
|
||||
for (const mat of materials) {
|
||||
if (mat) this.material(mat);
|
||||
}
|
||||
}
|
||||
|
||||
static renderTarget(rt: THREE.WebGLRenderTarget): void {
|
||||
rt.texture.dispose();
|
||||
rt.dispose();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage in React components
|
||||
|
||||
```tsx
|
||||
useEffect(() => {
|
||||
const material = new THREE.ShaderMaterial({ vertexShader, fragmentShader });
|
||||
meshRef.current.material = material;
|
||||
|
||||
return () => {
|
||||
Dispose.material(material);
|
||||
};
|
||||
}, []);
|
||||
```
|
||||
|
||||
## Usage in managers
|
||||
|
||||
```ts
|
||||
destroy(): void {
|
||||
if (this.renderTarget) {
|
||||
Dispose.renderTarget(this.renderTarget)
|
||||
this.renderTarget = null
|
||||
}
|
||||
SomeManager._instance = null
|
||||
}
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
- Every `useEffect` that creates a GPU resource must return a cleanup that disposes it
|
||||
- Every manager `destroy()` must dispose its owned GPU resources
|
||||
- Never call `.dispose()` on assets returned by drei loaders (`useGLTF`, `useTexture`)
|
||||
- When in doubt, don't dispose — a small leak is better than a crash from disposing shared resources
|
||||
Reference in New Issue
Block a user