@plasius/gpu-worker 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.wgsl CHANGED
@@ -1,134 +1,37 @@
1
- struct RenderParams {
2
- width: u32,
3
- height: u32,
4
- tile_size: u32,
5
- _pad0: u32,
6
- camera_pos: vec4<f32>,
7
- camera_target: vec4<f32>,
8
- fov_y: f32,
9
- aspect: f32,
10
- time: f32,
11
- _pad1: f32,
12
- };
13
-
14
- @group(1) @binding(0) var<storage, read_write> framebuffer: array<u32>;
15
- @group(1) @binding(1) var<uniform> render: RenderParams;
16
-
17
- fn hit_sphere(center: vec3<f32>, radius: f32, origin: vec3<f32>, dir: vec3<f32>) -> f32 {
18
- let oc = origin - center;
19
- let a = dot(dir, dir);
20
- let b = 2.0 * dot(oc, dir);
21
- let c = dot(oc, oc) - radius * radius;
22
- let disc = b * b - 4.0 * a * c;
23
- if (disc < 0.0) {
24
- return -1.0;
25
- }
26
- let sq = sqrt(disc);
27
- let t0 = (-b - sq) / (2.0 * a);
28
- if (t0 > 0.001) {
29
- return t0;
1
+ // Minimal GPU worker entry point.
2
+ //
3
+ // This file is intended to be concatenated with the lock-free queue WGSL
4
+ // via assembleWorkerWgsl(). It only handles dequeue and dispatches to a
5
+ // user hook. Replace this file (or provide your own WGSL) to implement
6
+ // real workloads.
7
+
8
+ fn payload_word(job_index: u32, word_index: u32) -> u32 {
9
+ let stride = params.output_stride;
10
+ if (stride == 0u || word_index >= stride) {
11
+ return 0u;
30
12
  }
31
- let t1 = (-b + sq) / (2.0 * a);
32
- if (t1 > 0.001) {
33
- return t1;
34
- }
35
- return -1.0;
13
+ let base = job_index * stride;
14
+ return output_payloads[base + word_index];
36
15
  }
37
16
 
38
- fn background(dir: vec3<f32>) -> vec3<f32> {
39
- let t = 0.5 * (dir.y + 1.0);
40
- return mix(vec3<f32>(0.04, 0.05, 0.08), vec3<f32>(0.65, 0.78, 0.92), t);
41
- }
42
-
43
- fn shade_point(pos: vec3<f32>, normal: vec3<f32>, base: vec3<f32>) -> vec3<f32> {
44
- let light_dir = normalize(vec3<f32>(0.6 + 0.2 * sin(render.time), 0.9, 0.3));
45
- let diff = max(dot(normal, light_dir), 0.0);
46
- let ambient = 0.2;
47
- return base * (ambient + diff * 0.8);
48
- }
49
-
50
- fn pack_color(color: vec3<f32>) -> u32 {
51
- let c = clamp(color, vec3<f32>(0.0), vec3<f32>(1.0));
52
- let r = u32(round(c.x * 255.0));
53
- let g = u32(round(c.y * 255.0));
54
- let b = u32(round(c.z * 255.0));
55
- return (255u << 24) | (b << 16) | (g << 8) | r;
56
- }
17
+ // process_job(job_index, job_type, payload_words) must be defined by the
18
+ // job WGSL that you concatenate before this file.
57
19
 
58
20
  @compute @workgroup_size(64)
59
- fn raytrace_main(@builtin(global_invocation_id) gid: vec3<u32>) {
21
+ fn worker_main(@builtin(global_invocation_id) gid: vec3<u32>) {
60
22
  let idx = gid.x;
61
- if (idx >= params.job_count) {
23
+ let job_count = dequeue_job_count();
24
+ if (idx >= job_count) {
25
+ return;
26
+ }
27
+ if (!queue_config_valid()) {
62
28
  return;
63
29
  }
64
-
65
30
  let ok = dequeue(idx);
66
31
  if (ok == 0u) {
67
32
  return;
68
33
  }
69
34
 
70
- let job = output_jobs[idx];
71
- let tiles_x = (render.width + render.tile_size - 1u) / render.tile_size;
72
- let tile_x = job % tiles_x;
73
- let tile_y = job / tiles_x;
74
- let start_x = tile_x * render.tile_size;
75
- let start_y = tile_y * render.tile_size;
76
-
77
- let forward = normalize(render.camera_target.xyz - render.camera_pos.xyz);
78
- let right = normalize(cross(forward, vec3<f32>(0.0, 1.0, 0.0)));
79
- let up = normalize(cross(right, forward));
80
- let tan_half = tan(0.5 * render.fov_y);
81
-
82
- for (var y: u32 = 0u; y < render.tile_size; y = y + 1u) {
83
- let py = start_y + y;
84
- if (py >= render.height) {
85
- continue;
86
- }
87
- for (var x: u32 = 0u; x < render.tile_size; x = x + 1u) {
88
- let px = start_x + x;
89
- if (px >= render.width) {
90
- continue;
91
- }
92
-
93
- let u = (f32(px) + 0.5) / f32(render.width);
94
- let v = (f32(py) + 0.5) / f32(render.height);
95
- let ndc = vec2<f32>(u * 2.0 - 1.0, 1.0 - v * 2.0);
96
- let dir = normalize(forward + ndc.x * render.aspect * tan_half * right + ndc.y * tan_half * up);
97
-
98
- let origin = render.camera_pos.xyz;
99
- var color = background(dir);
100
-
101
- let t1 = hit_sphere(vec3<f32>(0.0, 1.0, 0.0), 1.0, origin, dir);
102
- let t2 = hit_sphere(vec3<f32>(-1.6, 0.6, -0.5), 0.6, origin, dir);
103
- let t3 = hit_sphere(vec3<f32>(0.0, -1000.0, 0.0), 999.0, origin, dir);
104
-
105
- var t_hit = -1.0;
106
- var base = vec3<f32>(0.0);
107
- var center = vec3<f32>(0.0);
108
- if (t1 > 0.0) {
109
- t_hit = t1;
110
- base = vec3<f32>(0.86, 0.42, 0.32);
111
- center = vec3<f32>(0.0, 1.0, 0.0);
112
- }
113
- if (t2 > 0.0 && (t_hit < 0.0 || t2 < t_hit)) {
114
- t_hit = t2;
115
- base = vec3<f32>(0.2, 0.7, 0.9);
116
- center = vec3<f32>(-1.6, 0.6, -0.5);
117
- }
118
- if (t3 > 0.0 && (t_hit < 0.0 || t3 < t_hit)) {
119
- t_hit = t3;
120
- base = vec3<f32>(0.32, 0.3, 0.26);
121
- center = vec3<f32>(0.0, -1000.0, 0.0);
122
- }
123
-
124
- if (t_hit > 0.0) {
125
- let pos = origin + t_hit * dir;
126
- let normal = normalize(pos - center);
127
- color = shade_point(pos, normal, base);
128
- }
129
-
130
- let pixel_index = py * render.width + px;
131
- framebuffer[pixel_index] = pack_color(color);
132
- }
133
- }
35
+ let job_info = output_jobs[idx];
36
+ process_job(idx, job_info.job_type, job_info.payload_words);
134
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/gpu-worker",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "WebGPU worker runtime with a lock-free job queue for WGSL workloads.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -26,6 +26,7 @@
26
26
  "scripts": {
27
27
  "build": "tsup && cp src/worker.wgsl dist/worker.wgsl",
28
28
  "demo": "python3 -m http.server",
29
+ "demo:https": "node demo/serve-https.js",
29
30
  "test": "npm run test:unit",
30
31
  "test:unit": "node --test",
31
32
  "test:e2e": "npx playwright install chromium && playwright test",
@@ -46,7 +47,7 @@
46
47
  "author": "Plasius LTD <development@plasius.co.uk>",
47
48
  "license": "Apache-2.0",
48
49
  "dependencies": {
49
- "@plasius/gpu-lock-free-queue": "^0.1.1-beta.1"
50
+ "@plasius/gpu-lock-free-queue": "^0.2.1"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@playwright/test": "^1.57.0",