#include <stdafx.h> #include "Pipeline.h" #include "Context.h" #include "Device.h" #include "RenderGraph.h" #include "Vertex.h" #include "IO.h" #include "SwapChain.h" #define FRAGMENT_SHADER_PATH "Shaders/FragmentShader.spv" #define VERTEX_SHADER_PATH "Shaders/VertexShader.spv" #define DEPTH_SHADER_PATH "Shaders/EarlyZ.spv" #define COMPUTE_SHADER_PATH "Shaders/LightComputeShader.spv" namespace fpr { PipelineOptions Pipeline::GetDefaultGraphicsPipeline() { PipelineOptions options; auto& context = fpr::Context::Get(); auto vertex_shader = fpr::ReadFile(VERTEX_SHADER_PATH); auto fragment_shader = fpr::ReadFile(FRAGMENT_SHADER_PATH); vk::ShaderModule vertex_shader_module = CreateShaderModule(vertex_shader); vk::ShaderModule fragment_shader_module = CreateShaderModule(fragment_shader); options.modules = { { vertex_shader_module, vk::ShaderStageFlagBits::eVertex }, { fragment_shader_module, vk::ShaderStageFlagBits::eFragment } }; vk::PipelineInputAssemblyStateCreateInfo input_assembly_create_info; input_assembly_create_info.topology = vk::PrimitiveTopology::eTriangleList; input_assembly_create_info.primitiveRestartEnable = false; vk::PushConstantRange push_constant_range; push_constant_range.stageFlags = vk::ShaderStageFlagBits::eFragment; push_constant_range.offset = 0; push_constant_range.size = sizeof(ViewportConstants); options.push_constant_ranges.push_back(push_constant_range); vk::PipelineRasterizationStateCreateInfo rasterizer_create_info{}; rasterizer_create_info.depthClampEnable = false; rasterizer_create_info.rasterizerDiscardEnable = false; rasterizer_create_info.polygonMode = vk::PolygonMode::eFill; rasterizer_create_info.lineWidth = 1.0f; rasterizer_create_info.cullMode = vk::CullModeFlagBits::eBack; rasterizer_create_info.frontFace = vk::FrontFace::eCounterClockwise; rasterizer_create_info.depthBiasEnable = false; vk::PipelineMultisampleStateCreateInfo multisample_create_info{}; multisample_create_info.sampleShadingEnable = false; multisample_create_info.rasterizationSamples = vk::SampleCountFlagBits::e1; vk::PipelineColorBlendAttachmentState blend_attach_state{}; blend_attach_state.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA; blend_attach_state.alphaBlendOp = vk::BlendOp::eAdd; std::vector<vk::DescriptorSetLayout> layouts = { context.m_render_graph->DescriptorSetLayouts.Get("Camera"), context.m_render_graph->DescriptorSetLayouts.Get("Model"), context.m_render_graph->DescriptorSetLayouts.Get("Sampler"), context.m_render_graph->DescriptorSetLayouts.Get("PointLight") }; std::vector<vk::DynamicState> dynamic_states = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; vk::PipelineDepthStencilStateCreateInfo depth_stencil_ceate_info{}; depth_stencil_ceate_info.depthTestEnable = true; depth_stencil_ceate_info.depthWriteEnable = false; depth_stencil_ceate_info.depthCompareOp = vk::CompareOp::eLessOrEqual; depth_stencil_ceate_info.depthBoundsTestEnable = false; depth_stencil_ceate_info.stencilTestEnable = false; options.input_assembly = input_assembly_create_info; options.rasterizer = rasterizer_create_info; options.multisample = multisample_create_info; options.blend_attach_states = { blend_attach_state }; options.depth_stencil = depth_stencil_ceate_info; options.layouts = layouts; options.render_pass = context.m_render_graph->RenderPasses.Get("Default")->GetvkRenderPass(); options.dynamic_states = dynamic_states; options.flags = vk::PipelineCreateFlagBits::eAllowDerivatives; return options; } PipelineOptions Pipeline::GetDepthPassPipeline() { PipelineOptions options; auto& context = fpr::Context::Get(); auto early_z_shader = fpr::ReadFile(DEPTH_SHADER_PATH); vk::ShaderModule early_z_module = CreateShaderModule(early_z_shader); options.modules = { { early_z_module, vk::ShaderStageFlagBits::eVertex } }; vk::PipelineInputAssemblyStateCreateInfo input_assembly_create_info; input_assembly_create_info.topology = vk::PrimitiveTopology::eTriangleList; input_assembly_create_info.primitiveRestartEnable = false; vk::PipelineRasterizationStateCreateInfo rasterizer_create_info{}; rasterizer_create_info.depthClampEnable = false; rasterizer_create_info.rasterizerDiscardEnable = false; rasterizer_create_info.polygonMode = vk::PolygonMode::eFill; rasterizer_create_info.lineWidth = 1.0f; rasterizer_create_info.cullMode = vk::CullModeFlagBits::eBack; rasterizer_create_info.frontFace = vk::FrontFace::eCounterClockwise; rasterizer_create_info.depthBiasEnable = false; vk::PipelineMultisampleStateCreateInfo multisample_create_info{}; multisample_create_info.sampleShadingEnable = false; multisample_create_info.rasterizationSamples = vk::SampleCountFlagBits::e1; vk::PipelineColorBlendAttachmentState blend_attach_state{}; blend_attach_state.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA; std::vector<vk::DescriptorSetLayout> layouts = { context.m_render_graph->DescriptorSetLayouts.Get("Camera"), context.m_render_graph->DescriptorSetLayouts.Get("Model") }; vk::PipelineDepthStencilStateCreateInfo depth_stencil_ceate_info{}; depth_stencil_ceate_info.depthTestEnable = true; depth_stencil_ceate_info.depthWriteEnable = true; depth_stencil_ceate_info.depthCompareOp = vk::CompareOp::eLess; depth_stencil_ceate_info.depthBoundsTestEnable = false; depth_stencil_ceate_info.stencilTestEnable = false; std::vector<vk::DynamicState> dynamic_states = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; options.input_assembly = input_assembly_create_info; options.rasterizer = rasterizer_create_info; options.multisample = multisample_create_info; options.blend_attach_states = { blend_attach_state }; options.depth_stencil = depth_stencil_ceate_info; options.layouts = layouts; options.render_pass = context.m_render_graph->RenderPasses.Get("EarlyZ")->GetvkRenderPass(); options.flags = vk::PipelineCreateFlagBits::eDerivative; options.dynamic_states = dynamic_states; return options; } PipelineOptions Pipeline::GetLightCullingPipeline() { auto& context = fpr::Context::Get(); PipelineOptions options; auto compute_shader = fpr::ReadFile(COMPUTE_SHADER_PATH); vk::ShaderModule compute_shader_module = CreateShaderModule(compute_shader); vk::PushConstantRange push_constant_range; push_constant_range.stageFlags = vk::ShaderStageFlagBits::eCompute; push_constant_range.offset = 0; push_constant_range.size = sizeof(ViewportConstants); options.push_constant_ranges.push_back(push_constant_range); options.modules = { { compute_shader_module, vk::ShaderStageFlagBits::eCompute } }; std::vector<vk::DescriptorSetLayout> layouts = { context.m_render_graph->DescriptorSetLayouts.Get("Camera"), context.m_render_graph->DescriptorSetLayouts.Get("PointLight"), context.m_render_graph->DescriptorSetLayouts.Get("Sampler") }; options.layouts = layouts; return options; } Pipeline::Pipeline(const PipelineOptions& options, Pipeline* parent, EPipelineType type) { auto& context = fpr::Context::Get(); vk::PipelineLayoutCreateInfo layout_info; layout_info.setSetLayouts(options.layouts); layout_info.setPushConstantRanges(options.push_constant_ranges); auto [layout_result, layout] = context.GetDevice()->GetLogicalDeviceHandle().createPipelineLayoutUnique(layout_info); assert(layout_result == vk::Result::eSuccess); m_layout = std::move(layout); std::vector<vk::PipelineShaderStageCreateInfo> shader_stages; for(const auto& module : options.modules) { vk::PipelineShaderStageCreateInfo shader_stage; const auto& [shader_module, stage] = module; shader_stage.stage = stage; shader_stage.module = shader_module; shader_stage.pName = "main"; shader_stages.push_back(shader_stage); } m_options = options; vk::PipelineCacheCreateInfo cache_info; auto [cache_result, cache] = context.GetDevice()->GetLogicalDeviceHandle().createPipelineCacheUnique(cache_info); assert(cache_result == vk::Result::eSuccess); m_cache = std::move(cache); switch(type) { case EPipelineType::EPT_Graphics: { vk::GraphicsPipelineCreateInfo create_info; if(parent != nullptr) { m_parent = parent; create_info.setBasePipelineHandle(*m_parent->m_pipeline); } create_info.setFlags(options.flags); auto [vertex_binding_desc, vertex_attr_desc] = Vertex::MakeVertexInputStateData(); vk::PipelineVertexInputStateCreateInfo vertex_input_create_info{}; vertex_input_create_info.vertexBindingDescriptionCount = (uint32_t)vertex_binding_desc.size(); vertex_input_create_info.pVertexBindingDescriptions = vertex_binding_desc.data(); vertex_input_create_info.vertexAttributeDescriptionCount = (uint32_t)vertex_attr_desc.size(); vertex_input_create_info.pVertexAttributeDescriptions = vertex_attr_desc.data(); vk::PipelineColorBlendStateCreateInfo blend_state_create_info{}; blend_state_create_info.setAttachments(options.blend_attach_states); vk::PipelineViewportStateCreateInfo viewport_state_create_info{}; viewport_state_create_info.scissorCount = 1; viewport_state_create_info.viewportCount = 1; vk::PipelineDynamicStateCreateInfo dynamic_state_info; dynamic_state_info.setDynamicStates(options.dynamic_states); create_info.setLayout(*m_layout); create_info.setPColorBlendState(&blend_state_create_info); create_info.setPDepthStencilState(&options.depth_stencil); create_info.setPDynamicState(&dynamic_state_info); create_info.setPInputAssemblyState(&options.input_assembly); create_info.setPMultisampleState(&options.multisample); create_info.setPRasterizationState(&options.rasterizer); create_info.setPVertexInputState(&vertex_input_create_info); create_info.setPViewportState(&viewport_state_create_info); create_info.setRenderPass(options.render_pass); create_info.setStages(shader_stages); create_info.setSubpass(options.subpass); create_info.basePipelineIndex = -1; auto [pipeline_result, pipeline] = context.GetDevice()->GetLogicalDeviceHandle().createGraphicsPipelineUnique(*m_cache, create_info); m_pipeline = std::move(pipeline); break; } case EPipelineType::EPT_Compute: { vk::ComputePipelineCreateInfo create_info{}; create_info.setLayout(*m_layout).setStage(shader_stages[0]); auto [pipeline_result, pipeline] = context.GetDevice()->GetLogicalDeviceHandle().createComputePipelineUnique(*m_cache, create_info); break; } } for(auto& shader : shader_stages) context.GetDevice()->GetLogicalDeviceHandle().destroyShaderModule(shader.module); } vk::Pipeline& Pipeline::GetPipeline() { return m_pipeline.get(); } vk::PipelineLayout& Pipeline::GetLayout() { return m_layout.get(); } vk::ShaderModule CreateShaderModule(const std::vector<char>& shader) { assert(("Shader malformed!", shader.size() % sizeof(uint32_t) == 0)); vk::ShaderModuleCreateInfo shader_create_info{}; shader_create_info.codeSize = shader.size(); shader_create_info.pCode = reinterpret_cast<const uint32_t*>(shader.data()); auto [result_signal, shader_module] = fpr::Context::Get().GetDevice()->GetLogicalDeviceHandle().createShaderModule(shader_create_info); assert(("Shader module creation failed", result_signal == vk::Result::eSuccess)); return shader_module; } } // namespace fpr