1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

wgpu 仕様書 -次元圧縮-

1
Last updated at Posted at 2026-05-15

WGPU

wgpuは素晴らしいぞ!
この先、AIの未来があるぞ

学習方法

CGを触っている人なら実はLLMの現実的なパイプラインとGPUの動きというのは同じになる
逆にCGを触っていないとGPU設計をAIに使うのは厳しすぎる(あとrust)

パイプランはこのように対応している

(大事なところ以外削っている)
CG用パイプライン renderPass->viewport->vertexBuffer(0,1,2)->indexBuffer->bindGroup(0,1,2)
LLM用パイプライン embedLayer->seq2seq->attention

GPUの構造

GPUは早いか?
A.クロック数はおそいGPUはだいたい2.5GHz(CPUは3.5~5GHzとか)

プログラミングについて
GPUってのはそもそも、普通のプログラミングじゃなくて、物流センターの操作が一番近い

アーキテクチャ

Unified Shader Unit(統合シェーダーユニット)
昔はfragmentやvertexで専用回路が組まれていたが、今は統合されている。

それがcompute shader
昔の名残+使い勝手のために@vertexなどの命令は残っている
この@は属性(attribute)という
blender,hudini触ったことのある人はわかるだろう

VRAM(strage buffer)

校舎の倉庫みたいなもの、遠い
巨大、GPUの9割はこれ

Shared Memory(Workgroup memory)

プロセッサの近くにある
爆速、ただし、KB程度の保存しかできない

Register(普通の変数)

最速、1変数しか見れない

CG pipeline直通

vertex

定義 説明
input
@builtin(vertex_index) u32 頂点番号
@builtin(instance_index) u32 インスタンスID(メッシュのID)
output
@builtin(position) vec4f GPU上でのxyzポジション(配列だが、構造体に近く,id.xみたいにアクセスする)

fragment

定義 説明
input
@builtin(vertex_index) vec4f ピクセル座標,画面上のx,z+z+w(遠近補正)
@builtin(front_facing) bool 表面かどうか
@builtin(sample_index) u32 マルチサンプルのindex,MSAA
output
@builtin(frag_depth) f32 深度地の上書き,zbufferの値を自分で操作するときに使う

compute Stage(Compute Shader?)

定義 説明
input
@builtin(global_invocation_id) vec3u workgroupID,x,y,zで一意に決める
@builtin(local_invocation_id) vec3u ワークグループ内での相対ID,SharedMemへのIOに使う
@builtin(workgroup_id) vec3u ワークグループの指定
@builtin(num_workgroups) vec3u すべてのワークグループ数
@builtin(local_invocation_index) u32 グループ内通し番号,local_invocation_idの1次元圧縮

computeshaderについての説明

  • global_invocation_id:クラス全体での通し番号
  • num_workgroups:全クラス数
  • workgroup_id:何組か
  • local_invocation_id:クラス内での出席番号

attribute一覧

基本

@builtin(name):gpuが提供する変数をマッピングする

@group(n):bindgroupのグループ番号を指定
@binding(n):bindgroupのリソースのバインディング番号を指定

@workgroup_size(x, y, z):compute shaderのスレッドサイズを指定

描画周り

@vertex:vertex shaderのエントリーポイントであることを示す
@fragment:fragment shaderのエントリーポイントであることを示す
@compute:compute shaderのエントリーポイントであることを示す

@location(n) 頂点バッファ、fragmentなどの入出力の先
@interpolate(type, sampling):vertex shaderからfragmentへのデータ変換方法を指定
@invariant:vertex shaderの出力が入力に対して、同じ値を生成することを保証

アライメント

@align(n):アライメントをバイト単位で指定
@size(n):構造体メンバーのサイズをバイト単位で指定する
@must_use:関数の戻り値を無視するとエラーを出す
@id(n):override変数に対して、パイプライン生成時に値を上書きする識別子を指定
@diagnostic:特定のコードブロックに対して診断メッセージのフィルタリングルールを設定

strage_shaderたちの設定

@group(0) @binding(1) var<storage, read_write> rnn_w: array<f32>;

@group(0):0番目のデータ群を選択
@binding(1):1番目の層にあるデータ群
:strage(いわゆるVRAM)にread_writeでおく。ほかにはreadだけなのもありこっちのほうが早い
array:jsとかならなじみがあるだろう

構造的には

value = GPU_Mem[Group_ID(0..4)][Binding_ID(0..999)]

GroupBindingは4つまでしか使えない
Bindingは0~999の1000個

さらに、WEBGPUは同時にworkgroupが動いて値をめちゃくちゃにすることを保証しない

  • group0 全体での定数、グローバル情報
  • group1 今描画しているモデル、素材
  • group2 今描画しているモデルの素材などの情報
  • group3 予備
    bindingは999まで
    つまり1度に認識できるPORTは4000個までしか配列が入らない
    (配列のなかに配列を入れることで制限は回避できるー>GPUではindexを入れてVRAM内を多重参照することができる)
    極論をいえばgroupはbindingが枯渇するまで上げる必要はない

あとは割とrustっぽくかける

余談vertexshader

@vertex
fn vs(@builtin(vertex_index) in_v: u32) -> @builtin(position) vec4f {
  let pos = positions[in_v];
  return vec4f(pos.x, pos.y, pos.z, 1.0);
}

fragment

@fragment
fn fs() -> @location(0) vec4f {
  return vec4f(1, 0, 0, 1);
}

compute

//workinggroup_sizeを指定する必要がある
@compute @workgroup_size(1) fn computeSomething{
  @builtin(global_invocation_id) vec3u {
    
  }
}

なぜcompute shaderの返り値がvec3uなのか、これはCG周りの名残りらしい<-悪手!

HLSLなんかより百倍簡単だろう?

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?