Created
December 14, 2023 08:41
-
-
Save Kiterai/f4c18e041b36521c726313c54eb743f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define STB_IMAGE_WRITE_IMPLEMENTATION | |
#include "stb_image_write.h" | |
#include <vulkan/vulkan.hpp> | |
#include <fstream> | |
#include <filesystem> | |
#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(); 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; | |
} | |
std::cout << physicalDevice.getProperties().deviceName << std::endl; | |
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::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::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::eGeneral; | |
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::PipelineVertexInputStateCreateInfo vertexInputInfo; | |
vertexInputInfo.vertexAttributeDescriptionCount = 0; | |
vertexInputInfo.pVertexAttributeDescriptions = nullptr; | |
vertexInputInfo.vertexBindingDescriptionCount = 0; | |
vertexInputInfo.pVertexBindingDescriptions = nullptr; | |
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; | |
vk::PipelineLayoutCreateInfo layoutCreateInfo; | |
layoutCreateInfo.setLayoutCount = 0; | |
layoutCreateInfo.pSetLayouts = nullptr; | |
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]->draw(3, 1, 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()); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 | |
#extension GL_ARB_separate_shader_objects : enable | |
layout(location = 0) in vec3 inColor; | |
layout(location = 0) out vec4 outColor; | |
void main() { | |
outColor = vec4(inColor, 1.0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 | |
#extension GL_ARB_separate_shader_objects : enable | |
vec4 vPos[] = { | |
vec4(0.0, -0.5, 0.0, 1.0), | |
vec4(0.5, 0.5, 0.0, 1.0), | |
vec4(-0.5, 0.5, 0.0, 1.0), | |
}; | |
vec3 vColor[] = { | |
vec3(0.0, 1.0, 1.0), | |
vec3(1.0, 0.0, 1.0), | |
vec3(1.0, 1.0, 0.0), | |
}; | |
layout(location = 0) out vec3 fragmentColor; | |
void main() { | |
gl_Position = vPos[gl_VertexIndex]; | |
fragmentColor = vColor[gl_VertexIndex]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment