diff --git a/geometry.js b/geometry.js index c69a0aa..1ab0134 100644 --- a/geometry.js +++ b/geometry.js @@ -1,196 +1,3 @@ -let colors = {}; -let rasterized = {}; - -// https://stackoverflow.com/a/17243070 -function hsv_to_rgb(h, s, v) { - let r, g, b; - - const i = Math.floor(h * 6); - const f = h * 6 - i; - const p = v * (1 - s); - const q = v * (1 - f * s); - const t = v * (1 - (1 - f) * s); - - switch (i % 6) { - case 0: r = v, g = t, b = p; break; - case 1: r = q, g = v, b = p; break; - case 2: r = p, g = v, b = t; break; - case 3: r = p, g = q, b = v; break; - case 4: r = t, g = p, b = v; break; - case 5: r = v, g = p, b = q; break; - } - - return [ - Math.round(r * 255), - Math.round(g * 255), - Math.round(b * 255) - ]; -} -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]; - } - - colors[stage_name] = hsv_to_rgb(Math.random(), 0.56, 0.56); - - return colors[stage_name]; -} - -function rasterize_and_pack(text, cycles) { - // TODO: handle texture is full or stuff don't fit (unlikely) - - const key = text; - - if (key in rasterized) { - return rasterized[key]; - } - - 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; - if (raster_tile.x === config.raster_texture_size / config.w) { - raster_tile.x = 0; - raster_tile.y += 1; - } - - rasterized[key] = [u, v]; - - if (cycles > 1) { - gl.bindTexture(gl.TEXTURE_2D, textures['numbers']); - for (let i = numbers_rasterized + 1; i <= cycles; ++i) { - const u = number_tile.x * config.w / config.raster_texture_size; - const v = number_tile.y * config.h / config.raster_texture_size; - - rasterize(i); - - gl.texSubImage2D(gl.TEXTURE_2D, 0, - number_tile.x * config.w, number_tile.y * config.h, - config.w, config.h, - gl.RGBA, gl.UNSIGNED_BYTE, - c2d.canvas - ); - - number_tile.x += 1; - if (number_tile.x === config.raster_texture_size / config.w) { - number_tile.x = 0; - number_tile.y += 1; - } - - rasterized[i] = [u, v]; - } - - if (cycles > numbers_rasterized) { - numbers_rasterized = cycles; - } - } - - return [u, v]; -} - -function pack_instruction(instruction, positions, sizes, colors, uvs, starts, y) { - starts.push(positions.length); - - 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) { - a = 80; - } - - 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); - } - - return instruction.lanes['0'].length; -} - -function generate(trace_id) { - const before = performance.now(); - - const result = { - 'count': 0, - }; - - const positions = []; - const sizes = []; - const colors = []; - const uvs = []; - const starts = []; - - let instructions = {}; - - if (trace_id in traces) { - instructions = traces[trace_id].raw; - } - - let y = 0; - - for (let i = 0; i < instructions.length; ++i) { - const instruction = instructions[i]; - // TODO: make all quads same size, abuse this fact - result.count += pack_instruction(instruction, positions, sizes, colors, uvs, starts, y); - if (config.limit > 0 && result.count >= config.limit) { - break; - } - ++y; - } - - starts.push(positions.length); - - if (config.show_texture) { - 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; - result.trace_id = trace_id; - result.uploaded = false; - } else { - result.pos = new Float32Array(positions); - result.size = new Float32Array(sizes); - result.color = new Uint8Array(colors); - result.uv = new Float32Array(uvs); - result.trace_id = trace_id; - result.uploaded = false; - result.start = new Int32Array(starts); - } - - const after = performance.now(); - - console.log(`Generated geometry in ${Math.round(after - before)}ms`); - - return result; -} - function clip(quads) { if (config.show_texture) { return quads; diff --git a/parse.js b/import_worker.js similarity index 50% rename from parse.js rename to import_worker.js index 3f34916..141a4ce 100644 --- a/parse.js +++ b/import_worker.js @@ -1,3 +1,22 @@ +let traces = {}; +let config = {}; +let raster_tile = {'x': 0, 'y': 0}; +let numbers_rasterized = 0; + +onmessage = (e) => { + const msg = e.data; + + if (msg.type === 'init') { + config = msg.config; + } else if (msg.type === 'import') { + const text = msg.text; + if (parse(text)) { + traces['0'].geo = generate('0'); + postMessage({'type': 'trace', 'data': traces['0']}); + } + } +} + function parse(text) { // https://github.com/shioyadan/Konata/blob/master/docs/kanata-log-format.md @@ -12,6 +31,13 @@ function parse(text) { //console.log(text); for (let i = 0; i < text.length; ++i) { + const last_percent = Math.round((i - 1) / text.length * 100); + const this_percent = Math.round(i / text.length * 100); + + if (this_percent != last_percent) { + postMessage({'type': 'progress_parse', 'data': this_percent}) + } + if (text[i] === '\n') { // TODO: speed const line_copy = text.substring(line_start, i); @@ -163,18 +189,15 @@ function parse(text) { } } - traces['0'] = { // The fact these are sorted is used extensively over the code 'raw': Object.values(instructions).sort((a, b) => a.cycle - b.cycle), }; - - traces['0'].geo = generate('0'); - const after = performance.now(); console.log(`Parsed in ${Math.round(after - before)}ms`); + return true; } @@ -195,3 +218,192 @@ function assert_arglenmin(args, arglen, command) { return true; } + +let colors = {}; +let rasterized = {}; + +// https://stackoverflow.com/a/17243070 +function hsv_to_rgb(h, s, v) { + let r, g, b; + + const i = Math.floor(h * 6); + const f = h * 6 - i; + const p = v * (1 - s); + const q = v * (1 - f * s); + const t = v * (1 - (1 - f) * s); + + switch (i % 6) { + case 0: r = v, g = t, b = p; break; + case 1: r = q, g = v, b = p; break; + case 2: r = p, g = v, b = t; break; + case 3: r = p, g = q, b = v; break; + case 4: r = t, g = p, b = v; break; + case 5: r = v, g = p, b = q; break; + } + + return [ + Math.round(r * 255), + Math.round(g * 255), + Math.round(b * 255) + ]; +} + +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]; + } + + colors[stage_name] = hsv_to_rgb(Math.random(), 0.56, 0.56); + + return colors[stage_name]; +} + +function rasterize_and_pack(text, cycles) { + // TODO: handle texture is full or stuff don't fit (unlikely) + + const key = text; + + if (key in rasterized) { + return rasterized[key]; + } + + const u = raster_tile.x * config.w / config.raster_texture_size; + const v = raster_tile.y * config.h / config.raster_texture_size; + + postMessage({'type': 'rasterize', 'data': { 'text': text, 'at': {'x': raster_tile.x, 'y': raster_tile.y}}}); + + 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]; + + if (cycles > 1) { + for (let i = numbers_rasterized + 1; i <= cycles; ++i) { + const u = raster_tile.x * config.w / config.raster_texture_size; + const v = raster_tile.y * config.h / config.raster_texture_size; + + postMessage({'type': 'rasterize', 'data': { 'text': i, 'at': {'x': raster_tile.x, 'y': raster_tile.y}}}); + + raster_tile.x += 1; + + if (raster_tile.x === config.raster_texture_size / config.w) { + raster_tile.x = 0; + raster_tile.y += 1; + } + + rasterized[i] = [u, v]; + } + + if (cycles > numbers_rasterized) { + numbers_rasterized = cycles; + } + } + + return [u, v]; +} + +function pack_instruction(instruction, positions, sizes, colors, uvs, starts, y) { + starts.push(positions.length); + + 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) { + a = 80; + } + + 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); + } + + return instruction.lanes['0'].length; +} + +function generate(trace_id) { + const before = performance.now(); + + const result = { + 'count': 0, + }; + + const positions = []; + const sizes = []; + const colors = []; + const uvs = []; + const starts = []; + + let instructions = {}; + + if (trace_id in traces) { + instructions = traces[trace_id].raw; + } + + let y = 0; + + for (let i = 0; i < instructions.length; ++i) { + const last_percent = Math.round((i - 1) / instructions.length * 100); + const this_percent = Math.round(i / instructions.length * 100); + + if (this_percent !== last_percent) { + postMessage({'type': 'progress_generate', 'data': this_percent}) + } + + const instruction = instructions[i]; + // TODO: make all quads same size, abuse this fact + result.count += pack_instruction(instruction, positions, sizes, colors, uvs, starts, y); + if (config.limit > 0 && result.count >= config.limit) { + break; + } + ++y; + } + + starts.push(positions.length); + + if (config.show_texture) { + 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; + result.trace_id = trace_id; + result.uploaded = false; + } else { + result.pos = new Float32Array(positions); + result.size = new Float32Array(sizes); + result.color = new Uint8Array(colors); + result.uv = new Float32Array(uvs); + result.trace_id = trace_id; + result.uploaded = false; + result.start = new Int32Array(starts); + } + + const after = performance.now(); + + console.log(`Generated geometry in ${Math.round(after - before)}ms`); + + return result; +} + diff --git a/index.html b/index.html index 7d17418..5161125 100644 --- a/index.html +++ b/index.html @@ -12,12 +12,11 @@ - - +