Yang Gu commited on
Commit
ab4a702
1 Parent(s): 7be4bb6

Add more demos

Browse files
css/DemoLayout.css ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #demo {
2
+ flex: 1 1 auto;
3
+ display: flex;
4
+ flex-direction: column;
5
+ }
6
+
7
+ .demoContainer {
8
+ text-align: center;
9
+ width: 100%;
10
+ }
11
+ .demoContainer iframe {
12
+ width: 100%;
13
+ height: 100%;
14
+ border: none;
15
+ display: block;
16
+ /* should should remain white because demos in iframes expect a white background */
17
+ color-scheme: light;
18
+ background-color: #fff;
19
+ }
20
+
21
+ .demoCategory {
22
+ margin-top: 0.25em;
23
+ margin-bottom: 0.25em;
24
+ position: relative;
25
+ }
26
+
27
+ [data-tooltip] {
28
+ cursor: pointer;
29
+ }
30
+
31
+ [data-tooltip]::after {
32
+ pointer-events: none;
33
+ content: attr(data-tooltip);
34
+ background-color: var(--tooltip-background);
35
+ box-shadow: 0 0 2px 2px var(--tooltip-border);
36
+ border-radius: 10px;
37
+ transition: opacity 0.2s ease-in, transform 0.2s ease-out;
38
+ padding: 0.5em;
39
+ opacity: 0;
40
+ display: block;
41
+ position: absolute;
42
+ transform: translateY(-0.5em);
43
+ }
44
+
45
+ [data-tooltip]:hover::after {
46
+ opacity: 1;
47
+ transform: translateY(0.25em);
48
+ }
49
+
50
+ nav.sourceFileNav {
51
+ display: flex;
52
+ align-items: flex-start;
53
+ }
54
+
55
+ nav.sourceFileNav ul {
56
+ box-sizing: border-box;
57
+ list-style-type: none;
58
+ padding: 0;
59
+ margin: 0;
60
+ margin-top: 15px;
61
+ position: relative;
62
+ }
63
+
64
+ nav.sourceFileNav li {
65
+ display: inline-block;
66
+ margin: 0;
67
+ padding: 0;
68
+ transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
69
+ }
70
+
71
+ nav.sourceFileNav::before {
72
+ content: '';
73
+ position: absolute;
74
+ display: flex;
75
+ flex-direction: column;
76
+ justify-content: center;
77
+ align-items: flex-start;
78
+ width: 30px;
79
+ height: 37px;
80
+ top: 15px;
81
+ left: 0px;
82
+ pointer-events: none;
83
+ }
84
+
85
+ nav.sourceFileNav[data-left=true]::before {
86
+ background: linear-gradient(90deg, rgba(0, 0, 0, 0.35), transparent);
87
+ }
88
+
89
+ nav.sourceFileNav::after {
90
+ content: '';
91
+ position: absolute;
92
+ display: flex;
93
+ justify-content: center;
94
+ align-items: center;
95
+ width: 30px;
96
+ height: 37px;
97
+ top: 15px;
98
+ right: 0px;
99
+ pointer-events: none;
100
+ }
101
+
102
+ nav.sourceFileNav[data-right=true]::after {
103
+ background: linear-gradient(270deg, rgba(0, 0, 0, 0.35), transparent);
104
+ }
105
+
106
+ .sourceLR {
107
+ display: none;
108
+ cursor: pointer;
109
+ width: 5em;
110
+ padding: 10px;
111
+ margin-top: 15px;
112
+ text-align: center;
113
+ color: var(--source-tab-color);
114
+ background-color: var(--source-tab-background);
115
+ border-left: 1px solid rgba(0, 0, 0, 0.5);
116
+ border-right: 1px solid rgba(0, 0, 0, 0.5);
117
+ }
118
+ .sourceLR:hover {
119
+ text-decoration: underline;
120
+ }
121
+ .sourceLRShow .sourceLR {
122
+ display: block;
123
+ }
124
+
125
+ nav.sourceFileNav div.sourceFileScrollContainer {
126
+ white-space: nowrap;
127
+ overflow-x: auto;
128
+ scrollbar-width: thin;
129
+ }
130
+
131
+ nav.sourceFileNav div.sourceFileScrollContainer::-webkit-scrollbar {
132
+ display: inline;
133
+ margin-top: 10px;
134
+ margin-bottom: 10px;
135
+ height: 11px;
136
+ width: 10px;
137
+ }
138
+
139
+ nav.sourceFileNav div.sourceFileScrollContainer::-webkit-scrollbar-thumb {
140
+ background: rgb(200, 200, 200);
141
+ height: 4px;
142
+ border-radius: 20px;
143
+ -webkit-box-shadow: inset 0px 0px 10px rgb(45, 33, 33);
144
+ border: 0.5px solid transparent;
145
+ background-clip: content-box;
146
+ }
147
+
148
+ nav.sourceFileNav div.sourceFileScrollContainer::-webkit-scrollbar-track {
149
+ background: rgba(0, 0, 0, 0);
150
+ }
151
+
152
+ nav.sourceFileNav li a {
153
+ display: block;
154
+ margin: 0;
155
+ padding: 10px;
156
+ color: var(--source-tab-color);
157
+ background-color: var(--source-tab-background);
158
+ border-right: 1px solid rgba(0, 0, 0, 0.5);
159
+ }
160
+
161
+ nav.sourceFileNav li:hover {
162
+ height: 100%;
163
+ box-shadow: 0 -10px 0 0 rgb(167, 167, 167);
164
+ border-radius: 10px
165
+ }
166
+
167
+ nav.sourceFileNav li a[data-active=true] {
168
+ background-color: var(--source-tab-active-background);
169
+ }
170
+
171
+ nav.sourceFileNav li:has(a[data-active=true]) {
172
+ box-shadow: 0 -10px 0 0 var(--source-tab-active-shadow);
173
+ border-radius: 10px;
174
+ }
175
+
176
+ .sourceFileContainer {
177
+ overflow: hidden;
178
+ height: 0;
179
+ }
180
+
181
+ .sourceFileContainer[data-active=true] {
182
+ height: auto;
183
+ }
184
+
185
+ .sourceFileContainer :global(.CodeMirror) {
186
+ margin-top: 0;
187
+ }
css/HomePage.css ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ color-scheme: light dark;
3
+
4
+ /* these are the light colors */
5
+ --background: #eee;
6
+
7
+ --code-background: #ccc;
8
+ --link: #045b88;
9
+
10
+ --panel-color: #000;
11
+ --panel-background: #ddd;
12
+ --panel-emphasis: rgb(20, 62, 84);
13
+
14
+ --tooltip-background: #eee;
15
+ --tooltip-border: rgba(0, 0, 0, 0.1);
16
+
17
+ --source-tab-color: black;
18
+ --source-tab-background: #CCC;
19
+ --source-tab-active-background: #FFF;
20
+ --source-tab-active-shadow: #EEE;
21
+ }
22
+
23
+ @media (prefers-color-scheme: dark) {
24
+ :root {
25
+ /* these are the dark colors */
26
+ --background: #000;
27
+
28
+ --code-background: #555;
29
+ --link: #02abff;
30
+
31
+ --panel-color: #02abff;
32
+ --panel-background: #222;
33
+ --panel-emphasis: rgb(115, 206, 255);
34
+
35
+ --tooltip-background: #111;
36
+ --tooltip-border: rgba(255, 255, 255, 0.1);
37
+
38
+ --source-tab-color: white;
39
+ --source-tab-background: #444;
40
+ --source-tab-active-background: #282828;
41
+ --source-tab-active-shadow: rgb(167, 167, 167);
42
+ }
43
+ }
44
+
45
+ .homePage {
46
+ }
css/MainLayout.css ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .container {
2
+ padding-left: 15px;
3
+ padding-right: 15px;
4
+ }
5
+
6
+ .wrapper {
7
+ display: flex;
8
+ height: 100%;
9
+ }
10
+
11
+ .panel {
12
+ flex: 1 0 auto;
13
+ max-width: 300px;
14
+ height: 100%;
15
+ overflow-y: auto;
16
+ position: relative;
17
+ color: var(--panel-color);
18
+ background-color: var(--panel-background);
19
+ }
20
+
21
+ .exampleList {
22
+ padding: 0;
23
+ margin-block-start: 16px;
24
+ margin-block-end: 16px;
25
+ }
26
+
27
+ .exampleList h3 {
28
+ color: var(--panel-emphasis);
29
+ }
30
+
31
+ code {
32
+ background-color: var(--code-background);
33
+ border: 2px solid var(--code-background);
34
+ border-radius: 0.25em;
35
+ }
36
+
37
+ .exampleList li {
38
+ list-style: none;
39
+ padding: 0.3em 0;
40
+ }
41
+
42
+ .expand {
43
+ display: none;
44
+ position: absolute;
45
+ right: 1em;
46
+ top: 1em;
47
+ width: 36px;
48
+ height: 36px;
49
+ background-image: url(../menu.svg);
50
+ background-size: cover;
51
+ }
52
+
53
+ .panel .panelContents {
54
+ display: block;
55
+ transition: max-height 0s;
56
+ max-height: 100vh;
57
+ }
58
+
59
+ #menuToggle {
60
+ display: none;
61
+ }
62
+
63
+ main {
64
+ overflow: auto;
65
+ }
66
+
67
+ @media only screen and (max-width: 768px) {
68
+ .wrapper {
69
+ flex-direction: column;
70
+ }
71
+
72
+ main {
73
+ overflow: visible;
74
+ }
75
+
76
+ #menuToggle ~ .panelContents {
77
+ max-height: 0;
78
+ overflow: hidden;
79
+ }
80
+
81
+ #menuToggle:checked ~ .panelContents {
82
+ max-height: 2000px;
83
+ }
84
+
85
+ .panel .panelContents {
86
+ display: block;
87
+ transition: max-height 0.3s ease-out;
88
+ }
89
+
90
+ .panel {
91
+ flex: 0 0 fit-content;
92
+ max-width: 100%;
93
+ height: auto;
94
+ overflow: hidden;
95
+ }
96
+
97
+ .expand {
98
+ display: inline-block;
99
+ }
100
+
101
+ }
102
+
css/styles.css ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('HomePage.css');
2
+ @import url('MainLayout.css');
3
+ @import url('DemoLayout.css');
4
+
5
+ * {
6
+ box-sizing: border-box;
7
+ }
8
+ *, *:before, *:after {
9
+ box-sizing: inherit;
10
+ }
11
+
12
+ html, body {
13
+ margin: 0;
14
+ height: 100%;
15
+ background-color: var(--background);
16
+ }
17
+
18
+ body {
19
+ font-family: 'Inconsolata', monospace;
20
+ }
21
+
22
+ a {
23
+ text-decoration: none;
24
+ color: var(--link)
25
+ }
26
+
27
+ a:hover {
28
+ text-decoration: underline;
29
+ }
30
+
31
+ main {
32
+ display: flex;
33
+ flex-direction: column;
34
+ position: relative;
35
+ flex: 1;
36
+ padding-left: 15px;
37
+ padding-right: 15px;
38
+ }
39
+
40
+ .CodeMirror {
41
+ height: auto !important;
42
+ margin: 1em 0;
43
+ }
44
+
45
+ .CodeMirror-scroll {
46
+ height: auto !important;
47
+ overflow: visible !important;
48
+ }
{llm-inference → demos/llm-inference}/gemma-2b-it-gpu-int4.bin RENAMED
File without changes
{llm-inference → demos/llm-inference}/index.html RENAMED
@@ -18,7 +18,7 @@ limitations under the License. -->
18
  <title>LLM Inference Web Demo</title>
19
  </head>
20
  <body>
21
- <script src="../util.js"></script>
22
  <div style="text-align: center">
23
  <text id="model-progress">Downloading model</text><br />
24
  Input<br />
 
18
  <title>LLM Inference Web Demo</title>
19
  </head>
20
  <body>
21
+ <script src="../../util.js"></script>
22
  <div style="text-align: center">
23
  <text id="model-progress">Downloading model</text><br />
24
  Input<br />
{llm-inference → demos/llm-inference}/index.js RENAMED
File without changes
demos/sd-turbo/index.html ADDED
@@ -0,0 +1,717 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"
3
+ integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous" />
4
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"
5
+ integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous">
6
+ </script>
7
+ <script type="module">
8
+ import { env, AutoTokenizer } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers/dist/transformers.js'
9
+ window.AutoTokenizer = AutoTokenizer;
10
+ env.localModelPath = 'models';
11
+ </script>
12
+ <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@dev/dist/ort.webgpu.min.js">
13
+ </script>
14
+
15
+ <head>
16
+ <title>Stable Diffusion Turbo</title>
17
+ </head>
18
+
19
+ <style>
20
+ .onerow {
21
+ display: flex;
22
+ }
23
+ </style>
24
+
25
+ <body data-bs-theme="dark">
26
+ <div class="container">
27
+ <div class="row pt-3">
28
+ <div class="col-md-9 col-12">
29
+ <h2>Stable Diffusion Turbo</h2>
30
+ </div>
31
+ </div>
32
+ <div class="container p-2 card" id="input-area">
33
+ <div class="input-group">
34
+ <textarea class="form-control" id="user-input" placeholder="Type your question here..."></textarea>
35
+ <button id="send-button" class="btn btn-primary">Send</button>
36
+ </div>
37
+ </div>
38
+ <!--<div id="image_area">
39
+ <div class="onerow">
40
+ <div id="img_div_0" style="margin-right: 4px;">
41
+ <canvas id="img_canvas_0"></canvas>
42
+ </div>
43
+ <div id="img_div_1" style="margin-right: 4px;">
44
+ <canvas id="img_canvas_1"></canvas>
45
+ </div>
46
+ <div id="img_div_2" style="margin-right: 4px;">
47
+ <canvas id="img_canvas_2"></canvas>
48
+ </div>
49
+ <div id="img_div_3" style="margin-right: 4px;">
50
+ <canvas id="img_canvas_3"></canvas>
51
+ </div>
52
+ </div>
53
+ </div>-->
54
+ <div class="right">
55
+ <canvas class='canvas' id='canvas' width='512' height='512'>
56
+ Canvas is not supported. You'll need to try a newer browser version or another browser.
57
+ </canvas>
58
+ </div>
59
+ <p class="text-lg-start">
60
+ <div id="status" style="font: 1em consolas;"></div>
61
+ </p>
62
+ </div>
63
+ </body>
64
+
65
+ <script>
66
+
67
+ var deviceWebgpu = null;
68
+ var queueWebgpu = null;
69
+ var textEncoderOutputsBuffer = null;
70
+ var textEncoderOutputsTensor = null;
71
+ var textEncoderOutputs = {};
72
+ var latentData = null;
73
+ var latentBuffer = null;
74
+ var unetSampleInputsBuffer = null;
75
+ var unetSampleInputsTensor = null;
76
+ var unetOutSampleBuffer = null;
77
+ var unetOutSampleTensor = null;
78
+ var prescaleLatentSpacePipeline = null;
79
+ var prescaleLatentSpaceBindGroup = null;
80
+ var stepLatentSpacePipeline = null;
81
+ var stepLatentSpaceBindGroup = null;
82
+ var decodedOutputsBuffer = null;
83
+ var decodedOutputsTensor = null;
84
+ const pixelHeight = 512;
85
+ const pixelWidth = 512;
86
+ var renderContext = null;
87
+ var renderPipeline = null;
88
+ var renderBindGroup = null;
89
+
90
+ const PRESCALE_LATENT_SPACE_SHADER = `
91
+ @binding(0) @group(0) var<storage, read_write> result: array<vec4<f32>>;
92
+ @binding(1) @group(0) var<storage, read> latentData: array<vec4<f32>>;
93
+
94
+ @compute @workgroup_size(128, 1, 1)
95
+ fn _start(@builtin(global_invocation_id) GlobalId : vec3<u32>) {
96
+ let index = GlobalId.x;
97
+ let value = latentData[index] / 14.64877241136608;
98
+ result[index] = value;
99
+ }
100
+ `;
101
+
102
+ const STEP_LATENT_SPACE_SHADER = `
103
+ @binding(0) @group(0) var<storage, read_write> result: array<vec4<f32>>;
104
+ @binding(1) @group(0) var<storage, read> latentData: array<vec4<f32>>;
105
+
106
+ @compute @workgroup_size(128, 1, 1)
107
+ fn _start(@builtin(global_invocation_id) GlobalId : vec3<u32>) {
108
+ let index = GlobalId.x;
109
+ let sigma_hat = 14.6146;
110
+ let latentVal = latentData[index];
111
+ let outputSampleVal = result[index];
112
+
113
+ let pred_original_sample = latentVal - 14.6146 * outputSampleVal;
114
+ let derivative = (latentVal - pred_original_sample) / 14.6146;
115
+ let dt = -14.6146;
116
+ result[index] = (latentVal + derivative * dt) / 0.18215;
117
+ }
118
+ `;
119
+
120
+ const VERTEX_SHADER = `
121
+ struct VertexOutput {
122
+ @builtin(position) Position : vec4<f32>,
123
+ @location(0) fragUV : vec2<f32>,
124
+ }
125
+
126
+ @vertex
127
+ fn main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
128
+ var pos = array<vec2<f32>, 6>(
129
+ vec2<f32>( 1.0, 1.0),
130
+ vec2<f32>( 1.0, -1.0),
131
+ vec2<f32>(-1.0, -1.0),
132
+ vec2<f32>( 1.0, 1.0),
133
+ vec2<f32>(-1.0, -1.0),
134
+ vec2<f32>(-1.0, 1.0)
135
+ );
136
+
137
+ var uv = array<vec2<f32>, 6>(
138
+ vec2<f32>(1.0, 0.0),
139
+ vec2<f32>(1.0, 1.0),
140
+ vec2<f32>(0.0, 1.0),
141
+ vec2<f32>(1.0, 0.0),
142
+ vec2<f32>(0.0, 1.0),
143
+ vec2<f32>(0.0, 0.0)
144
+ );
145
+
146
+ var output : VertexOutput;
147
+ output.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
148
+ output.fragUV = uv[VertexIndex];
149
+ return output;
150
+ }
151
+ `;
152
+
153
+ const PIXEL_SHADER = `
154
+ @group(0) @binding(1) var<storage, read> buf : array<f32>;
155
+
156
+ @fragment
157
+ fn main(@location(0) fragUV : vec2<f32>) -> @location(0) vec4<f32> {
158
+ // The user-facing camera is mirrored, flip horizontally.
159
+ var coord = vec2(0.0, 0.0);
160
+ if (fragUV.x < 0.5) {
161
+ coord = vec2(fragUV.x + 0.5, fragUV.y);
162
+ } else {
163
+ coord = vec2(fragUV.x - 0.5, fragUV.y);
164
+ }
165
+
166
+ let redInputOffset = 0;
167
+ let greenInputOffset = 262144;
168
+ let blueInputOffset = 524288;
169
+ let index = i32(coord.x * f32(512)) + i32(coord.y * f32(512) * f32(512)); // pixelWidth = pixelHeight= 512
170
+ let r = clamp(buf[index] / 2 + 0.5, 0.0, 1.0);
171
+ let g = clamp(buf[262144 + index] / 2 + 0.5, 0.0, 1.0);
172
+ let b = clamp(buf[524288 + index] / 2 + 0.5, 0.0, 1.0);
173
+ let a = 1.0;
174
+
175
+ var out_color = vec4<f32>(r, g, b, a);
176
+
177
+ return out_color;
178
+ }
179
+ `
180
+
181
+ function log(i) { console.log(i); document.getElementById('status').innerText += `\n${i}`; }
182
+
183
+ function getConfig() {
184
+ const query = window.location.search.substring(1);
185
+ var config = {
186
+ // model: "models/onnx-sd-turbo-fp16",
187
+ //model: "https://huggingface.co/schmuell/sd-turbo-ort-web/resolve/main",
188
+ model: "models",
189
+ provider: "webgpu",
190
+ device: "gpu",
191
+ threads: "1",
192
+ images: "1",
193
+ };
194
+ let vars = query.split("&");
195
+ for (var i = 0; i < vars.length; i++) {
196
+ let pair = vars[i].split("=");
197
+ if (pair[0] in config) {
198
+ config[pair[0]] = decodeURIComponent(pair[1]);
199
+ } else if (pair[0].length > 0) {
200
+ throw new Error("unknown argument: " + pair[0]);
201
+ }
202
+ }
203
+ config.threads = parseInt(config.threads);
204
+ config.images = parseInt(config.images);
205
+ return config;
206
+ }
207
+
208
+ function randn_latents(shape, noise_sigma) {
209
+ function randn() {
210
+ // Use the Box-Muller transform
211
+ let u = Math.random();
212
+ let v = Math.random();
213
+ let z = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
214
+ return z;
215
+ }
216
+ let size = 1;
217
+ shape.forEach(element => {
218
+ size *= element;
219
+ });
220
+
221
+ let data = new Float32Array(size);
222
+ // Loop over the shape dimensions
223
+ for (let i = 0; i < size; i++) {
224
+ data[i] = randn() * noise_sigma;
225
+ }
226
+ return data;
227
+ }
228
+
229
+ async function fetchAndCache(base_url, model_path) {
230
+ const url = `${base_url}/${model_path}`;
231
+ try {
232
+ const cache = await caches.open("onnx");
233
+ let cachedResponse = await cache.match(url);
234
+ if (cachedResponse == undefined) {
235
+ await cache.add(url);
236
+ cachedResponse = await cache.match(url);
237
+ log(`${model_path} (network)`);
238
+ } else {
239
+ log(`${model_path} (cached)`);
240
+ }
241
+ const data = await cachedResponse.arrayBuffer();
242
+ return data;
243
+ } catch (error) {
244
+ log(`${model_path} (network)`);
245
+ return await fetch(url).then(response => response.arrayBuffer());
246
+ }
247
+ }
248
+
249
+ function uploadToGPU(buffer, values, type) {
250
+
251
+ const stagingBuffer = deviceWebgpu.createBuffer({
252
+ usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC,
253
+ size: values.buffer.byteLength,
254
+ mappedAtCreation: true
255
+ });
256
+ const arrayBuffer = stagingBuffer.getMappedRange();
257
+ if (type === 'float32') {
258
+ new Float32Array(arrayBuffer).set(values);
259
+ } else if (type === 'int32') {
260
+ new Int32Array(arrayBuffer).set(values);
261
+ }
262
+ stagingBuffer.unmap();
263
+ const encoder = deviceWebgpu.createCommandEncoder();
264
+ encoder.copyBufferToBuffer(stagingBuffer, 0, buffer, 0, values.byteLength);
265
+ deviceWebgpu.queue.submit([encoder.finish()]);
266
+ stagingBuffer.destroy();
267
+ }
268
+
269
+ function submitComputeTask(pipeline, bindGroup) {
270
+ let commandEncoderWebgpu = deviceWebgpu.createCommandEncoder();
271
+ let computePassEncoder = commandEncoderWebgpu.beginComputePass();
272
+ computePassEncoder.setPipeline(pipeline);
273
+ computePassEncoder.setBindGroup(0, bindGroup);
274
+ computePassEncoder.dispatchWorkgroups(32, 1, 1);
275
+ computePassEncoder.end();
276
+ computePassEncoder = null;
277
+ queueWebgpu.submit([commandEncoderWebgpu.finish()]);
278
+ }
279
+
280
+ async function load_models(models) {
281
+ const cache = await caches.open("onnx");
282
+ let missing = 0;
283
+ for (const [name, model] of Object.entries(models)) {
284
+ const url = `${config.model}/${model.url}`;
285
+ let cachedResponse = await cache.match(url);
286
+ if (cachedResponse === undefined) {
287
+ missing += model.size;
288
+ }
289
+ }
290
+ if (missing > 0) {
291
+ log(`downloading ${missing} MB from network ... it might take a while`);
292
+ } else {
293
+ log("loading...");
294
+ }
295
+ let loadedCount = 0;
296
+ for (const [name, model] of Object.entries(models)) {
297
+ try {
298
+ if (loadedCount === 1) {
299
+ webgpuResourceInitialize();
300
+ }
301
+ const start = performance.now();
302
+ const model_bytes = await fetchAndCache(config.model, model.url);
303
+ const sess_opt = { ...opt, ...model.opt };
304
+ // profiling
305
+ //ort.env.webgpu.profiling = { mode: "default" };
306
+ models[name].sess = await ort.InferenceSession.create(model_bytes, sess_opt);
307
+ const stop = performance.now();
308
+ loadedCount++;
309
+ log(`${model.url} in ${(stop - start).toFixed(1)}ms`);
310
+ } catch (e) {
311
+ log(`${model.url} failed, ${e}`);
312
+ }
313
+ }
314
+ const latent_shape = [1, 4, 64, 64];
315
+ latentData = randn_latents(latent_shape, sigma);
316
+ uploadToGPU(latentBuffer, latentData, "float32");
317
+ submitComputeTask(prescaleLatentSpacePipeline, prescaleLatentSpaceBindGroup);
318
+
319
+ log("ready.");
320
+ }
321
+
322
+ const config = getConfig();
323
+
324
+ const models = {
325
+ "unet": {
326
+ url: "unet/model.onnx", size: 640,
327
+ // should have 'steps: 1' but will fail to create the session
328
+ opt: { freeDimensionOverrides: { batch_size: 1, num_channels: 4, height: 64, width: 64, sequence_length: 77, } }
329
+ },
330
+ "text_encoder": {
331
+ url: "text_encoder/model.onnx", size: 1700,
332
+ // should have 'sequence_length: 77' but produces a bad image
333
+ opt: { freeDimensionOverrides: { batch_size: 1, } },
334
+ },
335
+ "vae_decoder": {
336
+ url: "vae_decoder/model.onnx", size: 95,
337
+ opt: { freeDimensionOverrides: { batch_size: 1, num_channels_latent: 4, height_latent: 64, width_latent: 64 } }
338
+ }
339
+ }
340
+
341
+ const text = document.getElementById("user-input");
342
+
343
+ let tokenizer;
344
+ let loading;
345
+ const sigma = 14.6146;
346
+ const gamma = 0;
347
+ const vae_scaling_factor = 0.18215;
348
+
349
+ // text.value = "A cinematic shot of a baby racoon wearing an intricate italian priest robe.";
350
+ text.value = "Paris with the river in the background";
351
+
352
+ if (config.provider == "webgpu") {
353
+ ort.env.wasm.numThreads = 1;
354
+ ort.env.wasm.simd = true;
355
+ } else {
356
+ ort.env.wasm.numThreads = config.threads;
357
+ ort.env.wasm.simd = true;
358
+ }
359
+
360
+ const opt = {
361
+ executionProviders: [config.provider],
362
+ enableMemPattern: false,
363
+ enableCpuMemArena: false,
364
+ extra: {
365
+ session: {
366
+ disable_prepacking: "1",
367
+ use_device_allocator_for_initializers: "1",
368
+ use_ort_model_bytes_directly: "1",
369
+ use_ort_model_bytes_for_initializers: "1"
370
+ }
371
+ },
372
+ };
373
+
374
+ switch (config.provider) {
375
+ case "webgpu":
376
+ if (!("gpu" in navigator)) {
377
+ throw new Error("webgpu is NOT supported");
378
+ }
379
+ opt.preferredOutputLocation = { last_hidden_state: "gpu-buffer" };
380
+ break;
381
+ case "webnn":
382
+ if (!("ml" in navigator)) {
383
+ throw new Error("webnn is NOT supported");
384
+ }
385
+ opt.executionProviders = [{
386
+ name: "webnn",
387
+ deviceType: config.device,
388
+ powerPreference: 'default'
389
+ }];
390
+ break;
391
+ }
392
+
393
+ // Event listener for Ctrl + Enter or CMD + Enter
394
+ document.getElementById('user-input').addEventListener('keydown', function (e) {
395
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
396
+ run();
397
+ const latent_shape = [1, 4, 64, 64];
398
+ latentData = randn_latents(latent_shape, sigma);
399
+ uploadToGPU(latentBuffer, latentData, "float32");
400
+ submitComputeTask(prescaleLatentSpacePipeline, prescaleLatentSpaceBindGroup);
401
+ }
402
+ });
403
+ document.getElementById('send-button').addEventListener('click', function (e) {
404
+ run();
405
+ const latent_shape = [1, 4, 64, 64];
406
+ latentData = randn_latents(latent_shape, sigma);
407
+ uploadToGPU(latentBuffer, latentData, "float32");
408
+ submitComputeTask(prescaleLatentSpacePipeline, prescaleLatentSpaceBindGroup);
409
+ });
410
+
411
+ function init_latents(t) {
412
+ const d = t.data;
413
+ for (let i = 0; i < d.length; i++) {
414
+ d[i] = d[i] * sigma;
415
+ }
416
+ return t;
417
+ }
418
+
419
+ function scale_model_inputs(t) {
420
+ const d_i = t.data;
421
+ const d_o = new Float32Array(d_i.length);
422
+
423
+ const divi = (sigma ** 2 + 1) ** 0.5;
424
+ for (let i = 0; i < d_i.length; i++) {
425
+ d_o[i] = d_i[i] / divi;
426
+ }
427
+ return new ort.Tensor(d_o, t.dims);
428
+ }
429
+
430
+ function step(model_output, sample) {
431
+ // poor mens EulerA.
432
+ // Since this is just a example for sd-turbo, only implement the absolute minimum
433
+ // needed to create an image
434
+ const d_o = new Float32Array(model_output.data.length);
435
+ const prev_sample = new ort.Tensor(d_o, model_output.dims);
436
+ const sigma_hat = sigma * (gamma + 1);
437
+
438
+ for (let i = 0; i < model_output.data.length; i++) {
439
+ pred_original_sample = sample.data[i] - sigma_hat * model_output.data[i];
440
+ derivative = (sample.data[i] - pred_original_sample) / sigma_hat;
441
+ dt = 0 - sigma_hat;
442
+ d_o[i] = (sample.data[i] + derivative * dt) / vae_scaling_factor;
443
+ }
444
+ return prev_sample;
445
+ }
446
+
447
+ function draw_image(t, image_nr) {
448
+ let pix = t.data;
449
+ for (var i = 0; i < pix.length; i++) {
450
+ let x = pix[i];
451
+ x = x / 2 + 0.5
452
+ if (x < 0.) x = 0.;
453
+ if (x > 1.) x = 1.;
454
+ pix[i] = x;
455
+ }
456
+ const imageData = t.toImageData({ tensorLayout: 'NCWH', format: 'RGB' });
457
+ const canvas = document.getElementById(`img_canvas_${image_nr}`);
458
+ canvas.width = imageData.width;
459
+ canvas.height = imageData.height;
460
+ canvas.getContext('2d').putImageData(imageData, 0, 0);
461
+ const div = document.getElementById(`img_div_${image_nr}`);
462
+ div.style.opacity = 1.
463
+ }
464
+
465
+ async function downloadToCPU(buffer) {
466
+ const stagingBuffer = deviceWebgpu.createBuffer({
467
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
468
+ size: buffer.size
469
+ });
470
+ const encoder = deviceWebgpu.createCommandEncoder();
471
+ encoder.copyBufferToBuffer(buffer, 0, stagingBuffer, 0, buffer.size);
472
+ deviceWebgpu.queue.submit([encoder.finish()]);
473
+
474
+ await stagingBuffer.mapAsync(GPUMapMode.READ);
475
+ const arrayBuffer = stagingBuffer.getMappedRange().slice(0, buffer.size / 4);
476
+ stagingBuffer.destroy();
477
+ return new Float32Array(arrayBuffer);
478
+ };
479
+
480
+ async function run() {
481
+ try {
482
+ document.getElementById('status').innerText = "generating ...";
483
+
484
+ if (tokenizer === undefined) {
485
+ tokenizer = await AutoTokenizer.from_pretrained('tokenizer', quantized = false, local_files_only = false);
486
+ tokenizer.pad_token_id = 0;
487
+ }
488
+ let canvases = [];
489
+ await loading;
490
+
491
+ const { input_ids } = await tokenizer(text.value, { padding: true, max_length: 77, truncation: true, return_tensor: false });
492
+
493
+ // text-encoder
494
+ let start = performance.now();
495
+ const executionStart = performance.now();
496
+ textEncoderOutputs['last_hidden_state'] = textEncoderOutputsTensor;
497
+ await models.text_encoder.sess.run({ "input_ids": new ort.Tensor("int32", input_ids, [1, input_ids.length]) }, textEncoderOutputs);
498
+
499
+ let perf_info = [`text_encoder: ${(performance.now() - start).toFixed(1)}ms`];
500
+
501
+ for (let j = 0; j < config.images; j++) {
502
+ start = performance.now();
503
+ let feed = {
504
+ "sample": unetSampleInputsTensor,
505
+ "timestep": new ort.Tensor("int64", [999n], [1]),
506
+ "encoder_hidden_states": textEncoderOutputsTensor,
507
+ };
508
+ var unetOutSampleOutputs = {};
509
+ unetOutSampleOutputs['out_sample'] = unetOutSampleTensor;
510
+ let { out_sample } = await models.unet.sess.run(feed, unetOutSampleOutputs);
511
+ perf_info.push(`unet: ${(performance.now() - start).toFixed(1)}ms`);
512
+
513
+ submitComputeTask(stepLatentSpacePipeline, stepLatentSpaceBindGroup);
514
+
515
+ start = performance.now();
516
+ var vaeDecodeInputs = {};
517
+ vaeDecodeInputs['latent_sample'] = unetOutSampleTensor;
518
+ const decodedOutputs = {};
519
+ decodedOutputs['sample'] = decodedOutputsTensor;
520
+ await models.vae_decoder.sess.run(vaeDecodeInputs, decodedOutputs);
521
+ // profiling
522
+ // ort.env.webgpu.profiling = { mode: "" };
523
+
524
+
525
+ const commandEncoder = deviceWebgpu.createCommandEncoder();
526
+ const textureView = renderContext.getCurrentTexture().createView();
527
+ const renderPassDescriptor = {
528
+ colorAttachments: [
529
+ {
530
+ view: textureView,
531
+ clearValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
532
+ loadOp: 'clear',
533
+ storeOp: 'store',
534
+ },
535
+ ],
536
+ };
537
+
538
+ const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
539
+ passEncoder.setPipeline(renderPipeline);
540
+ passEncoder.setBindGroup(0, renderBindGroup);
541
+ passEncoder.draw(6, 1, 0, 0);
542
+ passEncoder.end();
543
+ deviceWebgpu.queue.submit([commandEncoder.finish()]);
544
+ await deviceWebgpu.queue.onSubmittedWorkDone();
545
+
546
+ const executionEnd = performance.now();
547
+ perf_info.push(`vae_decoder: ${(executionEnd - start).toFixed(1)}ms`);
548
+ perf_info.push(`execution time: ${(executionEnd - executionStart).toFixed(1)}ms`);
549
+ log(perf_info.join(", "))
550
+ perf_info = [];
551
+ }
552
+ //last_hidden_state.dispose();
553
+
554
+ log("done");
555
+ } catch (e) {
556
+ log(e);
557
+ }
558
+ }
559
+
560
+ function webgpuResourceInitialize() {
561
+ deviceWebgpu = ort.env.webgpu.device;
562
+ queueWebgpu = deviceWebgpu.queue;
563
+
564
+ textEncoderOutputsBuffer = deviceWebgpu.createBuffer({
565
+ size: Math.ceil((1 * 77 * 1024 * 4) / 16) * 16,
566
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
567
+ });
568
+ textEncoderOutputsTensor = ort.Tensor.fromGpuBuffer(textEncoderOutputsBuffer, {
569
+ dataType: 'float32', dims: [1, 77, 1024],
570
+ dispose: () => textEncoderOutputsBuffer.destroy()
571
+ });
572
+
573
+ unetOutSampleBuffer = deviceWebgpu.createBuffer({
574
+ size: Math.ceil((1 * 4 * 64 * 64 * 4) / 16) * 16,
575
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
576
+ });
577
+ unetOutSampleTensor = ort.Tensor.fromGpuBuffer(unetOutSampleBuffer, {
578
+ dataType: 'float32', dims: [1, 4, 64, 64],
579
+ dispose: () => unetOutSampleBuffer.destroy()
580
+ });
581
+ latentBuffer = deviceWebgpu.createBuffer({
582
+ size: Math.ceil((1 * 4 * 64 * 64 * 4) / 16) * 16,
583
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
584
+ });
585
+ unetSampleInputsBuffer = deviceWebgpu.createBuffer({
586
+ size: Math.ceil((1 * 4 * 64 * 64 * 4) / 16) * 16,
587
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
588
+ });
589
+ unetSampleInputsTensor = ort.Tensor.fromGpuBuffer(unetSampleInputsBuffer, {
590
+ dataType: 'float32', dims: [1, 4, 64, 64],
591
+ dispose: () => unetSampleInputsBuffer.destroy()
592
+ });
593
+ decodedOutputsBuffer = deviceWebgpu.createBuffer({
594
+ size: Math.ceil((1 * 3 * pixelHeight * pixelWidth * 4) / 16) * 16,
595
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
596
+ });
597
+ decodedOutputsTensor = ort.Tensor.fromGpuBuffer(decodedOutputsBuffer, {
598
+ dataType: 'float32', dims: [1, 3, pixelHeight, pixelWidth],
599
+ dispose: () => decodedOutputsBuffer.destroy()
600
+ });
601
+
602
+ prescaleLatentSpacePipeline = deviceWebgpu.createComputePipeline({
603
+ layout: 'auto',
604
+ compute: {
605
+ module: deviceWebgpu.createShaderModule({
606
+ code: PRESCALE_LATENT_SPACE_SHADER,
607
+ }),
608
+ entryPoint: '_start',
609
+ },
610
+ });
611
+
612
+ prescaleLatentSpaceBindGroup = deviceWebgpu.createBindGroup({
613
+ layout: prescaleLatentSpacePipeline.getBindGroupLayout(0),
614
+ entries: [
615
+ {
616
+ binding: 0,
617
+ resource: {
618
+ buffer: unetSampleInputsBuffer,
619
+ },
620
+ },
621
+ {
622
+ binding: 1,
623
+ resource: {
624
+ buffer: latentBuffer,
625
+ },
626
+ }
627
+ ],
628
+ });
629
+
630
+ stepLatentSpacePipeline = deviceWebgpu.createComputePipeline({
631
+ layout: 'auto',
632
+ compute: {
633
+ module: deviceWebgpu.createShaderModule({
634
+ code: STEP_LATENT_SPACE_SHADER,
635
+ }),
636
+ entryPoint: '_start',
637
+ },
638
+ });
639
+ stepLatentSpaceBindGroup = deviceWebgpu.createBindGroup({
640
+ layout: stepLatentSpacePipeline.getBindGroupLayout(0),
641
+ entries: [
642
+ {
643
+ binding: 0,
644
+ resource: {
645
+ buffer: unetOutSampleBuffer,
646
+ },
647
+ },
648
+ {
649
+ binding: 1,
650
+ resource: {
651
+ buffer: latentBuffer,
652
+ },
653
+ }
654
+ ],
655
+ });
656
+
657
+
658
+
659
+ const canvas = document.getElementById(`canvas`);
660
+ canvas.width = pixelWidth;
661
+ canvas.height = pixelHeight;
662
+ renderContext = canvas.getContext('webgpu');
663
+ const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
664
+ const presentationSize = [pixelWidth, pixelHeight];
665
+ renderContext.configure({
666
+ device: deviceWebgpu,
667
+ size: presentationSize,
668
+ format: presentationFormat,
669
+ alphaMode: 'opaque',
670
+ });
671
+ renderPipeline = deviceWebgpu.createRenderPipeline({
672
+ layout: 'auto',
673
+ vertex: {
674
+ module: deviceWebgpu.createShaderModule({
675
+ code: VERTEX_SHADER,
676
+ }),
677
+ entryPoint: 'main',
678
+ },
679
+ fragment: {
680
+ module: deviceWebgpu.createShaderModule({
681
+ code: PIXEL_SHADER,
682
+ }),
683
+ entryPoint: 'main',
684
+ targets: [
685
+ {
686
+ format: presentationFormat,
687
+ },
688
+ ],
689
+ },
690
+ primitive: {
691
+ topology: 'triangle-list',
692
+ },
693
+ });
694
+
695
+ renderBindGroup = deviceWebgpu.createBindGroup({
696
+ layout: renderPipeline.getBindGroupLayout(0),
697
+ entries: [
698
+ {
699
+ binding: 1,
700
+ resource: {
701
+ buffer: decodedOutputsBuffer,
702
+ },
703
+ }
704
+ ],
705
+ });
706
+ }
707
+
708
+ async function main() {
709
+ loading = load_models(models);
710
+ }
711
+
712
+ window.onload = () => {
713
+ main();
714
+ }
715
+ </script>
716
+
717
+ </html>
demos/sd-turbo/models/text_encoder/model.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c1ab8b82cee150bf2affbcf4bc05eda98a14e082d973429b7e668d3f49e62445
3
+ size 681434530
demos/sd-turbo/models/tokenizer/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
demos/sd-turbo/models/tokenizer/tokenizer_config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "bos_token": {
4
+ "__type": "AddedToken",
5
+ "content": "<|startoftext|>",
6
+ "lstrip": false,
7
+ "normalized": true,
8
+ "rstrip": false,
9
+ "single_word": false
10
+ },
11
+ "clean_up_tokenization_spaces": true,
12
+ "do_lower_case": true,
13
+ "eos_token": {
14
+ "__type": "AddedToken",
15
+ "content": "<|endoftext|>",
16
+ "lstrip": false,
17
+ "normalized": true,
18
+ "rstrip": false,
19
+ "single_word": false
20
+ },
21
+ "errors": "replace",
22
+ "model_max_length": 77,
23
+ "pad_token": "<|endoftext|>",
24
+ "processor_class": "CLIPProcessor",
25
+ "tokenizer_class": "CLIPTokenizer",
26
+ "unk_token": {
27
+ "__type": "AddedToken",
28
+ "content": "<|endoftext|>",
29
+ "lstrip": false,
30
+ "normalized": true,
31
+ "rstrip": false,
32
+ "single_word": false
33
+ }
34
+ }
demos/sd-turbo/models/unet/model.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:111a916278adea77511eeab6662ffe356c924b15127a3556608ad557abbf3fab
3
+ size 1733736024
demos/sd-turbo/models/vae_decoder/model.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b506b8b8bedbfe342c60fb2a931fb7f666cbc910e1869a68b9b55a99500ed17a
3
+ size 99116807
index.html CHANGED
@@ -1,44 +1,41 @@
1
- <title>WebAI Demos</title>
 
 
 
 
2
  <body>
3
- <h1 align="center">WebAI Demos</h1>
4
- <script src="util.js"></script>
5
- <script>
6
- "use strict";
7
- const demos = [
8
- [
9
- "LLMs with MediaPipe and TFLite",
10
- "llm-inference",
11
- "<a href=https://github.com/googlesamples/mediapipe/tree/main/examples/llm_inference/js>original code</a>, <a href=https://developers.googleblog.com/2024/03/running-large-language-models-on-device-with-mediapipe-andtensorflow-lite.html>more info</a>",
12
- ],
13
- ];
14
 
15
- // table
16
- const table = document.createElement("table");
17
- table.align = "center";
18
- table.style.width = "80%";
19
- table.setAttribute("border", "1");
20
- document.body.appendChild(table);
21
-
22
- // first line
23
- let row = table.insertRow(-1);
24
- const headers = ["Name", "Description"];
25
- row.style.fontWeight = "bold";
26
- for (let header of headers) {
27
- let td = row.insertCell(-1);
28
- td.innerHTML = header;
29
- }
30
-
31
- // rest of lines
32
- for (let demo of demos) {
33
- row = table.insertRow(-1);
34
- let td = row.insertCell(-1);
35
- let href = `${demo[1]}/index.html`;
36
- if (window.location.origin.includes("hf")) {
37
- href = `/${href}`;
38
- }
39
- td.innerHTML = `<a href=${href}>${demo[0]}</a>`;
40
- td = row.insertCell(-1);
41
- td.innerHTML = demo[2];
42
- }
43
- </script>
44
- </body>
 
1
+ <head>
2
+ <title>WebAI Demos</title>
3
+ <link href="css/styles.css" rel="stylesheet">
4
+ </head>
5
+ <script defer type="module" src="main.js"></script>
6
  <body>
7
+ <div class="wrapper">
8
+ <nav class="panel container">
9
+ <h1><a href="./">WebAI Demos</a></h1>
10
+ <input type="checkbox" id="menuToggle">
11
+ <label class="expand" for="menuToggle"></label>
12
+ <div class="panelContents">
13
+ <hr>
14
+ <div id="demoList"></div>
15
+ </div>
16
+ </nav>
 
17
 
18
+ <main>
19
+ <div id="intro">
20
+ <p>
21
+ The WebAI demos demonstrate the use of the <a href="//webgpu.dev">WebGPU API</a>.
22
+ </p>
23
+ </div>
24
+ <div id="demo" style="display: none;">
25
+ <div class="demoInfo">
26
+ <h1 id="title"></h1>
27
+ <p id="description"></p>
28
+ </div>
29
+ <div class="demoContainer"></div>
30
+ </div>
31
+ <nav id="code" class="sourceFileNav">
32
+ <div class="sourceLR" id="sourceL">&lt;</div>
33
+ <div id="sourceTabs" class="sourceFileScrollContainer">
34
+ <ul id="codeTabs"></ul>
35
+ </div>
36
+ <div class="sourceLR" id="sourceR">&gt;</div>
37
+ </nav>
38
+ <div id="sources"></div>
39
+ </main>
40
+ </div>
41
+ </body>
 
 
 
 
 
 
main.js ADDED
The diff for this file is too large to render. See raw diff
 
menu.svg ADDED