3-1. イメージの作成

これから行う描画処理はメモリの中の話とはいえ、絵を描くキャンバスにあたるものは必要です。

とりあえず幅と高さは決めてしまいましょう。

const uint32_t screenWidth = 640;
const uint32_t screenHeight = 480;

Vulkanにおいて画像はvk::Imageというオブジェクトで表されます。これはvk::DevicecreateImageメソッドで作成できます。

vk::ImageCreateInfo imgCreateInfo;
imgCreateInfo.imageType = vk::ImageType::e2D;
imgCreateInfo.extent = vk::Extent3D(screenWidth, screenHeight, 1);
imgCreateInfo.mipLevels = 1;
imgCreateInfo.arrayLayers = 1;
imgCreateInfo.format = vk::Format::eR8G8B8A8Unorm;
imgCreateInfo.tiling = vk::ImageTiling::eLinear;
imgCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imgCreateInfo.usage = vk::ImageUsageFlagBits::eColorAttachment;
imgCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imgCreateInfo.samples = vk::SampleCountFlagBits::e1;

vk::UniqueImage image = device->createImageUnique(imgCreateInfo);

ばかでかい初期化用構造体がありますね。ここでは要点だけ書くにとどめて、詳細については必要に応じておいおい解説していくことにします。気になるという人は公式ドキュメントを見てみてください。

imageTypeには画像の次元を指定します。1次元から3次元まで指定できます。2次元以外の画像ってなんじゃらほいという感じですが、Rampテクスチャやvoxelなど、普通に使い道があります。ここでは普通の2次元の画像のためvk::ImageType::e2Dを指定しています。

extentには画像のサイズを指定します。ここでは640×480を指定しています。最大3次元の画像を扱うためvk::Extent3Dによる指定ですが、今回は2次元であるため、第3引数の奥行には1を指定しています。640x480x1のマス目と思ってください。

formatには画素のフォーマットの種類を指定します。どのように各ピクセルが色を保存しているかの情報です。

これで画像オブジェクトを作成することができました。しかしこの段階ではまだ画像にメモリが割り当てられていません。メモリを割り当ててやらないと画像データを記録することは出来ません。


この節ではイメージの作成をやりました。次節ではメモリの確保をやります。

// 環境に合わせて
#define VK_USE_PLATFORM_WIN32_KHR

#define VULKAN_HPP_TYPESAFE_CONVERSION

#include <vulkan/vulkan.hpp>
#include <iostream>
#include <vector>

const uint32_t screenWidth = 640;
const uint32_t screenHeight = 480;

int main()
{
    vk::InstanceCreateInfo createInfo;

    vk::UniqueInstance instance;
    instance = vk::createInstanceUnique(createInfo);

    std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();

    vk::PhysicalDevice physicalDevice;
    bool existsSuitablePhysicalDevice = false;
    uint32_t graphicsQueueFamilyIndex;

    for (size_t i = 0; i < physicalDevices.size(); i++)
    {
        std::vector<vk::QueueFamilyProperties> queueProps = physicalDevices[i].getQueueFamilyProperties();
        bool existsGraphicsQueue = false;

        for (size_t j = 0; j < queueProps.size(); i++)
        {
            if (queueProps[j].queueFlags & vk::QueueFlagBits::eGraphics)
            {
                existsGraphicsQueue = true;
                graphicsQueueFamilyIndex = j;
                break;
            }
        }

        if (existsGraphicsQueue)
        {
            physicalDevice = physicalDevices[i];
            existsSuitablePhysicalDevice = true;
            break;
        }
    }

    if (!existsSuitablePhysicalDevice)
    {
        std::cerr << "使用可能な物理デバイスがありません。" << std::endl;
        return -1;
    }

    vk::DeviceCreateInfo devCreateInfo;

    vk::DeviceQueueCreateInfo queueCreateInfo[1];
    queueCreateInfo[0].queueFamilyIndex = graphicsQueueFamilyIndex;
    queueCreateInfo[0].queueCount = 1;

    float queuePriorities[1] = { 1.0 };

    queueCreateInfo[0].pQueuePriorities = queuePriorities;

    devCreateInfo.pQueueCreateInfos = queueCreateInfo;
    devCreateInfo.queueCreateInfoCount = 1;
    vk::UniqueDevice device = physicalDevice.createDeviceUnique(devCreateInfo);

    vk::Queue graphicsQueue = device->getQueue(graphicsQueueFamilyIndex, 0);

    vk::CommandPoolCreateInfo cmdPoolCreateInfo;
    cmdPoolCreateInfo.queueFamilyIndex = graphicsQueueFamilyIndex;
    vk::UniqueCommandPool cmdPool = device->createCommandPoolUnique(cmdPoolCreateInfo);

    vk::CommandBufferAllocateInfo cmdBufAllocInfo;
    cmdBufAllocInfo.commandPool = cmdPool.get();
    cmdBufAllocInfo.commandBufferCount = 1;
    cmdBufAllocInfo.level = vk::CommandBufferLevel::ePrimary;
    std::vector<vk::UniqueCommandBuffer> cmdBufs =
        device->allocateCommandBuffersUnique(cmdBufAllocInfo);

    vk::ImageCreateInfo imgCreateInfo;
    imgCreateInfo.imageType = vk::ImageType::e2D;
    imgCreateInfo.extent = vk::Extent3D(screenWidth, screenHeight, 1);
    imgCreateInfo.mipLevels = 1;
    imgCreateInfo.arrayLayers = 1;
    imgCreateInfo.format = vk::Format::eR8G8B8A8Unorm;
    imgCreateInfo.tiling = vk::ImageTiling::eLinear;
    imgCreateInfo.initialLayout = vk::ImageLayout::eColorAttachmentOptimal;
    imgCreateInfo.usage = vk::ImageUsageFlagBits::eColorAttachment;
    imgCreateInfo.sharingMode = vk::SharingMode::eExclusive;
    imgCreateInfo.samples = vk::SampleCountFlagBits::e1;

    vk::UniqueImage image = device->createImageUnique(imgCreateInfo);

    vk::CommandBufferBeginInfo cmdBeginInfo;
    cmdBufs[0]->begin(cmdBeginInfo);

    // コマンドを記録

    cmdBufs[0]->end();

    vk::CommandBuffer submitCmdBuf[1] = { cmdBufs[0].get() };
    vk::SubmitInfo submitInfo;
    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = submitCmdBuf;

    graphicsQueue.submit({ submitInfo }, nullptr);

    return 0;
}

 

コメントを残す

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