Skip to content

Commit 79adea4

Browse files
committed
Add better color map for total overview, allow customization of that
This also fixes the incorrect calculation of the highest total access count.
1 parent 6215580 commit 79adea4

9 files changed

Lines changed: 324 additions & 18 deletions

File tree

html/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@typescript-eslint/parser": "^5.49.0",
2424
"autoprefixer": "^10.4.13",
2525
"color2k": "^2.0.1",
26+
"cubehelix": "^1.0.4",
2627
"esbuild": "^0.17.4",
2728
"eslint": "^8.32.0",
2829
"eslint-config-prettier": "^8.6.0",

html/pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

html/src/App.svelte

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script lang="ts">
2+
import { fade, slide, scale } from 'svelte/transition';
3+
24
import Layout from './components/Layout.svelte';
35
46
// Have map storing for each memory address the corresponding memory accesses
@@ -111,20 +113,22 @@
111113
</script>
112114

113115
<Layout>
114-
<div class="h-full mx-auto flex flex-row">
116+
<div class="h-full mx-auto flex flex-row" transition:fade>
115117
{#if validTemplate}
116118
{#if $currentMemoryRegion != null && !('isPlaceHolder' in $currentMemoryRegion)}
117-
<VisualizeMemoryRegion MemoryRegion={$currentMemoryRegion} />
119+
<div out:fade={{ duration: 200 }} in:slide>
120+
<VisualizeMemoryRegion MemoryRegion={$currentMemoryRegion} />
121+
</div>
118122
{:else}
119-
<div class="flex flex-col justify-center items-center w-full h-full">
123+
<div class="flex flex-col justify-center items-center w-full h-full" in:slide={{ delay: 200 }}>
120124
<h1 class="text-3xl font-bold opacity-30 ">Please select a memory region</h1>
121125
<div class="px-12 my-12 w-full">
122126
<FileDropzone bind:files title="You can upload additional .json files here." />
123127
</div>
124128
</div>
125129
{/if}
126130
{:else}
127-
<div class="flex flex-col justify-center items-center w-full h-full text-center">
131+
<div class="flex flex-col justify-center items-center w-full h-full text-center" in:slide={{ delay: 200 }}>
128132
<h1 class="text-3xl font-bold opacity-30 ">
129133
Please load in valid data for this template.<br /> Without data this HTML file can't do anything.
130134
</h1>

html/src/components/Layout.svelte

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
<script>
1+
<script lang="ts">
22
import '../app.pcss';
3-
import { AppShell, AppBar, LightSwitch, tooltip, Modal, modalStore } from '@skeletonlabs/skeleton';
3+
import {
4+
AppShell,
5+
AppBar,
6+
LightSwitch,
7+
tooltip,
8+
Modal,
9+
modalStore,
10+
type ModalComponent
11+
} from '@skeletonlabs/skeleton';
12+
import { slide } from 'svelte/transition';
413
import Icon from '@iconify/svelte';
514
import baselineLightbulb from '@iconify/icons-ic/baseline-lightbulb';
615
import outlineSplitscreen from '@iconify/icons-ic/outline-splitscreen';
@@ -9,8 +18,10 @@
918
import baselineFormatListNumbered from '@iconify/icons-ic/baseline-format-list-numbered';
1019
import baselineLinearScale from '@iconify/icons-ic/baseline-linear-scale';
1120
import roundGridView from '@iconify/icons-ic/round-grid-view';
21+
import twotoneColorLens from '@iconify/icons-ic/twotone-color-lens';
1222
import { pageState, drawerState } from '../lib/stores';
1323
import SideBar from './SideBar.svelte';
24+
import ModalColorSelection from './ModalColorSelection.svelte';
1425
1526
const openInfoModal = () => {
1627
modalStore.trigger({
@@ -20,6 +31,17 @@
2031
body: '<div class="overflow-y-auto">This is a Utility which allows you to visualize memory accesses on the GPU. Using a C++ Header only library you can export the necessary data. This is then visualized in the center screen. <br> You achieve the fastest loading times by dragging and dropping a <code>.json</code> into the empty window, as the parsing of just a file is much faster than using the HTML DOM parser on page load. <br><br>To the left side you can select the memory structure you want to visualize currently. On the bottom left, you can set a memory width, which will cause the cells to automatically align to that width, and break after this width. Y goes down. <br> When showing both read and write accesses, the upper part <div class="text-access-read inline">(blue)</div> are read accesses, the lower part <div class="text-access-write inline">(orange)</div> are write accesses. When toggling to total accesses, the <div class="text-access-all inline high-contrast-text-shadow-white">purple</div> block represents the combined read and write accesses.<br> When showing the index, it is visible to the left of the read/write counts. <br><br>On this top bar, you also have a few utility buttons to change what is visualized. They have tooltips on hover, but the best thing would be to just try out the different buttons. <br><br> This application is a single page app made with Svelte and skeleton.dev as UI framework.</div>'
2132
});
2233
};
34+
35+
const openColorModal = () => {
36+
const component: ModalComponent = {
37+
ref: ModalColorSelection
38+
};
39+
40+
modalStore.trigger({
41+
type: 'component',
42+
component
43+
});
44+
};
2345
</script>
2446

2547
<!-- App Shell -->
@@ -32,6 +54,25 @@
3254
<strong class="px-3">v1.0.0</strong>
3355
</svelte:fragment>
3456
<svelte:fragment slot="trail">
57+
{#if $pageState.showCombinedAccess}
58+
<button
59+
class="btn-icon variant-soft min-w-[50px "
60+
on:click={openColorModal}
61+
use:tooltip={{
62+
content: 'Open a menu to configure the color scale of the combined accesses',
63+
position: 'bottom'
64+
}}
65+
transition:slide
66+
>
67+
<Icon
68+
class="drop-shadow-xl min-w-[32px] dark:text-primary-400 text-primary-600"
69+
height="32"
70+
icon={twotoneColorLens}
71+
width="32"
72+
/>
73+
</button>
74+
<div class="pl-1 mx-3 bg-surface-400/30 min-h-[30px]" />
75+
{/if}
3576
<button
3677
class="btn-icon variant-soft min-w-[50px]"
3778
on:click={() => ($pageState.showGrid = !$pageState.showGrid)}

html/src/components/MemoryRegionBlock.svelte

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<script lang="ts">
2-
import { drawerState } from '../lib/stores';
2+
import { cubeHelixLookup, drawerState } from '../lib/stores';
33
import { MemoryRegionManager } from '../lib/types';
44
import { drawerStore, tooltip } from '@skeletonlabs/skeleton';
55
import { pageState } from '../lib/stores';
6-
import type { ArgsTooltip } from '@skeletonlabs/skeleton/utilities/Tooltip/tooltip';
76
87
export let MemoryRegion: MemoryRegionManager;
98
export let index: number;
@@ -26,6 +25,9 @@
2625
readOpacity = readCount / MemoryRegion.highestReadCount || 0;
2726
writeOpacity = writeCount / MemoryRegion.highestWriteCount || 0;
2827
totalOpacity = totalCount / MemoryRegion.highestTotalCount || 0;
28+
if ($pageState.customTotalAccessCount > 0) {
29+
totalOpacity = totalCount / $pageState.customTotalAccessCount;
30+
}
2931
3032
originalMemoryAddress = MemoryRegion.convertIndexToAddressString(index);
3133
}
@@ -40,8 +42,10 @@
4042
<div class="flex flex-col flex-1" title={'Index: ' + index}>
4143
{#if $pageState.showCombinedAccess}
4244
<div
43-
class="flex-1 flex justify-center items-center bg-access-all high-contrast-text-shadow content-cell"
44-
style="--tw-bg-opacity: {totalOpacity}"
45+
class="flex-1 flex justify-center bg-access-all font-black high-contrast-stroke items-center high-contrast-text-shadow content-cell"
46+
style="--tw-bg-opacity: {totalOpacity};{$pageState.useCustomColorScheme
47+
? 'background-color: ' + $cubeHelixLookup(totalOpacity) + ';'
48+
: ''}"
4549
on:click={() => {
4650
drawerStore.open({
4751
position: 'bottom'
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<script lang="ts">
2+
import { Modal, modalStore, RangeSlider, SlideToggle } from '@skeletonlabs/skeleton';
3+
import {
4+
pageState,
5+
cubeHelixParameters,
6+
cubeHelixLookup,
7+
cubeHelixMapFunction,
8+
currentMemoryRegion
9+
} from '../lib/stores';
10+
import { derived, writable } from 'svelte/store';
11+
import { cubehelix } from 'cubehelix';
12+
13+
export let parent: Modal;
14+
const localCubeHelixParameters = writable(Object.assign({}, $cubeHelixParameters));
15+
const localCubeHelixLookup = derived(localCubeHelixParameters, ($localCubeHelixParameters) => {
16+
const colorArray = new Array(1000);
17+
18+
const func = cubehelix($localCubeHelixParameters);
19+
20+
// Fill the color array with the correct colors
21+
for (let i = 0; i < 1000; i++) {
22+
const color = func(i / 1000);
23+
colorArray[i] = `rgb(${color.r[0] * 255}, ${color.g[0] * 255}, ${color.b[0] * 255})`;
24+
}
25+
26+
return (index: number) => {
27+
// Clamp index between 0 and 1
28+
index = Math.max(0, Math.min(1, index));
29+
return colorArray[Math.floor(index * (1000 - 1))];
30+
};
31+
});
32+
33+
let gradientWidth: number;
34+
let multiplier = 1;
35+
let parametersUnchanged = true;
36+
37+
$: {
38+
if ('name' in $currentMemoryRegion && $pageState.customTotalAccessCount) {
39+
multiplier = $currentMemoryRegion.highestTotalCount / $pageState.customTotalAccessCount;
40+
} else {
41+
multiplier = 1;
42+
}
43+
44+
parametersUnchanged = JSON.stringify($cubeHelixParameters) !== JSON.stringify($localCubeHelixParameters);
45+
}
46+
</script>
47+
48+
<div>
49+
<div class="w-full h-full flex flex-col align-middle justify-center items-center gap-2">
50+
<SlideToggle bind:checked={$pageState.useCustomColorScheme}
51+
>Use a cube helix color scheme for the combined view</SlideToggle
52+
>
53+
<div class="flex align-middle items-center justify-evenly">
54+
<div class="mr-4">Overwrite reference maximum number:</div>
55+
<div class=""><input type="number" class="w-8" bind:value={$pageState.customTotalAccessCount} /></div>
56+
</div>
57+
<div class="variant-soft rounded-3xl w-full h-full my-4 mx-2 p-3">
58+
<div class="font-black text-center mb-4">Cube Helix Settings</div>
59+
60+
<div class="flex flex-col gap-4">
61+
<div class="flex">
62+
<div class="flex-1">
63+
<RangeSlider bind:value={$localCubeHelixParameters.start} min={0} max={5} step={0.05} ticked>
64+
<div class="flex justify-between items-center">
65+
<div class="move-down text-xs">0</div>
66+
<div class="flex-1 text-center">Start Parameter</div>
67+
<div class="move-down text-xs">5</div>
68+
</div>
69+
</RangeSlider>
70+
</div>
71+
<div class="flex align-middle items-center justify-center ml-6">
72+
<div class="mr-4">Value:</div>
73+
<input
74+
class="max-w-[64px] text-xs p-2"
75+
min="0"
76+
max="5"
77+
type="number"
78+
bind:value={$localCubeHelixParameters.start}
79+
/>
80+
</div>
81+
</div>
82+
<div class="flex">
83+
<div class="flex-1">
84+
<RangeSlider bind:value={$localCubeHelixParameters.r} min={-10} max={30} step={0.1} ticked>
85+
<div class="flex justify-between items-center">
86+
<div class="move-down text-xs">-10</div>
87+
<div class="flex-1 text-center">Rotation Parameter</div>
88+
<div class="move-down text-xs">30</div>
89+
</div>
90+
</RangeSlider>
91+
</div>
92+
<div class="flex align-middle items-center justify-center ml-6">
93+
<div class="mr-4">Value:</div>
94+
<input
95+
class="max-w-[64px] text-xs p-2"
96+
min="-10"
97+
max="30"
98+
type="number"
99+
bind:value={$localCubeHelixParameters.r}
100+
/>
101+
</div>
102+
</div>
103+
<div class="flex">
104+
<div class="flex-1">
105+
<RangeSlider bind:value={$localCubeHelixParameters.hue} min={0} max={10} step={0.05} ticked>
106+
<div class="flex justify-between items-center">
107+
<div class="move-down text-xs">0</div>
108+
<div class="flex-1 text-center">Hue Parameter</div>
109+
<div class="move-down text-xs">10</div>
110+
</div>
111+
</RangeSlider>
112+
</div>
113+
<div class="flex align-middle items-center justify-center ml-6">
114+
<div class="mr-4">Value:</div>
115+
<input
116+
class="max-w-[64px] text-xs p-2"
117+
min="0.00"
118+
max="10"
119+
type="number"
120+
bind:value={$localCubeHelixParameters.hue}
121+
/>
122+
</div>
123+
</div>
124+
<div class="flex">
125+
<div class="flex-1">
126+
<RangeSlider bind:value={$localCubeHelixParameters.gamma} min={0.0} max={5} step={0.05} ticked>
127+
<div class="flex justify-between items-center">
128+
<div class="move-down text-xs">0</div>
129+
<div class="flex-1 text-center">Gamma Parameter</div>
130+
<div class="move-down text-xs">5</div>
131+
</div>
132+
</RangeSlider>
133+
</div>
134+
<div class="flex align-middle items-center justify-center ml-6">
135+
<div class="mr-4">Value:</div>
136+
<input
137+
class="max-w-[64px] text-xs p-2"
138+
min="0.01"
139+
max="5"
140+
type="number"
141+
bind:value={$localCubeHelixParameters.gamma}
142+
/>
143+
</div>
144+
</div>
145+
</div>
146+
147+
<div class="font-mono text-center mt-4">Preview</div>
148+
<div class="flex rounded-3xl overflow-hidden" bind:clientWidth={gradientWidth}>
149+
{#each Array.from({ length: Math.floor(gradientWidth / 2) }) as _, i}
150+
<div
151+
class="h-8 flex-1"
152+
style={`background-color: ${$localCubeHelixLookup((i / (gradientWidth / 2)) * multiplier)}`}
153+
/>
154+
{/each}
155+
</div>
156+
<div class="font-mono text-center mt-4">Presets</div>
157+
<div class="flex justify-evenly items-center">
158+
<button
159+
class="btn variant-soft"
160+
on:click={() => {
161+
$localCubeHelixParameters = { start: 0, r: 0.6, hue: 3.0, gamma: 1.0 };
162+
}}
163+
>
164+
Heat
165+
</button>
166+
<button
167+
class="btn variant-soft"
168+
on:click={() => {
169+
$localCubeHelixParameters = { start: 0.75, r: -0.4, hue: 4.2, gamma: 1.55 };
170+
}}
171+
>
172+
Winter
173+
</button>
174+
<button
175+
class="btn variant-soft"
176+
on:click={() => {
177+
$localCubeHelixParameters = { start: 2.55, r: 0.1, hue: 5.9, gamma: 1.55 };
178+
}}
179+
>
180+
Blue
181+
</button>
182+
<button
183+
class="btn variant-soft"
184+
on:click={() => {
185+
$localCubeHelixParameters = { start: 5, r: 1.6, hue: 2.15, gamma: 7 };
186+
}}
187+
>
188+
Peak
189+
</button>
190+
</div>
191+
</div>
192+
</div>
193+
194+
<div class="h-[1px] w-full bg-surface-400/30 mb-4" />
195+
<footer class="modal-footer {parent.regionFooter}">
196+
<button class="btn {parent.buttonNeutral}" on:click={parent.onClose}>Close</button>
197+
<button
198+
class="btn {parent.buttonPositive}"
199+
on:click={() => {
200+
$cubeHelixParameters = Object.assign({}, $localCubeHelixParameters);
201+
}}
202+
disabled={!parametersUnchanged}>Apply</button
203+
>
204+
</footer>
205+
</div>
206+
207+
<style>
208+
.move-down {
209+
transform: translateY(0.5rem);
210+
}
211+
</style>

0 commit comments

Comments
 (0)