Trivial Pipeline object.

This commit is contained in:
Anish Bhobe 2024-07-01 19:53:06 +02:00
parent eaf4556bad
commit 5744e7a13c
4 changed files with 218 additions and 158 deletions

View File

@ -19,7 +19,8 @@ set(HEADER_FILES
window.h window.h
physical_device.h physical_device.h
device.h device.h
swapchain.h) swapchain.h
"pipeline.h")
set(SOURCE_FILES set(SOURCE_FILES
logger.cpp logger.cpp
@ -28,7 +29,8 @@ set(SOURCE_FILES
window.cpp window.cpp
physical_device.cpp physical_device.cpp
device.cpp device.cpp
swapchain.cpp) swapchain.cpp
pipeline.cpp)
add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES}) add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20) set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)

21
aster/pipeline.cpp Normal file
View File

@ -0,0 +1,21 @@
// =============================================
// Aster: pipeline.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "pipeline.h"
#include "device.h"
Pipeline::Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline)
: m_Device(device)
, m_Layout(layout)
, m_Pipeline(pipeline)
{
}
Pipeline::~Pipeline()
{
m_Device->m_Device.destroy(m_Pipeline, nullptr);
m_Device->m_Device.destroy(m_Layout, nullptr);
}

20
aster/pipeline.h Normal file
View File

@ -0,0 +1,20 @@
// =============================================
// Aster: pipeline.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "global.h"
struct Device;
struct Pipeline
{
const Device *m_Device;
vk::PipelineLayout m_Layout;
vk::Pipeline m_Pipeline;
Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline);
~Pipeline();
};

View File

@ -6,6 +6,7 @@
#include "aster/window.h" #include "aster/window.h"
#include "aster/global.h" #include "aster/global.h"
#include "aster/pipeline.h"
#include "aster/swapchain.h" #include "aster/swapchain.h"
#include <EASTL/array.h> #include <EASTL/array.h>
@ -39,10 +40,13 @@ struct Shader
vk::ShaderStageFlags m_Stage; vk::ShaderStageFlags m_Stage;
}; };
Pipeline
CreatePipeline(const Device *device, const Swapchain *swapchain, cstr vertexShaderFile, cstr fragmentShaderFile);
int int
main(int, char **) main(int, char **)
{ {
MIN_LOG_LEVEL(Logger::LogType::eVerbose); MIN_LOG_LEVEL(Logger::LogType::eInfo);
GlfwContext glfwContext = {}; GlfwContext glfwContext = {};
Context context = {"Aster", VERSION}; Context context = {"Aster", VERSION};
@ -61,125 +65,12 @@ main(int, char **)
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&window, &device, "Primary Chain"};
auto vertexShaderModule = CreateShader(&device, "shader/triangle.vs.hlsl.spv"); auto vertexShaderFile = "shader/triangle.vs.hlsl.spv";
auto fragmentShaderModule = CreateShader(&device, "shader/white.frag.glsl.spv"); auto fragmentShaderFile = "shader/white.frag.glsl.spv";
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{ Pipeline pipeline = CreatePipeline(&device, &swapchain, vertexShaderFile, fragmentShaderFile);
{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertexShaderModule,
.pName = "main",
},
{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragmentShaderModule,
.pName = "main",
},
}};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = 0,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
vk::PipelineLayout pipelineLayout;
vk::Result result = device.m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result);
device.SetName(pipelineLayout, "Triangle Layout");
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
.vertexBindingDescriptionCount = 0,
.pVertexBindingDescriptions = nullptr,
.vertexAttributeDescriptionCount = 0,
.pVertexAttributeDescriptions = nullptr,
};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = vk::False,
};
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
.depthClampEnable = vk::False,
.rasterizerDiscardEnable = vk::False,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = vk::False,
.lineWidth = 1.0,
};
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = vk::False,
};
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
.depthTestEnable = vk::False,
.depthWriteEnable = vk::False,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
.blendEnable = vk::False,
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
.logicOpEnable = vk::False,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachmentState,
};
eastl::array dynamicStates = {
vk::DynamicState::eScissor,
vk::DynamicState::eViewport,
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &swapchain.m_Format,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportStateCreateInfo,
.pRasterizationState = &rasterizationStateCreateInfo,
.pMultisampleState = &multisampleStateCreateInfo,
.pDepthStencilState = &depthStencilStateCreateInfo,
.pColorBlendState = &colorBlendStateCreateInfo,
.pDynamicState = &dynamicStateCreateInfo,
.layout = pipelineLayout,
};
vk::Pipeline pipeline;
result = device.m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline);
ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result) THEN_ABORT(result);
device.SetName(pipelineLayout, "Triangle Pipeline");
// Frames
eastl::fixed_vector<Frame, MAX_FRAMES_IN_FLIGHT> frames;
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
frames.emplace_back(&device, queueAllocation.m_Family, i);
}
// Persistent variables
vk::Viewport viewport = { vk::Viewport viewport = {
.x = 0, .x = 0,
.y = Cast<f32>(swapchain.m_Extent.height), .y = Cast<f32>(swapchain.m_Extent.height),
@ -194,12 +85,48 @@ main(int, char **)
.extent = swapchain.m_Extent, .extent = swapchain.m_Extent,
}; };
vk::ImageMemoryBarrier topOfThePipeBarrier = {
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
vk::ImageMemoryBarrier renderToPresentBarrier = {
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
.newLayout = vk::ImageLayout::ePresentSrcKHR,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
// Frames
eastl::fixed_vector<Frame, MAX_FRAMES_IN_FLIGHT> frames;
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
frames.emplace_back(&device, queueAllocation.m_Family, i);
}
u32 frameIndex = 0; u32 frameIndex = 0;
while (window.Poll()) while (window.Poll())
{ {
Frame *currentFrame = &frames[frameIndex]; Frame *currentFrame = &frames[frameIndex];
result = device.m_Device.waitForFences(1, &currentFrame->m_FrameAvailableFence, vk::True, MaxValue<u64>); auto result = device.m_Device.waitForFences(1, &currentFrame->m_FrameAvailableFence, vk::True, MaxValue<u64>);
ERROR_IF(Failed(result), "Waiting for fence {} failed. Cause: {}", frameIndex, result) ERROR_IF(Failed(result), "Waiting for fence {} failed. Cause: {}", frameIndex, result)
THEN_ABORT(result); THEN_ABORT(result);
@ -237,36 +164,8 @@ main(int, char **)
vk::Image currentImage = swapchain.m_Images[imageIndex]; vk::Image currentImage = swapchain.m_Images[imageIndex];
vk::CommandBuffer cmd = currentFrame->AllocateCommandBuffer(); vk::CommandBuffer cmd = currentFrame->AllocateCommandBuffer();
vk::ImageMemoryBarrier topOfThePipeBarrier = { topOfThePipeBarrier.image = currentImage;
.oldLayout = vk::ImageLayout::eUndefined, renderToPresentBarrier.image = currentImage;
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.image = currentImage,
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
vk::ImageMemoryBarrier renderToPresentBarrier = {
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
.newLayout = vk::ImageLayout::ePresentSrcKHR,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.image = currentImage,
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit}; vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
result = cmd.begin(&beginInfo); result = cmd.begin(&beginInfo);
@ -297,7 +196,7 @@ main(int, char **)
cmd.setViewport(0, 1, &viewport); cmd.setViewport(0, 1, &viewport);
cmd.setScissor(0, 1, &scissor); cmd.setScissor(0, 1, &scissor);
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
cmd.draw(3, 1, 0, 0); cmd.draw(3, 1, 0, 0);
cmd.endRendering(); cmd.endRendering();
@ -353,14 +252,9 @@ main(int, char **)
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
} }
result = device.m_Device.waitIdle(); auto result = device.m_Device.waitIdle();
ERROR_IF(Failed(result), "Wait idle failed. Cause: {}", result); ERROR_IF(Failed(result), "Wait idle failed. Cause: {}", result);
device.m_Device.destroy(pipeline, nullptr);
device.m_Device.destroy(pipelineLayout, nullptr);
device.m_Device.destroy(vertexShaderModule, nullptr);
device.m_Device.destroy(fragmentShaderModule, nullptr);
return 0; return 0;
} }
@ -399,6 +293,7 @@ FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
ERROR("No suitable queue family on the GPU.") ERROR("No suitable queue family on the GPU.")
THEN_ABORT(vk::Result::eErrorUnknown); THEN_ABORT(vk::Result::eErrorUnknown);
} }
eastl::optional<eastl::vector<u32>> eastl::optional<eastl::vector<u32>>
ReadFile(cstr fileName) ReadFile(cstr fileName)
{ {
@ -467,6 +362,128 @@ Frame::AllocateCommandBuffer() const
return commandBuffer; return commandBuffer;
} }
Pipeline
CreatePipeline(const Device *device, const Swapchain *swapchain, cstr vertexShaderFile, cstr fragmentShaderFile)
{
// Pipeline Setup
auto vertexShaderModule = CreateShader(device, vertexShaderFile);
auto fragmentShaderModule = CreateShader(device, fragmentShaderFile);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertexShaderModule,
.pName = "main",
},
{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragmentShaderModule,
.pName = "main",
},
}};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = 0,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
vk::PipelineLayout pipelineLayout;
vk::Result result = device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result);
device->SetName(pipelineLayout, "Triangle Layout");
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
.vertexBindingDescriptionCount = 0,
.pVertexBindingDescriptions = nullptr,
.vertexAttributeDescriptionCount = 0,
.pVertexAttributeDescriptions = nullptr,
};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = vk::False,
};
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
.depthClampEnable = vk::False,
.rasterizerDiscardEnable = vk::False,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = vk::False,
.lineWidth = 1.0,
};
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = vk::False,
};
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
.depthTestEnable = vk::False,
.depthWriteEnable = vk::False,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
.blendEnable = vk::False,
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
.logicOpEnable = vk::False,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachmentState,
};
eastl::array dynamicStates = {
vk::DynamicState::eScissor,
vk::DynamicState::eViewport,
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &swapchain->m_Format,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportStateCreateInfo,
.pRasterizationState = &rasterizationStateCreateInfo,
.pMultisampleState = &multisampleStateCreateInfo,
.pDepthStencilState = &depthStencilStateCreateInfo,
.pColorBlendState = &colorBlendStateCreateInfo,
.pDynamicState = &dynamicStateCreateInfo,
.layout = pipelineLayout,
};
vk::Pipeline pipeline;
result = device->m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline);
ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result)
THEN_ABORT(result);
device->SetName(pipeline, "Triangle Pipeline");
device->m_Device.destroy(vertexShaderModule, nullptr);
device->m_Device.destroy(fragmentShaderModule, nullptr);
return {device, pipelineLayout, pipeline};
}
vk::ShaderModule vk::ShaderModule
CreateShader(const Device *device, cstr shaderFile) CreateShader(const Device *device, cstr shaderFile)