Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions src/WebGPU/pointer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
on_pointer_move,
on_pointer_leave,
on_pointer_down,
on_pointer_up,
on_press_escape,
} from '../logic/index.zig'
import * as Logic from '../logic/index.zig'
import clamp from '../utils/clamp'

const OUTSIDE_CANVAS = -1
Expand Down Expand Up @@ -64,7 +58,7 @@ export default function initMouseController(
const update = () => {
pointer.x = OUTSIDE_CANVAS
pointer.y = OUTSIDE_CANVAS
on_pointer_leave()
Logic.on_pointer_leave()
}
if (pointer.afterPickEventsQueue.length > 0) {
pointer.afterPickEventsQueue.push({
Expand All @@ -89,7 +83,7 @@ export default function initMouseController(

const move = () => {
updatePointer(e)
on_pointer_move(...getZigAbsolutePointer())
Logic.on_pointer_move(...getZigAbsolutePointer())
}
if (pointer.afterPickEventsQueue.length > 0) {
pointer.afterPickEventsQueue.push({
Expand Down Expand Up @@ -118,7 +112,7 @@ export default function initMouseController(
updatePointer(e)
pointer.afterPickEventsQueue.push({
requireNewPick: true,
cb: on_pointer_down.bind(null, ...getZigAbsolutePointer()),
cb: Logic.on_pointer_down.bind(null, ...getZigAbsolutePointer()),
})
})

Expand All @@ -132,10 +126,10 @@ export default function initMouseController(
if (pointer.afterPickEventsQueue.length > 0) {
pointer.afterPickEventsQueue.push({
requireNewPick: false,
cb: on_pointer_up,
cb: Logic.on_pointer_up,
})
} else {
on_pointer_up()
Logic.on_pointer_up()
}
})

Expand Down Expand Up @@ -183,7 +177,7 @@ export default function initMouseController(
break
case 'Escape':
event.preventDefault()
on_press_escape()
Logic.commitChanges()
break
}
})
Expand Down
73 changes: 73 additions & 0 deletions src/WebGPU/textureCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { canvasMatrixBuffer } from 'WebGPU/programs/initPrograms'
import mat4 from 'utils/mat4'
import { updateRenderPass } from 'run'
import * as Textures from 'textures'
import getMultisampleTexture from 'getMultisampleTexture'

let endCacheCallback: VoidFunction = () => {
throw new Error('Cache not started')
}

export function endCache() {
endCacheCallback()
}

export function startCache(
device: GPUDevice,
presentationFormat: GPUTextureFormat,
currTextureId: number | null,
boundingBox: BoundingBox,
outputWidth: number,
outputHeight: number
): number {
const width = boundingBox.max_x - boundingBox.min_x
const height = boundingBox.max_y - boundingBox.min_y

const texture = device.createTexture({
label: 'texture cache',
format: presentationFormat,
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
size: [outputWidth, outputHeight],
})

const encoder = device.createCommandEncoder()

const multisampleTexture = getMultisampleTexture(
device,
outputWidth,
outputHeight,
presentationFormat
)
const descriptor: GPURenderPassDescriptor = {
label: 'texture cache pass',
colorAttachments: [
{
view: multisampleTexture.createView(),
resolveTarget: texture.createView(),
loadOp: 'clear',
storeOp: 'store',
},
],
}

const pass = encoder.beginRenderPass(descriptor)
updateRenderPass(pass)
const matrix = mat4.ortho(
boundingBox.min_x, // left
boundingBox.min_x + width, // right
boundingBox.min_y + height, // bottom
boundingBox.min_y, // top, yes top and bottom and reversed on purpose to make texture start at bottom-left corner
1, // near
-1 // far
)

device.queue.writeBuffer(canvasMatrixBuffer, 0, matrix)

endCacheCallback = () => {
pass.end()
const commandBuffer = encoder.finish()
device.queue.submit([commandBuffer])
}

return Textures.setTexture(texture, currTextureId)
}
5 changes: 0 additions & 5 deletions src/getMultisampleTexture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ export default function getMultisampleTexture(
multisampleTexture.height !== height
) {
multisampleTexture?.destroy()
multisampleTexture = device.createTexture({
size: [width, height],
format: 'depth24plus',
usage: GPUTextureUsage.RENDER_ATTACHMENT,
})
multisampleTexture = device.createTexture({
format: format,
usage: GPUTextureUsage.RENDER_ATTACHMENT,
Expand Down
38 changes: 16 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,13 @@ import canvasSizeObserver from 'WebGPU/canvasSizeObserver'
import getDevice from 'WebGPU/getDevice'
import initPrograms from 'WebGPU/programs/initPrograms'
import runCreator from 'run'
import {
init_state,
add_asset,
remove_asset,
reset_assets,
connect_on_asset_update_callback,
connect_on_asset_selection_callback,
destroy_state,
import_icons,
update_render_scale,
set_tool,
} from './logic/index.zig'
import * as Logic from './logic/index.zig'
import initMouseController, { camera } from 'WebGPU/pointer'
import IconsPng from '../msdf/output/icons.png'
import IconsJson from '../msdf/output/icons.json'
import getDefaultPoints from 'utils/getDefaultPoints'
import * as Textures from 'textures'
import { startCache, endCache } from 'WebGPU/textureCache'

export type SerializedInputAsset = {
id?: number // not needed while loading project but useful for undo/redo to maintain selection
Expand Down Expand Up @@ -70,7 +60,7 @@ export default async function initCreator(
const projectWidth = canvas.clientWidth / 2
const projectHeight = canvas.clientHeight / 2

init_state(projectWidth, projectHeight)
Logic.init_state(projectWidth, projectHeight, device.limits.maxTextureDimension2D)
// rotation doesnt work
const context = canvas.getContext('webgpu')
if (!context) throw Error('WebGPU from canvas needs to be always provided')
Expand All @@ -84,7 +74,7 @@ export default async function initCreator(
})

function updateRenderScale() {
update_render_scale(canvas.width / (canvas.clientWidth * camera.zoom))
Logic.update_render_scale(canvas.width / (canvas.clientWidth * camera.zoom))
}

let wasInitialOffsetSet = false
Expand All @@ -104,7 +94,7 @@ export default async function initCreator(
updateProcessing()
})

connect_on_asset_update_callback((serializedData: ZigAssetOutput[]) => {
Logic.connect_on_asset_update_callback((serializedData: ZigAssetOutput[]) => {
const serializedAssetsTextureUrl = [...serializedData].map<SerializedOutputAsset>((asset) => ({
id: asset.id,
textureId: asset.texture_id,
Expand All @@ -119,12 +109,16 @@ export default async function initCreator(
onAssetsUpdate(serializedAssetsTextureUrl)
})

connect_on_asset_selection_callback(onAssetSelect)
Logic.connect_on_asset_selection_callback(onAssetSelect)

Logic.connect_cache_callbacks((textureId, boundingBox, width, height) => {
return startCache(device, presentationFormat, textureId, boundingBox, width, height)
}, endCache)

const addImage: CreatorAPI['addImage'] = (url) => {
const textureId = Textures.add(url, (width, height, isNew) => {
const points = getDefaultPoints(width, height, projectWidth, projectHeight)
add_asset(0 /* no id yet, needs to be generated */, points, textureId)
Logic.add_asset(0 /* no id yet, needs to be generated */, points, textureId)

if (isNew) {
uploadTexture(url, (newUrl) => {
Expand All @@ -135,7 +129,7 @@ export default async function initCreator(
}

Textures.add(IconsPng, (width, height) => {
import_icons(
Logic.import_icons(
IconsJson.chars.flatMap((char) => [
char.id,
char.x / width,
Expand Down Expand Up @@ -199,19 +193,19 @@ export default async function initCreator(
.filter((result) => result.status === 'fulfilled')
.map((result) => result.value)

reset_assets(serializedAssets, withSnapshot)
Logic.reset_assets(serializedAssets, withSnapshot)
}

return {
addImage,
removeAsset: remove_asset,
removeAsset: Logic.remove_asset,
resetAssets,
destroy: () => {
stopCreator()
destroy_state()
Logic.destroy_state()
context.unconfigure()
device.destroy()
},
setTool: set_tool,
setTool: Logic.set_tool,
}
}
20 changes: 18 additions & 2 deletions src/logic/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ interface PointUV {
v: number
}

interface BoundingBox {
min_x: number
min_y: number
max_x: number
max_y: number
}

type ZigF32Array = { typedArray: Float32Array }
type ZigAssetInput = {
id: number
Expand All @@ -29,7 +36,7 @@ type PointerDataView = {
}

declare module '*.zig' {
export const init_state: (width: number, height: number) => void
export const init_state: (width: number, height: number, max_texture_size: number) => void
export const add_asset: (maybe_asset_id: number, points: PointUV[], texture_id: number) => void
export const remove_asset: () => void
export const reset_assets: (assets: ZigAssetInput[], with_snapshot: boolean) => void
Expand All @@ -46,7 +53,7 @@ declare module '*.zig' {
export const on_pointer_up: () => void
export const on_pointer_move: (x: number, y: number) => void
export const on_pointer_leave: VoidFunction
export const on_press_escape: VoidFunction
export const commitChanges: VoidFunction
export const update_render_scale: (render_scale: number) => void

export const connect_web_gpu_programs: (programs: {
Expand All @@ -63,6 +70,15 @@ declare module '*.zig' {
}) => void
export const connect_on_asset_update_callback: (cb: (data: ZigAssetOutput[]) => void) => void
export const connect_on_asset_selection_callback: (cb: (data: number) => void) => void
export const connect_cache_callbacks: (
start_cache: (
texture_id: number | null,
box: BoundingBox,
width: number,
height: number
) => number,
end_cache: VoidFunction
) => void

export const render_draw: VoidFunction
export const render_pick: VoidFunction
Expand Down
Loading