Program Listing for File VkScopedPipeline.cpp¶
↰ Return to documentation for file (Source\Azura\RenderSystem\Src\Vulkan\VkScopedPipeline.cpp
)
#include "Vulkan/VkScopedPipeline.h"
#include "Memory/Allocator.h"
#include "Vulkan/VkMacros.h"
#include "Vulkan/VkTypeMapping.h"
namespace Azura {
namespace Vulkan {
VkScopedPipeline::VkScopedPipeline(VkPipeline pipeline)
: m_pipeline(pipeline) {
}
VkPipeline VkScopedPipeline::Real() const {
return m_pipeline;
}
void VkScopedPipeline::CleanUp(VkDevice device) const {
vkDestroyPipeline(device, m_pipeline, nullptr);
}
// TODO(vasumahesh1): Figure out a way to adjust size properly
VkPipelineFactory::VkPipelineFactory(VkDevice device, Memory::Allocator& allocator, Log logger)
: m_device(device),
m_bindingInfo(10, allocator),
m_attributeDescription(10, allocator),
m_stages(10, allocator),
log_VulkanRenderSystem(std::move(logger)) {
}
VkPipelineFactory& VkPipelineFactory::AddBindingDescription(U32 stride, VertexSlot slot, U32 binding) {
VkVertexInputBindingDescription bindingDesc;
const auto rate = ToVkVertexInputRate(slot.m_rate);
VERIFY_OPT(log_VulkanRenderSystem, rate, "Unknown Format");
bindingDesc.binding = binding;
bindingDesc.stride = stride;
bindingDesc.inputRate = rate.value();
m_bindingInfo.PushBack(bindingDesc);
return *this;
}
VkPipelineFactory& VkPipelineFactory::BulkAddAttributeDescription(const VertexSlot& vertexSlot, U32 binding) {
auto bindingInfo = m_bindingMap[binding];
for (const auto& semanticStride : vertexSlot.m_stride) {
const auto format = ToVkFormat(semanticStride.m_format);
LOG_DBG(log_VulkanRenderSystem, LOG_LEVEL, "Binding Vertex Attribute: Binding: %d Location: %d Format: %s", binding, m_currentLocation, ToString(semanticStride.m_format).c_str());
VERIFY_OPT(log_VulkanRenderSystem, format, "Unknown Format");
VkVertexInputAttributeDescription attrDesc;
attrDesc.binding = binding;
attrDesc.location = m_currentLocation;
attrDesc.format = format.value();
attrDesc.offset = bindingInfo.m_offset;
// TODO(vasumahesh1):[FORMATS]: Handle 64bit formats taking 2 locations
m_currentLocation++;
bindingInfo.m_offset += GetFormatSize(semanticStride.m_format);
m_attributeDescription.PushBack(attrDesc);
}
m_bindingMap[binding] = bindingInfo;
return *this;
}
VkPipelineFactory& VkPipelineFactory::SetInputAssemblyStage(PrimitiveTopology topology) {
const auto vkTopology = ToVkPrimitiveTopology(topology);
VERIFY_OPT(log_VulkanRenderSystem, vkTopology, "Unknown Topology");
m_inputAssemblyStage.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
m_inputAssemblyStage.topology = vkTopology.value();
// TODO(vasumahesh1): Might need to expose
m_inputAssemblyStage.primitiveRestartEnable = VK_FALSE;
return *this;
}
VkPipelineFactory& VkPipelineFactory::SetViewportStage(ViewportDimensions viewportDimensions,
const VkScopedSwapChain& swapChain) {
m_viewport.x = viewportDimensions.m_x;
m_viewport.y = viewportDimensions.m_height - viewportDimensions.m_y;
m_viewport.width = viewportDimensions.m_width;
m_viewport.height = -viewportDimensions.m_height; // Flipped
m_viewport.minDepth = viewportDimensions.m_minDepth;
m_viewport.maxDepth = viewportDimensions.m_maxDepth;
// TODO(vasumahesh1): Might need custom scissoring
m_scissors.offset = {0, 0};
m_scissors.extent = swapChain.GetExtent();
// TODO(vasumahesh1): Might need arrays here one day
m_viewportStage.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
m_viewportStage.viewportCount = 1;
m_viewportStage.pViewports = &m_viewport;
m_viewportStage.scissorCount = 1;
m_viewportStage.pScissors = &m_scissors;
return *this;
}
VkPipelineFactory& VkPipelineFactory::SetRasterizerStage(CullMode cullMode, FrontFace faceOrder) {
const auto vkCullMode = ToVkCullModeFlags(cullMode);
VERIFY_OPT(log_VulkanRenderSystem, vkCullMode, "Unknown Cull Mode");
const auto vkFrontFace = ToVkFrontFace(faceOrder);
VERIFY_OPT(log_VulkanRenderSystem, vkFrontFace, "Unknown Face Order");
// TODO(vasumahesh1): Might need to expose some values later on
m_rasterizerStage.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
m_rasterizerStage.depthClampEnable = VK_FALSE;
m_rasterizerStage.rasterizerDiscardEnable = VK_FALSE;
m_rasterizerStage.polygonMode = VK_POLYGON_MODE_FILL;
m_rasterizerStage.lineWidth = 1.0f;
m_rasterizerStage.cullMode = vkCullMode.value();
m_rasterizerStage.frontFace = vkFrontFace.value();
m_rasterizerStage.depthBiasEnable = VK_FALSE;
return *this;
}
// Not Supported Yet
VkPipelineFactory& VkPipelineFactory::SetMultisampleStage() {
m_multisampleStage.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
m_multisampleStage.sampleShadingEnable = VK_FALSE;
m_multisampleStage.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
// TODO(vasumahesh1): Add Support
return *this;
}
VkPipelineFactory& VkPipelineFactory::SetPipelineLayout(VkPipelineLayout layout) {
m_layout = layout;
return *this;
}
VkPipelineFactory& VkPipelineFactory::AddShaderStage(const VkPipelineShaderStageCreateInfo& shaderStageCreateInfo) {
// TODO(vasumahesh1): Emplace?
m_stages.PushBack(shaderStageCreateInfo);
return *this;
}
void VkPipelineFactory::Submit(Containers::Vector<std::reference_wrapper<VkScopedRenderPass>> renderPasses,
Containers::Vector<VkScopedPipeline>& result) const {
result.Reserve(renderPasses.GetSize());
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = m_bindingInfo.GetSize();
vertexInputInfo.pVertexBindingDescriptions = m_bindingInfo.Data();
vertexInputInfo.vertexAttributeDescriptionCount = m_attributeDescription.GetSize();
vertexInputInfo.pVertexAttributeDescriptions = m_attributeDescription.Data();
LOG_DBG(log_VulkanRenderSystem, LOG_LEVEL, "Creating Pipeline");
LOG_DBG(log_VulkanRenderSystem, LOG_LEVEL, "Num Attribute Descriptions: %d", m_attributeDescription.GetSize());
LOG_DBG(log_VulkanRenderSystem, LOG_LEVEL, "Num Binding Info: %d", m_bindingInfo.GetSize());
// TODO(vasumahesh1):[DEPTH-STENCIL]: Expose this via an API
VkPipelineDepthStencilStateCreateInfo depthStencil = {};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; // *
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &m_inputAssemblyStage;
pipelineInfo.pViewportState = &m_viewportStage;
pipelineInfo.pRasterizationState = &m_rasterizerStage;
pipelineInfo.pMultisampleState = &m_multisampleStage;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pDynamicState = nullptr;
pipelineInfo.layout = m_layout;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = -1;
VkPipelineColorBlendStateCreateInfo colorBlendStage{};
colorBlendStage.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
for (const auto& renderPass : renderPasses) {
const auto& colorBlendAttachments = renderPass.get().GetColorBlendAttachments();
colorBlendStage.logicOpEnable = VK_FALSE;
colorBlendStage.attachmentCount = colorBlendAttachments.GetSize();
colorBlendStage.pAttachments = colorBlendAttachments.Data();
pipelineInfo.pColorBlendState = &colorBlendStage;
const auto& stages = renderPass.get().GetShaderStageInfo();
pipelineInfo.stageCount = stages.GetSize();
pipelineInfo.pStages = stages.Data();
pipelineInfo.renderPass = renderPass.get().GetRenderPass();
// Locally assigned Shaders present
if (m_stages.GetSize() > 0) {
pipelineInfo.stageCount = m_stages.GetSize();
pipelineInfo.pStages = m_stages.Data();
}
LOG_DBG(log_VulkanRenderSystem, LOG_LEVEL, "Pipeline Creation: Local Shader Stages: %d", stages.GetSize());
LOG_DBG(log_VulkanRenderSystem, LOG_LEVEL, "Pipeline Creation: Render Pass Shader Stages: %d", stages.GetSize());
VkPipeline pipeline;
VERIFY_VK_OP(log_VulkanRenderSystem, vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&pipeline),
"Failed to create pipeline");
result.PushBack(VkScopedPipeline(pipeline));
}
}
} // namespace Vulkan
} // namespace Azura