147 lines
5.4 KiB
C++
147 lines
5.4 KiB
C++
/*
|
|
* Little Vulkan Engine Pipeline class
|
|
*
|
|
* Copyright (C) 2020 by Blurrypiano - https://github.com/blurrypiano/littleVulkanEngine
|
|
*
|
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
|
*/
|
|
|
|
#include "lve_pipeline.hpp"
|
|
|
|
#include "lve_initializers.hpp"
|
|
|
|
// std
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
|
|
namespace lve {
|
|
|
|
LvePipeline::LvePipeline(std::string filePrefix, LveDevice& device, LveSwapChain& swapChain)
|
|
: device_{device}, filePrefix_{filePrefix}, swapChain_{swapChain} {
|
|
createGraphicsPipeline();
|
|
}
|
|
|
|
LvePipeline::~LvePipeline() {
|
|
vkDestroyPipeline(device_.device(), graphicsPipeline_, nullptr);
|
|
vkDestroyPipelineLayout(device_.device(), pipelineLayout_, nullptr);
|
|
}
|
|
|
|
void LvePipeline::bind(VkCommandBuffer commandBuffer) {
|
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline_);
|
|
}
|
|
|
|
std::vector<char> LvePipeline::readFile(const std::string& filename) {
|
|
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
|
|
|
if (!file.is_open()) {
|
|
throw std::runtime_error("failed to open file!");
|
|
}
|
|
|
|
size_t fileSize = (size_t)file.tellg();
|
|
std::vector<char> buffer(fileSize);
|
|
|
|
file.seekg(0);
|
|
file.read(buffer.data(), fileSize);
|
|
|
|
file.close();
|
|
|
|
return buffer;
|
|
}
|
|
|
|
void LvePipeline::createGraphicsPipeline() {
|
|
auto vertCode = readFile(filePrefix_ + ".vert.spv");
|
|
auto fragCode = readFile(filePrefix_ + ".frag.spv");
|
|
|
|
VkShaderModule vertShaderModule = createShaderModule(vertCode);
|
|
VkShaderModule fragShaderModule = createShaderModule(fragCode);
|
|
auto vertShaderStageInfo =
|
|
initializers::shaderStage(vertShaderModule, VK_SHADER_STAGE_VERTEX_BIT);
|
|
auto fragShaderStageInfo =
|
|
initializers::shaderStage(fragShaderModule, VK_SHADER_STAGE_FRAGMENT_BIT);
|
|
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
vertexInputInfo.vertexBindingDescriptionCount = 0;
|
|
vertexInputInfo.pVertexBindingDescriptions = nullptr; // Optional
|
|
vertexInputInfo.vertexAttributeDescriptionCount = 0;
|
|
vertexInputInfo.pVertexAttributeDescriptions = nullptr; // Optional
|
|
|
|
auto inputAssembly = initializers::inputAssemblyState();
|
|
VkExtent2D swapChainExtent = swapChain_.getSwapChainExtent();
|
|
VkViewport viewport =
|
|
{0.0f, 0.0f, (float)swapChainExtent.width, (float)swapChainExtent.height, 0.0f, 1.0f};
|
|
VkRect2D scissor = {{0, 0}, swapChainExtent};
|
|
auto viewportState = initializers::viewportState(viewport, scissor);
|
|
auto rasterizer = initializers::rasterizationState();
|
|
auto multisampling = initializers::multisampleState();
|
|
auto colorBlendAttachment = initializers::colorBlendAttachmentState();
|
|
auto colorBlending = initializers::colorBlendingState(colorBlendAttachment);
|
|
auto depthStencil = initializers::depthStencilState();
|
|
|
|
// pipeline layout is used passing uniform information
|
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
pipelineLayoutInfo.setLayoutCount = 0; // Optional
|
|
pipelineLayoutInfo.pSetLayouts = nullptr; // Optional
|
|
pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
|
|
pipelineLayoutInfo.pPushConstantRanges = nullptr; // Optional
|
|
|
|
if (vkCreatePipelineLayout(device_.device(), &pipelineLayoutInfo, nullptr, &pipelineLayout_) !=
|
|
VK_SUCCESS) {
|
|
throw std::runtime_error("failed to create pipeline layout!");
|
|
}
|
|
|
|
VkGraphicsPipelineCreateInfo pipelineInfo = {};
|
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
pipelineInfo.stageCount = 2;
|
|
pipelineInfo.pStages = shaderStages;
|
|
|
|
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
|
pipelineInfo.pInputAssemblyState = &inputAssembly;
|
|
pipelineInfo.pViewportState = &viewportState;
|
|
pipelineInfo.pRasterizationState = &rasterizer;
|
|
pipelineInfo.pMultisampleState = &multisampling;
|
|
pipelineInfo.pDepthStencilState = nullptr; // Optional
|
|
pipelineInfo.pColorBlendState = &colorBlending;
|
|
pipelineInfo.pDynamicState = nullptr; // Optional
|
|
pipelineInfo.pDepthStencilState = &depthStencil;
|
|
|
|
pipelineInfo.layout = pipelineLayout_;
|
|
pipelineInfo.renderPass = swapChain_.getRenderPass();
|
|
pipelineInfo.subpass = 0;
|
|
|
|
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
|
|
pipelineInfo.basePipelineIndex = -1; // Optional
|
|
|
|
if (vkCreateGraphicsPipelines(
|
|
device_.device(),
|
|
VK_NULL_HANDLE,
|
|
1,
|
|
&pipelineInfo,
|
|
nullptr,
|
|
&graphicsPipeline_) != VK_SUCCESS) {
|
|
throw std::runtime_error("failed to create graphics pipeline!");
|
|
}
|
|
|
|
vkDestroyShaderModule(device_.device(), fragShaderModule, nullptr);
|
|
vkDestroyShaderModule(device_.device(), vertShaderModule, nullptr);
|
|
}
|
|
|
|
VkShaderModule LvePipeline::createShaderModule(const std::vector<char>& code) {
|
|
VkShaderModuleCreateInfo createInfo = {};
|
|
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
createInfo.codeSize = code.size();
|
|
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
|
|
|
|
VkShaderModule shaderModule;
|
|
if (vkCreateShaderModule(device_.device(), &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
|
|
throw std::runtime_error("failed to create shader module!");
|
|
}
|
|
return shaderModule;
|
|
}
|
|
|
|
} // namespace lve
|