From 31cfc7f82aa775dda29b0cf70c9727b840415916 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Wed, 3 Apr 2024 19:44:58 +0200 Subject: [PATCH 01/22] graph startup collapsed, group overlay bug, collapsed NestedSDFG lod change --- src/overlays/logical_group_overlay.ts | 4 ++++ src/renderer/renderer.ts | 24 ++++++++++++++++++++++++ src/renderer/renderer_elements.ts | 4 +++- src/sdfv.ts | 2 +- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/overlays/logical_group_overlay.ts b/src/overlays/logical_group_overlay.ts index 98c0c6f0..52acabb5 100644 --- a/src/overlays/logical_group_overlay.ts +++ b/src/overlays/logical_group_overlay.ts @@ -91,6 +91,10 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { if (sdfgGroups === undefined) return; + if (!graph) { + return; + } + graph.nodes().forEach(v => { const block = graph.node(v); diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index d88422e7..416cd349 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -859,6 +859,30 @@ export class SDFGRenderer extends EventEmitter { // Create the initial SDFG layout // Loading animation already started in the file_read_complete function in sdfv.ts // to also include the JSON parsing step. + // Initial layout collapsed + this.for_all_sdfg_elements( + (_t: SDFGElementGroup, _d: any, obj: any) => { + if ('is_collapsed' in obj.attributes && + !obj.type.endsWith('Exit')) + obj.attributes.is_collapsed = true; + } + ); + this.emit('collapse_state_changed', true, true); + + this.relayout(); + + if (this.graph) { + traverseSDFGScopes( + this.graph, (node: SDFGNode, _: DagreSDFG) => { + if(node.attributes().is_collapsed) { + node.attributes().is_collapsed = false; + return false; + } + return true; + } + ); + } + this.emit('collapse_state_changed', false, true); this.relayout(); // Set mouse event handlers diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 85a4ba81..68197e34 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -2624,7 +2624,8 @@ export function drawStateContents( )) continue; - if (node instanceof NestedSDFG) { + // Simple draw for non-collapsed NestedSDFGs + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { if (lod && ( Math.sqrt(node.height * node.width) / ppp ) < SDFV.STATE_LOD) { @@ -2633,6 +2634,7 @@ export function drawStateContents( continue; } } else { + // Simple draw node if (lod && ppp > SDFV.NODE_LOD) { node.simple_draw(renderer, ctx, mousePos); node.debug_draw(renderer, ctx); diff --git a/src/sdfv.ts b/src/sdfv.ts index d1d5055b..f3d3a792 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -528,7 +528,7 @@ function file_read_complete(sdfv: SDFV): void { sdfv.get_renderer()?.destroy(); sdfv.set_renderer(new SDFGRenderer(sdfv, sdfg, container, mouse_event)); sdfv.close_menu(); - }, 20); + }, 10); } } From 85627ceec3c80ce8e2bb087b3a6fe0ae90a9281c Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Wed, 3 Apr 2024 19:48:35 +0200 Subject: [PATCH 02/22] added missing comment --- src/renderer/renderer.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 416cd349..f7b117cf 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -856,10 +856,12 @@ export class SDFGRenderer extends EventEmitter { else this.bgcolor = window.getComputedStyle(this.canvas).backgroundColor; + // Create the initial SDFG layout // Loading animation already started in the file_read_complete function in sdfv.ts // to also include the JSON parsing step. - // Initial layout collapsed + + // Initial layout fully collapsed this.for_all_sdfg_elements( (_t: SDFGElementGroup, _d: any, obj: any) => { if ('is_collapsed' in obj.attributes && @@ -868,9 +870,9 @@ export class SDFGRenderer extends EventEmitter { } ); this.emit('collapse_state_changed', true, true); - this.relayout(); + // Expand by one level if (this.graph) { traverseSDFGScopes( this.graph, (node: SDFGNode, _: DagreSDFG) => { From 378630ed796997e4e845fad1dcddea90106805a4 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Sun, 7 Apr 2024 18:33:20 +0200 Subject: [PATCH 03/22] added code to layouter to order the connectors (much less edges intertwine) --- src/renderer/renderer.ts | 65 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index f7b117cf..185b3e28 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -4078,7 +4078,7 @@ function relayoutSDFGState( state.nodes.forEach((node: JsonSDFGNode, id: number) => { const gnode: any = g.node(id.toString()); if (!gnode || (omitAccessNodes && gnode instanceof AccessNode)) { - // Rgnore nodes that should not be drawn. + // Ignore nodes that should not be drawn. return; } const topleft = gnode.topleft(); @@ -4121,6 +4121,69 @@ function relayoutSDFGState( } }); + + // Re-order in_connectors for the edges to not intertwine + state.nodes.forEach((node: JsonSDFGNode, id: number) => { + const gnode: any = g.node(id.toString()); + if (!gnode || (omitAccessNodes && gnode instanceof AccessNode)) { + // Ignore nodes that should not be drawn. + return; + } + + const SPACING = SDFV.LINEHEIGHT; + const iConnLength = (SDFV.LINEHEIGHT + SPACING) * Object.keys( + node.attributes.layout.in_connectors + ).length - SPACING; + let iConnX = gnode.x - iConnLength / 2.0 + SDFV.LINEHEIGHT / 2.0; + + // Dictionary that saves the x coordinates of each connector's source node or source connector. + // This is later used to reorder the in_connectors based on the sources' x coordinates. + let sources_x_coordinates: { [key: string]: number } = {}; + + // For each in_connector, find the x coordinate of the source node connector + for (const c of gnode.in_connectors) { + state.edges.forEach((edge: JsonSDFGEdge, id: number) => { + if (edge.dst === gnode.id.toString() && edge.dst_connector === c.data.name) { + + const source_node: SDFGNode = g.node(edge.src); + if (source_node) { + + // If source node doesn't have out_connectors, take + // the source node's own x coordinate + if (source_node.out_connectors.length === 0) { + sources_x_coordinates[c.data.name] = source_node.x; + } + else { + // Find the corresponding out_connector and take its x coordinate + for (let i = 0; i < source_node.out_connectors.length; ++i) { + if (source_node.out_connectors[i].data.name === edge.src_connector) { + sources_x_coordinates[c.data.name] = source_node.out_connectors[i].x; + break; + } + } + } + } + } + }); + + } + + // Sort the dictionary by x coordinate values + let sources_x_coordinates_sorted = Object.entries(sources_x_coordinates); + sources_x_coordinates_sorted.sort((a, b) => a[1] - b[1]); + + // In the order of the sorted source x coordinates, set the x coordinates of the in_connectors + for (const element of sources_x_coordinates_sorted) { + for (const c of gnode.in_connectors) { + if (c.data.name === element[0]) { + c.x = iConnX; + iConnX += SDFV.LINEHEIGHT + SPACING; + continue; + } + } + } + }); + state.edges.forEach((edge: JsonSDFGEdge, id: number) => { const nedge = check_and_redirect_edge(edge, drawnNodes, state); if (!nedge) return; From e6b9576fea8ed9293336e4518c26585cd5d49eda Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Mon, 8 Apr 2024 19:29:27 +0200 Subject: [PATCH 04/22] first code for summarised edges, adjusted nodesep & ranksep --- src/renderer/renderer.ts | 33 ++++++++++++- src/renderer/renderer_elements.ts | 78 ++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 185b3e28..514c4fdd 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -3839,6 +3839,8 @@ function relayoutSDFGState( if (state.nodes.length >= 1000) layoutOptions.ranker = 'longest-path'; + layoutOptions.nodesep = 20; // default: 50 + layoutOptions.ranksep = 70; // default: 50 g.setGraph(layoutOptions); // Set an object for the graph label. @@ -4129,7 +4131,16 @@ function relayoutSDFGState( // Ignore nodes that should not be drawn. return; } - + + const n_of_in_connectors = gnode.in_connectors.length; + const n_of_out_connectors = gnode.out_connectors.length; + if (n_of_in_connectors > 10) { + gnode.summarise_in_edges = true; + } + if (n_of_out_connectors > 10) { + gnode.summarise_out_edges = true; + } + const SPACING = SDFV.LINEHEIGHT; const iConnLength = (SDFV.LINEHEIGHT + SPACING) * Object.keys( node.attributes.layout.in_connectors @@ -4144,6 +4155,12 @@ function relayoutSDFGState( for (const c of gnode.in_connectors) { state.edges.forEach((edge: JsonSDFGEdge, id: number) => { if (edge.dst === gnode.id.toString() && edge.dst_connector === c.data.name) { + + // If in-edges are to be summarised, set Memlet.summarised + const gedge = g.edge(edge.src, edge.dst, id.toString()) as Memlet; + if (gedge && gnode.summarise_in_edges) { + gedge.summarised = true; + } const source_node: SDFGNode = g.node(edge.src); if (source_node) { @@ -4182,6 +4199,20 @@ function relayoutSDFGState( } } } + + // For out_connectors set Memlet.summarised for all out-edges if needed + if (gnode.summarise_out_edges) { + for (const c of gnode.out_connectors) { + state.edges.forEach((edge: JsonSDFGEdge, id: number) => { + if (edge.src === gnode.id.toString() && edge.src_connector === c.data.name) { + const gedge = g.edge(edge.src, edge.dst, id.toString()) as Memlet; + if (gedge) { + gedge.summarised = true; + } + } + }); + } + } }); state.edges.forEach((edge: JsonSDFGEdge, id: number) => { diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 68197e34..c30a45b7 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -54,6 +54,13 @@ export class SDFGElement { public selected: boolean = false; public highlighted: boolean = false; public hovered: boolean = false; + + // Used to draw edge summary instead of all edges separately. + // Helps with rendering performance when too many edges would be drawn on the screen. + // These two fields get set in the layouter, depending on the number of in/out_connectors + // of a node. + public summarise_in_edges: boolean = false; + public summarise_out_edges: boolean = false; public x: number = 0; public y: number = 0; @@ -206,6 +213,59 @@ export class SDFGElement { ): string { return renderer.getCssProperty(propertyName); } + + public draw_edge_summary( + renderer: SDFGRenderer, ctx: CanvasRenderingContext2D + ): void { + + // Only draw if close enough + const canvas_manager = renderer.get_canvas_manager(); + const ppp = canvas_manager?.points_per_pixel(); + if (!(ctx as any).lod || (ppp && ppp < SDFV.EDGE_LOD)) { + const topleft = this.topleft(); + + if (this.summarise_in_edges) { + if (this.in_connectors.length > 0) { + let min_connector_x = Number.MAX_SAFE_INTEGER; + let max_connector_x = Number.MIN_SAFE_INTEGER; + this.in_connectors.forEach((c: Connector) => { + if (c.x < min_connector_x) { + min_connector_x = c.x; + } + if (c.x > max_connector_x) { + max_connector_x = c.x; + } + }) + ctx.beginPath(); + ctx.moveTo(min_connector_x, topleft.y - 12); + ctx.lineTo(max_connector_x, topleft.y - 12); + ctx.closePath(); + ctx.strokeStyle = this.strokeStyle(renderer); + ctx.stroke(); + } + } + if (this.summarise_out_edges) { + if (this.out_connectors.length > 0) { + let min_connector_x = Number.MAX_SAFE_INTEGER; + let max_connector_x = Number.MIN_SAFE_INTEGER; + this.out_connectors.forEach((c: Connector) => { + if (c.x < min_connector_x) { + min_connector_x = c.x; + } + if (c.x > max_connector_x) { + max_connector_x = c.x; + } + }) + ctx.beginPath(); + ctx.moveTo(min_connector_x, topleft.y + this.height + 12); + ctx.lineTo(max_connector_x, topleft.y + this.height + 12); + ctx.closePath(); + ctx.strokeStyle = this.strokeStyle(renderer); + ctx.stroke(); + } + } + } + } } // SDFG as an element (to support properties) @@ -1085,7 +1145,11 @@ export abstract class Edge extends SDFGElement { } -export class Memlet extends Edge { +export class Memlet extends Edge { + + // Currently used for Memlets to decide if they need to be drawn or not. + // Set in the layouter. + public summarised: boolean = false; public create_arrow_line(ctx: CanvasRenderingContext2D): void { // Draw memlet edges with quadratic curves through the arrow points. @@ -1715,6 +1779,9 @@ export class ScopeNode extends SDFGNode { renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, _mousepos?: Point2D ): void { + + this.draw_edge_summary(renderer, ctx); + let draw_shape; if (this.data.node.attributes.is_collapsed) { draw_shape = () => { @@ -2165,6 +2232,8 @@ export class Tasklet extends SDFGNode { if (!canvas_manager) return; + this.draw_edge_summary(renderer, ctx); + const topleft = this.topleft(); drawOctagon(ctx, topleft, this.width, this.height); ctx.strokeStyle = this.strokeStyle(renderer); @@ -2294,6 +2363,9 @@ export class NestedSDFG extends SDFGNode { renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, mousepos?: Point2D ): void { + + this.draw_edge_summary(renderer, ctx); + if (this.data.node.attributes.is_collapsed) { const topleft = this.topleft(); drawOctagon(ctx, topleft, this.width, this.height); @@ -2562,6 +2634,10 @@ function batchedDrawEdges( deferredEdges.push(edge); return; } + // Dont draw if Memlet is summarised + else if (edge instanceof Memlet && edge.summarised) { + return; + } const lPoint = edge.points[edge.points.length - 1]; if (visible_rect && lPoint.x >= visible_rect.x && From 0cb61c5fed0062f414875bb998fc00473c0a79fb Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Tue, 9 Apr 2024 12:48:01 +0200 Subject: [PATCH 05/22] removed edge summary for tasklets, added summary symbol --- src/renderer/renderer.ts | 21 +++--- src/renderer/renderer_elements.ts | 104 +++++++++++++++++++++++++----- 2 files changed, 101 insertions(+), 24 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 514c4fdd..0f2dc11e 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -59,7 +59,8 @@ import { Tasklet, drawSDFG, offset_sdfg, - offset_state + offset_state, + ScopeNode } from './renderer_elements'; // External, non-typescript libraries which are presented as previously loaded @@ -4132,13 +4133,17 @@ function relayoutSDFGState( return; } - const n_of_in_connectors = gnode.in_connectors.length; - const n_of_out_connectors = gnode.out_connectors.length; - if (n_of_in_connectors > 10) { - gnode.summarise_in_edges = true; - } - if (n_of_out_connectors > 10) { - gnode.summarise_out_edges = true; + // Summarise edges for NestedSDFGs and ScopeNodes + if (gnode instanceof NestedSDFG || gnode instanceof ScopeNode) { + const n_of_in_connectors = gnode.in_connectors.length; + const n_of_out_connectors = gnode.out_connectors.length; + + if (n_of_in_connectors > 10) { + gnode.summarise_in_edges = true; + } + if (n_of_out_connectors > 10) { + gnode.summarise_out_edges = true; + } } const SPACING = SDFV.LINEHEIGHT; diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index c30a45b7..8138646d 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -223,8 +223,83 @@ export class SDFGElement { const ppp = canvas_manager?.points_per_pixel(); if (!(ctx as any).lod || (ppp && ppp < SDFV.EDGE_LOD)) { const topleft = this.topleft(); + ctx.strokeStyle = this.strokeStyle(renderer); + ctx.fillStyle = ctx.strokeStyle; + + function draw_summary_symbol(ctx: CanvasRenderingContext2D, + min_connector_x: number, max_connector_x: number, + horizontal_line_level: number, draw_arrows_above_line: boolean + ): void { + + // Draw horizontal line + ctx.beginPath(); + ctx.moveTo(min_connector_x, horizontal_line_level); + ctx.lineTo(max_connector_x, horizontal_line_level); + ctx.closePath(); + ctx.stroke(); + + // Draw left arrow + const middle_of_line = (min_connector_x + max_connector_x) / 2; + const left_arrow_x = middle_of_line - 10; + const righ_arrow_x = middle_of_line + 10; + let arrow_start_y = horizontal_line_level + 2; + let arrow_end_y = horizontal_line_level + 8; + if (draw_arrows_above_line) { + arrow_start_y = horizontal_line_level - 10; + arrow_end_y = horizontal_line_level - 4; + } + const dot_height = (arrow_start_y + arrow_end_y) / 2; + // Arrow line + ctx.beginPath(); + ctx.moveTo(left_arrow_x, arrow_start_y); + ctx.lineTo(left_arrow_x, arrow_end_y); + ctx.closePath(); + ctx.stroke(); + // Arrow head + ctx.beginPath(); + ctx.moveTo(left_arrow_x, arrow_end_y + 2); + ctx.lineTo(left_arrow_x - 2, arrow_end_y); + ctx.lineTo(left_arrow_x + 2, arrow_end_y); + ctx.lineTo(left_arrow_x, arrow_end_y + 2); + ctx.closePath(); + ctx.fill(); + + // 3 dots + ctx.beginPath(); + ctx.moveTo(middle_of_line - 5, dot_height) + ctx.lineTo(middle_of_line - 4, dot_height) + ctx.closePath(); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(middle_of_line - 0.5, dot_height) + ctx.lineTo(middle_of_line + 0.5, dot_height) + ctx.closePath(); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(middle_of_line + 4, dot_height) + ctx.lineTo(middle_of_line + 5, dot_height) + ctx.closePath(); + ctx.stroke(); + + // Draw right arrow + // Arrow line + ctx.beginPath(); + ctx.moveTo(righ_arrow_x, arrow_start_y); + ctx.lineTo(righ_arrow_x, arrow_end_y); + ctx.closePath(); + ctx.stroke(); + // Arrow head + ctx.beginPath(); + ctx.moveTo(righ_arrow_x, arrow_end_y + 2); + ctx.lineTo(righ_arrow_x - 2, arrow_end_y); + ctx.lineTo(righ_arrow_x + 2, arrow_end_y); + ctx.lineTo(righ_arrow_x, arrow_end_y + 2); + ctx.closePath(); + ctx.fill(); + } if (this.summarise_in_edges) { + // Find the left most and right most connector coordinates if (this.in_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; let max_connector_x = Number.MIN_SAFE_INTEGER; @@ -235,16 +310,16 @@ export class SDFGElement { if (c.x > max_connector_x) { max_connector_x = c.x; } - }) - ctx.beginPath(); - ctx.moveTo(min_connector_x, topleft.y - 12); - ctx.lineTo(max_connector_x, topleft.y - 12); - ctx.closePath(); - ctx.strokeStyle = this.strokeStyle(renderer); - ctx.stroke(); + }); + + // Draw the summary symbol above the node + draw_summary_symbol(ctx, + min_connector_x, max_connector_x, + topleft.y - 12, true); } } if (this.summarise_out_edges) { + // Find the left most and right most connector coordinates if (this.out_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; let max_connector_x = Number.MIN_SAFE_INTEGER; @@ -255,13 +330,12 @@ export class SDFGElement { if (c.x > max_connector_x) { max_connector_x = c.x; } - }) - ctx.beginPath(); - ctx.moveTo(min_connector_x, topleft.y + this.height + 12); - ctx.lineTo(max_connector_x, topleft.y + this.height + 12); - ctx.closePath(); - ctx.strokeStyle = this.strokeStyle(renderer); - ctx.stroke(); + }); + + // Draw the summary symbol below the node + draw_summary_symbol(ctx, + min_connector_x, max_connector_x, + topleft.y + this.height + 12, false); } } } @@ -2232,8 +2306,6 @@ export class Tasklet extends SDFGNode { if (!canvas_manager) return; - this.draw_edge_summary(renderer, ctx); - const topleft = this.topleft(); drawOctagon(ctx, topleft, this.width, this.height); ctx.strokeStyle = this.strokeStyle(renderer); From 683f45119359504cffeec31cd4b16e93131b23be Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Tue, 9 Apr 2024 16:59:04 +0200 Subject: [PATCH 06/22] changed edge summary symbol, hovering nodes and connectors shows summarised edges --- src/renderer/renderer.ts | 76 ++++++++++++++++++++++++++++++- src/renderer/renderer_elements.ts | 16 +++---- 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 0f2dc11e..665bd2a2 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -2819,7 +2819,7 @@ export class SDFGRenderer extends EventEmitter { highlighting_changed = true; hover_changed = true; } - + // Highlight all edges of the memlet tree if (obj instanceof Edge && obj.parent_id !== null) { if (obj.hovered && hover_changed) { @@ -2878,6 +2878,44 @@ export class SDFGRenderer extends EventEmitter { } if (obj instanceof Connector) { + + // Highlight the incoming/outgoing Edge + const parent_node = obj.linkedElem; + if (obj.hovered && (hover_changed || (!parent_node?.hovered))) { + const state = obj.linkedElem?.parentElem; + if (state && state instanceof State && state.data) { + const state_json = state.data.state; + const state_graph = state.data.graph; + state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { + if (edge.src_connector === obj.data.name || edge.dst_connector === obj.data.name) { + const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; + if (gedge) { + gedge.highlighted = true; + } + } + }); + } + } + if (!obj.hovered && hover_changed) { + // Prevent de-highlighting of edge if parent is already hovered (to show all edges) + if (parent_node && !parent_node.hovered) { + const state = obj.linkedElem?.parentElem; + if (state && state instanceof State && state.data) { + const state_json = state.data.state; + const state_graph = state.data.graph; + state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { + if (edge.src_connector === obj.data.name || edge.dst_connector === obj.data.name) { + const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; + if (gedge) { + gedge.highlighted = false; + } + } + }); + } + } + } + + // Highlight all access nodes with the same name as the // hovered connector in the nested sdfg if (obj.hovered && hover_changed) { @@ -2958,6 +2996,42 @@ export class SDFGRenderer extends EventEmitter { } } } + + // Make all edges of a node visible and remove the edge summary symbol + if (obj.hovered && hover_changed) { + obj.summarise_in_edges = false; + obj.summarise_out_edges = false; + const state = obj.parentElem; + if (state && state instanceof State && state.data) { + const state_json = state.data.state; + const state_graph = state.data.graph; + state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { + if (edge.src === obj.id.toString() || edge.dst === obj.id.toString()) { + const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; + if (gedge) { + gedge.highlighted = true; + } + } + }); + } + } + else if (!obj.hovered && hover_changed) { + obj.summarise_in_edges = true; + obj.summarise_out_edges = true; + const state = obj.parentElem; + if (state && state instanceof State && state.data) { + const state_json = state.data.state; + const state_graph = state.data.graph; + state_json.edges.forEach((edge: JsonSDFGEdge, id: number) => { + if (edge.src === obj.id.toString() || edge.dst === obj.id.toString()) { + const gedge = state_graph.edge(edge.src, edge.dst, id.toString()) as Memlet; + if (gedge) { + gedge.highlighted = false; + } + } + }); + } + } } ); diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 8138646d..1c4d3e8f 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -231,12 +231,12 @@ export class SDFGElement { horizontal_line_level: number, draw_arrows_above_line: boolean ): void { - // Draw horizontal line - ctx.beginPath(); - ctx.moveTo(min_connector_x, horizontal_line_level); - ctx.lineTo(max_connector_x, horizontal_line_level); - ctx.closePath(); - ctx.stroke(); + // Draw horizontal line (looks better without) + // ctx.beginPath(); + // ctx.moveTo(min_connector_x, horizontal_line_level); + // ctx.lineTo(max_connector_x, horizontal_line_level); + // ctx.closePath(); + // ctx.stroke(); // Draw left arrow const middle_of_line = (min_connector_x + max_connector_x) / 2; @@ -315,7 +315,7 @@ export class SDFGElement { // Draw the summary symbol above the node draw_summary_symbol(ctx, min_connector_x, max_connector_x, - topleft.y - 12, true); + topleft.y - 8, true); } } if (this.summarise_out_edges) { @@ -335,7 +335,7 @@ export class SDFGElement { // Draw the summary symbol below the node draw_summary_symbol(ctx, min_connector_x, max_connector_x, - topleft.y + this.height + 12, false); + topleft.y + this.height + 8, false); } } } From cfadf0363fd96d3562349f5e82e1dd474d00b872 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Wed, 10 Apr 2024 19:04:56 +0200 Subject: [PATCH 07/22] fixed error when selecting memlet --- src/sdfv.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sdfv.ts b/src/sdfv.ts index f3d3a792..9777f867 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -250,10 +250,12 @@ export class SDFV { if (elem instanceof Memlet && elem.parent_id && elem.id) { const sdfg_edge = elem.parentElem?.data.state.edges[elem.id]; - contents.append($('

', { - html: 'Connectors: ' + sdfg_edge.src_connector + ' → ' + - sdfg_edge.dst_connector, - })); + if (sdfg_edge) { + contents.append($('

', { + html: 'Connectors: ' + sdfg_edge.src_connector + ' → ' + + sdfg_edge.dst_connector, + })); + } } contents.append($('
')); From 8dc77e3117b8692ec6b49396ecd20f405bdda0d1 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Fri, 12 Apr 2024 14:02:57 +0200 Subject: [PATCH 08/22] fixed fill_info to show memlet src/dst connectors --- src/renderer/renderer.ts | 2 ++ src/sdfv.ts | 13 +++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 665bd2a2..9961d8cf 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -2999,6 +2999,8 @@ export class SDFGRenderer extends EventEmitter { // Make all edges of a node visible and remove the edge summary symbol if (obj.hovered && hover_changed) { + // Setting these to false will cause the summary symbol + // not to be drawn in renderer_elements.ts obj.summarise_in_edges = false; obj.summarise_out_edges = false; const state = obj.parentElem; diff --git a/src/sdfv.ts b/src/sdfv.ts index 9777f867..b92bc3b1 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -248,14 +248,11 @@ export class SDFV { const contents = $(contentsRaw); contents.html(''); - if (elem instanceof Memlet && elem.parent_id && elem.id) { - const sdfg_edge = elem.parentElem?.data.state.edges[elem.id]; - if (sdfg_edge) { - contents.append($('

', { - html: 'Connectors: ' + sdfg_edge.src_connector + ' → ' + - sdfg_edge.dst_connector, - })); - } + if (elem instanceof Memlet) { + contents.append($('

', { + html: 'Connectors: ' + elem.src_connector + ' → ' + + elem.dst_connector, + })); } contents.append($('


')); From 58559d86eeaab0328764bb2d9febc89798d8c9ec Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Fri, 12 Apr 2024 14:27:46 +0200 Subject: [PATCH 09/22] fixed summary symbol toggled on when not applicable --- src/renderer/renderer.ts | 2 ++ src/renderer/renderer_elements.ts | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 9961d8cf..fa0b3d8e 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -4216,9 +4216,11 @@ function relayoutSDFGState( if (n_of_in_connectors > 10) { gnode.summarise_in_edges = true; + gnode.in_summary_has_effect = true; } if (n_of_out_connectors > 10) { gnode.summarise_out_edges = true; + gnode.out_summary_has_effect = true; } } diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 1c4d3e8f..ace332ba 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -58,9 +58,15 @@ export class SDFGElement { // Used to draw edge summary instead of all edges separately. // Helps with rendering performance when too many edges would be drawn on the screen. // These two fields get set in the layouter, depending on the number of in/out_connectors - // of a node. + // of a node. They also get toggled in the mousehandler when the hover status changes. + // Currently only used for NestedSDFGs and ScopeNodes. public summarise_in_edges: boolean = false; public summarise_out_edges: boolean = false; + // Used in draw_edge_summary to decide if edge summary is applicable. Set in the layouter + // only for NestedSDFGs and ScopeNodes. This prevents the summary to get toggled on + // by the mousehandler when it is not applicable. + public in_summary_has_effect: boolean = false; + public out_summary_has_effect: boolean = false; public x: number = 0; public y: number = 0; @@ -298,7 +304,7 @@ export class SDFGElement { ctx.fill(); } - if (this.summarise_in_edges) { + if (this.summarise_in_edges && this.in_summary_has_effect) { // Find the left most and right most connector coordinates if (this.in_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; @@ -318,7 +324,7 @@ export class SDFGElement { topleft.y - 8, true); } } - if (this.summarise_out_edges) { + if (this.summarise_out_edges && this.out_summary_has_effect) { // Find the left most and right most connector coordinates if (this.out_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; From 371486873c0bc7a815e2a53bd83ca520d357bc81 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Fri, 12 Apr 2024 19:00:04 +0200 Subject: [PATCH 10/22] added shift+rightclick to expand, ctrl+scroll to verticalscroll --- src/renderer/renderer.ts | 90 ++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index fa0b3d8e..6332a862 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -2451,6 +2451,47 @@ export class SDFGRenderer extends EventEmitter { return correctedMovement; } + // Toggles collapsed state of foreground_elem if applicable. + // Returns true if re-layout occured and re-draw is necessary. + public toggle_element_collapse(foreground_elem: any): boolean { + + const sdfg = (foreground_elem ? foreground_elem.sdfg : null); + let sdfg_elem = null; + if (foreground_elem instanceof State) + sdfg_elem = foreground_elem.data.state; + else if (foreground_elem instanceof ControlFlowRegion) + sdfg_elem = foreground_elem.data.block; + else if (foreground_elem instanceof SDFGNode) { + sdfg_elem = foreground_elem.data.node; + + // If a scope exit node, use entry instead + if (sdfg_elem.type.endsWith('Exit') && + foreground_elem.parent_id !== null) + sdfg_elem = sdfg.nodes[foreground_elem.parent_id].nodes[ + sdfg_elem.scope_entry + ]; + } else + sdfg_elem = null; + + // Toggle collapsed state + if (sdfg_elem && 'is_collapsed' in sdfg_elem.attributes) { + sdfg_elem.attributes.is_collapsed = + !sdfg_elem.attributes.is_collapsed; + + this.emit('collapse_state_changed'); + + // Re-layout SDFG + this.add_loading_animation(); + setTimeout(() => { + this.relayout(); + }, 10); + + return true; + } + + return false; + } + // TODO(later): Improve event system using event types (instanceof) instead // of passing string eventtypes. /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ @@ -2697,7 +2738,9 @@ export class SDFGRenderer extends EventEmitter { return false; } } else if (evtype === 'wheel') { - if (SDFVSettings.useVerticalScrollNavigation && !event.ctrlKey) { + if (SDFVSettings.useVerticalScrollNavigation && !event.ctrlKey + || !SDFVSettings.useVerticalScrollNavigation && event.ctrlKey + ) { // If vertical scroll navigation is turned on, use this to // move the viewport up and down. If the control key is held // down while scrolling, treat it as a typical zoom operation. @@ -3058,36 +3101,9 @@ export class SDFGRenderer extends EventEmitter { } if (evtype === 'dblclick') { - const sdfg = (foreground_elem ? foreground_elem.sdfg : null); - let sdfg_elem = null; - if (foreground_elem instanceof State) - sdfg_elem = foreground_elem.data.state; - else if (foreground_elem instanceof ControlFlowRegion) - sdfg_elem = foreground_elem.data.block; - else if (foreground_elem instanceof SDFGNode) { - sdfg_elem = foreground_elem.data.node; - - // If a scope exit node, use entry instead - if (sdfg_elem.type.endsWith('Exit') && - foreground_elem.parent_id !== null) - sdfg_elem = sdfg.nodes[foreground_elem.parent_id].nodes[ - sdfg_elem.scope_entry - ]; - } else - sdfg_elem = null; - - // Toggle collapsed state - if (sdfg_elem && 'is_collapsed' in sdfg_elem.attributes) { - sdfg_elem.attributes.is_collapsed = - !sdfg_elem.attributes.is_collapsed; - - this.emit('collapse_state_changed'); - - // Re-layout SDFG - this.add_loading_animation(); - setTimeout(() => { - this.relayout(); - }, 10); + + const relayout_happened = this.toggle_element_collapse(foreground_elem); + if (relayout_happened) { dirty = true; element_focus_changed = true; } @@ -3266,6 +3282,7 @@ export class SDFGRenderer extends EventEmitter { el.selected = true; }); + // Handle right-clicks if (evtype === 'contextmenu') { if (this.mouse_mode === 'move') { let elements_to_reset = [foreground_elem]; @@ -3363,6 +3380,17 @@ export class SDFGRenderer extends EventEmitter { if (this.panmode_btn?.onclick) this.panmode_btn?.onclick(event); } + else if (this.mouse_mode === 'pan') { + + // Shift + Rightclick to toggle expand/collapse + if (event.shiftKey) { + const relayout_happened = this.toggle_element_collapse(foreground_elem); + if (relayout_happened) { + dirty = true; + element_focus_changed = true; + } + } + } } const mouse_x = comp_x_func(event); From 257926ed366c8a233b34d54f26397a572a166466 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Mon, 15 Apr 2024 13:04:00 +0200 Subject: [PATCH 11/22] memory overlays LOD threshold fixes --- src/overlays/memory_location_overlay.ts | 7 +++++-- src/overlays/memory_volume_overlay.ts | 24 +++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/overlays/memory_location_overlay.ts b/src/overlays/memory_location_overlay.ts index 7d492218..eee00ddd 100644 --- a/src/overlays/memory_location_overlay.ts +++ b/src/overlays/memory_location_overlay.ts @@ -237,8 +237,9 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { // The state is collapsed or invisible, so we don't need to // traverse its insides. @@ -261,7 +262,9 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { node.data.graph, ctx, ppp, visibleRect ); } else if (node instanceof AccessNode) { - this.shadeNode(node, ctx); + if (!(ctx as any).lod || ppp < SDFV.NODE_LOD) { + this.shadeNode(node, ctx); + } } }); } diff --git a/src/overlays/memory_volume_overlay.ts b/src/overlays/memory_volume_overlay.ts index c85de285..91d72cab 100644 --- a/src/overlays/memory_volume_overlay.ts +++ b/src/overlays/memory_volume_overlay.ts @@ -162,13 +162,6 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { graph.nodes().forEach(v => { const state: State = graph.node(v); - // If we're zoomed out enough that the contents aren't visible, we - // skip the state. - if ((ctx as any).lod && ( - ppp >= SDFV.STATE_LOD || state.width / ppp < SDFV.STATE_LOD - )) - return; - // If the node's invisible, we skip it. if ((ctx as any).lod && !state.intersect( visible_rect.x, visible_rect.y, @@ -176,6 +169,15 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { )) return; + // If we're zoomed out enough that the contents aren't visible, we + // skip the state. + const stateppp = Math.sqrt(state.width * state.height) / ppp; + if ((ctx as any).lod && ( + ppp >= SDFV.STATE_LOD || stateppp < SDFV.STATE_LOD + )) + return; + + const state_graph = state.data.graph; if (state_graph && !state.data.state.attributes.is_collapsed) { state_graph.nodes().forEach((v: string) => { @@ -205,8 +207,12 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { state_graph.edges().forEach((e: any) => { const edge: Edge = state_graph.edge(e); - if ((ctx as any).lod && !edge.intersect(visible_rect.x, - visible_rect.y, visible_rect.w, visible_rect.h)) + // Skip if edge is invisible, or zoomed out far + if ((ctx as any).lod + && (!edge.intersect(visible_rect.x, visible_rect.y, visible_rect.w, visible_rect.h) + || ppp > SDFV.EDGE_LOD + ) + ) return; this.shade_edge(edge, ctx); From ad5e64c8e602a5f8fa1e3a6ce073d3ec71aea208 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Mon, 15 Apr 2024 13:47:25 +0200 Subject: [PATCH 12/22] overlays state LOD changes --- src/overlays/avg_parallelism_overlay.ts | 3 ++- src/overlays/depth_overlay.ts | 3 ++- src/overlays/logical_group_overlay.ts | 3 ++- src/overlays/operational_intensity_overlay.ts | 3 ++- src/overlays/runtime_micro_seconds_overlay.ts | 3 ++- src/overlays/simulated_operational_intensity_overlay.ts | 3 ++- src/overlays/static_flops_overlay.ts | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/overlays/avg_parallelism_overlay.ts b/src/overlays/avg_parallelism_overlay.ts index 231e9f75..94e5f7c9 100644 --- a/src/overlays/avg_parallelism_overlay.ts +++ b/src/overlays/avg_parallelism_overlay.ts @@ -208,8 +208,9 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { diff --git a/src/overlays/depth_overlay.ts b/src/overlays/depth_overlay.ts index 7cdbe65c..4bd0e34a 100644 --- a/src/overlays/depth_overlay.ts +++ b/src/overlays/depth_overlay.ts @@ -208,8 +208,9 @@ export class DepthOverlay extends GenericSdfgOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { diff --git a/src/overlays/logical_group_overlay.ts b/src/overlays/logical_group_overlay.ts index 52acabb5..b8eef341 100644 --- a/src/overlays/logical_group_overlay.ts +++ b/src/overlays/logical_group_overlay.ts @@ -105,8 +105,9 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { )) return; + const blockppp = Math.sqrt(block.width * block.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - block.width / ppp <= SDFV.STATE_LOD)) || + blockppp <= SDFV.STATE_LOD)) || block.attributes().is_collapsed ) { this.shade_node(block, sdfgGroups, ctx); diff --git a/src/overlays/operational_intensity_overlay.ts b/src/overlays/operational_intensity_overlay.ts index cca400cb..cf970210 100644 --- a/src/overlays/operational_intensity_overlay.ts +++ b/src/overlays/operational_intensity_overlay.ts @@ -252,8 +252,9 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { diff --git a/src/overlays/runtime_micro_seconds_overlay.ts b/src/overlays/runtime_micro_seconds_overlay.ts index 2f18461d..6c66bbd1 100644 --- a/src/overlays/runtime_micro_seconds_overlay.ts +++ b/src/overlays/runtime_micro_seconds_overlay.ts @@ -129,8 +129,9 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { diff --git a/src/overlays/simulated_operational_intensity_overlay.ts b/src/overlays/simulated_operational_intensity_overlay.ts index 6c807116..0c8db8c7 100644 --- a/src/overlays/simulated_operational_intensity_overlay.ts +++ b/src/overlays/simulated_operational_intensity_overlay.ts @@ -209,8 +209,9 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { diff --git a/src/overlays/static_flops_overlay.ts b/src/overlays/static_flops_overlay.ts index e35d654f..aa99aff2 100644 --- a/src/overlays/static_flops_overlay.ts +++ b/src/overlays/static_flops_overlay.ts @@ -208,8 +208,9 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { )) return; + const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || + stateppp <= SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { From 87268aef9296c9b60b09aff956bad38cb1cd541e Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Mon, 15 Apr 2024 14:40:03 +0200 Subject: [PATCH 13/22] renderer loop region bugfix and overlay comment --- src/overlays/memory_location_overlay.ts | 1 + src/renderer/renderer.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/overlays/memory_location_overlay.ts b/src/overlays/memory_location_overlay.ts index eee00ddd..2e3f06f3 100644 --- a/src/overlays/memory_location_overlay.ts +++ b/src/overlays/memory_location_overlay.ts @@ -240,6 +240,7 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { const stateppp = Math.sqrt(state.width * state.height) / ppp; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || stateppp <= SDFV.STATE_LOD)) || + // TODO: For all overlays: handle LoopRegions, which don't have the state.data.state attribute state.data.state.attributes.is_collapsed) { // The state is collapsed or invisible, so we don't need to // traverse its insides. diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 6332a862..51411b48 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -2184,7 +2184,9 @@ export class SDFGRenderer extends EventEmitter { state ); - if (state.data.state.attributes.is_collapsed) + if (state instanceof State && state.data.state.attributes.is_collapsed) + return; + if (state instanceof LoopRegion && state.data.block.attributes.is_collapsed) return; const ng = state.data.graph; From d85c305f01e329a4ab87ee86e1ff5f6c61c508a8 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Tue, 16 Apr 2024 14:38:38 +0200 Subject: [PATCH 14/22] fixed LogicalGroupOverlay on by default but UI not updated, optimized code if logical groups array has length 0 --- src/overlays/logical_group_overlay.ts | 3 ++- src/renderer/renderer.ts | 31 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/overlays/logical_group_overlay.ts b/src/overlays/logical_group_overlay.ts index b8eef341..e43a5443 100644 --- a/src/overlays/logical_group_overlay.ts +++ b/src/overlays/logical_group_overlay.ts @@ -88,8 +88,9 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { // In that case, we overlay the correct grouping color(s). // If it's expanded or zoomed in close enough, we traverse inside. const sdfgGroups = sdfg.attributes.logical_groups; - if (sdfgGroups === undefined) + if (sdfgGroups === undefined || sdfgGroups.length === 0) { return; + } if (!graph) { return; diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 51411b48..0bd9cad2 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -14,6 +14,12 @@ import { JsonSDFGState, MemoryLocationOverlay, MemoryVolumeOverlay, + AvgParallelismOverlay, + DepthOverlay, + OperationalIntensityOverlay, + RuntimeMicroSecondsOverlay, + SimulatedOperationalIntensityOverlay, + StaticFlopsOverlay, ModeButtons, Point2D, SDFVTooltipFunc, @@ -220,9 +226,6 @@ export class SDFGRenderer extends EventEmitter { this.overlay_manager = new OverlayManager(this); - // Register overlays that are turned on by default. - this.overlay_manager.register_overlay(LogicalGroupOverlay); - this.in_vscode = false; try { vscode; @@ -552,7 +555,7 @@ export class SDFGRenderer extends EventEmitter { }).appendTo(this.toolbar).append(overlayDropdown); const addOverlayToMenu = ( - txt: string, ol: typeof GenericSdfgOverlay + txt: string, ol: typeof GenericSdfgOverlay, default_state: boolean ) => { const olItem = $('
  • ', { css: { @@ -565,6 +568,7 @@ export class SDFGRenderer extends EventEmitter { const olInput = $('', { class: 'form-check-input', type: 'checkbox', + checked: default_state, change: () => { if (olInput.prop('checked')) this.overlay_manager?.register_overlay(ol); @@ -578,11 +582,20 @@ export class SDFGRenderer extends EventEmitter { }).appendTo(olContainer); }; - addOverlayToMenu('Logical groups', LogicalGroupOverlay); - addOverlayToMenu('Storage locations', MemoryLocationOverlay); - addOverlayToMenu( - 'Logical data movement volume', MemoryVolumeOverlay - ); + // Register overlays that are turned on by default. + this.overlay_manager.register_overlay(LogicalGroupOverlay); + addOverlayToMenu('Logical groups', LogicalGroupOverlay, true); + + // Add overlays that are turned off by default. + addOverlayToMenu('Storage locations', MemoryLocationOverlay, false); + addOverlayToMenu('Logical data movement volume', MemoryVolumeOverlay, false); + + addOverlayToMenu('AvgParallelismOverlay', AvgParallelismOverlay, false); + addOverlayToMenu('DepthOverlay', DepthOverlay, false); + addOverlayToMenu('OperationalIntensityOverlay', OperationalIntensityOverlay, false); + addOverlayToMenu('RuntimeMicroSecondsOverlay', RuntimeMicroSecondsOverlay, false); + addOverlayToMenu('SimulatedOperationalIntensityOverlay', SimulatedOperationalIntensityOverlay, false); + addOverlayToMenu('StaticFlopsOverlay', StaticFlopsOverlay, false); } // Zoom to fit. From ce0815564845a48438e1788ef3f89d149c7f1027 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Tue, 16 Apr 2024 15:53:15 +0200 Subject: [PATCH 15/22] AvgParallelismOverlay reworked lod code based on new renderer --- src/overlays/avg_parallelism_overlay.ts | 21 ++++++++++----------- src/renderer/renderer_elements.ts | 5 ++--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/overlays/avg_parallelism_overlay.ts b/src/overlays/avg_parallelism_overlay.ts index 94e5f7c9..0dc7f000 100644 --- a/src/overlays/avg_parallelism_overlay.ts +++ b/src/overlays/avg_parallelism_overlay.ts @@ -209,8 +209,7 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { @@ -224,20 +223,20 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { visible_rect.y, visible_rect.w, visible_rect.h)) return; - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { - this.shade_node(node, ctx); - } else { - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') { + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if ((ctx as any).lod && nodeppp < SDFV.STATE_LOD) { + this.shade_node(node, ctx); + } + else if (node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { this.recursively_shade_sdfg( node.data.graph, ctx, ppp, visible_rect ); - } else { - this.shade_node(node, ctx); } } + else { + this.shade_node(node, ctx); + } }); } } diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index ace332ba..acfa2eb2 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -2780,9 +2780,8 @@ export function drawStateContents( // Simple draw for non-collapsed NestedSDFGs if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { - if (lod && ( - Math.sqrt(node.height * node.width) / ppp - ) < SDFV.STATE_LOD) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if (lod && nodeppp < SDFV.STATE_LOD) { node.simple_draw(renderer, ctx, mousePos); node.debug_draw(renderer, ctx); continue; From ebcd7e6992e0129d9821c1ca270c2cc326e40d14 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Tue, 16 Apr 2024 16:10:18 +0200 Subject: [PATCH 16/22] STATE_LOD comment, changed all LOD threshold checks to strict inequalities --- src/overlays/depth_overlay.ts | 2 +- src/overlays/logical_group_overlay.ts | 2 +- src/overlays/memory_volume_overlay.ts | 2 +- src/overlays/operational_intensity_overlay.ts | 2 +- src/overlays/runtime_micro_seconds_overlay.ts | 2 +- src/overlays/simulated_operational_intensity_overlay.ts | 2 +- src/overlays/static_flops_overlay.ts | 2 +- src/renderer/renderer_elements.ts | 4 ++-- src/sdfv.ts | 5 ++++- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/overlays/depth_overlay.ts b/src/overlays/depth_overlay.ts index 4bd0e34a..71b42b10 100644 --- a/src/overlays/depth_overlay.ts +++ b/src/overlays/depth_overlay.ts @@ -225,7 +225,7 @@ export class DepthOverlay extends GenericSdfgOverlay { return; if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { this.shade_node(node, ctx); } else { if (node instanceof NestedSDFG && diff --git a/src/overlays/logical_group_overlay.ts b/src/overlays/logical_group_overlay.ts index e43a5443..0d106be1 100644 --- a/src/overlays/logical_group_overlay.ts +++ b/src/overlays/logical_group_overlay.ts @@ -127,7 +127,7 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { return; if (node.attributes().is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { this.shade_node(node, sdfgGroups, ctx); } else { if (node instanceof NestedSDFG && diff --git a/src/overlays/memory_volume_overlay.ts b/src/overlays/memory_volume_overlay.ts index 91d72cab..38dd8972 100644 --- a/src/overlays/memory_volume_overlay.ts +++ b/src/overlays/memory_volume_overlay.ts @@ -193,7 +193,7 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { // If we're zoomed out enough that the node's contents // aren't visible or the node is collapsed, we skip it. if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) return; if (node instanceof NestedSDFG && diff --git a/src/overlays/operational_intensity_overlay.ts b/src/overlays/operational_intensity_overlay.ts index cf970210..5c265156 100644 --- a/src/overlays/operational_intensity_overlay.ts +++ b/src/overlays/operational_intensity_overlay.ts @@ -269,7 +269,7 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { return; if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { this.shade_node(node, ctx); } else { if (node instanceof NestedSDFG && diff --git a/src/overlays/runtime_micro_seconds_overlay.ts b/src/overlays/runtime_micro_seconds_overlay.ts index 6c66bbd1..73f3895e 100644 --- a/src/overlays/runtime_micro_seconds_overlay.ts +++ b/src/overlays/runtime_micro_seconds_overlay.ts @@ -146,7 +146,7 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { return; if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { this.shade_node(node, ctx); } else { if (node instanceof NestedSDFG && diff --git a/src/overlays/simulated_operational_intensity_overlay.ts b/src/overlays/simulated_operational_intensity_overlay.ts index 0c8db8c7..fe7ddbd2 100644 --- a/src/overlays/simulated_operational_intensity_overlay.ts +++ b/src/overlays/simulated_operational_intensity_overlay.ts @@ -226,7 +226,7 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { return; if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { this.shade_node(node, ctx); } else { if (node instanceof NestedSDFG && diff --git a/src/overlays/static_flops_overlay.ts b/src/overlays/static_flops_overlay.ts index aa99aff2..d3e38a3d 100644 --- a/src/overlays/static_flops_overlay.ts +++ b/src/overlays/static_flops_overlay.ts @@ -225,7 +225,7 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { return; if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { + ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { this.shade_node(node, ctx); } else { if (node instanceof NestedSDFG && diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index acfa2eb2..69d0246b 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -1498,7 +1498,7 @@ export class InterstateEdge extends Edge { const ppp = renderer.get_canvas_manager()?.points_per_pixel(); if (ppp === undefined) return; - if ((ctx as any).lod && ppp >= SDFV.SCOPE_LOD) + if ((ctx as any).lod && ppp > SDFV.SCOPE_LOD) return; const labelLines = []; @@ -3024,7 +3024,7 @@ export function drawAdaptiveText( if (ppp === undefined) return; - const is_far: boolean = (ctx as any).lod && ppp >= ppp_thres; + const is_far: boolean = (ctx as any).lod && ppp > ppp_thres; const label = is_far ? far_text : close_text; let font_size = Math.min( diff --git a/src/sdfv.ts b/src/sdfv.ts index b92bc3b1..dd68e525 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -55,7 +55,10 @@ export class SDFV { public static NODE_LOD: number = 5.0; // 5.0 // Points-per-pixel threshold for not drawing node text. public static TEXT_LOD: number = 1.5; // 1.5 - // Pixel threshold for not drawing state contents. + + // Pixel threshold for not drawing State and NestedSDFG contents. + // This threshold behaves differently than the ones above. The State's size is compared to this + // threshold and if the State is smaller its contents are not drawn in the renderer. public static STATE_LOD: number = 100; // 100 public static DEFAULT_CANVAS_FONTSIZE: number = 10; From 52863dc8f0c37ae66244c605ed4f2af3d8384854 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Tue, 16 Apr 2024 16:28:33 +0200 Subject: [PATCH 17/22] DepthOverlay lod rework --- src/overlays/depth_overlay.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/overlays/depth_overlay.ts b/src/overlays/depth_overlay.ts index 71b42b10..4ffdcfe9 100644 --- a/src/overlays/depth_overlay.ts +++ b/src/overlays/depth_overlay.ts @@ -209,8 +209,7 @@ export class DepthOverlay extends GenericSdfgOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { @@ -224,20 +223,20 @@ export class DepthOverlay extends GenericSdfgOverlay { visible_rect.y, visible_rect.w, visible_rect.h)) return; - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { - this.shade_node(node, ctx); - } else { - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') { + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if ((ctx as any).lod && nodeppp < SDFV.STATE_LOD) { + this.shade_node(node, ctx); + } + else if (node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { this.recursively_shade_sdfg( node.data.graph, ctx, ppp, visible_rect ); - } else { - this.shade_node(node, ctx); } } + else { + this.shade_node(node, ctx); + } }); } } From d1ae7667e91ae6847e7bb4bc117e184bbe25a97f Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Wed, 17 Apr 2024 12:24:30 +0200 Subject: [PATCH 18/22] OpIntOverlay lod rework --- src/overlays/memory_location_overlay.ts | 5 ++--- src/overlays/memory_volume_overlay.ts | 4 +--- src/overlays/operational_intensity_overlay.ts | 21 +++++++++---------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/overlays/memory_location_overlay.ts b/src/overlays/memory_location_overlay.ts index 2e3f06f3..d457ccd5 100644 --- a/src/overlays/memory_location_overlay.ts +++ b/src/overlays/memory_location_overlay.ts @@ -238,11 +238,10 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || // TODO: For all overlays: handle LoopRegions, which don't have the state.data.state attribute state.data.state.attributes.is_collapsed) { - // The state is collapsed or invisible, so we don't need to + // The state is collapsed or too small, so we don't need to // traverse its insides. return; } else { diff --git a/src/overlays/memory_volume_overlay.ts b/src/overlays/memory_volume_overlay.ts index 38dd8972..cfe28ab2 100644 --- a/src/overlays/memory_volume_overlay.ts +++ b/src/overlays/memory_volume_overlay.ts @@ -172,9 +172,7 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { // If we're zoomed out enough that the contents aren't visible, we // skip the state. const stateppp = Math.sqrt(state.width * state.height) / ppp; - if ((ctx as any).lod && ( - ppp >= SDFV.STATE_LOD || stateppp < SDFV.STATE_LOD - )) + if ((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) return; diff --git a/src/overlays/operational_intensity_overlay.ts b/src/overlays/operational_intensity_overlay.ts index 5c265156..2f53f03c 100644 --- a/src/overlays/operational_intensity_overlay.ts +++ b/src/overlays/operational_intensity_overlay.ts @@ -253,8 +253,7 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { @@ -268,20 +267,20 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { visible_rect.y, visible_rect.w, visible_rect.h)) return; - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { - this.shade_node(node, ctx); - } else { - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') { + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if ((ctx as any).lod && nodeppp < SDFV.STATE_LOD) { + this.shade_node(node, ctx); + } + else if (node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { this.recursively_shade_sdfg( node.data.graph, ctx, ppp, visible_rect ); - } else { - this.shade_node(node, ctx); } } + else { + this.shade_node(node, ctx); + } }); } } From 8bebdc87dbf6a65ece55246310a6c460dc5d3e38 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Wed, 17 Apr 2024 13:54:30 +0200 Subject: [PATCH 19/22] Overlays State lod rework, removed debug --- src/overlays/logical_group_overlay.ts | 3 +-- src/overlays/runtime_micro_seconds_overlay.ts | 21 +++++++++---------- ...simulated_operational_intensity_overlay.ts | 21 +++++++++---------- src/overlays/static_flops_overlay.ts | 21 +++++++++---------- src/renderer/renderer.ts | 13 ------------ 5 files changed, 31 insertions(+), 48 deletions(-) diff --git a/src/overlays/logical_group_overlay.ts b/src/overlays/logical_group_overlay.ts index 0d106be1..560aaca5 100644 --- a/src/overlays/logical_group_overlay.ts +++ b/src/overlays/logical_group_overlay.ts @@ -107,8 +107,7 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { return; const blockppp = Math.sqrt(block.width * block.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - blockppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (blockppp < SDFV.STATE_LOD)) || block.attributes().is_collapsed ) { this.shade_node(block, sdfgGroups, ctx); diff --git a/src/overlays/runtime_micro_seconds_overlay.ts b/src/overlays/runtime_micro_seconds_overlay.ts index 73f3895e..650aba19 100644 --- a/src/overlays/runtime_micro_seconds_overlay.ts +++ b/src/overlays/runtime_micro_seconds_overlay.ts @@ -130,8 +130,7 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { @@ -145,20 +144,20 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { visible_rect.y, visible_rect.w, visible_rect.h)) return; - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { - this.shade_node(node, ctx); - } else { - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') { + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if ((ctx as any).lod && nodeppp < SDFV.STATE_LOD) { + this.shade_node(node, ctx); + } + else if (node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { this.recursively_shade_sdfg( node.data.graph, ctx, ppp, visible_rect ); - } else { - this.shade_node(node, ctx); } } + else { + this.shade_node(node, ctx); + } }); } } diff --git a/src/overlays/simulated_operational_intensity_overlay.ts b/src/overlays/simulated_operational_intensity_overlay.ts index fe7ddbd2..e8db1e8d 100644 --- a/src/overlays/simulated_operational_intensity_overlay.ts +++ b/src/overlays/simulated_operational_intensity_overlay.ts @@ -210,8 +210,7 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { @@ -225,20 +224,20 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { visible_rect.y, visible_rect.w, visible_rect.h)) return; - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { - this.shade_node(node, ctx); - } else { - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') { + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if ((ctx as any).lod && nodeppp < SDFV.STATE_LOD) { + this.shade_node(node, ctx); + } + else if (node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { this.recursively_shade_sdfg( node.data.graph, ctx, ppp, visible_rect ); - } else { - this.shade_node(node, ctx); } } + else { + this.shade_node(node, ctx); + } }); } } diff --git a/src/overlays/static_flops_overlay.ts b/src/overlays/static_flops_overlay.ts index d3e38a3d..4dd8a429 100644 --- a/src/overlays/static_flops_overlay.ts +++ b/src/overlays/static_flops_overlay.ts @@ -209,8 +209,7 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { return; const stateppp = Math.sqrt(state.width * state.height) / ppp; - if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - stateppp <= SDFV.STATE_LOD)) || + if (((ctx as any).lod && (stateppp < SDFV.STATE_LOD)) || state.data.state.attributes.is_collapsed) { this.shade_node(state, ctx); } else { @@ -224,20 +223,20 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { visible_rect.y, visible_rect.w, visible_rect.h)) return; - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp > SDFV.NODE_LOD)) { - this.shade_node(node, ctx); - } else { - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') { + if (node instanceof NestedSDFG && !node.data.node.attributes.is_collapsed) { + const nodeppp = Math.sqrt(node.width * node.height) / ppp; + if ((ctx as any).lod && nodeppp < SDFV.STATE_LOD) { + this.shade_node(node, ctx); + } + else if (node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { this.recursively_shade_sdfg( node.data.graph, ctx, ppp, visible_rect ); - } else { - this.shade_node(node, ctx); } } + else { + this.shade_node(node, ctx); + } }); } } diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 0bd9cad2..8463cb89 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -14,12 +14,6 @@ import { JsonSDFGState, MemoryLocationOverlay, MemoryVolumeOverlay, - AvgParallelismOverlay, - DepthOverlay, - OperationalIntensityOverlay, - RuntimeMicroSecondsOverlay, - SimulatedOperationalIntensityOverlay, - StaticFlopsOverlay, ModeButtons, Point2D, SDFVTooltipFunc, @@ -589,13 +583,6 @@ export class SDFGRenderer extends EventEmitter { // Add overlays that are turned off by default. addOverlayToMenu('Storage locations', MemoryLocationOverlay, false); addOverlayToMenu('Logical data movement volume', MemoryVolumeOverlay, false); - - addOverlayToMenu('AvgParallelismOverlay', AvgParallelismOverlay, false); - addOverlayToMenu('DepthOverlay', DepthOverlay, false); - addOverlayToMenu('OperationalIntensityOverlay', OperationalIntensityOverlay, false); - addOverlayToMenu('RuntimeMicroSecondsOverlay', RuntimeMicroSecondsOverlay, false); - addOverlayToMenu('SimulatedOperationalIntensityOverlay', SimulatedOperationalIntensityOverlay, false); - addOverlayToMenu('StaticFlopsOverlay', StaticFlopsOverlay, false); } // Zoom to fit. From d35ad780d350b57564e74e3204d9410f58176572 Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Wed, 24 Apr 2024 14:10:52 +0200 Subject: [PATCH 20/22] changed spelling to summarize --- src/renderer/renderer.ts | 26 +++++++++++++------------- src/renderer/renderer_elements.ts | 14 +++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 8463cb89..f3632f71 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -3046,8 +3046,8 @@ export class SDFGRenderer extends EventEmitter { if (obj.hovered && hover_changed) { // Setting these to false will cause the summary symbol // not to be drawn in renderer_elements.ts - obj.summarise_in_edges = false; - obj.summarise_out_edges = false; + obj.summarize_in_edges = false; + obj.summarize_out_edges = false; const state = obj.parentElem; if (state && state instanceof State && state.data) { const state_json = state.data.state; @@ -3063,8 +3063,8 @@ export class SDFGRenderer extends EventEmitter { } } else if (!obj.hovered && hover_changed) { - obj.summarise_in_edges = true; - obj.summarise_out_edges = true; + obj.summarize_in_edges = true; + obj.summarize_out_edges = true; const state = obj.parentElem; if (state && state instanceof State && state.data) { const state_json = state.data.state; @@ -4239,17 +4239,17 @@ function relayoutSDFGState( return; } - // Summarise edges for NestedSDFGs and ScopeNodes + // Summarize edges for NestedSDFGs and ScopeNodes if (gnode instanceof NestedSDFG || gnode instanceof ScopeNode) { const n_of_in_connectors = gnode.in_connectors.length; const n_of_out_connectors = gnode.out_connectors.length; if (n_of_in_connectors > 10) { - gnode.summarise_in_edges = true; + gnode.summarize_in_edges = true; gnode.in_summary_has_effect = true; } if (n_of_out_connectors > 10) { - gnode.summarise_out_edges = true; + gnode.summarize_out_edges = true; gnode.out_summary_has_effect = true; } } @@ -4269,10 +4269,10 @@ function relayoutSDFGState( state.edges.forEach((edge: JsonSDFGEdge, id: number) => { if (edge.dst === gnode.id.toString() && edge.dst_connector === c.data.name) { - // If in-edges are to be summarised, set Memlet.summarised + // If in-edges are to be summarized, set Memlet.summarized const gedge = g.edge(edge.src, edge.dst, id.toString()) as Memlet; - if (gedge && gnode.summarise_in_edges) { - gedge.summarised = true; + if (gedge && gnode.summarize_in_edges) { + gedge.summarized = true; } const source_node: SDFGNode = g.node(edge.src); @@ -4313,14 +4313,14 @@ function relayoutSDFGState( } } - // For out_connectors set Memlet.summarised for all out-edges if needed - if (gnode.summarise_out_edges) { + // For out_connectors set Memlet.summarized for all out-edges if needed + if (gnode.summarize_out_edges) { for (const c of gnode.out_connectors) { state.edges.forEach((edge: JsonSDFGEdge, id: number) => { if (edge.src === gnode.id.toString() && edge.src_connector === c.data.name) { const gedge = g.edge(edge.src, edge.dst, id.toString()) as Memlet; if (gedge) { - gedge.summarised = true; + gedge.summarized = true; } } }); diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 69d0246b..3fc8bcc5 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -60,8 +60,8 @@ export class SDFGElement { // These two fields get set in the layouter, depending on the number of in/out_connectors // of a node. They also get toggled in the mousehandler when the hover status changes. // Currently only used for NestedSDFGs and ScopeNodes. - public summarise_in_edges: boolean = false; - public summarise_out_edges: boolean = false; + public summarize_in_edges: boolean = false; + public summarize_out_edges: boolean = false; // Used in draw_edge_summary to decide if edge summary is applicable. Set in the layouter // only for NestedSDFGs and ScopeNodes. This prevents the summary to get toggled on // by the mousehandler when it is not applicable. @@ -304,7 +304,7 @@ export class SDFGElement { ctx.fill(); } - if (this.summarise_in_edges && this.in_summary_has_effect) { + if (this.summarize_in_edges && this.in_summary_has_effect) { // Find the left most and right most connector coordinates if (this.in_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; @@ -324,7 +324,7 @@ export class SDFGElement { topleft.y - 8, true); } } - if (this.summarise_out_edges && this.out_summary_has_effect) { + if (this.summarize_out_edges && this.out_summary_has_effect) { // Find the left most and right most connector coordinates if (this.out_connectors.length > 0) { let min_connector_x = Number.MAX_SAFE_INTEGER; @@ -1229,7 +1229,7 @@ export class Memlet extends Edge { // Currently used for Memlets to decide if they need to be drawn or not. // Set in the layouter. - public summarised: boolean = false; + public summarized: boolean = false; public create_arrow_line(ctx: CanvasRenderingContext2D): void { // Draw memlet edges with quadratic curves through the arrow points. @@ -2712,8 +2712,8 @@ function batchedDrawEdges( deferredEdges.push(edge); return; } - // Dont draw if Memlet is summarised - else if (edge instanceof Memlet && edge.summarised) { + // Dont draw if Memlet is summarized + else if (edge instanceof Memlet && edge.summarized) { return; } From bbbaf678addfc546da5b52c8d12d26301df33bec Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Thu, 2 May 2024 16:29:45 +0200 Subject: [PATCH 21/22] moved Dagre layout options to sdfv.ts --- src/renderer/renderer.ts | 5 ++--- src/sdfv.ts | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index 5a6b9e34..4759d61a 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -4239,12 +4239,11 @@ function relayoutSDFGState( const g: DagreGraph = new dagre.graphlib.Graph({ multigraph: true }); // Set layout options and a simpler algorithm for large graphs. - const layoutOptions: any = { ranksep: 30 }; + const layoutOptions: any = { ranksep: SDFV.RANKSEP }; if (state.nodes.length >= 1000) layoutOptions.ranker = 'longest-path'; - layoutOptions.nodesep = 20; // default: 50 - layoutOptions.ranksep = 70; // default: 50 + layoutOptions.nodesep = SDFV.NODESEP; g.setGraph(layoutOptions); // Set an object for the graph label. diff --git a/src/sdfv.ts b/src/sdfv.ts index d5c34894..7997fc85 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -67,9 +67,15 @@ export class SDFV { public static STATE_LOD: number = 100; // 100 public static DEFAULT_CANVAS_FONTSIZE: number = 10; - public static DEFAULT_MAX_FONTSIZE: number = 20; // 50 + public static DEFAULT_MAX_FONTSIZE: number = 20; // 20 public static DEFAULT_FAR_FONT_MULTIPLIER: number = 16; // 16 + // Dagre layout options. + // Separation between ranks (vertically) in pixels. + public static RANKSEP: number = 70; // Dagre default: 50 + // Separation between nodes (horizontally) in pixels. + public static NODESEP: number = 20; // Dagre default: 50 + protected renderer: SDFGRenderer | null = null; protected localViewRenderer: LViewRenderer | null = null; From 2e5b95809ae0e3edabe9f3837c694610c22e9f9c Mon Sep 17 00:00:00 2001 From: LeandroTreu Date: Fri, 3 May 2024 18:36:59 +0200 Subject: [PATCH 22/22] removed commented out section, formatting adjusted --- src/renderer/renderer.ts | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index a26fe1c0..1c4ff3a8 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -908,30 +908,6 @@ export class SDFGRenderer extends EventEmitter { // Create the initial SDFG layout // Loading animation already started in the file_read_complete function in sdfv.ts // to also include the JSON parsing step. - // Initial layout fully collapsed - // this.doForAllSDFGElements( - // (_t: SDFGElementGroup, _d: any, obj: any) => { - // if ('is_collapsed' in obj.attributes && - // !obj.type.endsWith('Exit')) - // obj.attributes.is_collapsed = true; - // } - // ); - // this.emit('collapse_state_changed', true, true); - // this.relayout(); - - // // Expand by one level - // if (this.graph) { - // traverseSDFGScopes( - // this.graph, (node: SDFGNode, _: DagreGraph) => { - // if(node.attributes().is_collapsed) { - // node.attributes().is_collapsed = false; - // return false; - // } - // return true; - // } - // ); - // } - // this.emit('collapse_state_changed', false, true); this.relayout(); // Set mouse event handlers @@ -3119,7 +3095,7 @@ export class SDFGRenderer extends EventEmitter { highlighting_changed = true; hover_changed = true; } - + // Highlight all edges of the memlet tree if (obj instanceof Edge && obj.parent_id !== null) { if (obj.hovered && hover_changed) {