let colors = {}; let rasterized = {}; function get_color(stage_name) { if (stage_name in config.predefined_colors) { return config.predefined_colors[stage_name]; } if (stage_name in colors) { return colors[stage_name]; } const r = Math.floor(Math.random() * 155); const g = Math.floor(Math.random() * 155); const b = Math.floor(Math.random() * 155); colors[stage_name] = [ 100 + r, 100 + g, 100 + b ]; return colors[stage_name]; } function rasterize_and_pack(text, cycles) { // TODO: handle texture is full or stuff don't fit (unlikely) const key = text + '@' + cycles; if (key in rasterized) { return rasterized[key]; } const tiles_needed = cycles - 1 + 1; // stage name + count from one if (tiles_needed > config.raster_texture_size / config.w - raster_tile.x) { raster_tile.x = 0; raster_tile.y += 1; } const u = raster_tile.x * config.w / config.raster_texture_size; const v = raster_tile.y * config.h / config.raster_texture_size; rasterize(text); gl.bindTexture(gl.TEXTURE_2D, textures['raster']); gl.texSubImage2D(gl.TEXTURE_2D, 0, raster_tile.x * config.w, raster_tile.y * config.h, config.w, config.h, gl.RGBA, gl.UNSIGNED_BYTE, c2d.canvas ); raster_tile.x += 1; for (let i = 1; i <= cycles; ++i) { rasterize(i); gl.bindTexture(gl.TEXTURE_2D, textures['raster']); gl.texSubImage2D(gl.TEXTURE_2D, 0, raster_tile.x * config.w, raster_tile.y * config.h, config.w, config.h, gl.RGBA, gl.UNSIGNED_BYTE, c2d.canvas ); raster_tile.x += 1; } if (raster_tile.x === config.raster_texture_size / config.w) { raster_tile.x = 0; raster_tile.y += 1; } rasterized[key] = [u, v]; return [u, v]; } function generate(trace_id) { const before = performance.now(); const result = { 'count': 0, }; const positions = []; const sizes = []; const colors = []; const uvs = []; let instructions = {}; if (trace_id in traces) { instructions = traces[trace_id].raw; } let y = 0; for (const id in instructions) { const instruction = instructions[id]; for (let i = 0; i < instruction.lanes['0'].length; ++i) { const stage = instruction.lanes['0'][i]; let stage_cycles; if (i < instruction.lanes['0'].length - 1) { const next_stage = instruction.lanes['0'][i + 1]; stage_cycles = next_stage.c - stage.c; } else { stage_cycles = instruction.retcyc - stage.c; } let [r, g, b] = get_color(stage.name); if (!instruction.retired) { r = Math.max(50, r - 50); g = Math.max(50, g - 50); b = Math.max(50, b - 50); } const [u, v] = rasterize_and_pack(stage.name, stage_cycles); sizes.push(stage_cycles * config.w, 1 * config.h); positions.push(config.w * stage.c, config.h * y); colors.push(r, g, b, 255); uvs.push(u, v); result.count++; if (config.limit > 0 && result.count >= config.limit) { break; } } ++y; } if (false) { result.pos = new Float32Array([0, 0]); result.size = new Float32Array([config.raster_texture_size, config.raster_texture_size]); result.color = new Uint8Array([0, 0, 0, 255]); result.uv = new Float32Array([0, 0]); result.count = 1; } else { result.pos = new Float32Array(positions); result.size = new Float32Array(sizes); result.color = new Uint8Array(colors); result.uv = new Float32Array(uvs); } const after = performance.now(); console.log(`Generated geometry in ${Math.round(after - before)}ms`); return result; }