Skip to content

Commit

Permalink
Merge pull request #238679 from microsoft/tyriar/233790_scroll
Browse files Browse the repository at this point in the history
Editor GPU: Pass content width through to scroll bar
  • Loading branch information
Tyriar authored Jan 24, 2025
2 parents 7717b47 + 90a24fb commit 535fe55
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 11 deletions.
6 changes: 5 additions & 1 deletion src/vs/editor/browser/gpu/gpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export interface IGpuRenderStrategy extends IDisposable {
* Resets the render strategy, clearing all data and setting up for a new frame.
*/
reset(): void;
update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): number;
update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): IGpuRenderStrategyUpdateResult;
draw(pass: GPURenderPassEncoder, viewportData: ViewportData): void;
}

export interface IGpuRenderStrategyUpdateResult {
localContentWidth: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ViewEventHandler } from '../../../common/viewEventHandler.js';
import type { ViewportData } from '../../../common/viewLayout/viewLinesViewportData.js';
import type { ViewContext } from '../../../common/viewModel/viewContext.js';
import type { ViewLineOptions } from '../../viewParts/viewLines/viewLineOptions.js';
import type { IGpuRenderStrategy } from '../gpu.js';
import type { IGpuRenderStrategy, IGpuRenderStrategyUpdateResult } from '../gpu.js';
import { GlyphRasterizer } from '../raster/glyphRasterizer.js';
import type { ViewGpuContext } from '../viewGpuContext.js';

Expand All @@ -31,6 +31,6 @@ export abstract class BaseRenderStrategy extends ViewEventHandler implements IGp
}

abstract reset(): void;
abstract update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): number;
abstract update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): IGpuRenderStrategyUpdateResult;
abstract draw(pass: GPURenderPassEncoder, viewportData: ViewportData): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { ViewLineOptions } from '../../viewParts/viewLines/viewLineOptions.
import type { ITextureAtlasPageGlyph } from '../atlas/atlas.js';
import { createContentSegmenter, type IContentSegmenter } from '../contentSegmenter.js';
import { fullFileRenderStrategyWgsl } from './fullFileRenderStrategy.wgsl.js';
import { BindingId } from '../gpu.js';
import { BindingId, type IGpuRenderStrategyUpdateResult } from '../gpu.js';
import { GPULifecycle } from '../gpuDisposable.js';
import { quadVertices } from '../gpuUtils.js';
import { GlyphRasterizer } from '../raster/glyphRasterizer.js';
Expand Down Expand Up @@ -232,7 +232,7 @@ export class FullFileRenderStrategy extends BaseRenderStrategy {
this._finalRenderedLine = 0;
}

update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): number {
update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): IGpuRenderStrategyUpdateResult {
// IMPORTANT: This is a hot function. Variables are pre-allocated and shared within the
// loop. This is done so we don't need to trust the JIT compiler to do this optimization to
// avoid potential additional blocking time in garbage collector which is a common cause of
Expand Down Expand Up @@ -272,6 +272,8 @@ export class FullFileRenderStrategy extends BaseRenderStrategy {
this._scrollInitialized = true;
}

let localContentWidth = 0;

// Update cell data
const cellBuffer = new Float32Array(this._cellValueBuffers[this._activeDoubleBufferIndex]);
const lineIndexCount = FullFileRenderStrategy.maxSupportedColumns * Constants.IndicesPerCell;
Expand Down Expand Up @@ -466,6 +468,7 @@ export class FullFileRenderStrategy extends BaseRenderStrategy {

// Adjust the x pixel offset for the next character
absoluteOffsetX += charWidth;
localContentWidth = Math.max(localContentWidth, absoluteOffsetX);
}

tokenStartIndex = tokenEndIndex;
Expand Down Expand Up @@ -500,7 +503,8 @@ export class FullFileRenderStrategy extends BaseRenderStrategy {
this._activeDoubleBufferIndex = this._activeDoubleBufferIndex ? 0 : 1;

this._visibleObjectCount = visibleObjectCount;
return visibleObjectCount;

return { localContentWidth };
}

draw(pass: GPURenderPassEncoder, viewportData: ViewportData): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { ViewContext } from '../../../common/viewModel/viewContext.js';
import type { ViewLineOptions } from '../../viewParts/viewLines/viewLineOptions.js';
import type { ITextureAtlasPageGlyph } from '../atlas/atlas.js';
import { createContentSegmenter, type IContentSegmenter } from '../contentSegmenter.js';
import { BindingId } from '../gpu.js';
import { BindingId, type IGpuRenderStrategyUpdateResult } from '../gpu.js';
import { GPULifecycle } from '../gpuDisposable.js';
import { quadVertices } from '../gpuUtils.js';
import { GlyphRasterizer } from '../raster/glyphRasterizer.js';
Expand Down Expand Up @@ -184,7 +184,7 @@ export class ViewportRenderStrategy extends BaseRenderStrategy {
}
}

update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): number {
update(viewportData: ViewportData, viewLineOptions: ViewLineOptions): IGpuRenderStrategyUpdateResult {
// IMPORTANT: This is a hot function. Variables are pre-allocated and shared within the
// loop. This is done so we don't need to trust the JIT compiler to do this optimization to
// avoid potential additional blocking time in garbage collector which is a common cause of
Expand Down Expand Up @@ -224,6 +224,8 @@ export class ViewportRenderStrategy extends BaseRenderStrategy {
this._scrollInitialized = true;
}

let localContentWidth = 0;

// Zero out cell buffer or rebuild if needed
if (this._cellBindBufferLineCapacity < viewportData.endLineNumber - viewportData.startLineNumber + 1) {
this._rebuildCellBuffer(viewportData.endLineNumber - viewportData.startLineNumber + 1);
Expand Down Expand Up @@ -369,6 +371,7 @@ export class ViewportRenderStrategy extends BaseRenderStrategy {

// Adjust the x pixel offset for the next character
absoluteOffsetX += charWidth;
localContentWidth = Math.max(localContentWidth, absoluteOffsetX);
}

tokenStartIndex = tokenEndIndex;
Expand All @@ -394,7 +397,7 @@ export class ViewportRenderStrategy extends BaseRenderStrategy {
this._activeDoubleBufferIndex = this._activeDoubleBufferIndex ? 0 : 1;

this._visibleObjectCount = visibleObjectCount;
return visibleObjectCount;
return { localContentWidth };
}

draw(pass: GPURenderPassEncoder, viewportData: ViewportData): void {
Expand Down
2 changes: 2 additions & 0 deletions src/vs/editor/browser/gpu/viewGpuContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class ViewGpuContext extends Disposable {
readonly maxGpuCols = ViewportRenderStrategy.maxSupportedColumns;

readonly canvas: FastDomNode<HTMLCanvasElement>;
readonly scrollWidthElement: FastDomNode<HTMLElement>;
readonly ctx: GPUCanvasContext;

static device: Promise<GPUDevice>;
Expand Down Expand Up @@ -87,6 +88,7 @@ export class ViewGpuContext extends Disposable {

this.canvas = createFastDomNode(document.createElement('canvas'));
this.canvas.setClassName('editorCanvas');
this.scrollWidthElement = createFastDomNode(document.createElement('div'));

// Adjust the canvas size to avoid drawing under the scroll bar
this._register(Event.runAndSubscribe(configurationService.onDidChangeConfiguration, e => {
Expand Down
1 change: 1 addition & 0 deletions src/vs/editor/browser/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ export class View extends ViewEventHandler {
this._overflowGuardContainer.appendChild(this._scrollbar.getDomNode());
if (this._viewGpuContext) {
this._overflowGuardContainer.appendChild(this._viewGpuContext.canvas);
this._linesContent.appendChild(this._viewGpuContext.scrollWidthElement);
}
this._overflowGuardContainer.appendChild(scrollDecoration.getDomNode());
this._overflowGuardContainer.appendChild(this._overlayWidgets.getDomNode());
Expand Down
11 changes: 9 additions & 2 deletions src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export class ViewLinesGpu extends ViewPart implements IViewLines {
private _initViewportData?: ViewportData[];
private _lastViewportData?: ViewportData;
private _lastViewLineOptions?: ViewLineOptions;
private _maxLocalContentWidthSoFar = 0;

private _device!: GPUDevice;
private _renderPassDescriptor!: GPURenderPassDescriptor;
Expand Down Expand Up @@ -429,7 +430,6 @@ export class ViewLinesGpu extends ViewPart implements IViewLines {
override onCursorStateChanged(e: viewEvents.ViewCursorStateChangedEvent): boolean { return true; }
override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { return true; }
override onFlushed(e: viewEvents.ViewFlushedEvent): boolean { return true; }

override onLinesChanged(e: viewEvents.ViewLinesChangedEvent): boolean { return true; }
override onLinesDeleted(e: viewEvents.ViewLinesDeletedEvent): boolean { return true; }
override onLinesInserted(e: viewEvents.ViewLinesInsertedEvent): boolean { return true; }
Expand Down Expand Up @@ -473,7 +473,14 @@ export class ViewLinesGpu extends ViewPart implements IViewLines {

const options = new ViewLineOptions(this._context.configuration, this._context.theme.type);

this._renderStrategy.value!.update(viewportData, options);
const { localContentWidth } = this._renderStrategy.value!.update(viewportData, options);

// Track the largest local content width so far in this session and use it as the scroll
// width. This is how the DOM renderer works as well, so you may not be able to scroll to
// the right in a file with long lines until you scroll down.
this._maxLocalContentWidthSoFar = Math.max(this._maxLocalContentWidthSoFar, localContentWidth);
this._context.viewModel.viewLayout.setMaxLineWidth(this._maxLocalContentWidthSoFar);
this._viewGpuContext.scrollWidthElement.setWidth(this._context.viewLayout.getScrollWidth());

this._updateAtlasStorageBufferAndTexture();

Expand Down

0 comments on commit 535fe55

Please sign in to comment.