FInished graphics pipeline basics
This commit is contained in:
parent
98bd5f7bc2
commit
e0b7e93bd8
|
@ -42,6 +42,7 @@
|
|||
fmt
|
||||
glfw
|
||||
glm
|
||||
shaderc
|
||||
vulkan-extension-layer
|
||||
vulkan-memory-allocator
|
||||
vulkan-utility-libraries
|
||||
|
|
179
src/main.cpp
179
src/main.cpp
|
@ -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
BIN
src/shaders/frag.spv
Normal file
Binary file not shown.
9
src/shaders/shader.frag
Normal file
9
src/shaders/shader.frag
Normal 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
20
src/shaders/shader.vert
Normal 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
7
src/shaders/shaderc
Executable 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
BIN
src/shaders/vert.spv
Normal file
Binary file not shown.
Loading…
Reference in a new issue