speedscope/flamechart.ts
2017-11-22 19:19:10 -08:00

128 lines
3.1 KiB
TypeScript

import {Profile, Frame} from './profile'
import regl, {ReglCommandConstructor} from 'regl'
interface FlamechartFrame {
frame: Frame
start: number
end: number
}
type StackLayer = FlamechartFrame[]
export class Flamechart {
// Bottom to top
private layers: StackLayer[] = []
private duration: number = 0
private getLayers() { return this.layers }
private appendFrame(layerIndex: number, frame: Frame, timeDelta: number) {
while (layerIndex <= this.layers.length) this.layers.push([])
this.layers[layerIndex].push({
frame: frame,
start: this.duration,
end: this.duration + timeDelta
})
}
private appendSample(stack: Frame[], timeDelta: number) {
for (let i = 0; i < stack.length; i++) {
this.appendFrame(i, stack[i], timeDelta)
}
this.duration += timeDelta
}
private static mergeAdjacentFrames(layer: StackLayer): StackLayer {
const ret: StackLayer = []
for (let flamechartFrame of layer) {
const prev = ret.length > 0 ? ret[ret.length - 1] : null
if (prev && prev.frame === flamechartFrame.frame && prev.end === flamechartFrame.start) {
prev.end = flamechartFrame.end
} else {
ret.push(flamechartFrame)
}
}
return ret
}
constructor(private profile: Profile) {
profile.forEachSample(this.appendSample.bind(this))
this.layers = this.layers.map(Flamechart.mergeAdjacentFrames)
}
}
interface Rect {
left: number
top: number
width: number
height: number
}
type vec2 = [number, number]
type vec3 = [number, number, number]
type mat3 = [number, number, number, number, number, number, number, number, number]
export const rectangleBatchRenderer = (ctx: WebGLRenderingContext, rects: Rect[], colors: vec3[]) => {
const gl = regl(ctx)
const positions: vec2[] = []
const vertexColors: vec3[] = []
const addRectangle = (r: Rect, color: [number, number, number]) => {
const NW: [number, number] = [r.left, r.top]
const NE: [number, number] = [r.left + r.width, r.top]
const SW: [number, number] = [r.left, r.top + r.height]
const SE: [number, number] = [r.left + r.width, r.top + r.height]
positions.push(NW)
positions.push(SW)
positions.push(NE)
positions.push(SW)
positions.push(NE)
positions.push(SE)
for (let i = 0; i < 6; i++) vertexColors.push(color)
}
for (let i = 0; i < rects.length; i++) addRectangle(rects[i], colors[i])
return gl<{
configSpaceToNDC: mat3
}>({
vert: `
uniform mat3 configSpaceToNDC;
attribute vec2 position;
attribute vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
gl_Position = vec4((configSpaceToNDC * vec3(position, 1)).xy, 0, 1);
}
`,
frag: `
precision mediump float;
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1);
}
`,
attributes: {
position: positions,
color: vertexColors
},
uniforms: {
configSpaceToNDC: (context, props) => {
return props.configSpaceToNDC
}
},
primitive: 'triangles',
count: colors.length
})
}