Skip to content

Commit bd885d1

Browse files
committed
Proof of concept with image data
1 parent 49a515b commit bd885d1

6 files changed

Lines changed: 146 additions & 8 deletions

File tree

divider.wgsl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@group(0) @binding(0) var<storage, read_write> data: array<f32>;
2+
3+
@compute @workgroup_size(1) fn divide(@builtin(global_invocation_id) id: vec3u){
4+
let i = id.x;
5+
data[i] = data[i] / 2.0;
6+
}

index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<!DOCTYPE html>
22
<html>
33
<body>
4+
<script src="scripts/main.js" type="module"></script>
45

6+
<div id="container"></div>
57
<table border="0" cellpadding="0" cellspacing="0" spacing="0" padding="0">
68
<tr>
79
<td bgcolor="#FF0000" width="1" height="1"></td>
@@ -13,5 +15,9 @@
1315
</tr>
1416
</table>
1517

18+
<input id="width" type="number">
19+
<input id="height" type="number">
20+
<button id="render">Render</button>
21+
1622
</body>
1723
</html>

scripts/cpu/image.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
function hsl2rgb(h, s, l) {
2+
const f_final = (n) => {
3+
const k = (n + h * 12) % 12;
4+
const color = l - s * Math.min(l, 1 - l) * Math.max(-1, Math.min(k - 3, 9 - k, 1));
5+
return 255 * color;
6+
};
7+
return [f_final(0), f_final(8), f_final(4)];
8+
}
9+
10+
export function generate_trash_data(width, height){
11+
const out = []
12+
const center_x = width / 2;
13+
const center_y = height / 2;
14+
for(let value_y=0;value_y<height;++value_y){
15+
let line = []
16+
for(let value_x=0;value_x<width;++value_x){
17+
const x = value_x - center_x;
18+
const y = center_y - value_y;
19+
20+
const angle = Math.atan2(y,x);
21+
const hue = ((angle + Math.PI)/(2.0 * Math.PI));
22+
const light = (2.0/Math.PI) * Math.atan(Math.sqrt(x**2 + y**2)/100);
23+
const color = hsl2rgb(hue,1.0,light);
24+
line.push(color);
25+
}
26+
out.push(line);
27+
}
28+
return out;
29+
}
Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@ const color_grid = [[red]];
2121
* @param {vec3} color
2222
* @returns {string}
2323
*/
24-
function to_hexcode(color){
25-
let output = "";
26-
for(const component of color){
27-
output += component.toString(16);
28-
}
29-
return output;
24+
function to_hexcode(color) {
25+
return color
26+
.map(c => Math.round(c).toString(16).padStart(2, '0'))
27+
.join('');
3028
}
3129

3230
/**
@@ -37,7 +35,7 @@ function to_hexcode(color){
3735
function normalize_grid_size(grid){
3836
let line_size = 0;
3937
for(const line of grid){
40-
line_size = Math.max(line.length);
38+
line_size = Math.max(line.length,line_size);
4139
}
4240
for(let line of grid){
4341
if(line.length == line_size) continue;
@@ -58,7 +56,7 @@ export function build_color_grid(color_grid){
5856
for(const row of color_grid){
5957
html+="<tr>";
6058
for(const color of row){
61-
html+= '<td bgcolor="' + to_hexcode(color) + '"width="1" height="1"></td>';
59+
html+= '<td bgcolor="#' + to_hexcode(color) + '"width="1" height="1"></td>';
6260
}
6361
html+="</tr>";
6462
}

scripts/main.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { generate_trash_data } from "./cpu/image.js";
2+
import { build_color_grid } from "./cpu/transformer.js";
3+
4+
5+
export function main(){
6+
const target = document.getElementById('container');
7+
const width = document.getElementById('width').valueAsNumber;
8+
const height = document.getElementById('height').valueAsNumber;
9+
10+
const image_data = generate_trash_data(width,height);
11+
const table_text = build_color_grid(image_data);
12+
target.innerHTML = table_text;
13+
}
14+
15+
document.getElementById('render').addEventListener('click', main);

testing.html

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
</head>
8+
<body>
9+
<script>
10+
const src = `
11+
@group(0) @binding(0) var<storage, read_write> data: array<f32>;
12+
@compute @workgroup_size(1) fn divide(@builtin(global_invocation_id) id: vec3u){
13+
let i = id.x;
14+
data[i] = data[i] / 2.0;
15+
}
16+
`
17+
async function main(){
18+
const adapter = await navigator.gpu?.requestAdapter();
19+
const device = await adapter?.requestDevice();
20+
if(!device){
21+
fail("browser does not support WebGPU");
22+
return;
23+
}
24+
const module = device.createShaderModule({
25+
label: 'i am the one who divides',
26+
code: src
27+
});
28+
const pipeline = device.createComputePipeline({
29+
label: 'i am the one who pipelines',
30+
layout: 'auto',
31+
compute:{
32+
module
33+
}
34+
})
35+
const input = new Float32Array([1,3,5]);
36+
const work_buffer = device.createBuffer({
37+
label: 'work buffer',
38+
size: input.byteLength,
39+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
40+
});
41+
device.queue.writeBuffer(work_buffer,0,input);
42+
const result_buffer = device.createBuffer({
43+
label: 'result buffer',
44+
size: input.byteLength,
45+
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
46+
})
47+
const bind_group = device.createBindGroup({
48+
label: 'bind group for work buffer',
49+
layout: pipeline.getBindGroupLayout(0),
50+
entries: [
51+
{binding:0, resource: work_buffer}
52+
]
53+
});
54+
const encoder = device.createCommandEncoder({
55+
label: 'doubling encoder',
56+
});
57+
const pass = encoder.beginComputePass({
58+
label: 'doubling compute pass',
59+
});
60+
pass.setPipeline(pipeline);
61+
pass.setBindGroup(0, bind_group);
62+
pass.dispatchWorkgroups(input.length);
63+
pass.end();
64+
encoder.copyBufferToBuffer(work_buffer, 0, result_buffer, 0, result_buffer.size);
65+
const commandBuffer = encoder.finish();
66+
device.queue.submit([commandBuffer]);
67+
68+
await result_buffer.mapAsync(GPUMapMode.READ);
69+
const result = new Float32Array(result_buffer.getMappedRange());
70+
71+
console.log('input',input);
72+
console.log('result',result);
73+
result_buffer.unmap();
74+
}
75+
main();
76+
77+
78+
79+
80+
81+
82+
</script>
83+
</body>
84+
</html>

0 commit comments

Comments
 (0)