これから行う描画処理はメモリの中の話とはいえ、絵を描くキャンバスにあたるものは必要です。
とりあえず幅と高さは決めてしまいましょう。
const uint32_t screenWidth = 640; const uint32_t screenHeight = 480;
Vulkanにおいて画像はvk::Imageというオブジェクトで表されます。これはvk::DeviceのcreateImageメソッドで作成できます。
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; }