Skip to content

Commit 57d5bfc

Browse files
authored
feat: generate asset ids in zig, add source maps to JS (#16)
* Move id generation to zig * free assets memory * small cleanup * rename all zig names to sneak case * remove unnecessary comment * fix typo, improve allocating vertex array
1 parent f358103 commit 57d5bfc

File tree

13 files changed

+137
-139
lines changed

13 files changed

+137
-139
lines changed

eslint.config copy.mjs

Lines changed: 0 additions & 20 deletions
This file was deleted.

eslint.config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @ts-check
2+
3+
import eslint from '@eslint/js'
4+
import tseslint from 'typescript-eslint'
5+
import stylisticJs from '@stylistic/eslint-plugin-js'
6+
7+
export default tseslint.config(eslint.configs.recommended, tseslint.configs.recommended, {
8+
rules: {
9+
'no-multiple-empty-lines': 'error',
10+
semi: ['error', 'never'],
11+
},
12+
plugins: {
13+
'@stylistic/js': stylisticJs,
14+
},
15+
})

eslint.config.mjs

Lines changed: 0 additions & 19 deletions
This file was deleted.

integration-tests/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import initCreator from '../src/index'
22
import SampleImg from './image-sample.png'
33

4-
let new_asset_id = 1001
5-
64
const params = new URLSearchParams(document.location.search)
75
const isSampleParam = params.has('sample') // is the string "Jonathan"
86

@@ -13,7 +11,6 @@ async function test() {
1311
isSampleParam
1412
? [
1513
{
16-
id: 1000,
1714
points: [
1815
{
1916
u: 0,
@@ -55,8 +52,7 @@ async function test() {
5552
const img = new Image()
5653
img.src = URL.createObjectURL(files[0])
5754
img.onload = () => {
58-
creator.addImage(new_asset_id, img)
59-
new_asset_id++
55+
creator.addImage(img)
6056
}
6157
})
6258
}

jestWgslTransformer.js

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
/* eslint-disable no-undef */
2-
/* eslint-disable @typescript-eslint/no-require-imports */
3-
const path = require("path");
4-
5-
module.exports = {
6-
process(sourceText, sourcePath, options) {
7-
return {
8-
code: `module.exports = \`${sourceText}\`;`,
9-
};
10-
},
11-
};
1+
export const process = (sourceText, sourcePath, options) => {
2+
return {
3+
code: `module.exports = \`${sourceText}\`;`,
4+
}
5+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"webpack-dev-server": "^5.2.0",
5252
"zigar-loader": "^0.14.0"
5353
},
54-
"types": "./lib/types/src/index.d.ts",
54+
"types": "./lib/types/index.d.ts",
5555
"main": "./lib/index.mjs",
5656
"type": "module",
5757
"repository": {

src/WebGPU/pick.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1-
import mat4 from "utils/mat4"
2-
import { pointer } from "./pointer"
3-
import { on_update_pick } from "../logic/index.zig"
1+
import mat4 from 'utils/mat4'
2+
import { pointer } from './pointer'
3+
import { on_update_pick } from '../logic/index.zig'
44

55
const NUM_PIXELS = 1
66

77
export default class PickManager {
8-
98
private pickBuffer: GPUBuffer
109
private pickTexture: GPUTexture
1110
private pickDepthTexture: GPUTexture
1211
private isPreviousPickDone = true
1312

14-
constructor (
15-
private device: GPUDevice,
16-
) {
13+
constructor(device: GPUDevice) {
1714
this.pickBuffer = device.createBuffer({
1815
size: NUM_PIXELS * 4,
1916
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
@@ -31,21 +28,22 @@ export default class PickManager {
3128
usage: GPUTextureUsage.RENDER_ATTACHMENT,
3229
})
3330
}
31+
3432
/**
3533
* Starts a picking render pass.
3634
* @param encoder The GPUCommandEncoder to use for the render pass.
3735
* @returns An object which contains render pass and a callback to end picking.
3836
*/
39-
startPicking(encoder: GPUCommandEncoder): { pass: GPURenderPassEncoder, end: VoidFunction } {
37+
startPicking(encoder: GPUCommandEncoder): { pass: GPURenderPassEncoder; end: VoidFunction } {
4038
const descriptor: GPURenderPassDescriptor = {
4139
// describe which textures we want to raw to and how use them
42-
label: "our render to canvas renderPass",
40+
label: 'our render to canvas renderPass',
4341
colorAttachments: [
4442
{
4543
view: this.pickTexture.createView(),
46-
loadOp: "clear",
44+
loadOp: 'clear',
4745
clearValue: [0, 0, 0, 1],
48-
storeOp: "store",
46+
storeOp: 'store',
4947
} as const,
5048
],
5149
// depthStencilAttachment: {
@@ -68,19 +66,22 @@ export default class PickManager {
6866
pass.end()
6967

7068
if (this.isPreviousPickDone) {
71-
encoder.copyTextureToBuffer({
69+
encoder.copyTextureToBuffer(
70+
{
7271
texture: this.pickTexture,
73-
origin: { x: 0, y: 0 }
74-
}, {
72+
origin: { x: 0, y: 0 },
73+
},
74+
{
7575
buffer: this.pickBuffer,
76-
}, {
76+
},
77+
{
7778
width: NUM_PIXELS,
7879
}
7980
)
8081
}
8182
}
8283

83-
return {pass, end: endPicking}
84+
return { pass, end: endPicking }
8485
}
8586

8687
createMatrix(canvas: HTMLCanvasElement, canvasMatrix: Float32Array) {
@@ -104,10 +105,15 @@ export default class PickManager {
104105
async asyncPick() {
105106
if (!this.isPreviousPickDone) return
106107
this.isPreviousPickDone = false
107-
await this.pickBuffer.mapAsync(GPUMapMode.READ, 0, 4 * NUM_PIXELS)
108-
const [id] = new Uint32Array(this.pickBuffer.getMappedRange(0, 4 * NUM_PIXELS))
109-
on_update_pick(id)
110-
this.pickBuffer.unmap()
108+
try {
109+
await this.pickBuffer.mapAsync(GPUMapMode.READ, 0, 4 * NUM_PIXELS)
110+
const [id] = new Uint32Array(this.pickBuffer.getMappedRange(0, 4 * NUM_PIXELS))
111+
on_update_pick(id)
112+
this.pickBuffer.unmap()
113+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
114+
} catch (err) {
115+
/* ignorign errors when map fails because device was destroyed(so buffer too and was unmapped before mapAsync completed)*/
116+
}
111117
this.isPreviousPickDone = true
112118
}
113-
}
119+
}

src/index.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ import { createTextureFromSource } from 'WebGPU/getTexture'
66
import {
77
init_state,
88
add_texture,
9-
connectOnAssetUpdateCallback,
10-
ASSET_ID_TRESHOLD,
9+
connect_on_asset_update_callback,
10+
destroy_state,
1111
} from './logic/index.zig'
1212
import initMouseController from 'WebGPU/pointer'
1313
import getDefaultPoints from 'utils/getDefaultPoints'
1414

15-
export type SerializedAsset = Omit<Texture, 'texture_id'> & {
15+
export type SerializedAsset = Omit<AssetZig, 'texture_id'> & {
1616
url: string
1717
}
1818

1919
export interface CreatorAPI {
20-
addImage: (id: number, img: HTMLImageElement, points?: PointUV[]) => void
20+
addImage: (img: HTMLImageElement, points?: PointUV[]) => void
2121
destroy: VoidFunction
2222
}
2323

@@ -55,10 +55,8 @@ export default async function initCreator(
5555
initMouseController(canvas)
5656

5757
const textures: TextureSource[] = []
58-
runCreator(canvas, context, device, presentationFormat, textures)
59-
connectOnAssetUpdateCallback((serializedData: Texture[]) => {
58+
connect_on_asset_update_callback((serializedData: AssetZig[]) => {
6059
const serializedAssetsTextureUrl = [...serializedData].map<SerializedAsset>((asset) => ({
61-
id: asset.id,
6260
points: [...asset.points].map((point) => ({
6361
x: point.x,
6462
y: point.y,
@@ -70,31 +68,31 @@ export default async function initCreator(
7068
onAssetsUpdate(serializedAssetsTextureUrl)
7169
})
7270

73-
function addImage(id: number, img: HTMLImageElement, points?: PointUV[]) {
74-
if (id < ASSET_ID_TRESHOLD) {
75-
throw Error(`ID should be unique and not smaller than ${ASSET_ID_TRESHOLD}.`)
76-
}
77-
71+
function addImage(img: HTMLImageElement, points?: PointUV[]) {
7872
const newTextureId = textures.length
7973
textures.push({
8074
url: img.src,
8175
texture: createTextureFromSource(device, img, { flipY: true }),
8276
})
8377

84-
add_texture(id, points || getDefaultPoints(img, canvas), newTextureId)
78+
add_texture(points || getDefaultPoints(img, canvas), newTextureId)
8579
}
8680

8781
assets.forEach((asset) => {
8882
const img = new Image()
8983
img.src = asset.url
9084
img.onload = () => {
91-
addImage(asset.id, img, asset.points)
85+
addImage(img, asset.points)
9286
}
9387
})
9488

89+
const stopCreator = runCreator(canvas, context, device, presentationFormat, textures)
90+
9591
return {
9692
addImage,
9793
destroy: () => {
94+
stopCreator()
95+
destroy_state()
9896
context.unconfigure()
9997
device.destroy()
10098
},

src/logic/index.d.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,30 @@ interface PointUV {
66
}
77

88
type ZigF32Array = { typedArray: Float32Array }
9-
type Texture = {
10-
id: number
9+
type AssetZig = {
1110
points: PointUV[]
1211
texture_id: number
1312
}
1413

1514
declare module '*.zig' {
16-
export const ASSET_ID_TRESHOLD: number
1715
export const init_state: (width: number, height: number) => void
18-
export const add_texture: (id: number, points: PointUV[], texture_id: number) => void
16+
export const add_texture: (points: PointUV[], texture_id: number) => void
1917
export const update_points: (id: number, points: PointUV[]) => void
2018

2119
export const on_update_pick: (id: number) => void
2220
export const on_pointer_down: (x: number, y: number) => void
2321
export const on_pointer_up: () => void
2422
export const on_pointer_move: (x: number, y: number) => void
2523

26-
export const connectWebGPUPrograms: (programs: {
24+
export const connect_web_gpu_programs: (programs: {
2725
draw_texture: (vertexData: ZigF32Array, texture_id: number) => void
2826
draw_triangle: (vertexData: ZigF32Array) => void
2927
pick_texture: (vertexData: ZigF32Array, texture_id: number) => void
3028
pick_triangle: (vertexData: ZigF32Array) => void
3129
}) => void
32-
export const connectOnAssetUpdateCallback: (cb: (data: Texture[]) => void) => void
30+
export const connect_on_asset_update_callback: (cb: (data: AssetZig[]) => void) => void
3331

3432
export const canvas_render: VoidFunction
3533
export const picks_render: VoidFunction
34+
export const destroy_state: VoidFunction
3635
}

0 commit comments

Comments
 (0)