Skip to content

Commit 4a2b256

Browse files
authored
fix(web): resolve rendering bug of sub-second timeline revisions (#558)
* fix(web): resolve rendering bug of sub-second timeline revisions The timeline visualizer previously failed to render revisions with durations shorter than 1 second properly. This was caused by an integer underflow in the vertex shader (`revision-v2.vertex.glsl`) when calculating the lower bound for clipping (`minTime.y`). By subtracting `1e10-1.0` (which is too large to safely cast to a uint) from `vs.leftEdgeTime.y`, the calculation yielded a corrupted huge number. The subsequent component-wise `max(time.xy, minTime)` overwrote the starting nanoseconds (`time.y`) with this corrupt number, resulting in incorrect width calculations for sub-second revisions. The shader logic has been updated to set the nanosecond bound `minTime.y` explicitly to `0`. This securely preserves the actual nanoseconds `time.y` when applying the component-wise max. Also added a new `DenseRevisions` story in `timeline-chart.stories.ts` to test high-density short revisions. Fixe #557 * Fix issues pointed by gemini code assist
1 parent 20a3cc4 commit 4a2b256

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

web/src/app/timeline/components/timeline-chart.stories.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,43 @@ export const Composer: Story = {
261261
activeLogsIndices: composerBuilder.getAllActiveLogIndices(),
262262
},
263263
};
264+
265+
function generateMockDenseRevisionsViewModel(): DemoViewModelBuilder {
266+
const testDuration = 200 * 10; // 2 seconds (10 revisions * 200ms)
267+
const builder = new DemoViewModelBuilder(
268+
START_TIME,
269+
START_TIME + testDuration,
270+
);
271+
272+
const revisions = [];
273+
for (let i = 0; i < 10; i++) {
274+
revisions.push(
275+
builder.createRevision(
276+
START_TIME + i * 200,
277+
START_TIME + (i + 1) * 200,
278+
i % 2 === 0
279+
? RevisionState.RevisionStateExisting
280+
: RevisionState.RevisionStateInferred,
281+
RevisionVerb.RevisionVerbUpdate,
282+
),
283+
);
284+
}
285+
286+
builder.createTimeline(
287+
'core/v1#pod#default#dense-revisions',
288+
ParentRelationship.RelationshipChild,
289+
...revisions,
290+
);
291+
292+
return builder;
293+
}
294+
295+
const denseBuilder = generateMockDenseRevisionsViewModel();
296+
export const DenseRevisions: Story = {
297+
args: {
298+
chartViewModel: denseBuilder.getChartViewModel(),
299+
rulerViewModel: denseBuilder.getRulerViewModel(window.innerWidth),
300+
activeLogsIndices: denseBuilder.getAllActiveLogIndices(),
301+
pixelsPerMs: window.innerWidth / (200 * 10),
302+
},
303+
};

web/src/assets/revision-v2.vertex.glsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ precision highp float;
33
precision highp int;
44

55
#define MAX_REVISION_INDEX_DIGITS 5
6-
#define MIN_LEFT_REVISION_LOCATION -300.0
6+
#define MIN_LEFT_REVISION_LOCATION 300.0
77

88
#include "v2.shared.glsl"
99
#include "revision-v2.shared.glsl"
@@ -54,7 +54,7 @@ void main(){
5454
// 1. Calculate relative time difference from the viewport left edge.
5555
// Caps the time.xy with the time calculated from the screen space value not to subtract very small value and cause float precision issue on uv.
5656
// We can ignore the edge case that minTime could be negative because vs.leftEdgeTime should be enough larger than 0.(It's unix time)
57-
uvec2 minTime = vs.leftEdgeTime - uvec2(MIN_LEFT_REVISION_LOCATION / float(vs.pixelsPerMs) / 1000.0, 1e10-1.0); // y component should always larger than time.y
57+
uvec2 minTime = uvec2(vs.leftEdgeTime.x - uint(max(1.0,MIN_LEFT_REVISION_LOCATION / float(vs.pixelsPerMs) / 1000.0)), 0);
5858
uvec2 cappedTime = max(time.xy, minTime);
5959
ivec2 leftEdgeRelativeTime = ivec2(cappedTime.xy - vs.leftEdgeTime);
6060
ivec2 durationTime = ivec2(time.zw - cappedTime.xy);

0 commit comments

Comments
 (0)