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]; } let cycles_total_padding = (cycles - 1) * config.padding; let bonus_cells = Math.ceil(cycles_total_padding / config.w); const tiles_needed = cycles - 1 + 1 + bonus_cells; // stage name + count cycles 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; raster_tile.x += cycles + bonus_cells; 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); let a = 255; if (!instruction.retired) { r = Math.max(50, r - 50); g = Math.max(50, g - 50); b = Math.max(50, b - 50); a = 100; } const [u, v] = rasterize_and_pack(stage.name, stage_cycles); sizes.push(stage_cycles * config.w + (stage_cycles - 1) * config.padding, 1 * config.h); positions.push(config.w * stage.c + config.padding * (stage.c - 1), config.h * y + config.padding * (y - 1)); colors.push(r, g, b, a); 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; }