描画関数の中で行うこと

WebGPUの初期化とRenderPipelineの作成が行えたら、次に描画関数を記述します。

function frame({context, pipeline}) { ... }

CommandEncoder

WebGPUをはじめとした低レベル3D APIでは、一般的にCommandBufferというGPUへの各種命令をパッキングするバッファが存在します。WebGPUではCommandEncoderという名称です。

const commandEncoder = g_device.createCommandEncoder();

このCommandEncoderの使い方ですが、生成後にbeginRenderPassという関数を呼び出し、renderPassEncoderというオブジェクトを取得します。このrenderPassEncoderに対して様々な命令を積んでいくことになるのですが、まずbeginRenderPass関数の呼び出しにはGPURenderPassDescriptorという型の引数オブジェクトを事前に用意する必要があります。

const commandEncoder = g_device.createCommandEncoder(); const textureView = context.getCurrentTexture().createView(); const renderPassDescriptor: GPURenderPassDescriptor = { colorAttachments: [ { view: textureView, clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }, loadOp: 'clear', storeOp: 'store', }, ], }; const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);

WebGPUにはレンダーパス(一連の描画処理の単位)の概念があり、コマンドを積むためにはまずこのレンダーパスの設定を行う必要があります。
レンダーパスではcolorAttachmentsの設定を行います。これは描画先のカラーバッファについての設定になります。

viewには描画先のレンダーターゲットテクスチャを指定します。初歩的な利用では、contextからgetCurrentTexture().createView();という呼び出しで得たオブジェクトを指定すればOKです。これは、描画先のCanvasに結びついたバックバッファを意味します。
loadOpには、各種命令を実施する前に行う処理を指定します。'clear'を指定すると、まず最初に指定のバッファをクリアします。
clearValueにはその際のカラー情報を設定します。
storeOpには、各種命令を実施した後のバッファの扱いを指定します。今回はそのまま保持しますので、'store'を指定します。

コマンドを積む

次にいよいよコマンドを積んでいきます。といっても、今回は三角形を描画するだけなのでコマンドの数はそれほど多くはありません。
まず、setPipeline関数で、前ページで作成したRenderPipelineを設定します。
次に、draw関数を呼びます。実質的な描画を指示する関数ですね。
最後にend関数を呼び、コマンドシーケンスの記録の終了を指示します。

そして、renderPassEncoderの大元であるcommandEncoderのfinish()関数の戻り値をg_device.queue.submit()に与えます。これでGPUにコマンドが発行され、GPUは三角形を描画します。

const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.setPipeline(pipeline); //プリミティブを描画する。詳細な仕様は,[[#rendering-operations]]を参照してください. // param vertexCount - 描画する頂点の数. // param instanceCount - 描画するインスタンスの数. // param firstVertex - 描画を開始する頂点バッファ内のオフセット(頂点単位). // param firstInstance - 描画する最初のインスタンス. passEncoder.draw(3, 1, 0, 0); // レンダーパスコマンドシーケンスの記録を完了する。 passEncoder.end(); g_device.queue.submit([commandEncoder.finish()]);

作り置きできるもの、できないもの

WebGPUの利点は、WebGLと比べてGPU設定の作り置き・再利用ができることです。その設定オブジェクトがRenderPipelineになります。
WebGLではそうしたことができず、描画物が切り替わるたびに各種gl関数を再び呼んで設定を行う必要がありましたが、WebGPUではあらかじめ作りおいたRenderPipelineに切り替えればすみます。

逆に作り置きできないもの、つまり、描画のたびに生成・設定しなければならないものもあります。
それが、本ページで解説したCommandEncoderやRenderPassEncoderなどです。Vulkanなどの一部のAPIでは、これらに相当するものも作り置き・再利用できたりもするのですが、WebGPUでは残念ながらそこまではできません。

それでも、WebGPUではRenderPipelineの再利用ができることでWebGLと比べて相当に効率的なAPIになっています。

前のページ
次のページ