@vib3code/sdk 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +118 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
- package/DOCS/CI_TESTING.md +38 -0
- package/DOCS/CLI_ONBOARDING.md +75 -0
- package/DOCS/CONTROL_REFERENCE.md +64 -0
- package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
- package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
- package/DOCS/ENV_SETUP.md +189 -0
- package/DOCS/EXPORT_FORMATS.md +417 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
- package/DOCS/LICENSING_TIERS.md +275 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
- package/DOCS/OBS_SETUP_GUIDE.md +98 -0
- package/DOCS/PROJECT_SETUP.md +66 -0
- package/DOCS/RENDERER_LIFECYCLE.md +40 -0
- package/DOCS/REPO_MANIFEST.md +121 -0
- package/DOCS/SESSION_014_PLAN.md +195 -0
- package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
- package/DOCS/SYSTEM_INVENTORY.md +520 -0
- package/DOCS/TELEMETRY_EXPORTS.md +34 -0
- package/DOCS/WEBGPU_STATUS.md +38 -0
- package/DOCS/XR_BENCHMARKS.md +608 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/docs/.nojekyll +0 -0
- package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/02-hyperspatial_ego_death.html +346 -0
- package/docs/03-post_cartesian_sublime.html +346 -0
- package/docs/04-crystalline_void_meditation.html +346 -0
- package/docs/05-quantum_decoherence_ballet.html +346 -0
- package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/07-hyperspatial_ego_death.html +346 -0
- package/docs/08-post_cartesian_sublime.html +346 -0
- package/docs/09-crystalline_void_meditation.html +346 -0
- package/docs/10-quantum_decoherence_ballet.html +346 -0
- package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/12-hyperspatial_ego_death.html +346 -0
- package/docs/13-post_cartesian_sublime.html +346 -0
- package/docs/index.html +794 -0
- package/docs/test-hub.html +441 -0
- package/docs/url-state.js +102 -0
- package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
- package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
- package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
- package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
- package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
- package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
- package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
- package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
- package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
- package/docs/vib3-exports/index.html +238 -0
- package/docs/webgpu-live.html +702 -0
- package/package.json +367 -0
- package/src/advanced/AIPresetGenerator.js +777 -0
- package/src/advanced/MIDIController.js +703 -0
- package/src/advanced/OffscreenWorker.js +1051 -0
- package/src/advanced/WebGPUCompute.js +1051 -0
- package/src/advanced/WebXRRenderer.js +680 -0
- package/src/agent/cli/AgentCLI.js +615 -0
- package/src/agent/cli/index.js +14 -0
- package/src/agent/index.js +73 -0
- package/src/agent/mcp/MCPServer.js +950 -0
- package/src/agent/mcp/index.js +9 -0
- package/src/agent/mcp/tools.js +548 -0
- package/src/agent/telemetry/EventStream.js +669 -0
- package/src/agent/telemetry/Instrumentation.js +618 -0
- package/src/agent/telemetry/TelemetryExporters.js +427 -0
- package/src/agent/telemetry/TelemetryService.js +464 -0
- package/src/agent/telemetry/index.js +52 -0
- package/src/benchmarks/BenchmarkRunner.js +381 -0
- package/src/benchmarks/MetricsCollector.js +299 -0
- package/src/benchmarks/index.js +9 -0
- package/src/benchmarks/scenes.js +259 -0
- package/src/cli/index.js +675 -0
- package/src/config/ApiConfig.js +88 -0
- package/src/core/CanvasManager.js +217 -0
- package/src/core/ErrorReporter.js +117 -0
- package/src/core/ParameterMapper.js +333 -0
- package/src/core/Parameters.js +396 -0
- package/src/core/RendererContracts.js +200 -0
- package/src/core/UnifiedResourceManager.js +370 -0
- package/src/core/VIB3Engine.js +636 -0
- package/src/core/renderers/FacetedRendererAdapter.js +32 -0
- package/src/core/renderers/HolographicRendererAdapter.js +29 -0
- package/src/core/renderers/QuantumRendererAdapter.js +29 -0
- package/src/core/renderers/RendererLifecycleManager.js +63 -0
- package/src/creative/ColorPresetsSystem.js +980 -0
- package/src/creative/ParameterTimeline.js +1061 -0
- package/src/creative/PostProcessingPipeline.js +1113 -0
- package/src/creative/TransitionAnimator.js +683 -0
- package/src/export/CSSExporter.js +226 -0
- package/src/export/CardGeneratorBase.js +279 -0
- package/src/export/ExportManager.js +580 -0
- package/src/export/FacetedCardGenerator.js +279 -0
- package/src/export/HolographicCardGenerator.js +543 -0
- package/src/export/LottieExporter.js +552 -0
- package/src/export/QuantumCardGenerator.js +315 -0
- package/src/export/SVGExporter.js +519 -0
- package/src/export/ShaderExporter.js +903 -0
- package/src/export/TradingCardGenerator.js +3055 -0
- package/src/export/TradingCardManager.js +181 -0
- package/src/export/VIB3PackageExporter.js +559 -0
- package/src/export/index.js +14 -0
- package/src/export/systems/TradingCardSystemFaceted.js +494 -0
- package/src/export/systems/TradingCardSystemHolographic.js +452 -0
- package/src/export/systems/TradingCardSystemQuantum.js +411 -0
- package/src/faceted/FacetedSystem.js +963 -0
- package/src/features/CollectionManager.js +433 -0
- package/src/gallery/CollectionManager.js +240 -0
- package/src/gallery/GallerySystem.js +485 -0
- package/src/geometry/GeometryFactory.js +314 -0
- package/src/geometry/GeometryLibrary.js +72 -0
- package/src/geometry/buffers/BufferBuilder.js +338 -0
- package/src/geometry/buffers/index.js +18 -0
- package/src/geometry/generators/Crystal.js +420 -0
- package/src/geometry/generators/Fractal.js +298 -0
- package/src/geometry/generators/KleinBottle.js +197 -0
- package/src/geometry/generators/Sphere.js +192 -0
- package/src/geometry/generators/Tesseract.js +160 -0
- package/src/geometry/generators/Tetrahedron.js +225 -0
- package/src/geometry/generators/Torus.js +304 -0
- package/src/geometry/generators/Wave.js +341 -0
- package/src/geometry/index.js +142 -0
- package/src/geometry/warp/HypersphereCore.js +211 -0
- package/src/geometry/warp/HypertetraCore.js +386 -0
- package/src/geometry/warp/index.js +57 -0
- package/src/holograms/HolographicVisualizer.js +1073 -0
- package/src/holograms/RealHolographicSystem.js +966 -0
- package/src/holograms/variantRegistry.js +69 -0
- package/src/integrations/FigmaPlugin.js +854 -0
- package/src/integrations/OBSMode.js +754 -0
- package/src/integrations/ThreeJsPackage.js +660 -0
- package/src/integrations/TouchDesignerExport.js +552 -0
- package/src/integrations/frameworks/Vib3React.js +591 -0
- package/src/integrations/frameworks/Vib3Svelte.js +654 -0
- package/src/integrations/frameworks/Vib3Vue.js +628 -0
- package/src/llm/LLMParameterInterface.js +240 -0
- package/src/llm/LLMParameterUI.js +577 -0
- package/src/math/Mat4x4.js +708 -0
- package/src/math/Projection.js +341 -0
- package/src/math/Rotor4D.js +637 -0
- package/src/math/Vec4.js +476 -0
- package/src/math/constants.js +164 -0
- package/src/math/index.js +68 -0
- package/src/math/projections.js +54 -0
- package/src/math/rotations.js +196 -0
- package/src/quantum/QuantumEngine.js +906 -0
- package/src/quantum/QuantumVisualizer.js +1103 -0
- package/src/reactivity/ReactivityConfig.js +499 -0
- package/src/reactivity/ReactivityManager.js +586 -0
- package/src/reactivity/SpatialInputSystem.js +1783 -0
- package/src/reactivity/index.js +93 -0
- package/src/render/CommandBuffer.js +465 -0
- package/src/render/MultiCanvasBridge.js +340 -0
- package/src/render/RenderCommand.js +514 -0
- package/src/render/RenderResourceRegistry.js +523 -0
- package/src/render/RenderState.js +552 -0
- package/src/render/RenderTarget.js +512 -0
- package/src/render/ShaderLoader.js +253 -0
- package/src/render/ShaderProgram.js +599 -0
- package/src/render/UnifiedRenderBridge.js +496 -0
- package/src/render/backends/WebGLBackend.js +1108 -0
- package/src/render/backends/WebGPUBackend.js +1409 -0
- package/src/render/commands/CommandBufferExecutor.js +607 -0
- package/src/render/commands/RenderCommandBuffer.js +661 -0
- package/src/render/commands/index.js +17 -0
- package/src/render/index.js +367 -0
- package/src/scene/Disposable.js +498 -0
- package/src/scene/MemoryPool.js +618 -0
- package/src/scene/Node4D.js +697 -0
- package/src/scene/ResourceManager.js +599 -0
- package/src/scene/Scene4D.js +540 -0
- package/src/scene/index.js +98 -0
- package/src/schemas/error.schema.json +84 -0
- package/src/schemas/extension.schema.json +88 -0
- package/src/schemas/index.js +214 -0
- package/src/schemas/parameters.schema.json +142 -0
- package/src/schemas/tool-pack.schema.json +44 -0
- package/src/schemas/tool-response.schema.json +127 -0
- package/src/shaders/common/fullscreen.vert.glsl +5 -0
- package/src/shaders/common/fullscreen.vert.wgsl +17 -0
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +85 -0
- package/src/shaders/common/rotation4d.wgsl +86 -0
- package/src/shaders/common/uniforms.glsl +44 -0
- package/src/shaders/common/uniforms.wgsl +48 -0
- package/src/shaders/faceted/faceted.frag.glsl +129 -0
- package/src/shaders/faceted/faceted.frag.wgsl +164 -0
- package/src/shaders/holographic/holographic.frag.glsl +406 -0
- package/src/shaders/holographic/holographic.frag.wgsl +185 -0
- package/src/shaders/quantum/quantum.frag.glsl +513 -0
- package/src/shaders/quantum/quantum.frag.wgsl +361 -0
- package/src/testing/ParallelTestFramework.js +519 -0
- package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
- package/src/testing/exportFormats.test.js +8 -0
- package/src/testing/projections.test.js +14 -0
- package/src/testing/rotations.test.js +37 -0
- package/src/ui/InteractivityMenu.js +516 -0
- package/src/ui/StatusManager.js +96 -0
- package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
- package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
- package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
- package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
- package/src/variations/VariationManager.js +431 -0
- package/src/viewer/AudioReactivity.js +505 -0
- package/src/viewer/CardBending.js +481 -0
- package/src/viewer/GalleryUI.js +832 -0
- package/src/viewer/ReactivityManager.js +590 -0
- package/src/viewer/TradingCardExporter.js +600 -0
- package/src/viewer/ViewerPortal.js +374 -0
- package/src/viewer/index.js +12 -0
- package/src/wasm/WasmLoader.js +296 -0
- package/src/wasm/index.js +132 -0
- package/tools/agentic/mcpTools.js +88 -0
- package/tools/cli/agent-cli.js +92 -0
- package/tools/export/formats.js +24 -0
- package/tools/math/rotation-baseline.mjs +64 -0
- package/tools/shader-sync-verify.js +937 -0
- package/tools/telemetry/manifestPipeline.js +141 -0
- package/tools/telemetry/telemetryEvents.js +35 -0
- package/types/adaptive-sdk.d.ts +185 -0
- package/types/advanced/AIPresetGenerator.d.ts +81 -0
- package/types/advanced/MIDIController.d.ts +100 -0
- package/types/advanced/OffscreenWorker.d.ts +82 -0
- package/types/advanced/WebGPUCompute.d.ts +52 -0
- package/types/advanced/WebXRRenderer.d.ts +77 -0
- package/types/advanced/index.d.ts +46 -0
- package/types/core/ErrorReporter.d.ts +50 -0
- package/types/core/VIB3Engine.d.ts +204 -0
- package/types/creative/ColorPresetsSystem.d.ts +91 -0
- package/types/creative/ParameterTimeline.d.ts +74 -0
- package/types/creative/PostProcessingPipeline.d.ts +109 -0
- package/types/creative/TransitionAnimator.d.ts +71 -0
- package/types/creative/index.d.ts +35 -0
- package/types/integrations/FigmaPlugin.d.ts +46 -0
- package/types/integrations/OBSMode.d.ts +74 -0
- package/types/integrations/ThreeJsPackage.d.ts +62 -0
- package/types/integrations/TouchDesignerExport.d.ts +36 -0
- package/types/integrations/Vib3React.d.ts +74 -0
- package/types/integrations/Vib3Svelte.d.ts +63 -0
- package/types/integrations/Vib3Vue.d.ts +55 -0
- package/types/integrations/index.d.ts +52 -0
- package/types/reactivity/SpatialInputSystem.d.ts +173 -0
- package/types/reactivity/index.d.ts +394 -0
- package/types/render/CommandBuffer.d.ts +169 -0
- package/types/render/RenderCommand.d.ts +312 -0
- package/types/render/RenderState.d.ts +279 -0
- package/types/render/RenderTarget.d.ts +254 -0
- package/types/render/ShaderProgram.d.ts +277 -0
- package/types/render/UnifiedRenderBridge.d.ts +143 -0
- package/types/render/WebGLBackend.d.ts +168 -0
- package/types/render/WebGPUBackend.d.ts +186 -0
- package/types/render/index.d.ts +141 -0
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ResourceManager - Manages resources with reference counting
|
|
3
|
+
*
|
|
4
|
+
* Provides centralized resource management for:
|
|
5
|
+
* - Geometries
|
|
6
|
+
* - Materials
|
|
7
|
+
* - Textures
|
|
8
|
+
* - Buffers
|
|
9
|
+
* - Shaders
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Reference counting for shared resources
|
|
13
|
+
* - Automatic disposal when reference count reaches 0
|
|
14
|
+
* - Resource caching and deduplication
|
|
15
|
+
* - Memory usage tracking
|
|
16
|
+
* - Async loading support
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resource wrapper with reference counting
|
|
21
|
+
*/
|
|
22
|
+
class ManagedResource {
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} id - Resource identifier
|
|
25
|
+
* @param {string} type - Resource type
|
|
26
|
+
* @param {any} data - The actual resource data
|
|
27
|
+
* @param {number} size - Estimated size in bytes
|
|
28
|
+
*/
|
|
29
|
+
constructor(id, type, data, size = 0) {
|
|
30
|
+
/** @type {string} */
|
|
31
|
+
this.id = id;
|
|
32
|
+
|
|
33
|
+
/** @type {string} */
|
|
34
|
+
this.type = type;
|
|
35
|
+
|
|
36
|
+
/** @type {any} */
|
|
37
|
+
this.data = data;
|
|
38
|
+
|
|
39
|
+
/** @type {number} */
|
|
40
|
+
this.size = size;
|
|
41
|
+
|
|
42
|
+
/** @type {number} Reference count */
|
|
43
|
+
this.refCount = 0;
|
|
44
|
+
|
|
45
|
+
/** @type {number} Creation timestamp */
|
|
46
|
+
this.createdAt = Date.now();
|
|
47
|
+
|
|
48
|
+
/** @type {number} Last access timestamp */
|
|
49
|
+
this.lastAccessedAt = Date.now();
|
|
50
|
+
|
|
51
|
+
/** @type {boolean} Whether resource is disposed */
|
|
52
|
+
this.disposed = false;
|
|
53
|
+
|
|
54
|
+
/** @type {function|null} Custom dispose function */
|
|
55
|
+
this.disposeCallback = null;
|
|
56
|
+
|
|
57
|
+
/** @type {Map<string, any>} Resource metadata */
|
|
58
|
+
this.metadata = new Map();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Increment reference count
|
|
63
|
+
* @returns {this}
|
|
64
|
+
*/
|
|
65
|
+
addRef() {
|
|
66
|
+
if (this.disposed) {
|
|
67
|
+
throw new Error(`Cannot reference disposed resource: ${this.id}`);
|
|
68
|
+
}
|
|
69
|
+
this.refCount++;
|
|
70
|
+
this.lastAccessedAt = Date.now();
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Decrement reference count
|
|
76
|
+
* @returns {number} New reference count
|
|
77
|
+
*/
|
|
78
|
+
release() {
|
|
79
|
+
if (this.refCount > 0) {
|
|
80
|
+
this.refCount--;
|
|
81
|
+
}
|
|
82
|
+
return this.refCount;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Dispose the resource
|
|
87
|
+
*/
|
|
88
|
+
dispose() {
|
|
89
|
+
if (this.disposed) return;
|
|
90
|
+
|
|
91
|
+
if (this.disposeCallback) {
|
|
92
|
+
this.disposeCallback(this.data);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Clear data reference
|
|
96
|
+
this.data = null;
|
|
97
|
+
this.disposed = true;
|
|
98
|
+
this.metadata.clear();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* ResourceManager class
|
|
104
|
+
*/
|
|
105
|
+
export class ResourceManager {
|
|
106
|
+
constructor() {
|
|
107
|
+
/** @type {Map<string, ManagedResource>} All managed resources */
|
|
108
|
+
this._resources = new Map();
|
|
109
|
+
|
|
110
|
+
/** @type {Map<string, Map<string, ManagedResource>>} Resources by type */
|
|
111
|
+
this._byType = new Map();
|
|
112
|
+
|
|
113
|
+
/** @type {Map<string, string>} Hash to ID lookup for deduplication */
|
|
114
|
+
this._hashToId = new Map();
|
|
115
|
+
|
|
116
|
+
/** @type {number} Total memory usage estimate */
|
|
117
|
+
this._totalMemory = 0;
|
|
118
|
+
|
|
119
|
+
/** @type {number} Memory limit (0 = unlimited) */
|
|
120
|
+
this.memoryLimit = 0;
|
|
121
|
+
|
|
122
|
+
/** @type {boolean} Enable automatic garbage collection */
|
|
123
|
+
this.autoGC = true;
|
|
124
|
+
|
|
125
|
+
/** @type {number} GC threshold (0-1, fraction of memory limit) */
|
|
126
|
+
this.gcThreshold = 0.9;
|
|
127
|
+
|
|
128
|
+
/** @type {number} Resource idle time before eligible for GC (ms) */
|
|
129
|
+
this.gcIdleTime = 60000; // 1 minute
|
|
130
|
+
|
|
131
|
+
/** @type {function[]} Dispose listeners */
|
|
132
|
+
this._disposeListeners = [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ==================== Core Operations ====================
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Register a resource
|
|
139
|
+
* @param {string} id - Unique identifier
|
|
140
|
+
* @param {string} type - Resource type
|
|
141
|
+
* @param {any} data - Resource data
|
|
142
|
+
* @param {object} [options] - Options
|
|
143
|
+
* @returns {ManagedResource}
|
|
144
|
+
*/
|
|
145
|
+
register(id, type, data, options = {}) {
|
|
146
|
+
const {
|
|
147
|
+
size = 0,
|
|
148
|
+
hash = null,
|
|
149
|
+
disposeCallback = null,
|
|
150
|
+
metadata = {}
|
|
151
|
+
} = options;
|
|
152
|
+
|
|
153
|
+
// Check for existing resource with same hash
|
|
154
|
+
if (hash && this._hashToId.has(hash)) {
|
|
155
|
+
const existingId = this._hashToId.get(hash);
|
|
156
|
+
const existing = this._resources.get(existingId);
|
|
157
|
+
if (existing && !existing.disposed) {
|
|
158
|
+
return existing.addRef();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Check if ID already exists
|
|
163
|
+
if (this._resources.has(id)) {
|
|
164
|
+
const existing = this._resources.get(id);
|
|
165
|
+
if (!existing.disposed) {
|
|
166
|
+
return existing.addRef();
|
|
167
|
+
}
|
|
168
|
+
// Remove disposed resource
|
|
169
|
+
this._removeResource(existing);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Create new managed resource
|
|
173
|
+
const resource = new ManagedResource(id, type, data, size);
|
|
174
|
+
resource.disposeCallback = disposeCallback;
|
|
175
|
+
|
|
176
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
177
|
+
resource.metadata.set(key, value);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Store resource
|
|
181
|
+
this._resources.set(id, resource);
|
|
182
|
+
|
|
183
|
+
// Store by type
|
|
184
|
+
if (!this._byType.has(type)) {
|
|
185
|
+
this._byType.set(type, new Map());
|
|
186
|
+
}
|
|
187
|
+
this._byType.get(type).set(id, resource);
|
|
188
|
+
|
|
189
|
+
// Store hash mapping
|
|
190
|
+
if (hash) {
|
|
191
|
+
this._hashToId.set(hash, id);
|
|
192
|
+
resource.metadata.set('hash', hash);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Update memory tracking
|
|
196
|
+
this._totalMemory += size;
|
|
197
|
+
|
|
198
|
+
// Check memory limit
|
|
199
|
+
if (this.autoGC && this.memoryLimit > 0) {
|
|
200
|
+
this._checkMemoryLimit();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return resource.addRef();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get a resource by ID
|
|
208
|
+
* @param {string} id
|
|
209
|
+
* @returns {ManagedResource|undefined}
|
|
210
|
+
*/
|
|
211
|
+
get(id) {
|
|
212
|
+
const resource = this._resources.get(id);
|
|
213
|
+
if (resource && !resource.disposed) {
|
|
214
|
+
resource.lastAccessedAt = Date.now();
|
|
215
|
+
return resource;
|
|
216
|
+
}
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Get resource data by ID
|
|
222
|
+
* @param {string} id
|
|
223
|
+
* @returns {any}
|
|
224
|
+
*/
|
|
225
|
+
getData(id) {
|
|
226
|
+
const resource = this.get(id);
|
|
227
|
+
return resource ? resource.data : undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Acquire a reference to a resource
|
|
232
|
+
* @param {string} id
|
|
233
|
+
* @returns {ManagedResource|undefined}
|
|
234
|
+
*/
|
|
235
|
+
acquire(id) {
|
|
236
|
+
const resource = this.get(id);
|
|
237
|
+
if (resource) {
|
|
238
|
+
return resource.addRef();
|
|
239
|
+
}
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Release a reference to a resource
|
|
245
|
+
* @param {string} id
|
|
246
|
+
* @returns {boolean} True if resource was disposed
|
|
247
|
+
*/
|
|
248
|
+
release(id) {
|
|
249
|
+
const resource = this._resources.get(id);
|
|
250
|
+
if (!resource || resource.disposed) return false;
|
|
251
|
+
|
|
252
|
+
const newCount = resource.release();
|
|
253
|
+
|
|
254
|
+
if (newCount === 0 && this.autoGC) {
|
|
255
|
+
this._disposeResource(resource);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Check if resource exists and is not disposed
|
|
264
|
+
* @param {string} id
|
|
265
|
+
* @returns {boolean}
|
|
266
|
+
*/
|
|
267
|
+
has(id) {
|
|
268
|
+
const resource = this._resources.get(id);
|
|
269
|
+
return resource !== undefined && !resource.disposed;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ==================== Type-based Queries ====================
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get all resources of a type
|
|
276
|
+
* @param {string} type
|
|
277
|
+
* @returns {ManagedResource[]}
|
|
278
|
+
*/
|
|
279
|
+
getByType(type) {
|
|
280
|
+
const typeMap = this._byType.get(type);
|
|
281
|
+
if (!typeMap) return [];
|
|
282
|
+
|
|
283
|
+
return Array.from(typeMap.values()).filter(r => !r.disposed);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get resource count by type
|
|
288
|
+
* @param {string} type
|
|
289
|
+
* @returns {number}
|
|
290
|
+
*/
|
|
291
|
+
getCountByType(type) {
|
|
292
|
+
const typeMap = this._byType.get(type);
|
|
293
|
+
if (!typeMap) return 0;
|
|
294
|
+
|
|
295
|
+
let count = 0;
|
|
296
|
+
for (const resource of typeMap.values()) {
|
|
297
|
+
if (!resource.disposed) count++;
|
|
298
|
+
}
|
|
299
|
+
return count;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Get memory usage by type
|
|
304
|
+
* @param {string} type
|
|
305
|
+
* @returns {number}
|
|
306
|
+
*/
|
|
307
|
+
getMemoryByType(type) {
|
|
308
|
+
const typeMap = this._byType.get(type);
|
|
309
|
+
if (!typeMap) return 0;
|
|
310
|
+
|
|
311
|
+
let total = 0;
|
|
312
|
+
for (const resource of typeMap.values()) {
|
|
313
|
+
if (!resource.disposed) total += resource.size;
|
|
314
|
+
}
|
|
315
|
+
return total;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ==================== Memory Management ====================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Get total memory usage
|
|
322
|
+
* @returns {number}
|
|
323
|
+
*/
|
|
324
|
+
get totalMemory() {
|
|
325
|
+
return this._totalMemory;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get total resource count
|
|
330
|
+
* @returns {number}
|
|
331
|
+
*/
|
|
332
|
+
get resourceCount() {
|
|
333
|
+
let count = 0;
|
|
334
|
+
for (const resource of this._resources.values()) {
|
|
335
|
+
if (!resource.disposed) count++;
|
|
336
|
+
}
|
|
337
|
+
return count;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Check memory limit and run GC if needed
|
|
342
|
+
* @private
|
|
343
|
+
*/
|
|
344
|
+
_checkMemoryLimit() {
|
|
345
|
+
if (this._totalMemory > this.memoryLimit * this.gcThreshold) {
|
|
346
|
+
this.runGC();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Run garbage collection
|
|
352
|
+
* @param {object} [options]
|
|
353
|
+
* @returns {number} Number of resources disposed
|
|
354
|
+
*/
|
|
355
|
+
runGC(options = {}) {
|
|
356
|
+
const {
|
|
357
|
+
maxDispose = Infinity,
|
|
358
|
+
minIdleTime = this.gcIdleTime,
|
|
359
|
+
types = null
|
|
360
|
+
} = options;
|
|
361
|
+
|
|
362
|
+
const now = Date.now();
|
|
363
|
+
const candidates = [];
|
|
364
|
+
|
|
365
|
+
for (const resource of this._resources.values()) {
|
|
366
|
+
if (resource.disposed) continue;
|
|
367
|
+
if (resource.refCount > 0) continue;
|
|
368
|
+
if (types && !types.includes(resource.type)) continue;
|
|
369
|
+
if (now - resource.lastAccessedAt < minIdleTime) continue;
|
|
370
|
+
|
|
371
|
+
candidates.push(resource);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Sort by last access time (oldest first)
|
|
375
|
+
candidates.sort((a, b) => a.lastAccessedAt - b.lastAccessedAt);
|
|
376
|
+
|
|
377
|
+
let disposed = 0;
|
|
378
|
+
for (const resource of candidates) {
|
|
379
|
+
if (disposed >= maxDispose) break;
|
|
380
|
+
this._disposeResource(resource);
|
|
381
|
+
disposed++;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return disposed;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Dispose a resource
|
|
389
|
+
* @private
|
|
390
|
+
*/
|
|
391
|
+
_disposeResource(resource) {
|
|
392
|
+
if (resource.disposed) return;
|
|
393
|
+
|
|
394
|
+
// Notify listeners
|
|
395
|
+
for (const listener of this._disposeListeners) {
|
|
396
|
+
listener(resource);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Remove from hash lookup
|
|
400
|
+
const hash = resource.metadata.get('hash');
|
|
401
|
+
if (hash) {
|
|
402
|
+
this._hashToId.delete(hash);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Update memory tracking
|
|
406
|
+
this._totalMemory -= resource.size;
|
|
407
|
+
|
|
408
|
+
// Dispose resource
|
|
409
|
+
resource.dispose();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Remove resource from internal maps
|
|
414
|
+
* @private
|
|
415
|
+
*/
|
|
416
|
+
_removeResource(resource) {
|
|
417
|
+
this._resources.delete(resource.id);
|
|
418
|
+
|
|
419
|
+
const typeMap = this._byType.get(resource.type);
|
|
420
|
+
if (typeMap) {
|
|
421
|
+
typeMap.delete(resource.id);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const hash = resource.metadata.get('hash');
|
|
425
|
+
if (hash) {
|
|
426
|
+
this._hashToId.delete(hash);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Add dispose listener
|
|
432
|
+
* @param {function(ManagedResource): void} listener
|
|
433
|
+
* @returns {function} Unsubscribe function
|
|
434
|
+
*/
|
|
435
|
+
onDispose(listener) {
|
|
436
|
+
this._disposeListeners.push(listener);
|
|
437
|
+
return () => {
|
|
438
|
+
const idx = this._disposeListeners.indexOf(listener);
|
|
439
|
+
if (idx !== -1) {
|
|
440
|
+
this._disposeListeners.splice(idx, 1);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// ==================== Utility ====================
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Force dispose a resource regardless of reference count
|
|
449
|
+
* @param {string} id
|
|
450
|
+
* @returns {boolean}
|
|
451
|
+
*/
|
|
452
|
+
forceDispose(id) {
|
|
453
|
+
const resource = this._resources.get(id);
|
|
454
|
+
if (!resource || resource.disposed) return false;
|
|
455
|
+
|
|
456
|
+
this._disposeResource(resource);
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Dispose all resources of a type
|
|
462
|
+
* @param {string} type
|
|
463
|
+
* @returns {number} Number disposed
|
|
464
|
+
*/
|
|
465
|
+
disposeType(type) {
|
|
466
|
+
const typeMap = this._byType.get(type);
|
|
467
|
+
if (!typeMap) return 0;
|
|
468
|
+
|
|
469
|
+
let count = 0;
|
|
470
|
+
for (const resource of typeMap.values()) {
|
|
471
|
+
if (!resource.disposed) {
|
|
472
|
+
this._disposeResource(resource);
|
|
473
|
+
count++;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return count;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Dispose all resources
|
|
482
|
+
*/
|
|
483
|
+
disposeAll() {
|
|
484
|
+
for (const resource of this._resources.values()) {
|
|
485
|
+
if (!resource.disposed) {
|
|
486
|
+
this._disposeResource(resource);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
this._resources.clear();
|
|
491
|
+
this._byType.clear();
|
|
492
|
+
this._hashToId.clear();
|
|
493
|
+
this._totalMemory = 0;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Get statistics
|
|
498
|
+
* @returns {object}
|
|
499
|
+
*/
|
|
500
|
+
getStats() {
|
|
501
|
+
const stats = {
|
|
502
|
+
totalResources: 0,
|
|
503
|
+
totalMemory: this._totalMemory,
|
|
504
|
+
byType: {}
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
for (const [type, typeMap] of this._byType) {
|
|
508
|
+
let count = 0;
|
|
509
|
+
let memory = 0;
|
|
510
|
+
let refs = 0;
|
|
511
|
+
|
|
512
|
+
for (const resource of typeMap.values()) {
|
|
513
|
+
if (!resource.disposed) {
|
|
514
|
+
count++;
|
|
515
|
+
memory += resource.size;
|
|
516
|
+
refs += resource.refCount;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
stats.byType[type] = { count, memory, refs };
|
|
521
|
+
stats.totalResources += count;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return stats;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Generate hash for resource deduplication
|
|
529
|
+
* @param {any} data
|
|
530
|
+
* @returns {string}
|
|
531
|
+
*/
|
|
532
|
+
static generateHash(data) {
|
|
533
|
+
// Simple hash for common cases
|
|
534
|
+
if (typeof data === 'string') {
|
|
535
|
+
return `str_${hashString(data)}`;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (data instanceof Float32Array || data instanceof Uint16Array) {
|
|
539
|
+
return `arr_${hashTypedArray(data)}`;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (typeof data === 'object') {
|
|
543
|
+
return `obj_${hashString(JSON.stringify(data))}`;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return `val_${String(data)}`;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Simple string hash function
|
|
552
|
+
* @param {string} str
|
|
553
|
+
* @returns {number}
|
|
554
|
+
*/
|
|
555
|
+
function hashString(str) {
|
|
556
|
+
let hash = 0;
|
|
557
|
+
for (let i = 0; i < str.length; i++) {
|
|
558
|
+
const char = str.charCodeAt(i);
|
|
559
|
+
hash = ((hash << 5) - hash) + char;
|
|
560
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
561
|
+
}
|
|
562
|
+
return hash >>> 0;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Hash typed array
|
|
567
|
+
* @param {TypedArray} arr
|
|
568
|
+
* @returns {number}
|
|
569
|
+
*/
|
|
570
|
+
function hashTypedArray(arr) {
|
|
571
|
+
let hash = arr.length;
|
|
572
|
+
const step = Math.max(1, Math.floor(arr.length / 100));
|
|
573
|
+
|
|
574
|
+
for (let i = 0; i < arr.length; i += step) {
|
|
575
|
+
hash = ((hash << 5) - hash) + (arr[i] * 1000 | 0);
|
|
576
|
+
hash = hash & hash;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return hash >>> 0;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// ==================== Convenience Types ====================
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Pre-defined resource types
|
|
586
|
+
*/
|
|
587
|
+
export const ResourceTypes = {
|
|
588
|
+
GEOMETRY: 'geometry',
|
|
589
|
+
MATERIAL: 'material',
|
|
590
|
+
TEXTURE: 'texture',
|
|
591
|
+
BUFFER: 'buffer',
|
|
592
|
+
SHADER: 'shader',
|
|
593
|
+
MESH: 'mesh',
|
|
594
|
+
ANIMATION: 'animation',
|
|
595
|
+
AUDIO: 'audio'
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
export { ManagedResource };
|
|
599
|
+
export default ResourceManager;
|