Skip to content

Commit

Permalink
Fix some memory leaks
Browse files Browse the repository at this point in the history
DKR still needs a bit of work to address load-time performance.
  • Loading branch information
magcius committed Nov 16, 2024
1 parent bd48ca7 commit 0c2cc5e
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 46 deletions.
8 changes: 4 additions & 4 deletions src/DiddyKongRacing/DkrTexture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class DkrTexture {

private hasBeenDestroyed = false;

constructor(device: GfxDevice, cache: GfxRenderCache, private pixels: Uint8ClampedArray, headerData: Uint8Array) {
constructor(device: GfxDevice, cache: GfxRenderCache, private pixels: Uint8ClampedArray, headerData: Uint8Array, private debugName: string) {
const view = new DataView(headerData.buffer);
this.width = view.getUint8(0x00);
this.height = view.getUint8(0x01);
Expand Down Expand Up @@ -70,17 +70,17 @@ export class DkrTexture {

const gfxTexture = device.createTexture(makeTextureDescriptor2D(GfxFormat.U8_RGBA_NORM, this.width, this.height, 1));
device.uploadTextureData(gfxTexture, 0, [this.pixels.slice(frameStart, frameEnd)]);
device.setResourceName(gfxTexture, `${debugName} / ${i}`);

this.textureMappingsArray[i][0].gfxSampler = sampler;
this.textureMappingsArray[i][0].gfxTexture = gfxTexture;
}
}

public destroy(device: GfxDevice): void {
if(!this.hasBeenDestroyed) {
for(const textureMapping of this.textureMappingsArray) {
if (!this.hasBeenDestroyed) {
for (const textureMapping of this.textureMappingsArray)
device.destroyTexture(textureMapping[0].gfxTexture!);
}
this.hasBeenDestroyed = true;
}
}
Expand Down
67 changes: 28 additions & 39 deletions src/DiddyKongRacing/DkrTextureCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { GfxDevice } from "../gfx/platform/GfxPlatform.js";
import { GfxRenderCache } from "../gfx/render/GfxRenderCache.js";

export class DkrTextureCache {
private textures3d: { [k: string]: DkrTexture } = {};
private textures2d: { [k: string]: DkrTexture } = {};
private textures3d = new Map<number, DkrTexture>();
private textures2d = new Map<number, DkrTexture>();

constructor(private device: GfxDevice, private cache: GfxRenderCache, private dataManager: DataManager) {
}
Expand All @@ -19,78 +19,67 @@ export class DkrTextureCache {

for (let i = 0; i < indices.length; i++) {
const index = indices[i];
if (this.textures3d.has(index))
continue;

const header = this.dataManager.get3dTextureHeader(index).createTypedArray(Uint8Array);
const imageData = imageDatas[i];
this.textures3d[index] = new DkrTexture(this.device, this.cache, imageData.data, header);
this.textures3d.set(index, new DkrTexture(this.device, this.cache, imageData.data, header, `DkrTexture 3D ${index}`));
}

callback();
}

// 3D texture = texture used mainly in 3d geometry.
public get3dTexture(index: number, callback: Function): void {
if(!!this.textures3d[index]) {
// Texture was found in cache, so just return it.
callback(this.textures3d[index]);
public get3dTexture(index: number, callback: (texture: DkrTexture) => void): void {
if (this.textures3d.has(index)) {
callback(this.textures3d.get(index)!);
} else {
// Texture was not found, so it needs to be loaded.
this.dataManager.get3dTexture(index).then((tex) => {
if (!!this.textures3d[index]) {
// Texture has already been loaded, so just return it.
callback(this.textures3d[index]);
} else {
if (!this.textures3d.has(index)) {
const headerData = this.dataManager.get3dTextureHeader(index).createTypedArray(Uint8Array);
this.textures3d[index] = new DkrTexture(this.device, this.cache, tex.data, headerData);
callback(this.textures3d[index]);
this.textures3d.set(index, new DkrTexture(this.device, this.cache, tex.data, headerData, `DkrTexture 3D ${index}`));
}

callback(this.textures3d.get(index)!);
});
}
}

// 2D texture = texture used mainly in sprites & particles.
public get2dTexture(index: number, callback: Function): void {
if(!!this.textures2d[index]) {
// Texture was found in cache, so just return it.
callback(this.textures2d[index]);
if (this.textures2d.has(index)) {
callback(this.textures2d.get(index)!);
} else {
// Texture was not found, so it needs to be loaded.
this.dataManager.get2dTexture(index).then((tex) => {
if (!!this.textures2d[index]) {
// Texture has already been loaded, so just return it.
callback(this.textures2d[index]);
} else {
if (!this.textures2d.has(index)) {
const headerData = this.dataManager.get2dTextureHeader(index).createTypedArray(Uint8Array);
this.textures2d[index] = new DkrTexture(this.device, this.cache, tex.data, headerData);
callback(this.textures2d[index]);
this.textures2d.set(index, new DkrTexture(this.device, this.cache, tex.data, headerData, `DkrTexture 2D ${index}`));
}

callback(this.textures2d.get(index)!);
});
}
}

public advanceTextureFrames(deltaTime: number): void {
const keys = Object.keys(this.textures3d);
for(const key of keys) {
this.textures3d[key].advanceFrame(deltaTime);
}
for (const v of this.textures3d.values())
v.advanceFrame(deltaTime);
}

public scrollTextures(texScrollers: { texIndex: number, scrollU: number, scrollV: number }[], dt: number): void {
for(const texScroller of texScrollers) {
if(!!this.textures3d[texScroller.texIndex]){
const tex: DkrTexture = this.textures3d[texScroller.texIndex];
for (const texScroller of texScrollers) {
if (this.textures3d.has(texScroller.texIndex)) {
const tex = this.textures3d.get(texScroller.texIndex)!;
tex.scrollTexture(texScroller.scrollU, texScroller.scrollV, dt);
}
}
}

public destroy(device: GfxDevice): void {
const keys3d = Object.keys(this.textures3d);
for(const key of keys3d) {
this.textures3d[key].destroy(device);
}
const keys2d = Object.keys(this.textures2d);
for(const key of keys2d) {
this.textures2d[key].destroy(device);
}
for (const v of this.textures3d.values())
v.destroy(device);
for (const v of this.textures2d.values())
v.destroy(device);
}
}
2 changes: 2 additions & 0 deletions src/ZeldaWindWaker/d_wood.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ class WoodModel {

public destroy(device: GfxDevice): void {
this.bufferCoalescer.destroy(device);
this.shadowTextureData.destroy(device);
this.bushTextureData.destroy(device);
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/gfx/platform/GfxPlatformWebGPU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1742,8 +1742,7 @@ export async function createSwapChainForWebGPU(canvas: HTMLCanvasElement | Offsc
if (device === null)
return null;

const context = canvas.getContext('webgpu') as any as GPUCanvasContext;

const context = canvas.getContext('webgpu');
if (!context)
return null;

Expand Down
1 change: 0 additions & 1 deletion src/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@ export class Viewer {
this.render();
}

// TODO(jstpierre): Move this to main
this.inputManager.afterFrame();

// Reset the delta for next frame.
Expand Down

0 comments on commit 0c2cc5e

Please sign in to comment.