Skip to content

Commit

Permalink
Fix metadata key, glyphinfo buffer size and make getGlyph page lookup…
Browse files Browse the repository at this point in the history
… O(1) amortized
  • Loading branch information
Tyriar committed Aug 21, 2024
1 parent ec77d19 commit 740ba1c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 16 deletions.
31 changes: 23 additions & 8 deletions src/vs/editor/browser/view/gpu/atlas/textureAtlas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { getActiveWindow } from 'vs/base/browser/dom';
import { Event } from 'vs/base/common/event';
import { Disposable, dispose, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { TwoKeyMap } from 'vs/base/common/map';
import type { IReadableTextureAtlasPage, ITextureAtlasPageGlyph } from 'vs/editor/browser/view/gpu/atlas/atlas';
import { TextureAtlasPage, type AllocatorType } from 'vs/editor/browser/view/gpu/atlas/textureAtlasPage';
import type { IGlyphRasterizer } from 'vs/editor/browser/view/gpu/raster/raster';
Expand Down Expand Up @@ -36,6 +37,14 @@ export class TextureAtlas extends Disposable {

readonly pageSize: number;

/**
* A maps of glyph keys to the page to start searching for the glyph. This is set before
* searching to have as little runtime overhead (branching, intermediate variables) as possible,
* so it is not guaranteed to be the actual page the glyph is on. But it is guaranteed that all
* pages with a lower index do not contain the glyph.
*/
private readonly _glyphPageIndex: TwoKeyMap<string, number, number> = new TwoKeyMap();

constructor(
/** The maximum texture size supported by the GPU. */
private readonly _maxTextureSize: number,
Expand All @@ -56,32 +65,38 @@ export class TextureAtlas extends Disposable {

this.pageSize = Math.min(1024 * dprFactor, this._maxTextureSize);
this._pages.push(this._instantiationService.createInstance(TextureAtlasPage, 0, this.pageSize, this._allocatorType));

this._register(toDisposable(() => dispose(this._pages)));
}

// TODO: Color, style etc.
public getGlyph(rasterizer: IGlyphRasterizer, chars: string, metadata: number): Readonly<ITextureAtlasPageGlyph> {
// Ignore metadata that doesn't affect the glyph
metadata &= ~(MetadataConsts.LANGUAGEID_MASK | MetadataConsts.TOKEN_TYPE_MASK | MetadataConsts.BALANCED_BRACKETS_MASK);

// TODO: Encode font size and family into key

if (!this._warmedUpRasterizers.has(rasterizer.id)) {
this._warmUpAtlas(rasterizer);
this._warmedUpRasterizers.add(rasterizer.id);
}
return this._tryGetGlyph(0, rasterizer, chars, metadata);
return this._tryGetGlyph(this._glyphPageIndex.get(chars, metadata) ?? 0, rasterizer, chars, metadata);
}

private _tryGetGlyph(pageIndex: number, rasterizer: IGlyphRasterizer, chars: string, metadata: number): Readonly<ITextureAtlasPageGlyph> {
// TODO: Should the texture atlas have a map of glyphs to pages so this doesn't iterate through all pages?
this._glyphPageIndex.set(chars, metadata, pageIndex);
return (
this._pages[pageIndex].getGlyph(rasterizer, chars, metadata) ?? (
(pageIndex + 1 < this._pages.length
? this._tryGetGlyph(pageIndex + 1, rasterizer, chars, metadata)
: undefined)
) ?? this._getGlyphFromNewPage(rasterizer, chars, metadata)
this._pages[pageIndex].getGlyph(rasterizer, chars, metadata)
?? (pageIndex + 1 < this._pages.length
? this._tryGetGlyph(pageIndex + 1, rasterizer, chars, metadata)
: undefined)
?? this._getGlyphFromNewPage(rasterizer, chars, metadata)
);
}

private _getGlyphFromNewPage(rasterizer: IGlyphRasterizer, chars: string, metadata: number): Readonly<ITextureAtlasPageGlyph> {
// TODO: Support more than 2 pages and the GPU texture layer limit
this._pages.push(this._instantiationService.createInstance(TextureAtlasPage, this._pages.length, this.pageSize, this._allocatorType));
this._glyphPageIndex.set(chars, metadata, this._pages.length - 1);
return this._pages[this._pages.length - 1].getGlyph(rasterizer, chars, metadata)!;
}

Expand Down
6 changes: 0 additions & 6 deletions src/vs/editor/browser/view/gpu/atlas/textureAtlasPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type { IReadableTextureAtlasPage, ITextureAtlasAllocator, ITextureAtlasPa
import { TextureAtlasShelfAllocator } from 'vs/editor/browser/view/gpu/atlas/textureAtlasShelfAllocator';
import { TextureAtlasSlabAllocator } from 'vs/editor/browser/view/gpu/atlas/textureAtlasSlabAllocator';
import type { IBoundingBox, IGlyphRasterizer } from 'vs/editor/browser/view/gpu/raster/raster';
import { MetadataConsts } from 'vs/editor/common/encodedTokenAttributes';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
import { IThemeService } from 'vs/platform/theme/common/themeService';

Expand Down Expand Up @@ -80,11 +79,6 @@ export class TextureAtlasPage extends Disposable implements IReadableTextureAtla
}

public getGlyph(rasterizer: IGlyphRasterizer, chars: string, metadata: number): Readonly<ITextureAtlasPageGlyph> | undefined {
// Ignore metadata that doesn't affect the glyph
metadata ^= (MetadataConsts.LANGUAGEID_MASK | MetadataConsts.TOKEN_TYPE_MASK | MetadataConsts.BALANCED_BRACKETS_MASK);

// TODO: Encode font size and family into key

// IMPORTANT: There are intentionally no intermediate variables here to aid in runtime
// optimization as it's a very hot function
return this._glyphMap.get(chars, metadata) ?? this._createGlyph(rasterizer, chars, metadata);
Expand Down
3 changes: 1 addition & 2 deletions src/vs/editor/browser/view/gpu/gpuViewLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ export class GpuViewLayerRenderer<T extends IVisibleLine> extends Disposable {
this._logService.trace('Updating atlas page[', layerIndex, '] from version ', this._atlasGpuTextureVersions[layerIndex], ' to version ', page.version);

// TODO: Dynamically set buffer size
const bufferSize = GlyphStorageBufferInfo.FloatsPerEntry * Constants.MaxAtlasPageGlyphCount;
const values = new Float32Array(bufferSize / 4);
const values = new Float32Array(GlyphStorageBufferInfo.FloatsPerEntry * Constants.MaxAtlasPageGlyphCount);
let entryOffset = 0;
for (const glyph of page.glyphs) {
values[entryOffset + GlyphStorageBufferInfo.Offset_TexturePosition] = glyph.x;
Expand Down

0 comments on commit 740ba1c

Please sign in to comment.