Skip to content

Instantly share code, notes, and snippets.

@Kiterai
Created December 14, 2023 09:40
Show Gist options
  • Save Kiterai/c7cfb2e79e44177e4366dc0c5615bf94 to your computer and use it in GitHub Desktop.
Save Kiterai/c7cfb2e79e44177e4366dc0c5615bf94 to your computer and use it in GitHub Desktop.
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"
#include "stb_image_write.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vulkan/vulkan.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
const uint32_t screenWidth = 640;
const uint32_t screenHeight = 640;
struct Vec2 {
float x, y;
};
struct Vec3 {
float x, y, z;
};
struct Vertex {
Vec3 pos;
Vec2 texUV;
};
std::vector<Vertex> vertices = {
Vertex{Vec3{-0.5f, -0.5f, -0.5f}, Vec2{0.0, 0.0}},
Vertex{Vec3{0.5f, 0.5f, -0.5f}, Vec2{1.0, 1.0}},
Vertex{Vec3{-0.5f, 0.5f, -0.5f}, Vec2{0.0, 1.0}},
Vertex{Vec3{0.5f, -0.5f, -0.5f}, Vec2{1.0, 0.0}},
Vertex{Vec3{-0.5f, -0.5f, -0.5f}, Vec2{0.0, 0.0}},
Vertex{Vec3{0.5f, -0.5f, 0.5f}, Vec2{1.0, 1.0}},
Vertex{Vec3{0.5f, -0.5f, -0.5f}, Vec2{0.0, 1.0}},
Vertex{Vec3{-0.5f, -0.5f, 0.5f}, Vec2{1.0, 0.0}},
Vertex{Vec3{-0.5f, -0.5f, -0.5f}, Vec2{0.0, 0.0}},
Vertex{Vec3{-0.5f, 0.5f, 0.5f}, Vec2{1.0, 1.0}},
Vertex{Vec3{-0.5f, -0.5f, 0.5f}, Vec2{0.0, 1.0}},
Vertex{Vec3{-0.5f, 0.5f, -0.5f}, Vec2{1.0, 0.0}},
Vertex{Vec3{0.5f, 0.5f, 0.5f}, Vec2{0.0, 0.0}},
Vertex{Vec3{-0.5f, -0.5f, 0.5f}, Vec2{1.0, 1.0}},
Vertex{Vec3{0.5f, -0.5f, 0.5f}, Vec2{0.0, 1.0}},
Vertex{Vec3{-0.5f, 0.5f, 0.5f}, Vec2{1.0, 0.0}},
Vertex{Vec3{0.5f, 0.5f, 0.5f}, Vec2{0.0, 0.0}},
Vertex{Vec3{-0.5f, 0.5f, -0.5f}, Vec2{1.0, 1.0}},
Vertex{Vec3{-0.5f, 0.5f, 0.5f}, Vec2{0.0, 1.0}},
Vertex{Vec3{0.5f, 0.5f, -0.5f}, Vec2{1.0, 0.0}},
Vertex{Vec3{0.5f, 0.5f, 0.5f}, Vec2{0.0, 0.0}},
Vertex{Vec3{0.5f, -0.5f, -0.5f}, Vec2{1.0, 1.0}},
Vertex{Vec3{0.5f, 0.5f, -0.5f}, Vec2{0.0, 1.0}},
Vertex{Vec3{0.5f, -0.5f, 0.5f}, Vec2{1.0, 0.0}},
};
std::vector<uint16_t> indices = {
0, 1, 2, 1, 0, 3,
4, 5, 6, 5, 4, 7,
8, 9, 10, 9, 8, 11,
12, 13, 14, 13, 12, 15,
16, 17, 18, 17, 16, 19,
20, 21, 22, 21, 20, 23};
struct SceneData {
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
SceneData sceneData = {
glm::mat4(1.0f),
glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)),
glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 10.0f)
};
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(); j++) {
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;
auto devRequiredExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
devCreateInfo.enabledExtensionCount = devRequiredExtensions.size();
devCreateInfo.ppEnabledExtensionNames = devRequiredExtensions.begin();
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::eUndefined;
imgCreateInfo.usage = vk::ImageUsageFlagBits::eColorAttachment;
imgCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imgCreateInfo.samples = vk::SampleCountFlagBits::e1;
vk::UniqueImage image = device->createImageUnique(imgCreateInfo);
vk::PhysicalDeviceMemoryProperties memProps = physicalDevice.getMemoryProperties();
vk::MemoryRequirements imgMemReq = device->getImageMemoryRequirements(image.get());
vk::MemoryAllocateInfo imgMemAllocInfo;
imgMemAllocInfo.allocationSize = imgMemReq.size;
bool suitableMemoryTypeFound = false;
for (size_t i = 0; i < memProps.memoryTypeCount; i++) {
if (imgMemReq.memoryTypeBits & (1 << i) &&
(memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)) {
imgMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "使用可能なメモリタイプがありません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory imgMem = device->allocateMemoryUnique(imgMemAllocInfo);
device->bindImageMemory(image.get(), imgMem.get(), 0);
vk::BufferCreateInfo vertBufferCreateInfo;
vertBufferCreateInfo.size = sizeof(Vertex) * vertices.size();
vertBufferCreateInfo.usage = vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst;
vertBufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::UniqueBuffer vertexBuf = device->createBufferUnique(vertBufferCreateInfo);
vk::MemoryRequirements vertexBufMemReq = device->getBufferMemoryRequirements(vertexBuf.get());
vk::MemoryAllocateInfo vertexBufMemAllocInfo;
vertexBufMemAllocInfo.allocationSize = vertexBufMemReq.size;
suitableMemoryTypeFound = false;
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
if (vertexBufMemReq.memoryTypeBits & (1 << i) && (memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal)) {
vertexBufMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory vertexBufMemory = device->allocateMemoryUnique(vertexBufMemAllocInfo);
device->bindBufferMemory(vertexBuf.get(), vertexBufMemory.get(), 0);
{
vk::BufferCreateInfo stagingBufferCreateInfo;
stagingBufferCreateInfo.size = sizeof(Vertex) * vertices.size();
stagingBufferCreateInfo.usage = vk::BufferUsageFlagBits::eTransferSrc;
stagingBufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::UniqueBuffer stagingBuf = device->createBufferUnique(stagingBufferCreateInfo);
vk::MemoryRequirements stagingBufMemReq = device->getBufferMemoryRequirements(stagingBuf.get());
vk::MemoryAllocateInfo stagingBufMemAllocInfo;
stagingBufMemAllocInfo.allocationSize = stagingBufMemReq.size;
suitableMemoryTypeFound = false;
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
if (stagingBufMemReq.memoryTypeBits & (1 << i) && (memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)) {
stagingBufMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory stagingBufMemory = device->allocateMemoryUnique(stagingBufMemAllocInfo);
device->bindBufferMemory(stagingBuf.get(), stagingBufMemory.get(), 0);
void *pStagingBufMem = device->mapMemory(stagingBufMemory.get(), 0, sizeof(Vertex) * vertices.size());
std::memcpy(pStagingBufMem, vertices.data(), sizeof(Vertex) * vertices.size());
vk::MappedMemoryRange flushMemoryRange;
flushMemoryRange.memory = stagingBufMemory.get();
flushMemoryRange.offset = 0;
flushMemoryRange.size = sizeof(Vertex) * vertices.size();
device->flushMappedMemoryRanges({flushMemoryRange});
device->unmapMemory(stagingBufMemory.get());
vk::CommandPoolCreateInfo tmpCmdPoolCreateInfo;
tmpCmdPoolCreateInfo.queueFamilyIndex = graphicsQueueFamilyIndex;
tmpCmdPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eTransient;
vk::UniqueCommandPool tmpCmdPool = device->createCommandPoolUnique(tmpCmdPoolCreateInfo);
vk::CommandBufferAllocateInfo tmpCmdBufAllocInfo;
tmpCmdBufAllocInfo.commandPool = tmpCmdPool.get();
tmpCmdBufAllocInfo.commandBufferCount = 1;
tmpCmdBufAllocInfo.level = vk::CommandBufferLevel::ePrimary;
std::vector<vk::UniqueCommandBuffer> tmpCmdBufs = device->allocateCommandBuffersUnique(tmpCmdBufAllocInfo);
vk::BufferCopy bufCopy;
bufCopy.srcOffset = 0;
bufCopy.dstOffset = 0;
bufCopy.size = sizeof(Vertex) * vertices.size();
vk::CommandBufferBeginInfo cmdBeginInfo;
cmdBeginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
tmpCmdBufs[0]->begin(cmdBeginInfo);
tmpCmdBufs[0]->copyBuffer(stagingBuf.get(), vertexBuf.get(), {bufCopy});
tmpCmdBufs[0]->end();
vk::CommandBuffer submitCmdBuf[1] = {tmpCmdBufs[0].get()};
vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = submitCmdBuf;
graphicsQueue.submit({submitInfo});
graphicsQueue.waitIdle();
}
vk::BufferCreateInfo indexBufferCreateInfo;
indexBufferCreateInfo.size = sizeof(uint16_t) * indices.size();
indexBufferCreateInfo.usage = vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst;
indexBufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::UniqueBuffer indexBuf = device->createBufferUnique(indexBufferCreateInfo);
vk::MemoryRequirements indexBufMemReq = device->getBufferMemoryRequirements(indexBuf.get());
vk::MemoryAllocateInfo indexBufMemAllocInfo;
indexBufMemAllocInfo.allocationSize = indexBufMemReq.size;
suitableMemoryTypeFound = false;
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
if (indexBufMemReq.memoryTypeBits & (1 << i) && (memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal)) {
indexBufMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory indexBufMemory = device->allocateMemoryUnique(indexBufMemAllocInfo);
device->bindBufferMemory(indexBuf.get(), indexBufMemory.get(), 0);
{
vk::BufferCreateInfo stagingBufferCreateInfo;
stagingBufferCreateInfo.size = sizeof(uint16_t) * indices.size();
stagingBufferCreateInfo.usage = vk::BufferUsageFlagBits::eTransferSrc;
stagingBufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::UniqueBuffer stagingBuf = device->createBufferUnique(stagingBufferCreateInfo);
vk::MemoryRequirements stagingBufMemReq = device->getBufferMemoryRequirements(stagingBuf.get());
vk::MemoryAllocateInfo stagingBufMemAllocInfo;
stagingBufMemAllocInfo.allocationSize = stagingBufMemReq.size;
suitableMemoryTypeFound = false;
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
if (stagingBufMemReq.memoryTypeBits & (1 << i) && (memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)) {
stagingBufMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory stagingBufMemory = device->allocateMemoryUnique(stagingBufMemAllocInfo);
device->bindBufferMemory(stagingBuf.get(), stagingBufMemory.get(), 0);
void *pStagingBufMem = device->mapMemory(stagingBufMemory.get(), 0, sizeof(uint16_t) * indices.size());
std::memcpy(pStagingBufMem, indices.data(), sizeof(uint16_t) * indices.size());
vk::MappedMemoryRange flushMemoryRange;
flushMemoryRange.memory = stagingBufMemory.get();
flushMemoryRange.offset = 0;
flushMemoryRange.size = sizeof(uint16_t) * indices.size();
device->flushMappedMemoryRanges({flushMemoryRange});
device->unmapMemory(stagingBufMemory.get());
vk::CommandPoolCreateInfo tmpCmdPoolCreateInfo;
tmpCmdPoolCreateInfo.queueFamilyIndex = graphicsQueueFamilyIndex;
tmpCmdPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eTransient;
vk::UniqueCommandPool tmpCmdPool = device->createCommandPoolUnique(tmpCmdPoolCreateInfo);
vk::CommandBufferAllocateInfo tmpCmdBufAllocInfo;
tmpCmdBufAllocInfo.commandPool = tmpCmdPool.get();
tmpCmdBufAllocInfo.commandBufferCount = 1;
tmpCmdBufAllocInfo.level = vk::CommandBufferLevel::ePrimary;
std::vector<vk::UniqueCommandBuffer> tmpCmdBufs = device->allocateCommandBuffersUnique(tmpCmdBufAllocInfo);
vk::BufferCopy bufCopy;
bufCopy.srcOffset = 0;
bufCopy.dstOffset = 0;
bufCopy.size = sizeof(uint16_t) * indices.size();
vk::CommandBufferBeginInfo cmdBeginInfo;
cmdBeginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
tmpCmdBufs[0]->begin(cmdBeginInfo);
tmpCmdBufs[0]->copyBuffer(stagingBuf.get(), indexBuf.get(), {bufCopy});
tmpCmdBufs[0]->end();
vk::CommandBuffer submitCmdBuf[1] = {tmpCmdBufs[0].get()};
vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = submitCmdBuf;
graphicsQueue.submit({submitInfo});
graphicsQueue.waitIdle();
}
vk::BufferCreateInfo uniformBufferCreateInfo;
uniformBufferCreateInfo.size = sizeof(SceneData);
uniformBufferCreateInfo.usage = vk::BufferUsageFlagBits::eUniformBuffer;
uniformBufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::UniqueBuffer uniformBuf = device->createBufferUnique(uniformBufferCreateInfo);
vk::MemoryRequirements uniformBufMemReq = device->getBufferMemoryRequirements(uniformBuf.get());
vk::MemoryAllocateInfo uniformBufMemAllocInfo;
uniformBufMemAllocInfo.allocationSize = uniformBufMemReq.size;
suitableMemoryTypeFound = false;
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
if (uniformBufMemReq.memoryTypeBits & (1 << i) &&
(memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)) {
uniformBufMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory uniformBufMemory = device->allocateMemoryUnique(uniformBufMemAllocInfo);
device->bindBufferMemory(uniformBuf.get(), uniformBufMemory.get(), 0);
{
void* pUniformBufMem = device->mapMemory(uniformBufMemory.get(), 0, sizeof(SceneData));
std::memcpy(pUniformBufMem, &sceneData, sizeof(SceneData));
vk::MappedMemoryRange flushMemoryRange;
flushMemoryRange.memory = uniformBufMemory.get();
flushMemoryRange.offset = 0;
flushMemoryRange.size = sizeof(SceneData);
device->flushMappedMemoryRanges({ flushMemoryRange });
device->unmapMemory(uniformBufMemory.get());
}
int imgWidth, imgHeight, imgCh;
auto pImgData = stbi_load("image.png", &imgWidth, &imgHeight, &imgCh, STBI_rgb_alpha);
if (pImgData == nullptr) {
std::cerr << "画像ファイルの読み込みに失敗しました。" << std::endl;
return -1;
}
vk::ImageCreateInfo texImgCreateInfo;
texImgCreateInfo.imageType = vk::ImageType::e2D;
texImgCreateInfo.extent = vk::Extent3D(imgWidth, imgHeight, 1);
texImgCreateInfo.mipLevels = 1;
texImgCreateInfo.arrayLayers = 1;
texImgCreateInfo.format = vk::Format::eR8G8B8A8Unorm;
texImgCreateInfo.tiling = vk::ImageTiling::eOptimal;
texImgCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
texImgCreateInfo.usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
texImgCreateInfo.sharingMode = vk::SharingMode::eExclusive;
texImgCreateInfo.samples = vk::SampleCountFlagBits::e1;
vk::UniqueImage texImage = device->createImageUnique(texImgCreateInfo);
vk::MemoryRequirements texImgMemReq = device->getImageMemoryRequirements(texImage.get());
vk::MemoryAllocateInfo texImgMemAllocInfo;
texImgMemAllocInfo.allocationSize = texImgMemReq.size;
suitableMemoryTypeFound = false;
for (size_t i = 0; i < memProps.memoryTypeCount; i++) {
if (texImgMemReq.memoryTypeBits & (1 << i)) {
texImgMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "使用可能なメモリタイプがありません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory texImgMem = device->allocateMemoryUnique(texImgMemAllocInfo);
device->bindImageMemory(texImage.get(), texImgMem.get(), 0);
{
size_t imgDataSize = 4 * imgWidth * imgHeight;
vk::BufferCreateInfo imgStagingBufferCreateInfo;
imgStagingBufferCreateInfo.size = imgDataSize;
imgStagingBufferCreateInfo.usage = vk::BufferUsageFlagBits::eTransferSrc;
imgStagingBufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
vk::UniqueBuffer imgStagingBuf = device->createBufferUnique(imgStagingBufferCreateInfo);
vk::MemoryRequirements imgStagingBufMemReq = device->getBufferMemoryRequirements(imgStagingBuf.get());
vk::MemoryAllocateInfo imgStagingBufMemAllocInfo;
imgStagingBufMemAllocInfo.allocationSize = imgStagingBufMemReq.size;
suitableMemoryTypeFound = false;
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) {
if (imgStagingBufMemReq.memoryTypeBits & (1 << i) &&
(memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)) {
imgStagingBufMemAllocInfo.memoryTypeIndex = i;
suitableMemoryTypeFound = true;
break;
}
}
if (!suitableMemoryTypeFound) {
std::cerr << "適切なメモリタイプが存在しません。" << std::endl;
return -1;
}
vk::UniqueDeviceMemory imgStagingBufMemory = device->allocateMemoryUnique(imgStagingBufMemAllocInfo);
device->bindBufferMemory(imgStagingBuf.get(), imgStagingBufMemory.get(), 0);
void *pImgStagingBufMem = device->mapMemory(imgStagingBufMemory.get(), 0, imgDataSize);
std::memcpy(pImgStagingBufMem, pImgData, imgDataSize);
vk::MappedMemoryRange flushMemoryRange;
flushMemoryRange.memory = imgStagingBufMemory.get();
flushMemoryRange.offset = 0;
flushMemoryRange.size = imgDataSize;
device->flushMappedMemoryRanges({flushMemoryRange});
device->unmapMemory(imgStagingBufMemory.get());
stbi_image_free(pImgData);
vk::CommandPoolCreateInfo tmpCmdPoolCreateInfo;
tmpCmdPoolCreateInfo.queueFamilyIndex = graphicsQueueFamilyIndex;
tmpCmdPoolCreateInfo.flags = vk::CommandPoolCreateFlagBits::eTransient;
vk::UniqueCommandPool tmpCmdPool = device->createCommandPoolUnique(tmpCmdPoolCreateInfo);
vk::CommandBufferAllocateInfo tmpCmdBufAllocInfo;
tmpCmdBufAllocInfo.commandPool = tmpCmdPool.get();
tmpCmdBufAllocInfo.commandBufferCount = 1;
tmpCmdBufAllocInfo.level = vk::CommandBufferLevel::ePrimary;
std::vector<vk::UniqueCommandBuffer> tmpCmdBufs = device->allocateCommandBuffersUnique(tmpCmdBufAllocInfo);
vk::CommandBufferBeginInfo cmdBeginInfo;
cmdBeginInfo.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
tmpCmdBufs[0]->begin(cmdBeginInfo);
{
vk::ImageMemoryBarrier barrior;
barrior.oldLayout = vk::ImageLayout::eUndefined;
barrior.newLayout = vk::ImageLayout::eTransferDstOptimal;
barrior.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrior.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrior.image = texImage.get();
barrior.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
barrior.subresourceRange.baseMipLevel = 0;
barrior.subresourceRange.levelCount = 1;
barrior.subresourceRange.baseArrayLayer = 0;
barrior.subresourceRange.layerCount = 1;
barrior.srcAccessMask = {};
barrior.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
tmpCmdBufs[0]->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, {barrior});
}
vk::BufferImageCopy imgCopyRegion;
imgCopyRegion.bufferOffset = 0;
imgCopyRegion.imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
imgCopyRegion.imageSubresource.mipLevel = 0;
imgCopyRegion.imageSubresource.baseArrayLayer = 0;
imgCopyRegion.imageSubresource.layerCount = 1;
imgCopyRegion.imageOffset = vk::Offset3D{0, 0, 0};
imgCopyRegion.imageExtent = vk::Extent3D{uint32_t(imgWidth), uint32_t(imgHeight), 1};
imgCopyRegion.bufferRowLength = 0;
imgCopyRegion.bufferImageHeight = 0;
tmpCmdBufs[0]->copyBufferToImage(imgStagingBuf.get(), texImage.get(), vk::ImageLayout::eTransferDstOptimal, { imgCopyRegion });
{
vk::ImageMemoryBarrier barrior;
barrior.oldLayout = vk::ImageLayout::eTransferDstOptimal;
barrior.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
barrior.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrior.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrior.image = texImage.get();
barrior.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
barrior.subresourceRange.baseMipLevel = 0;
barrior.subresourceRange.levelCount = 1;
barrior.subresourceRange.baseArrayLayer = 0;
barrior.subresourceRange.layerCount = 1;
barrior.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
barrior.dstAccessMask = vk::AccessFlagBits::eShaderRead;
tmpCmdBufs[0]->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, {barrior});
}
tmpCmdBufs[0]->end();
vk::CommandBuffer submitCmdBuf[1] = {tmpCmdBufs[0].get()};
vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = submitCmdBuf;
graphicsQueue.submit({submitInfo});
graphicsQueue.waitIdle();
}
vk::SamplerCreateInfo samplerCreateInfo;
samplerCreateInfo.magFilter = vk::Filter::eNearest;
samplerCreateInfo.minFilter = vk::Filter::eNearest;
samplerCreateInfo.addressModeU = vk::SamplerAddressMode::eRepeat;
samplerCreateInfo.addressModeV = vk::SamplerAddressMode::eRepeat;
samplerCreateInfo.addressModeW = vk::SamplerAddressMode::eRepeat;
samplerCreateInfo.anisotropyEnable = false;
samplerCreateInfo.maxAnisotropy = 1.0f;
samplerCreateInfo.borderColor = vk::BorderColor::eIntOpaqueBlack;
samplerCreateInfo.unnormalizedCoordinates = false;
samplerCreateInfo.compareEnable = false;
samplerCreateInfo.compareOp = vk::CompareOp::eAlways;
samplerCreateInfo.mipmapMode = vk::SamplerMipmapMode::eLinear;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = 0.0f;
vk::UniqueSampler sampler = device->createSamplerUnique(samplerCreateInfo);
vk::ImageViewCreateInfo texImgViewCreateInfo;
texImgViewCreateInfo.image = texImage.get();
texImgViewCreateInfo.viewType = vk::ImageViewType::e2D;
texImgViewCreateInfo.format = vk::Format::eR8G8B8A8Unorm;
texImgViewCreateInfo.components.r = vk::ComponentSwizzle::eIdentity;
texImgViewCreateInfo.components.g = vk::ComponentSwizzle::eIdentity;
texImgViewCreateInfo.components.b = vk::ComponentSwizzle::eIdentity;
texImgViewCreateInfo.components.a = vk::ComponentSwizzle::eIdentity;
texImgViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
texImgViewCreateInfo.subresourceRange.baseMipLevel = 0;
texImgViewCreateInfo.subresourceRange.levelCount = 1;
texImgViewCreateInfo.subresourceRange.baseArrayLayer = 0;
texImgViewCreateInfo.subresourceRange.layerCount = 1;
vk::UniqueImageView texImageView = device->createImageViewUnique(texImgViewCreateInfo);
vk::DescriptorSetLayoutBinding descSetLayoutBinding[2];
descSetLayoutBinding[0].binding = 0;
descSetLayoutBinding[0].descriptorType = vk::DescriptorType::eUniformBuffer;
descSetLayoutBinding[0].descriptorCount = 1;
descSetLayoutBinding[0].stageFlags = vk::ShaderStageFlagBits::eVertex;
descSetLayoutBinding[1].binding = 1;
descSetLayoutBinding[1].descriptorType = vk::DescriptorType::eCombinedImageSampler;
descSetLayoutBinding[1].descriptorCount = 1;
descSetLayoutBinding[1].stageFlags = vk::ShaderStageFlagBits::eFragment;
vk::DescriptorSetLayoutCreateInfo descSetLayoutCreateInfo{};
descSetLayoutCreateInfo.bindingCount = std::size(descSetLayoutBinding);
descSetLayoutCreateInfo.pBindings = descSetLayoutBinding;
vk::UniqueDescriptorSetLayout descSetLayout = device->createDescriptorSetLayoutUnique(descSetLayoutCreateInfo);
vk::DescriptorPoolSize descPoolSize[2];
descPoolSize[0].type = vk::DescriptorType::eUniformBuffer;
descPoolSize[0].descriptorCount = 1;
descPoolSize[1].type = vk::DescriptorType::eCombinedImageSampler;
descPoolSize[1].descriptorCount = 1;
vk::DescriptorPoolCreateInfo descPoolCreateInfo;
descPoolCreateInfo.poolSizeCount = std::size(descPoolSize);
descPoolCreateInfo.pPoolSizes = descPoolSize;
descPoolCreateInfo.maxSets = 1;
vk::UniqueDescriptorPool descPool = device->createDescriptorPoolUnique(descPoolCreateInfo);
vk::DescriptorSetAllocateInfo descSetAllocInfo;
auto descSetLayouts = { descSetLayout.get() };
descSetAllocInfo.descriptorPool = descPool.get();
descSetAllocInfo.descriptorSetCount = descSetLayouts.size();
descSetAllocInfo.pSetLayouts = descSetLayouts.begin();
std::vector<vk::UniqueDescriptorSet> descSets = device->allocateDescriptorSetsUnique(descSetAllocInfo);
vk::WriteDescriptorSet writeDescSet;
writeDescSet.dstSet = descSets[0].get();
writeDescSet.dstBinding = 0;
writeDescSet.dstArrayElement = 0;
writeDescSet.descriptorType = vk::DescriptorType::eUniformBuffer;
vk::DescriptorBufferInfo descBufInfo[1];
descBufInfo[0].buffer = uniformBuf.get();
descBufInfo[0].offset = 0;
descBufInfo[0].range = sizeof(SceneData);
writeDescSet.descriptorCount = 1;
writeDescSet.pBufferInfo = descBufInfo;
device->updateDescriptorSets({ writeDescSet }, {});
vk::WriteDescriptorSet writeTexDescSet;
writeTexDescSet.dstSet = descSets[0].get();
writeTexDescSet.dstBinding = 1;
writeTexDescSet.dstArrayElement = 0;
writeTexDescSet.descriptorType = vk::DescriptorType::eCombinedImageSampler;
vk::DescriptorImageInfo descImgInfo[1];
descImgInfo[0].imageView = texImageView.get();
descImgInfo[0].imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
descImgInfo[0].sampler = sampler.get();
writeTexDescSet.descriptorCount = std::size(descImgInfo);
writeTexDescSet.pImageInfo = descImgInfo;
device->updateDescriptorSets({ writeTexDescSet }, {});
vk::AttachmentDescription attachments[1];
attachments[0].format = vk::Format::eR8G8B8A8Unorm;
attachments[0].samples = vk::SampleCountFlagBits::e1;
attachments[0].loadOp = vk::AttachmentLoadOp::eClear;
attachments[0].storeOp = vk::AttachmentStoreOp::eStore;
attachments[0].stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
attachments[0].stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
attachments[0].initialLayout = vk::ImageLayout::eUndefined;
attachments[0].finalLayout = vk::ImageLayout::ePresentSrcKHR;
vk::AttachmentReference subpass0_attachmentRefs[1];
subpass0_attachmentRefs[0].attachment = 0;
subpass0_attachmentRefs[0].layout = vk::ImageLayout::eColorAttachmentOptimal;
vk::SubpassDescription subpasses[1];
subpasses[0].pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
subpasses[0].colorAttachmentCount = 1;
subpasses[0].pColorAttachments = subpass0_attachmentRefs;
vk::RenderPassCreateInfo renderpassCreateInfo;
renderpassCreateInfo.attachmentCount = 1;
renderpassCreateInfo.pAttachments = attachments;
renderpassCreateInfo.subpassCount = 1;
renderpassCreateInfo.pSubpasses = subpasses;
renderpassCreateInfo.dependencyCount = 0;
renderpassCreateInfo.pDependencies = nullptr;
vk::UniqueRenderPass renderpass = device->createRenderPassUnique(renderpassCreateInfo);
vk::Viewport viewports[1];
viewports[0].x = 0.0;
viewports[0].y = 0.0;
viewports[0].minDepth = 0.0;
viewports[0].maxDepth = 1.0;
viewports[0].width = screenWidth;
viewports[0].height = screenHeight;
vk::Rect2D scissors[1];
scissors[0].offset = vk::Offset2D{0, 0};
scissors[0].extent = vk::Extent2D{screenWidth, screenHeight};
vk::PipelineViewportStateCreateInfo viewportState;
viewportState.viewportCount = 1;
viewportState.pViewports = viewports;
viewportState.scissorCount = 1;
viewportState.pScissors = scissors;
vk::VertexInputBindingDescription vertexBindingDescription[1];
vertexBindingDescription[0].binding = 0;
vertexBindingDescription[0].stride = sizeof(Vertex);
vertexBindingDescription[0].inputRate = vk::VertexInputRate::eVertex;
vk::VertexInputAttributeDescription vertexInputDescription[2];
vertexInputDescription[0].binding = 0;
vertexInputDescription[0].location = 0;
vertexInputDescription[0].format = vk::Format::eR32G32B32Sfloat;
vertexInputDescription[0].offset = offsetof(Vertex, pos);
vertexInputDescription[1].binding = 0;
vertexInputDescription[1].location = 1;
vertexInputDescription[1].format = vk::Format::eR32G32Sfloat;
vertexInputDescription[1].offset = offsetof(Vertex, texUV);
vk::PipelineVertexInputStateCreateInfo vertexInputInfo;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = vertexBindingDescription;
vertexInputInfo.vertexAttributeDescriptionCount = std::size(vertexInputDescription);
vertexInputInfo.pVertexAttributeDescriptions = vertexInputDescription;
vk::PipelineInputAssemblyStateCreateInfo inputAssembly;
inputAssembly.topology = vk::PrimitiveTopology::eTriangleList;
inputAssembly.primitiveRestartEnable = false;
vk::PipelineRasterizationStateCreateInfo rasterizer;
rasterizer.depthClampEnable = false;
rasterizer.rasterizerDiscardEnable = false;
rasterizer.polygonMode = vk::PolygonMode::eFill;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = vk::CullModeFlagBits::eBack;
rasterizer.frontFace = vk::FrontFace::eClockwise;
rasterizer.depthBiasEnable = false;
vk::PipelineMultisampleStateCreateInfo multisample;
multisample.sampleShadingEnable = false;
multisample.rasterizationSamples = vk::SampleCountFlagBits::e1;
vk::PipelineColorBlendAttachmentState blendattachment[1];
blendattachment[0].colorWriteMask = vk::ColorComponentFlagBits::eA | vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB;
blendattachment[0].blendEnable = false;
vk::PipelineColorBlendStateCreateInfo blend;
blend.logicOpEnable = false;
blend.attachmentCount = 1;
blend.pAttachments = blendattachment;
auto pipelineDescSetLayouts = { descSetLayout.get() };
vk::PipelineLayoutCreateInfo layoutCreateInfo;
layoutCreateInfo.setLayoutCount = pipelineDescSetLayouts.size();
layoutCreateInfo.pSetLayouts = pipelineDescSetLayouts.begin();
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(layoutCreateInfo);
size_t vertSpvFileSz = std::filesystem::file_size("shader.vert.spv");
std::ifstream vertSpvFile("shader.vert.spv", std::ios_base::binary);
std::vector<char> vertSpvFileData(vertSpvFileSz);
vertSpvFile.read(vertSpvFileData.data(), vertSpvFileSz);
vk::ShaderModuleCreateInfo vertShaderCreateInfo;
vertShaderCreateInfo.codeSize = vertSpvFileSz;
vertShaderCreateInfo.pCode = reinterpret_cast<const uint32_t *>(vertSpvFileData.data());
vk::UniqueShaderModule vertShader = device->createShaderModuleUnique(vertShaderCreateInfo);
size_t fragSpvFileSz = std::filesystem::file_size("shader.frag.spv");
std::ifstream fragSpvFile("shader.frag.spv", std::ios_base::binary);
std::vector<char> fragSpvFileData(fragSpvFileSz);
fragSpvFile.read(fragSpvFileData.data(), fragSpvFileSz);
vk::ShaderModuleCreateInfo fragShaderCreateInfo;
fragShaderCreateInfo.codeSize = fragSpvFileSz;
fragShaderCreateInfo.pCode = reinterpret_cast<const uint32_t *>(fragSpvFileData.data());
vk::UniqueShaderModule fragShader = device->createShaderModuleUnique(fragShaderCreateInfo);
vk::PipelineShaderStageCreateInfo shaderStage[2];
shaderStage[0].stage = vk::ShaderStageFlagBits::eVertex;
shaderStage[0].module = vertShader.get();
shaderStage[0].pName = "main";
shaderStage[1].stage = vk::ShaderStageFlagBits::eFragment;
shaderStage[1].module = fragShader.get();
shaderStage[1].pName = "main";
vk::GraphicsPipelineCreateInfo pipelineCreateInfo;
pipelineCreateInfo.pViewportState = &viewportState;
pipelineCreateInfo.pVertexInputState = &vertexInputInfo;
pipelineCreateInfo.pInputAssemblyState = &inputAssembly;
pipelineCreateInfo.pRasterizationState = &rasterizer;
pipelineCreateInfo.pMultisampleState = &multisample;
pipelineCreateInfo.pColorBlendState = &blend;
pipelineCreateInfo.layout = pipelineLayout.get();
pipelineCreateInfo.renderPass = renderpass.get();
pipelineCreateInfo.subpass = 0;
pipelineCreateInfo.stageCount = 2;
pipelineCreateInfo.pStages = shaderStage;
vk::UniquePipeline pipeline = device->createGraphicsPipelineUnique(nullptr, pipelineCreateInfo).value;
vk::ImageViewCreateInfo imgViewCreateInfo;
imgViewCreateInfo.image = image.get();
imgViewCreateInfo.viewType = vk::ImageViewType::e2D;
imgViewCreateInfo.format = vk::Format::eR8G8B8A8Unorm;
imgViewCreateInfo.components.r = vk::ComponentSwizzle::eIdentity;
imgViewCreateInfo.components.g = vk::ComponentSwizzle::eIdentity;
imgViewCreateInfo.components.b = vk::ComponentSwizzle::eIdentity;
imgViewCreateInfo.components.a = vk::ComponentSwizzle::eIdentity;
imgViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
imgViewCreateInfo.subresourceRange.baseMipLevel = 0;
imgViewCreateInfo.subresourceRange.levelCount = 1;
imgViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imgViewCreateInfo.subresourceRange.layerCount = 1;
vk::UniqueImageView imgView = device->createImageViewUnique(imgViewCreateInfo);
vk::ImageView frameBufAttachments[1];
frameBufAttachments[0] = imgView.get();
vk::FramebufferCreateInfo frameBufCreateInfo;
frameBufCreateInfo.width = screenWidth;
frameBufCreateInfo.height = screenHeight;
frameBufCreateInfo.layers = 1;
frameBufCreateInfo.renderPass = renderpass.get();
frameBufCreateInfo.attachmentCount = 1;
frameBufCreateInfo.pAttachments = frameBufAttachments;
vk::UniqueFramebuffer frameBuf = device->createFramebufferUnique(frameBufCreateInfo);
vk::CommandBufferBeginInfo cmdBeginInfo;
cmdBufs[0]->begin(cmdBeginInfo);
vk::ClearValue clearVal[1];
clearVal[0].color.float32[0] = 0.0f;
clearVal[0].color.float32[1] = 0.0f;
clearVal[0].color.float32[2] = 0.0f;
clearVal[0].color.float32[3] = 1.0f;
vk::RenderPassBeginInfo renderpassBeginInfo;
renderpassBeginInfo.renderPass = renderpass.get();
renderpassBeginInfo.framebuffer = frameBuf.get();
renderpassBeginInfo.renderArea = vk::Rect2D({ 0,0 }, { screenWidth, screenHeight });
renderpassBeginInfo.clearValueCount = 1;
renderpassBeginInfo.pClearValues = clearVal;
cmdBufs[0]->beginRenderPass(renderpassBeginInfo, vk::SubpassContents::eInline);
cmdBufs[0]->bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get());
cmdBufs[0]->bindVertexBuffers(0, {vertexBuf.get()}, {0});
cmdBufs[0]->bindIndexBuffer(indexBuf.get(), 0, vk::IndexType::eUint16);
cmdBufs[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, { descSets[0].get() }, {});
cmdBufs[0]->drawIndexed(indices.size(), 1, 0, 0, 0);
cmdBufs[0]->endRenderPass();
cmdBufs[0]->end();
vk::CommandBuffer submitCmdBuf[1] = { cmdBufs[0].get() };
vk::SubmitInfo submitInfo;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = submitCmdBuf;
graphicsQueue.submit({ submitInfo }, nullptr);
graphicsQueue.waitIdle();
void* imgData = device->mapMemory(imgMem.get(), 0, imgMemReq.size);
stbi_write_bmp("img.bmp", screenWidth, screenHeight, 4, imgData);
device->unmapMemory(imgMem.get());
graphicsQueue.waitIdle();
return 0;
}
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(set = 0, binding = 1) uniform sampler2D texSampler;
layout(location = 0) in vec2 fragmentTexUV;
layout(location = 0) out vec4 outColor;
void main() {
outColor = texture(texSampler, fragmentTexUV);
}
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(set = 0, binding = 0) uniform SceneData {
mat4 model;
mat4 view;
mat4 proj;
} sceneData;
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec2 inTexUV;
layout(location = 0) out vec2 fragmentTexUV;
void main() {
gl_Position = sceneData.proj * sceneData.view * sceneData.model * vec4(inPos, 1.0);
fragmentTexUV = inTexUV;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment