mirror of
https://github.com/jlfwong/speedscope.git
synced 2024-11-22 22:14:25 +03:00
Make NDC an implementation detail
This commit is contained in:
parent
37e2b78ad8
commit
5412573ba3
@ -63,15 +63,6 @@ export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps,
|
||||
)
|
||||
}
|
||||
|
||||
private physicalViewSpaceToNDC() {
|
||||
return AffineTransform.withScale(new Vec2(1, -1)).times(
|
||||
AffineTransform.betweenRects(
|
||||
new Rect(new Vec2(0, 0), this.physicalViewSize()),
|
||||
new Rect(new Vec2(-1, -1), new Vec2(2, 2))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private logicalToPhysicalViewSpace() {
|
||||
return AffineTransform.withScale(new Vec2(DEVICE_PIXEL_RATIO, DEVICE_PIXEL_RATIO))
|
||||
}
|
||||
@ -83,8 +74,7 @@ export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps,
|
||||
}
|
||||
|
||||
private cachedRenderer: TextureCachedRenderer<{
|
||||
physicalSize: Vec2,
|
||||
configSpaceToNDC: AffineTransform
|
||||
physicalSize: Vec2
|
||||
}> | null = null
|
||||
private renderRects() {
|
||||
if (!this.container) return
|
||||
@ -93,8 +83,6 @@ export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps,
|
||||
shouldUpdate(oldProps, newProps) {
|
||||
if (!oldProps.physicalSize.equals(newProps.physicalSize)) {
|
||||
return true
|
||||
} else if (!oldProps.configSpaceToNDC.equals(newProps.configSpaceToNDC)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
@ -110,11 +98,8 @@ export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps,
|
||||
})
|
||||
}
|
||||
|
||||
const configSpaceToNDC = this.physicalViewSpaceToNDC().times(this.configSpaceToPhysicalViewSpace())
|
||||
|
||||
this.props.canvasContext.renderInto(this.container, (context) => {
|
||||
this.cachedRenderer!.render(context, {
|
||||
configSpaceToNDC,
|
||||
physicalSize: this.physicalViewSize()
|
||||
})
|
||||
this.props.canvasContext.drawViewportRectangle({
|
||||
|
@ -11,7 +11,7 @@ interface RangeTreeNode {
|
||||
getMaxRight(): number
|
||||
getRectCount(): number
|
||||
getChildren(): RangeTreeNode[]
|
||||
forEachBatchInViewport(configSpaceViewport: Rect, cb: (batch: RectangleBatch) => void): void
|
||||
forEachBatchWithinBounds(configSpaceViewport: Rect, cb: (batch: RectangleBatch) => void): void
|
||||
}
|
||||
|
||||
class RangeTreeLeafNode implements RangeTreeNode {
|
||||
@ -27,7 +27,7 @@ class RangeTreeLeafNode implements RangeTreeNode {
|
||||
getMaxRight() { return this.maxRight }
|
||||
getRectCount() { return this.batch.getRectCount() }
|
||||
getChildren() { return this.children }
|
||||
forEachBatchInViewport(configSpaceViewport: Rect, cb: (batch: RectangleBatch) => void) {
|
||||
forEachBatchWithinBounds(configSpaceViewport: Rect, cb: (batch: RectangleBatch) => void) {
|
||||
if (this.maxRight < configSpaceViewport.left()) return
|
||||
if (this.minLeft > configSpaceViewport.right()) return
|
||||
cb(this.batch)
|
||||
@ -53,21 +53,16 @@ class RangeTreeInteriorNode implements RangeTreeNode {
|
||||
getMaxRight() { return this.children[this.children.length - 1].getMaxRight() }
|
||||
getRectCount() { return this.rectCount }
|
||||
getChildren() { return this.children }
|
||||
forEachBatchInViewport(configSpaceViewport: Rect, cb: (batch: RectangleBatch) => void) {
|
||||
if (this.getMaxRight() < configSpaceViewport.left()) return
|
||||
if (this.getMinLeft() > configSpaceViewport.right()) return
|
||||
forEachBatchWithinBounds(configSpaceViewport: Rect, cb: (batch: RectangleBatch) => void) {
|
||||
// if (this.getMaxRight() < configSpaceViewport.left()) return
|
||||
// if (this.getMinLeft() > configSpaceViewport.right()) return
|
||||
|
||||
for (let child of this.children) {
|
||||
child.forEachBatchInViewport(configSpaceViewport, cb)
|
||||
child.forEachBatchWithinBounds(configSpaceViewport, cb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface BoundedLayerProps {
|
||||
configSpaceToNDC: AffineTransform
|
||||
physicalSize: Vec2
|
||||
}
|
||||
|
||||
export interface FlamechartRendererProps {
|
||||
configSpaceSrcRect: Rect
|
||||
physicalSpaceDstRect: Rect
|
||||
@ -111,30 +106,25 @@ class BoundedLayer {
|
||||
this.rootNode = new RangeTreeInteriorNode(leafNodes)
|
||||
}
|
||||
|
||||
render(props: BoundedLayerProps) {
|
||||
render(props: FlamechartRendererProps) {
|
||||
const configSpaceTop = this.stackDepth + 1
|
||||
const configSpaceBottom = configSpaceTop + 1
|
||||
|
||||
const ndcToConfigSpace = props.configSpaceToNDC.inverted()
|
||||
if (!ndcToConfigSpace) return
|
||||
const configSpaceViewportRect = ndcToConfigSpace.transformRect(new Rect(
|
||||
new Vec2(-1, -1), new Vec2(2, 2)
|
||||
))
|
||||
|
||||
if (configSpaceTop > configSpaceViewportRect.bottom()) {
|
||||
// Entire layer is below the viewport
|
||||
const { configSpaceSrcRect, physicalSpaceDstRect } = props
|
||||
if (configSpaceTop > configSpaceSrcRect.bottom()) {
|
||||
// Entire layer is below the config space bounds
|
||||
return
|
||||
}
|
||||
|
||||
if (configSpaceBottom < configSpaceViewportRect.top()) {
|
||||
// Entire layer is above the viewport
|
||||
if (configSpaceBottom < configSpaceSrcRect.top()) {
|
||||
// Entire layer is above the config space bounds
|
||||
return
|
||||
}
|
||||
|
||||
this.rootNode.forEachBatchInViewport(configSpaceViewportRect, batch => {
|
||||
this.rootNode.forEachBatchWithinBounds(configSpaceSrcRect, batch => {
|
||||
this.canvasContext.drawRectangleBatch({
|
||||
configSpaceToNDC: props.configSpaceToNDC,
|
||||
physicalSize: props.physicalSize,
|
||||
configSpaceSrcRect,
|
||||
physicalSpaceDstRect,
|
||||
batch
|
||||
})
|
||||
})
|
||||
@ -173,12 +163,7 @@ export class FlamechartRenderer {
|
||||
})
|
||||
const fbo = canvasContext.gl.framebuffer({ color: [this.texture] })
|
||||
|
||||
const configSpaceToNDC = AffineTransform.withScale(new Vec2(1, -1)).times(
|
||||
AffineTransform.betweenRects(
|
||||
this.getConfigSpaceContentRect(),
|
||||
new Rect(new Vec2(-1, -1), new Vec2(2, 2))
|
||||
)
|
||||
)
|
||||
const configSpaceSrcRect = this.getConfigSpaceContentRect()
|
||||
|
||||
canvasContext.gl({
|
||||
viewport: (context, props) => {
|
||||
@ -191,12 +176,12 @@ export class FlamechartRenderer {
|
||||
},
|
||||
framebuffer: fbo
|
||||
})((context: regl.Context) => {
|
||||
const physicalSize = new Vec2(context.drawingBufferWidth, context.drawingBufferHeight)
|
||||
const physicalSpaceDstRect = new Rect(
|
||||
new Vec2(),
|
||||
new Vec2(context.viewportWidth, context.viewportHeight)
|
||||
)
|
||||
for (let layer of this.layers) {
|
||||
layer.render({
|
||||
physicalSize,
|
||||
configSpaceToNDC
|
||||
})
|
||||
layer.render({ configSpaceSrcRect, physicalSpaceDstRect })
|
||||
}
|
||||
})
|
||||
|
||||
@ -209,13 +194,13 @@ export class FlamechartRenderer {
|
||||
const { configSpaceSrcRect, physicalSpaceDstRect } = props
|
||||
const content = this.getConfigSpaceContentRect()
|
||||
|
||||
const textureSize = new Vec2(this.texture.width, this.texture.height)
|
||||
|
||||
const physicalSpaceSrcRect = new Rect(
|
||||
configSpaceSrcRect.origin.dividedByPointwise(content.size).timesPointwise(textureSize),
|
||||
configSpaceSrcRect.size.dividedByPointwise(content.size).timesPointwise(textureSize)
|
||||
const textureRect = new Rect(
|
||||
new Vec2(), new Vec2(this.texture.width, this.texture.height)
|
||||
)
|
||||
|
||||
const configToTexture = AffineTransform.betweenRects(content, textureRect)
|
||||
const physicalSpaceSrcRect = configToTexture.transformRect(configSpaceSrcRect)
|
||||
|
||||
this.canvasContext.drawTexture({
|
||||
texture: this.texture,
|
||||
srcRect: physicalSpaceSrcRect,
|
||||
|
@ -53,7 +53,7 @@ const DEVICE_PIXEL_RATIO = window.devicePixelRatio
|
||||
* Component to visualize a Flamechart and interact with it via hovering,
|
||||
* zooming, and panning.
|
||||
*
|
||||
* There are 4 vector spaces involved:
|
||||
* There are 3 vector spaces involved:
|
||||
* - Configuration Space: In this space, the horizontal unit is ms, and the
|
||||
* vertical unit is stack depth. Each stack frame is one unit high.
|
||||
* - Logical view space: Origin is top-left, with +y downwards. This represents
|
||||
@ -62,9 +62,6 @@ const DEVICE_PIXEL_RATIO = window.devicePixelRatio
|
||||
* - Physical view space: Origin is top-left, with +y downwards. This represents
|
||||
* the coordinate space of the view as specified in hardware pixels: horizontal
|
||||
* and vertical units are both "physical" pixels.
|
||||
* - Normalized device coordinates: Origin is center, +y upwards. This is the
|
||||
* coordinate space used by GL, which we use to render the frame rectangles
|
||||
* efficiently.
|
||||
*
|
||||
* We use two canvases to draw the flamechart itself: one for the rectangles,
|
||||
* which we render via WebGL, and one for the labels, which we render via 2D
|
||||
|
@ -68,9 +68,9 @@ export class RectangleBatch {
|
||||
}
|
||||
|
||||
export interface RectangleBatchRendererProps {
|
||||
configSpaceToNDC: AffineTransform
|
||||
physicalSize: Vec2
|
||||
batch: RectangleBatch
|
||||
configSpaceSrcRect: Rect
|
||||
physicalSpaceDstRect: Rect
|
||||
}
|
||||
|
||||
export class RectangleBatchRenderer {
|
||||
@ -150,7 +150,18 @@ export class RectangleBatchRenderer {
|
||||
|
||||
uniforms: {
|
||||
configSpaceToNDC: (context, props) => {
|
||||
return props.configSpaceToNDC.flatten()
|
||||
const configToPhysical = AffineTransform.betweenRects(
|
||||
props.configSpaceSrcRect,
|
||||
props.physicalSpaceDstRect
|
||||
)
|
||||
|
||||
const viewportSize = new Vec2(context.viewportWidth, context.viewportHeight)
|
||||
|
||||
const physicalToNDC = AffineTransform
|
||||
.withTranslation(new Vec2(-1, 1))
|
||||
.withScale(new Vec2(2, -2).dividedByPointwise(viewportSize))
|
||||
|
||||
return physicalToNDC.times(configToPhysical).flatten()
|
||||
}
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user