FInished graphics pipeline basics

This commit is contained in:
Mars 2024-10-01 18:30:31 -04:00
parent 98bd5f7bc2
commit e0b7e93bd8
Signed by untrusted user: pupbrained
GPG key ID: 0FF5B8826803F895
8 changed files with 209 additions and 8 deletions

1
.envrc
View file

@ -1 +1,2 @@
PATH_add ./src/shaders
use_flake

View file

@ -42,6 +42,7 @@
fmt
glfw
glm
shaderc
vulkan-extension-layer
vulkan-memory-allocator
vulkan-utility-libraries

View file

@ -1,4 +1,5 @@
#include <fmt/format.h>
#include <fstream>
#include <iostream>
#include <set>
@ -61,6 +62,10 @@ class VulkanApp {
vk::Extent2D mSwapChainExtent;
std::vector<vk::UniqueImageView> mSwapChainImageViews;
vk::UniqueRenderPass mRenderPass;
vk::UniquePipelineLayout mPipelineLayout;
vk::UniquePipeline mGraphicsPipeline;
struct QueueFamilyIndices {
std::optional<u32> graphics_family;
std::optional<u32> present_family;
@ -74,6 +79,23 @@ class VulkanApp {
std::vector<vk::PresentModeKHR> present_modes;
};
static fn readFile(const std::string& filename) -> std::vector<char> {
std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open())
throw std::runtime_error("Failed to open file! " + filename);
usize fileSize = static_cast<usize>(file.tellg());
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), static_cast<std::streamsize>(fileSize));
file.close();
return buffer;
}
fn initWindow() -> void {
mGLFWInstance = vkfw::initUnique();
@ -93,6 +115,8 @@ class VulkanApp {
createLogicalDevice();
createSwapChain();
createImageViews();
createRenderPass();
createGraphicsPipeline();
}
fn mainLoop() -> void {
@ -254,7 +278,7 @@ class VulkanApp {
.preTransform = swapChainSupport.capabilities.currentTransform,
.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque,
.presentMode = presentMode,
.clipped = VK_TRUE,
.clipped = vk::True,
.oldSwapchain = nullptr,
};
@ -274,20 +298,159 @@ class VulkanApp {
.viewType = vk::ImageViewType::e2D,
.format = mSwapChainImageFormat,
.components = { .r = vk::ComponentSwizzle::eIdentity,
.g = vk::ComponentSwizzle::eIdentity,
.b = vk::ComponentSwizzle::eIdentity,
.a = vk::ComponentSwizzle::eIdentity },
.g = vk::ComponentSwizzle::eIdentity,
.b = vk::ComponentSwizzle::eIdentity,
.a = vk::ComponentSwizzle::eIdentity },
.subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1 },
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1 },
};
mSwapChainImageViews[i] = mDevice->createImageViewUnique(createInfo);
}
}
fn createRenderPass() -> void {
vk::AttachmentDescription colorAttachment {
.format = mSwapChainImageFormat,
.samples = vk::SampleCountFlagBits::e1,
.loadOp = vk::AttachmentLoadOp::eClear,
.storeOp = vk::AttachmentStoreOp::eStore,
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
.initialLayout = vk::ImageLayout::eUndefined,
.finalLayout = vk::ImageLayout::ePresentSrcKHR,
};
vk::AttachmentReference colorAttachmentRef {
.attachment = 0,
.layout = vk::ImageLayout::eColorAttachmentOptimal,
};
vk::SubpassDescription subpass {
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
.colorAttachmentCount = 1,
.pColorAttachments = &colorAttachmentRef,
};
vk::RenderPassCreateInfo renderPassInfo {
.attachmentCount = 1,
.pAttachments = &colorAttachment,
.subpassCount = 1,
.pSubpasses = &subpass,
};
mRenderPass = mDevice->createRenderPassUnique(renderPassInfo);
}
fn createGraphicsPipeline() -> void {
std::vector<char> vertShaderCode = readFile("src/shaders/vert.spv");
std::vector<char> fragShaderCode = readFile("src/shaders/frag.spv");
vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode);
vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode);
vk::PipelineShaderStageCreateInfo vertShaderStageInfo {
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertShaderModule.get(),
.pName = "main",
};
vk::PipelineShaderStageCreateInfo fragShaderStageInfo {
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragShaderModule.get(),
.pName = "main",
};
std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = { vertShaderStageInfo,
fragShaderStageInfo };
vk::PipelineVertexInputStateCreateInfo vertexInputInfo {
.vertexBindingDescriptionCount = 0,
.pVertexBindingDescriptions = nullptr,
.vertexAttributeDescriptionCount = 0,
.pVertexAttributeDescriptions = nullptr,
};
vk::PipelineInputAssemblyStateCreateInfo inputAssembly {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = vk::False,
};
vk::PipelineViewportStateCreateInfo viewportState {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizer {
.depthClampEnable = vk::False,
.rasterizerDiscardEnable = vk::False,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eBack,
.frontFace = vk::FrontFace::eClockwise,
.depthBiasEnable = vk::False,
.lineWidth = 1.0F,
};
vk::PipelineMultisampleStateCreateInfo multisampling {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = vk::False,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachment {
.blendEnable = vk::False,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlending {
.logicOpEnable = vk::False,
.logicOp = vk::LogicOp::eCopy,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachment,
.blendConstants = std::array<float, 4> { 0.0F, 0.0F, 0.0F, 0.0F },
};
std::vector<vk::DynamicState> dynamicStates = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
vk::PipelineDynamicStateCreateInfo dynamicState {
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineLayoutCreateInfo pipelineLayoutInfo {
.setLayoutCount = 0,
.pushConstantRangeCount = 0,
};
mPipelineLayout = mDevice->createPipelineLayoutUnique(pipelineLayoutInfo);
vk::GraphicsPipelineCreateInfo pipelineInfo {
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputInfo,
.pInputAssemblyState = &inputAssembly,
.pViewportState = &viewportState,
.pRasterizationState = &rasterizer,
.pMultisampleState = &multisampling,
.pColorBlendState = &colorBlending,
.pDynamicState = &dynamicState,
.layout = mPipelineLayout.get(),
.renderPass = mRenderPass.get(),
.subpass = 0,
};
mGraphicsPipeline = mDevice->createGraphicsPipelineUnique(nullptr, pipelineInfo).value;
}
fn createShaderModule(const std::vector<char>& code) -> vk::UniqueShaderModule {
vk::ShaderModuleCreateInfo createInfo { .codeSize = code.size(),
.pCode = std::bit_cast<const u32*>(code.data()) };
return mDevice->createShaderModuleUnique(createInfo);
}
static fn chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats
) -> vk::SurfaceFormatKHR {
for (const auto& availableFormat : availableFormats)

BIN
src/shaders/frag.spv Normal file

Binary file not shown.

9
src/shaders/shader.frag Normal file
View file

@ -0,0 +1,9 @@
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}

20
src/shaders/shader.vert Normal file
View file

@ -0,0 +1,20 @@
#version 450
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}

7
src/shaders/shaderc Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env sh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR" || exit
glslc -c ./shader.vert -o ./vert.spv
glslc -c ./shader.frag -o ./frag.spv

BIN
src/shaders/vert.spv Normal file

Binary file not shown.