Program Listing for File pipelineStorage.cpp

Return to documentation for file (PrismEngine/src/pipelineStorage.cpp)

#include "pipelineStorage.h"
#include "shaderStagesLoader.h"

void prism::PGC::L1::PipelineStorage::createImpl() {
    shaderStagesLoader = new PGC::L2::ShaderStagesLoader(context, settings);
    createPipeline(&context->graphicsPipeline, settings->defaultPipeline);
}

VkPipeline prism::PGC::L1::PipelineStorage::add(utils::PipelineSettings pipelineSettings) {
    size_t pipelineSettingsHash = pipelineSettings.getHash();
    if (pipelines.count(pipelineSettingsHash)) { return pipelines[pipelineSettingsHash]; }
    pipelines[pipelineSettingsHash] = VkPipeline{};
    createPipeline(&pipelines[pipelineSettingsHash], pipelineSettings);

    return pipelines[pipelineSettingsHash];
}

void prism::PGC::L1::PipelineStorage::remove(VkPipeline pipeline)
{
    size_t delKey = -1;
    for (const auto& pair : pipelines) {
        if (pair.second == pipeline) {
            delKey = pair.first;
        }
    }

    if (delKey != -1) {
        vkDestroyPipeline(context->device, pipeline, nullptr);
        pipelines.erase(delKey);
    }
}

void prism::PGC::L1::PipelineStorage::cleanupImpl()
{
    for (const auto& pair : pipelines)
    {
        vkDestroyPipeline(context->device, pair.second, nullptr);
    }
    vkDestroyPipelineLayout(context->device, context->pipelineLayout, nullptr);

    pipelines.clear();

    delete shaderStagesLoader;
}

void prism::PGC::L1::PipelineStorage::createPipeline(VkPipeline* graphicsPipeline, utils::PipelineSettings pipelineSettings) {
    std::array<VkPipelineShaderStageCreateInfo, 2> stageArray = shaderStagesLoader->load(pipelineSettings);
    VkPipelineShaderStageCreateInfo shaderStages[] = { stageArray[0], stageArray[1] };

    VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
    vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;

    auto bindingDescription = Vertex::getBindingDescription();
    auto attributeDescriptions = Vertex::getAttributeDescriptions();

    vertexInputInfo.vertexBindingDescriptionCount = 1;
    vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
    vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
    vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();

    VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
    inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
    inputAssembly.topology = pipelineSettings.inputAssembly.topology;
    inputAssembly.primitiveRestartEnable = pipelineSettings.inputAssembly.primitiveRestartEnable;

    VkPipelineViewportStateCreateInfo viewportState{};
    viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
    viewportState.viewportCount = pipelineSettings.viewportState.viewportCount;
    viewportState.scissorCount = pipelineSettings.viewportState.scissorCount;

    VkPipelineRasterizationStateCreateInfo rasterizer{};
    rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
    rasterizer.depthClampEnable = pipelineSettings.rasterization.depthClampEnable;
    rasterizer.rasterizerDiscardEnable = pipelineSettings.rasterization.rasterizerDiscardEnable;
    rasterizer.polygonMode = pipelineSettings.rasterization.polygonMode; //VK_POLYGON_MODE_LINE;
    rasterizer.lineWidth = pipelineSettings.rasterization.lineWidth;
    rasterizer.cullMode = pipelineSettings.rasterization.cullMode;
    rasterizer.frontFace = pipelineSettings.rasterization.frontFace;
    rasterizer.depthBiasEnable = pipelineSettings.rasterization.depthBiasEnable;

    VkPipelineDepthStencilStateCreateInfo depthStencil{};
    depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
    depthStencil.depthTestEnable = pipelineSettings.depthStencil.depthTestEnable;
    depthStencil.depthWriteEnable = pipelineSettings.depthStencil.depthWriteEnable;
    depthStencil.depthCompareOp = pipelineSettings.depthStencil.depthCompareOp;
    depthStencil.depthBoundsTestEnable = pipelineSettings.depthStencil.depthBoundsTestEnable;
    depthStencil.minDepthBounds = pipelineSettings.depthStencil.minDepthBounds; // Optional
    depthStencil.maxDepthBounds = pipelineSettings.depthStencil.maxDepthBounds; // Optional
    depthStencil.stencilTestEnable = pipelineSettings.depthStencil.stencilTestEnable;
    depthStencil.front = pipelineSettings.depthStencil.front; // Optional
    depthStencil.back = pipelineSettings.depthStencil.back; // Optional

    VkPipelineMultisampleStateCreateInfo multisampling{};
    multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
    multisampling.sampleShadingEnable = pipelineSettings.multisample.sampleShadingEnable; // I_P
    multisampling.rasterizationSamples = context->msaaSamples;

    VkPipelineColorBlendStateCreateInfo colorBlending{};
    colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
    colorBlending.logicOpEnable = pipelineSettings.colorBlend.logicOpEnable;
    colorBlending.logicOp = pipelineSettings.colorBlend.logicOp;
    colorBlending.attachmentCount = pipelineSettings.colorBlend.attachments.size();
    colorBlending.pAttachments = pipelineSettings.colorBlend.attachments.data();
    colorBlending.blendConstants[0] = pipelineSettings.colorBlend.blendConstants[0];
    colorBlending.blendConstants[1] = pipelineSettings.colorBlend.blendConstants[1];
    colorBlending.blendConstants[2] = pipelineSettings.colorBlend.blendConstants[2];
    colorBlending.blendConstants[3] = pipelineSettings.colorBlend.blendConstants[3];

    VkPipelineDynamicStateCreateInfo dynamicState{};
    dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
    dynamicState.dynamicStateCount = static_cast<uint32_t>(pipelineSettings.dynamicState.dynamicStates.size());
    dynamicState.pDynamicStates = pipelineSettings.dynamicState.dynamicStates.data();

    std::vector<VkDescriptorSetLayout> setLayouts = { context->descriptorSetLayout, context->textureDescriptorSetLayout };

    VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
    pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(setLayouts.size());
    pipelineLayoutInfo.pSetLayouts = setLayouts.data();
    pipelineLayoutInfo.pushConstantRangeCount = 0;
    pipelineLayoutInfo.pPushConstantRanges = nullptr;
    if (vkCreatePipelineLayout(context->device, &pipelineLayoutInfo, nullptr, &context->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.pColorBlendState = &colorBlending;
    pipelineInfo.pDynamicState = &dynamicState;
    pipelineInfo.layout = context->pipelineLayout;
    pipelineInfo.renderPass = context->renderPass;
    pipelineInfo.subpass = 0;
    pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
    pipelineInfo.pDepthStencilState = &depthStencil;

    if (vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, graphicsPipeline) != VK_SUCCESS) {
        throw std::runtime_error("failed to create graphics pipeline!");
    }

    vkDestroyShaderModule(context->device, stageArray[0].module, nullptr);
    vkDestroyShaderModule(context->device, stageArray[1].module, nullptr);
}