From 3d96885ce0d15e0a01ca63e950c240fbc5ba5094 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Mon, 18 Nov 2024 06:37:04 -0800 Subject: [PATCH] Clear and commit all render data on view zones changed Fixes #233856 --- .../browser/gpu/fullFileRenderStrategy.ts | 61 ++++++++++++++----- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts b/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts index 88ff9b7b87579..a6df706d2b89e 100644 --- a/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts +++ b/src/vs/editor/browser/gpu/fullFileRenderStrategy.ts @@ -9,7 +9,7 @@ import { EditorOption } from '../../common/config/editorOptions.js'; import { CursorColumns } from '../../common/core/cursorColumns.js'; import type { IViewLineTokens } from '../../common/tokens/lineTokens.js'; import { ViewEventHandler } from '../../common/viewEventHandler.js'; -import type { ViewConfigurationChangedEvent, ViewLinesChangedEvent, ViewLinesDeletedEvent, ViewLinesInsertedEvent, ViewScrollChangedEvent, ViewTokensChangedEvent } from '../../common/viewEvents.js'; +import { ViewEventType, type ViewConfigurationChangedEvent, type ViewLinesChangedEvent, type ViewLinesDeletedEvent, type ViewLinesInsertedEvent, type ViewScrollChangedEvent, type ViewTokensChangedEvent, type ViewZonesChangedEvent } from '../../common/viewEvents.js'; import type { ViewportData } from '../../common/viewLayout/viewLinesViewportData.js'; import type { ViewLineRenderingData } from '../../common/viewModel.js'; import type { ViewContext } from '../../common/viewModel/viewContext.js'; @@ -38,6 +38,8 @@ const enum CellBufferInfo { TextureIndex = 5, } +type QueuedBufferEvent = ViewLinesDeletedEvent | ViewZonesChangedEvent; + export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRenderStrategy { readonly wgsl: string = fullFileRenderStrategyWgsl; @@ -61,7 +63,7 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend private _scrollOffsetValueBuffer: Float32Array; private _scrollInitialized: boolean = false; - private readonly _queuedBufferUpdates: [ViewLinesDeletedEvent[], ViewLinesDeletedEvent[]] = [[], []]; + private readonly _queuedBufferUpdates: [QueuedBufferEvent[], QueuedBufferEvent[]] = [[], []]; get bindGroupEntries(): GPUBindGroupEntry[] { return [ @@ -162,6 +164,18 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend return true; } + public override onZonesChanged(e: ViewZonesChangedEvent): boolean { + this._upToDateLines[0].clear(); + this._upToDateLines[1].clear(); + + // Queue updates that need to happen on the active buffer, not just the cache. This is + // deferred since the active buffer could be locked by the GPU which would block the main + // thread. + this._queueBufferUpdate(e); + + return true; + } + // #endregion private _invalidateLinesFrom(lineNumber: number): void { @@ -230,19 +244,34 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend while (queuedBufferUpdates.length) { const e = queuedBufferUpdates.shift()!; - // Shift content below deleted line up - const deletedLineContentStartIndex = (e.fromLineNumber - 1) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell; - const deletedLineContentEndIndex = (e.toLineNumber) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell; - const nullContentStartIndex = (this._finalRenderedLine - (e.toLineNumber - e.fromLineNumber + 1)) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell; - cellBuffer.set(cellBuffer.subarray(deletedLineContentEndIndex), deletedLineContentStartIndex); - - // Zero out content on lines that are no longer valid - cellBuffer.fill(0, nullContentStartIndex); - - // Update dirty lines and final rendered line - dirtyLineStart = Math.min(dirtyLineStart, e.fromLineNumber); - dirtyLineEnd = this._finalRenderedLine; - this._finalRenderedLine -= e.toLineNumber - e.fromLineNumber + 1; + switch (e.type) { + case ViewEventType.ViewLinesDeleted: { + // Shift content below deleted line up + const deletedLineContentStartIndex = (e.fromLineNumber - 1) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell; + const deletedLineContentEndIndex = (e.toLineNumber) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell; + const nullContentStartIndex = (this._finalRenderedLine - (e.toLineNumber - e.fromLineNumber + 1)) * this._viewGpuContext.maxGpuCols * Constants.IndicesPerCell; + cellBuffer.set(cellBuffer.subarray(deletedLineContentEndIndex), deletedLineContentStartIndex); + + // Zero out content on lines that are no longer valid + cellBuffer.fill(0, nullContentStartIndex); + + // Update dirty lines and final rendered line + dirtyLineStart = Math.min(dirtyLineStart, e.fromLineNumber); + dirtyLineEnd = this._finalRenderedLine; + this._finalRenderedLine -= e.toLineNumber - e.fromLineNumber + 1; + break; + } + case ViewEventType.ViewZonesChanged: { + // TODO: We could retain render data if we know what view zones changed and how + // Zero out content on all lines + cellBuffer.fill(0); + + dirtyLineStart = 1; + dirtyLineEnd = this._finalRenderedLine; + this._finalRenderedLine = 0; + break; + } + } } for (y = viewportData.startLineNumber; y <= viewportData.endLineNumber; y++) { @@ -360,7 +389,7 @@ export class FullFileRenderStrategy extends ViewEventHandler implements IGpuRend ); } - private _queueBufferUpdate(e: ViewLinesDeletedEvent) { + private _queueBufferUpdate(e: QueuedBufferEvent) { this._queuedBufferUpdates[0].push(e); this._queuedBufferUpdates[1].push(e); }