WebGPU with Firefox Nightly ( Linux ) 2
HTMLとJavaScriptで書かれたWebGPUのサンプルがありましたので、
Firefox Nightlyでトライしてみました。
プログラムは、以下のサイトにあります。
tsherif/webgpu-examples
https://github.com/tsherif/webgpu-examples
triangle
particles
cube
cube-texture-lighting
・glslang.js を使用している。ただし、最新版を使っています。
import("https://unpkg.com/@webgpu/glslang@0.0.15/dist/web-devel/glslang.js").then(m => m.default())
・example.css, gl-matrix.js, utils/utils.js はそのまま使用している。
言語仕様のバージョンアップがありますので、いくつかプログラム文の変更が必要です。
変更箇所は以下の通り。
1 swapChainFormat
const swapChainFormat = await context.getSwapChainPreferredFormat(device); => getSwapChainPreferredFormat()が使えません。 変更 const swapChainFormat = "bgra8unorm";
2 createBuffer関連
const positionBuffer = device.createBuffer({ size: cubeData.positions.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }); positionBuffer.setSubData(0, cubeData.positions); => setSubData()が使えません。 変更 const [positionBuffer, positionMapping] = device.createBufferMapped({ size: cubeData.positions.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST }); new Float32Array(positionMapping).set(cubeData.positions); positionBuffer.unmap();
3 createRenderPipeline
const pipeline = device.createRenderPipeline({ vertexStage: { }, ・・・ }); => layout メンバーが必要です。 変更 const pipeline = device.createRenderPipeline({ layout: device.createPipelineLayout({bindGroupLayouts: []}), vertexStage: { }, ・・・ });
4 createBindGroup関連
const sceneUniformBindGroupLayout = device.createBindGroupLayout({ bindings: [{ }] }); => bindingsが使えません。 entriesを使います。 変更 const sceneUniformBindGroupLayout = device.createBindGroupLayout({ entries: [{ }] });
5 copyBufferToTexture
textureLoadEncoder.copyBufferToTexture({ buffer: textureDataBuffer, rowPitch: img.width * 4, imageHeight: img.height }, ・・・ => GPUBufferCopyViewには、 bytesPerRowメンバーが必要です。 変更 textureLoadEncoder.copyBufferToTexture({ buffer: textureDataBuffer, bytesPerRow: 4 * 256, // a multiple of 256 rowPitch: img.width * 4, imageHeight: img.height }, ・・・
6 uniform buffer dataのupdate
requestAnimationFrameループ内で、uniform buffer dataのupdateをします。
sceneUniformBuffer.setSubData(0, mvpMatrix); => setSubDataが使えません。 変更 update用関数を準備し、ループ内で実行する。 function updateBufferData(device, commandEncoder, uniformBuffer, mvpMatricesData) { const [srcBuffer, arrayBuffer] = device.createBufferMapped({ size: 64, usage: GPUBufferUsage.COPY_SRC }); new Float32Array(arrayBuffer).set(mvpMatricesData); srcBuffer.unmap(); commandEncoder.copyBufferToBuffer(srcBuffer, 0, uniformBuffer, 0, mvpMatricesData.byteLength); srcBuffer.destroy(); } 関数の実行 updateBufferData(device, commandEncoder, sceneUniformBuffer, mvpMatrix);
7 blank, triangle, point について
これはissueにもなっているのですが、これら3つのプログラムは、直ぐに描画されません。
何回かリロードを繰り返すと描画できるときがあります。
解決策として、以下の様にしています。
cubeやparticlesなどの様に、描画部分に
requestAnimationFrame(function draw() { ・・・ requestAnimationFrame(draw); });
を入れ、ループ状態にします。