Skip to content

グローバルワークグループをテクスチャで可視化

import shaderCode from "./compute.wgsl?raw"
import { rgba32ToCanvas } from "./texture-to-canvas"
const IMG_SIZE = 128
const FORMAT = "rgba32float"
const adapter = await navigator.gpu.requestAdapter()
if (!adapter) {
throw new Error("WebGPU cannot be initialized - Adapter not found")
}
const device = await adapter.requestDevice()
device.lost.then(() => {
throw new Error("WebGPU cannot be initialized - Device has been lost")
})
const shaderModule = device.createShaderModule({ code: shaderCode })
const outputTexture = device.createTexture({
size: [IMG_SIZE, IMG_SIZE, 1],
format: FORMAT,
usage:
GPUTextureUsage.COPY_SRC |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.STORAGE_BINDING |
GPUTextureUsage.TEXTURE_BINDING
})
const outputPixels = new Float32Array(IMG_SIZE * IMG_SIZE * 4)
const outputBuffer = device.createBuffer({
size: outputPixels.byteLength,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
})
device.queue.writeBuffer(outputBuffer, 0, outputPixels)
const bindgroupLayout = device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.COMPUTE,
storageTexture: {
format: FORMAT,
viewDimension: "2d",
access: "write-only"
}
}
]
})
const bindgroup = device.createBindGroup({
layout: bindgroupLayout,
entries: [
{
binding: 0,
resource: outputTexture.createView()
}
]
})
const computePipelineLayout = device.createPipelineLayout({
bindGroupLayouts: [bindgroupLayout]
})
const computePipeline = device.createComputePipeline({
layout: computePipelineLayout,
compute: {
module: shaderModule,
entryPoint: "main"
}
})
const commandEncoder = device.createCommandEncoder()
const computePass = commandEncoder.beginComputePass()
computePass.setPipeline(computePipeline)
computePass.setBindGroup(0, bindgroup)
computePass.dispatchWorkgroups(16, 16)
computePass.end()
commandEncoder.copyTextureToBuffer(
{ texture: outputTexture },
{ buffer: outputBuffer, bytesPerRow: IMG_SIZE * 4 * 4 },
{ width: IMG_SIZE, height: IMG_SIZE, depthOrArrayLayers: 1 }
)
device.queue.submit([commandEncoder.finish()])
await outputBuffer.mapAsync(GPUMapMode.READ)
const arrayBuffer = outputBuffer.getMappedRange()
const result = new Float32Array(arrayBuffer)
const $canvas = document.querySelector("canvas")!
rgba32ToCanvas($canvas, result, IMG_SIZE, IMG_SIZE)
outputBuffer.unmap()