🌋
VulkanのMesh shaderに入門してみた
コード
Vulkanに追加されたばかりのVK_EXT_mesh_shader
拡張機能を使ってみました。
コードはこちら。
参考資料
VulkanのMesh shader拡張機能についての資料を紹介します。ここには上げていませんがDirectX方面の資料も参考になりそうです。
Khronosの説明ページ
概要だけですが一読すると良さそうです。ちなみにこのページで紹介されているNVIDIAのサンプルは少し発展向けなので後回しで良いと思います。
Khronosのウェビナー
ウェビナーの動画と資料を見ると実装の雰囲気もなんとなく分かります。
SaschaWillems/Vulkan
Khronosのサンプルリポジトリにはmesh shaderがまだ含まれていないようなので、SaschaWillemsのサンプルが一番読みやすいです。
使ってみる
四角ポリゴンを三角形にtriangulateしてレンダリングする処理を書いてみます。ここではTask shaderは使わずに、Mesh shaderだけにしました。解説はコメントで。
#version 450
// 拡張機能を有効化する
#extension GL_EXT_mesh_shader : require
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
// 出力プリミティブを三角形に設定する
// linesやpointsに設定することもできる
// 出力する頂点数と三角形の数も設定する
// 1枚の四角ポリゴンをtriangulateするため4つの頂点と2つ三角形を出力する
layout(triangles, max_vertices = 4, max_primitives = 2) out;
// Vertex shaderと異なり頂点情報もただのバッファとして入力される
layout(binding = 0) buffer Vertices{vec4 v[];} vertices;
layout(binding = 1) buffer Indices{uint i[];} indices;
// 頂点ごとに出力したい情報
layout(location = 0) out VertexOutput
{
vec4 color;
} vertexOutput[];
void main()
{
// CPU側からは
// vkCmdDrawMeshTasksEXT(cmdBuf, groupCountX, groupCountY, groupCountZ)
// という形で実行される
uint primitiveID = gl_GlobalInvocationID.x;
uint i0 = indices.i[4 * primitiveID + 0];
uint i1 = indices.i[4 * primitiveID + 1];
uint i2 = indices.i[4 * primitiveID + 2];
uint i3 = indices.i[4 * primitiveID + 3];
vec4 v0 = vec4(vertices.v[i0]);
vec4 v1 = vec4(vertices.v[i1]);
vec4 v2 = vec4(vertices.v[i2]);
vec4 v3 = vec4(vertices.v[i3]);
// 出力する頂点数(4)とプリミティブ数(2)を設定
SetMeshOutputsEXT(4, 2);
// gl_MeshPerVertexEXTの中身を設定していく
gl_MeshVerticesEXT[0].gl_Position = v0;
gl_MeshVerticesEXT[1].gl_Position = v1;
gl_MeshVerticesEXT[2].gl_Position = v2;
gl_MeshVerticesEXT[3].gl_Position = v3;
vertexOutput[0].color = vec4(1.0, 0.0, 0.0, 1.0);
vertexOutput[1].color = vec4(0.0, 1.0, 0.0, 1.0);
vertexOutput[2].color = vec4(0.0, 0.0, 1.0, 1.0);
vertexOutput[3].color = vec4(0.0, 1.0, 0.0, 1.0);
// 2つのプリミティブ(三角形)のインデックスを設定する
gl_PrimitiveTriangleIndicesEXT[2*gl_LocalInvocationIndex + 0] = uvec3(0, 1, 2);
gl_PrimitiveTriangleIndicesEXT[2*gl_LocalInvocationIndex + 1] = uvec3(2, 3, 0);
}
Mesh shaderへの頂点データはどのような形式でもいいため、このようなコードで簡単に四角ポリゴンをレンダリングできるようになります。
Discussion