Vulkanチュートリアル翻訳の14 Vertex Bufferの作成


テキストリンク:https://vulkan.lunarg.com/doc/sdk/1.2.131.2/windows/tutorial/html/13-init_vertex_buffer.html

Vertex Bufferの作成


この章のコードファイルは13-init_です.vertex_buffer.cpp
vertex bufferは、レンダリングしたいオブジェクトメッシュを記述する頂点データを含むCPUとGPUの両方に表示されるバッファです.一般に、頂点データには、位置データ(x,y,z)とオプションの色、法線、またはその他の情報が含まれます.他の3 D APIと同様に,ここではバッファを頂点データで埋め,描画操作でGPUに渡す.

Vertex Bufferオブジェクトの作成


vertex bufferの作成とuniform bufferの作成は、uniformの例で行ったように、バッファオブジェクトの作成から始まります.
VkBufferCreateInfo buf_info = {};
buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buf_info.pNext = NULL;
buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
buf_info.size = sizeof(g_vb_solid_face_colors_Data);
buf_info.queueFamilyIndexCount = 0;
buf_info.pQueueFamilyIndices = NULL;
buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
buf_info.flags = 0;
res = vkCreateBuffer(info.device, &buf_info, NULL, &info.vertex_buffer.buf);

uniform bufferオブジェクトとvertex bufferオブジェクトを作成する唯一の本当の違いは、usageフィールドの設定です.
立方体のデータ(g_vb_solid_face_colors_Data)は36個の頂点を含み、12個の三角形を定義し、6個の立方体体面に各面2個を定義している.各三角形には表面の色が関連付けられています.cubeをチェックできますdata.hファイルは実際のデータを見てみましょう.

Vertex Bufferメモリの割り当て


ここでも、ステップはuniform bufferを割り当てるステップと似ています.まず、メモリの位置合わせなどのマシンの制限を考慮したメモリ要件をクエリーします.例のコードを表示すると、このプロシージャはuniform例で実行される手順と似ています.

頂点データをバッファに格納する


割り当てが完了すると、メモリがマッピングされ、頂点データで初期化され、マッピングがキャンセルされます.
uint8_t *pData;
res = vkMapMemory(info.device, info.vertex_buffer.mem, 0,
                  mem_reqs.size, 0, (void **)&pData);

memcpy(pData, g_vb_solid_face_colors_Data,
       sizeof(g_vb_solid_face_colors_Data));

vkUnmapMemory(info.device, info.vertex_buffer.mem);

最後のステップとして、メモリはバッファオブジェクトにバインドされます.
res = vkBindBufferMemory(info.device, info.vertex_buffer.buf,
                         info.vertex_buffer.mem, 0);

頂点データの説明を入力


例:頂点データを次の順序で並べます.
struct Vertex {
    float posX, posY, posZ, posW; // Position data
    float r, g, b, a;             // Color
};

GPUにデータ配列順序を記述するために頂点入力バインディングを作成する必要があります.以下のvi_bindingとvi_attribsメンバーはここで設定されていますが、後でsubsequentの例でグラフィックパイプの作成の一部として使用されます.頂点データフォーマットを見ているので、ここでこれらのコードを理解したほうがいいです.
info.vi_binding.binding = 0;
info.vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
info.vi_binding.stride = sizeof(g_vb_solid_face_colors_Data[0]);

info.vi_attribs[0].binding = 0;
info.vi_attribs[0].location = 0;
info.vi_attribs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
info.vi_attribs[0].offset = 0;
info.vi_attribs[1].binding = 0;
info.vi_attribs[1].location = 1;
info.vi_attribs[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
info.vi_attribs[1].offset = 16;

strideは、頂点のサイズ、または次の頂点を取得するためにポインタに追加する数です.
bindingメンバーとlocationメンバーはGLSL shaderソースコードのそれぞれの値を指します.シェーダーの例のシェーダソースコードをレビューして、対応関係を理解できます.
最初のattributeが位置データであっても、attribute 0のformatメンバーでは4バイトのfloatデータフォーマットで記述されます.attribute 1のformatは、atttibute 1が色であるため、より明らかに色フォーマットである.
offsetメンバーは、頂点データ内の各attributeがどこで見つかったかを簡単に示します.

Vertex BufferをRender Passにバインド


後の例で見ることができるので、render passを設定するコードの大部分をスキップすることができます.しかし、vertex bufferとrender passをバインドするコードが見つかりました.
vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);

vkCmdBindVertexBuffers(info.cmd, 0,             /* Start Binding */
                       1,                       /* Binding Count */
                       &info.vertex_buffer.buf, /* pBuffers */
                       offsets);                /* pOffsets */

vkCmdEndRenderPass(info.cmd);

render passの内部でvertex bufferとrender passを接続するしかないことに注意してください.つまり、vkCmdBeginRenderPassvkCmdEndRenderPassの間にcommand bufferが入力されたとき.これは実際にGPUが描画時にvertex bufferを使用する方法を示しています.