5-2. バッファの作成

この節では「バッファ(vk::Buffer)」の作成方法について説明します。

バッファというのはこの章の最初にも説明した通り、デバイスメモリ上のデータ列を表すオブジェクトです。デバイスメモリが分からない人は5. シェーダにデータを与えるを読んで来ましょう。

GPUに送信したいデータがある場合、基本的には変数などをそのまま受け渡すのではなく「バッファに書き込む」もしくは「バッファに書き込んで転送する」という形をとることになります。なんにせよ、変数などの中にデータを用意しただけではそのデータは使えず、バッファにデータを移さないと何もできないのです。

ということで、これから前節で用意した頂点座標のデータをシェーダに送るためのバッファを作成します。いわゆる頂点バッファです。


バッファオブジェクトはデバイスのcreateBufferメソッドを用いて作成します。

vk::BufferCreateInfo bufferCreateInfo;
bufferCreateInfo.size = sizeof(Vertex) * vertices.size();
bufferCreateInfo.usage = vk::BufferUsageFlagBits::eVertexBuffer;
bufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;

vk::UniqueBuffer vertexBuf = device->createBufferUnique(bufferCreateInfo);

sizeはバッファの大きさをバイト数で示すものです。ここに例えば100という値を指定すれば100バイトの大きさのバッファが作成できます。ここでは、前節で定義した構造体のバイト数をsizeof演算子で取得し、それにデータの数をかけています。

usageは作成するバッファの使い道を示すためのものです。今回のように頂点バッファを作る場合、上記のようにvk::BufferUsageFlagBits::eVertexBufferフラグを指定しなければなりません。他にも場合によって様々なフラグを指定する必要があり、複数のフラグを指定することもあります。

sharingModeについては今のところは無視してください。ここではvk::SharingMode::eExclusiveを指定します。


上のようにバッファオブジェクトを作成しても、すぐには使えません。データを入れるデバイスメモリを別途確保し、バッファオブジェクトと結びつける必要があります。

3章のイメージ(vk::Image)のときと同じですね。

イメージに対してgetImageMemoryRequirementsがあったように、バッファにもgetBufferMemoryRequirementsという関数があります。必要なデバイスメモリのタイプ・サイズを取得したらあとはイメージのときと同じ要領で、allocateMemoryを用いてメモリを確保します。

vk::MemoryRequirements vertexBufMemReq = device->getBufferMemoryRequirements(vertexBuf.get());
    
vk::MemoryAllocateInfo vertexBufMemAllocInfo;
vertexBufMemAllocInfo.allocationSize = vertexBufMemReq.size;

int memType = -1;
bool suitableMemoryTypeFound = false;
for (int i = 0; i < memProps.memoryTypeCount; i++) {
    if (vertexBufMemReq.memoryTypeBits & (1 << i)) {
        vertexBufMemAllocInfo.memoryTypeIndex = i;
        suitableMemoryTypeFound = true;
        break;
    }
}
if (!suitableMemoryTypeFound) {
    std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
    return -1;
}

vk::UniqueDeviceMemory vertexBufMemory = device->allocateMemoryUnique(vertexBufMemAllocInfo);

デバイスメモリが確保出来たらbindBufferMemoryで結び付けます。これもイメージの作成のときと同じですね。


device->bindBufferMemory(vertexBuf.get(), vertexBufMemory.get(), 0);

第3引数は、これも以前説明したbindImageMemoryと同じ要領で、確保したデバイスメモリのどこを(先頭から何バイト目以降を)使用するかを指定するものです。

これでデータを持てるバッファを作成することができるようになりました。


この節ではバッファを作成する方法について学びました。次節ではバッファへのデータの書き込みについて学びます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です