Stabilize WebGL reveal timing

This commit is contained in:
2026-06-07 16:42:09 +02:00
parent 9695d48368
commit 53c24e4fae
7 changed files with 217 additions and 22 deletions
+45
View File
@@ -34,9 +34,11 @@ class BookTextureRendererModule extends BaseModule {
this.animationFrameId = null;
this.lastAnimationFrameAt = 0;
this.targetFrameDurationMs = 1000 / 30;
this.pipelineTimings = [];
this.bindMethods([
'initialize',
'markPipelineTiming',
'waitForTextureFonts',
'ensureTextureFontFace',
'createPageCanvases',
@@ -69,6 +71,9 @@ class BookTextureRendererModule extends BaseModule {
this.pageFormat = this.getModule('book-page-format');
this.pagination = this.getModule('book-pagination');
this.localization = this.getModule('localization');
window.BookTextureRendererDebug = {
pipelineTimings: this.pipelineTimings
};
this.reportProgress(10, 'Waiting for book fonts');
await this.waitForTextureFonts();
this.reportProgress(20, 'Preparing page texture canvases');
@@ -104,6 +109,18 @@ class BookTextureRendererModule extends BaseModule {
return true;
}
markPipelineTiming(name, detail = {}) {
const entry = {
name,
at: performance.now(),
detail
};
this.pipelineTimings.push(entry);
if (this.pipelineTimings.length > 120) this.pipelineTimings.splice(0, this.pipelineTimings.length - 120);
document.documentElement.dataset.webglTexturePipeline = JSON.stringify(this.pipelineTimings);
return entry;
}
async waitForTextureFonts() {
if (!document.fonts) return;
await Promise.all([
@@ -140,6 +157,10 @@ class BookTextureRendererModule extends BaseModule {
drawSpread(spread = null, sides = null) {
this.currentSpread = spread || { left: [], right: [] };
const sidesToDraw = Array.isArray(sides) && sides.length ? sides : ['left', 'right'];
this.markPipelineTiming('drawSpread:start', {
sides: sidesToDraw,
revealBlockIds: this.revealPublishBlockIds ? Array.from(this.revealPublishBlockIds) : []
});
this.revealBounds = { left: null, right: null };
this.revealWords = { left: [], right: [] };
sidesToDraw.forEach((side) => {
@@ -148,6 +169,9 @@ class BookTextureRendererModule extends BaseModule {
this.drawPageLines(side, this.currentSpread?.[side] || []);
});
this.publishSpread(sidesToDraw);
this.markPipelineTiming('drawSpread:end', {
sides: sidesToDraw
});
this.revealBounds = null;
this.revealWords = null;
this.revealPublishBlockIds = null;
@@ -376,6 +400,10 @@ class BookTextureRendererModule extends BaseModule {
if (blockId == null || !Array.isArray(detail.wordTimings)) return;
const id = String(blockId);
const wordTimings = detail.wordTimings;
this.markPipelineTiming('prepareRevealBlock:start', {
blockId: id,
wordTimingCount: wordTimings.length
});
this.activeAnimations.set(id, {
blockId,
wordTimings,
@@ -390,12 +418,20 @@ class BookTextureRendererModule extends BaseModule {
this.pendingRevealBlockIds.delete(id);
this.revealPublishBlockIds = new Set([id]);
this.drawSpread(this.currentSpread || this.pagination?.getCurrentSpread?.(), this.getBlockSides(blockId));
this.markPipelineTiming('prepareRevealBlock:end', {
blockId: id,
wordTimingCount: wordTimings.length
});
}
startPreparedRevealAnimation(blockId) {
const id = String(blockId ?? '');
const animation = this.activeAnimations.get(id);
if (!animation) return false;
this.markPipelineTiming('startPreparedRevealAnimation', {
blockId: id,
wordTimingCount: Array.isArray(animation.wordTimings) ? animation.wordTimings.length : 0
});
animation.startedAt = performance.now();
animation.prepared = false;
animation.completed = false;
@@ -503,6 +539,10 @@ class BookTextureRendererModule extends BaseModule {
publishSpread(sides = null) {
const sidesToPublish = Array.isArray(sides) && sides.length ? sides : ['left', 'right'];
const wordCounts = {
left: this.revealWords?.left?.length || 0,
right: this.revealWords?.right?.length || 0
};
const detail = {
metrics: this.metrics,
hitMaps: this.hitMaps
@@ -537,6 +577,11 @@ class BookTextureRendererModule extends BaseModule {
};
});
if (Object.keys(reveal).length) detail.reveal = reveal;
this.markPipelineTiming('publishSpread', {
sides: sidesToPublish,
hasReveal: Object.keys(reveal).length > 0,
wordCounts
});
document.dispatchEvent(new CustomEvent('webgl-book:page-canvases', {
detail
}));