Add file structure to code
- Rename project to CopiumEngine
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
#include "copium/pipeline/DescriptorPool.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
DescriptorPool::DescriptorPool(Instance& instance)
|
||||
: instance{instance}
|
||||
{
|
||||
std::vector<VkDescriptorPoolSize> poolSizes{2};
|
||||
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
poolSizes[0].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
|
||||
|
||||
poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
poolSizes[1].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
|
||||
|
||||
VkDescriptorPoolCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
createInfo.poolSizeCount = poolSizes.size();
|
||||
createInfo.pPoolSizes = poolSizes.data();
|
||||
createInfo.maxSets = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight();
|
||||
createInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
|
||||
CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "DescriptorPool : Failed to initialize descriptor pool");
|
||||
}
|
||||
|
||||
DescriptorPool::~DescriptorPool()
|
||||
{
|
||||
vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr);
|
||||
}
|
||||
|
||||
std::vector<VkDescriptorSet> DescriptorPool::AllocateDescriptorSets(VkDescriptorSetLayout descriptorSetLayout)
|
||||
{
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
std::vector<VkDescriptorSetLayout> layouts{static_cast<size_t>(instance.GetMaxFramesInFlight()), descriptorSetLayout};
|
||||
VkDescriptorSetAllocateInfo allocateInfo{};
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocateInfo.descriptorPool = descriptorPool;
|
||||
allocateInfo.descriptorSetCount = instance.GetMaxFramesInFlight();
|
||||
allocateInfo.pSetLayouts = layouts.data();
|
||||
|
||||
descriptorSets.resize(instance.GetMaxFramesInFlight());
|
||||
CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "AllocateDescriptorSets : Failed to allocate descriptor sets");
|
||||
|
||||
return descriptorSets;
|
||||
}
|
||||
|
||||
void DescriptorPool::FreeDescriptorSets(const std::vector<VkDescriptorSet>& descriptorSets)
|
||||
{
|
||||
vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/util/Common.h"
|
||||
#include "copium/core/Instance.h"
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class DescriptorPool final
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorPool);
|
||||
private:
|
||||
Instance& instance;
|
||||
|
||||
VkDescriptorPool descriptorPool;
|
||||
static const int DESCRIPTOR_SET_COUNT = 100;
|
||||
public:
|
||||
DescriptorPool(Instance& instance);
|
||||
~DescriptorPool();
|
||||
|
||||
std::vector<VkDescriptorSet> AllocateDescriptorSets(VkDescriptorSetLayout descriptorSetLayout);
|
||||
void FreeDescriptorSets(const std::vector<VkDescriptorSet>& descriptorSets);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "copium/pipeline/DescriptorSet.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
DescriptorSet::DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout)
|
||||
: instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}
|
||||
{
|
||||
descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout);
|
||||
}
|
||||
|
||||
DescriptorSet::~DescriptorSet()
|
||||
{
|
||||
descriptorPool.FreeDescriptorSets(descriptorSets);
|
||||
}
|
||||
|
||||
void DescriptorSet::AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding)
|
||||
{
|
||||
for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
|
||||
VkDescriptorBufferInfo bufferInfo = uniformBuffer.GetDescriptorBufferInfo(i);
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[i];
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.pBufferInfo = &bufferInfo;
|
||||
descriptorWrite.pImageInfo = nullptr;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorSet::AddSampler(const Sampler& sampler, uint32_t binding)
|
||||
{
|
||||
for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
|
||||
VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo(i);
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[i];
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.pBufferInfo = nullptr;
|
||||
descriptorWrite.pImageInfo = &imageInfo;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorSet::operator VkDescriptorSet() const
|
||||
{
|
||||
return descriptorSets[instance.GetFlightIndex()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/buffer/UniformBuffer.h"
|
||||
#include "copium/pipeline/DescriptorPool.h"
|
||||
#include "copium/sampler/Sampler.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class DescriptorSet final
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet);
|
||||
private:
|
||||
Instance& instance;
|
||||
DescriptorPool& descriptorPool;
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
|
||||
public:
|
||||
DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout);
|
||||
~DescriptorSet();
|
||||
|
||||
void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding);
|
||||
void AddSampler(const Sampler& sampler, uint32_t binding);
|
||||
operator VkDescriptorSet() const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
#include "copium/pipeline/Pipeline.h"
|
||||
|
||||
#include "copium/pipeline/Shader.h"
|
||||
#include "copium/util/FileSystem.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
Pipeline::Pipeline(Instance& instance, PipelineCreator creator)
|
||||
: instance{instance}
|
||||
{
|
||||
InitializeDescriptorSetLayout(creator);
|
||||
InitializePipeline(creator);
|
||||
}
|
||||
|
||||
Pipeline::~Pipeline()
|
||||
{
|
||||
vkDestroyPipeline(instance.GetDevice(), graphicsPipeline, nullptr);
|
||||
vkDestroyPipelineLayout(instance.GetDevice(), pipelineLayout, nullptr);
|
||||
for (auto&& descriptorSetLayout : descriptorSetLayouts)
|
||||
{
|
||||
vkDestroyDescriptorSetLayout(instance.GetDevice(), descriptorSetLayout, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Pipeline::Bind(const CommandBuffer& commandBuffer)
|
||||
{
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
|
||||
}
|
||||
|
||||
void Pipeline::SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet)
|
||||
{
|
||||
CP_ASSERT(setIndex < boundDescriptorSets.size(), "SetDescriptorSet : DescriptorSet index is out of bounds");
|
||||
boundDescriptorSets[setIndex] = descriptorSet;
|
||||
}
|
||||
|
||||
void Pipeline::BindDescriptorSets(const CommandBuffer& commandBuffer)
|
||||
{
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, boundDescriptorSets.size(), boundDescriptorSets.data(), 0, nullptr);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout Pipeline::GetDescriptorSetLayout(uint32_t setIndex) const
|
||||
{
|
||||
return descriptorSetLayouts[setIndex];
|
||||
}
|
||||
|
||||
void Pipeline::InitializeDescriptorSetLayout(const PipelineCreator& creator)
|
||||
{
|
||||
boundDescriptorSets.resize(creator.descriptorSetLayouts.size());
|
||||
descriptorSetLayouts.resize(creator.descriptorSetLayouts.size());
|
||||
int i = 0;
|
||||
for (auto&& bindings : creator.descriptorSetLayouts)
|
||||
{
|
||||
std::vector<VkDescriptorSetLayoutBinding> layoutBindings{bindings.second.size()};
|
||||
int j = 0;
|
||||
for (auto&& binding : bindings.second)
|
||||
{
|
||||
layoutBindings[j].binding = binding.binding;
|
||||
layoutBindings[j].descriptorType = binding.type;
|
||||
layoutBindings[j].descriptorCount = binding.count;
|
||||
layoutBindings[j].stageFlags = binding.flags;
|
||||
layoutBindings[j].pImmutableSamplers = nullptr;
|
||||
j++;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
createInfo.bindingCount = layoutBindings.size();
|
||||
createInfo.pBindings = layoutBindings.data();
|
||||
|
||||
CP_VK_ASSERT(vkCreateDescriptorSetLayout(instance.GetDevice(), &createInfo, nullptr, &descriptorSetLayouts[i++]), "InitializeDescriptorSetLayout : Failed to initialize descriptor set layout");
|
||||
}
|
||||
}
|
||||
|
||||
void Pipeline::InitializePipeline(const PipelineCreator& creator)
|
||||
{
|
||||
Shader shader{instance, Shader::Type::GlslFile, creator.vertexShader, creator.fragmentShader};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo{};
|
||||
vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertexInputCreateInfo.vertexBindingDescriptionCount = creator.vertexDescriptor.GetBindings().size();
|
||||
vertexInputCreateInfo.pVertexBindingDescriptions = creator.vertexDescriptor.GetBindings().data();
|
||||
vertexInputCreateInfo.vertexAttributeDescriptionCount = creator.vertexDescriptor.GetAttributes().size();
|
||||
vertexInputCreateInfo.pVertexAttributeDescriptions = creator.vertexDescriptor.GetAttributes().data();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyCreateInfo{};
|
||||
inputAssemblyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
inputAssemblyCreateInfo.topology = creator.topology;
|
||||
inputAssemblyCreateInfo.primitiveRestartEnable = VK_FALSE;
|
||||
|
||||
VkViewport viewport{};
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = 1;
|
||||
viewport.height = 1;
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
VkRect2D scissor{};
|
||||
scissor.offset = {0, 0};
|
||||
scissor.extent = {1, 1};
|
||||
|
||||
std::vector<VkDynamicState> dynamicStates = {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
};
|
||||
|
||||
VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{};
|
||||
dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamicStateCreateInfo.dynamicStateCount = dynamicStates.size();
|
||||
dynamicStateCreateInfo.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportStateCreateInfo{};
|
||||
viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewportStateCreateInfo.viewportCount = 1;
|
||||
viewportStateCreateInfo.pViewports = &viewport;
|
||||
viewportStateCreateInfo.scissorCount = 1;
|
||||
viewportStateCreateInfo.pScissors = &scissor;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rasterizerCreateInfo{};
|
||||
rasterizerCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rasterizerCreateInfo.depthClampEnable = VK_FALSE;
|
||||
rasterizerCreateInfo.rasterizerDiscardEnable = VK_FALSE;
|
||||
rasterizerCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
rasterizerCreateInfo.lineWidth = 1.0f;
|
||||
rasterizerCreateInfo.cullMode = creator.cullMode;
|
||||
rasterizerCreateInfo.frontFace = creator.frontFace;
|
||||
|
||||
rasterizerCreateInfo.depthBiasEnable = VK_FALSE;
|
||||
rasterizerCreateInfo.depthBiasConstantFactor = 0.0f;
|
||||
rasterizerCreateInfo.depthBiasClamp = 0.0f;
|
||||
rasterizerCreateInfo.depthBiasSlopeFactor = 0.0f;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampleCreateInfo{};
|
||||
multisampleCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampleCreateInfo.sampleShadingEnable = VK_FALSE;
|
||||
multisampleCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
multisampleCreateInfo.minSampleShading = 1.0f;
|
||||
multisampleCreateInfo.pSampleMask = nullptr;
|
||||
multisampleCreateInfo.alphaToCoverageEnable = VK_FALSE;
|
||||
multisampleCreateInfo.alphaToOneEnable = VK_FALSE;
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilCreateInfo{};
|
||||
depthStencilCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
depthStencilCreateInfo.depthTestEnable = VK_TRUE;
|
||||
depthStencilCreateInfo.depthWriteEnable = VK_TRUE;
|
||||
depthStencilCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
|
||||
depthStencilCreateInfo.depthBoundsTestEnable = VK_FALSE;
|
||||
depthStencilCreateInfo.minDepthBounds = 0.0f;
|
||||
depthStencilCreateInfo.maxDepthBounds = 1.0f;
|
||||
depthStencilCreateInfo.stencilTestEnable = VK_FALSE;
|
||||
depthStencilCreateInfo.front = {};
|
||||
depthStencilCreateInfo.back = {};
|
||||
|
||||
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment{}; // TODO: Add to PipelineCreator
|
||||
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
|
||||
VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT |
|
||||
VK_COLOR_COMPONENT_A_BIT;
|
||||
colorBlendAttachment.blendEnable = VK_FALSE;
|
||||
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendCreateInfo{};
|
||||
colorBlendCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
colorBlendCreateInfo.logicOpEnable = VK_FALSE;
|
||||
colorBlendCreateInfo.logicOp = VK_LOGIC_OP_COPY;
|
||||
colorBlendCreateInfo.attachmentCount = 1;
|
||||
colorBlendCreateInfo.pAttachments = &colorBlendAttachment;
|
||||
colorBlendCreateInfo.blendConstants[0] = 0.0f;
|
||||
colorBlendCreateInfo.blendConstants[1] = 0.0f;
|
||||
colorBlendCreateInfo.blendConstants[2] = 0.0f;
|
||||
colorBlendCreateInfo.blendConstants[3] = 0.0f;
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{};
|
||||
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutCreateInfo.setLayoutCount = descriptorSetLayouts.size();
|
||||
pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts.data();
|
||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
|
||||
pipelineLayoutCreateInfo.pPushConstantRanges = nullptr;
|
||||
|
||||
CP_VK_ASSERT(vkCreatePipelineLayout(instance.GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout), "InitializePipeline : Failed to initialize pipeline layout");
|
||||
|
||||
const std::vector<VkPipelineShaderStageCreateInfo>& shaderStages = shader.GetShaderStages();
|
||||
VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo{};
|
||||
graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
graphicsPipelineCreateInfo.stageCount = shaderStages.size();
|
||||
graphicsPipelineCreateInfo.pStages = shaderStages.data();
|
||||
graphicsPipelineCreateInfo.pVertexInputState = &vertexInputCreateInfo;
|
||||
graphicsPipelineCreateInfo.pInputAssemblyState = &inputAssemblyCreateInfo;
|
||||
graphicsPipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
|
||||
graphicsPipelineCreateInfo.pRasterizationState = &rasterizerCreateInfo;
|
||||
graphicsPipelineCreateInfo.pMultisampleState = &multisampleCreateInfo;
|
||||
graphicsPipelineCreateInfo.pDepthStencilState = &depthStencilCreateInfo;
|
||||
graphicsPipelineCreateInfo.pColorBlendState = &colorBlendCreateInfo;
|
||||
graphicsPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
|
||||
graphicsPipelineCreateInfo.layout = pipelineLayout;
|
||||
graphicsPipelineCreateInfo.renderPass = creator.renderPass;
|
||||
graphicsPipelineCreateInfo.subpass = 0;
|
||||
graphicsPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
graphicsPipelineCreateInfo.basePipelineIndex = -1;
|
||||
|
||||
CP_VK_ASSERT(vkCreateGraphicsPipelines(instance.GetDevice(), VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &graphicsPipeline), "InitializePipeline : Failed to initialize graphics pipeline");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/buffer/CommandBuffer.h"
|
||||
#include "copium/core/Instance.h"
|
||||
#include "copium/pipeline/DescriptorSet.h"
|
||||
#include "copium/pipeline/PipelineCreator.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class Pipeline final
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(Pipeline);
|
||||
private:
|
||||
Instance& instance;
|
||||
|
||||
std::vector<VkDescriptorSetLayout> descriptorSetLayouts{};
|
||||
std::vector<VkDescriptorSet> boundDescriptorSets;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkPipeline graphicsPipeline;
|
||||
|
||||
public:
|
||||
Pipeline(Instance& instance, PipelineCreator creator);
|
||||
~Pipeline();
|
||||
void Bind(const CommandBuffer& commandBuffer);
|
||||
void SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet);
|
||||
void BindDescriptorSets(const CommandBuffer& commandBuffer);
|
||||
VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t setIndex) const;
|
||||
|
||||
private:
|
||||
void InitializeDescriptorSetLayout(const PipelineCreator& creator);
|
||||
void InitializePipeline(const PipelineCreator& creator);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "copium/pipeline/PipelineCreator.h"
|
||||
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
PipelineCreator::PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader)
|
||||
: vertexShader{vertexShader},
|
||||
fragmentShader{fragmentShader},
|
||||
renderPass{renderPass}
|
||||
{}
|
||||
|
||||
void PipelineCreator::SetVertexDescriptor(const VertexDescriptor& descriptor)
|
||||
{
|
||||
vertexDescriptor = descriptor;
|
||||
}
|
||||
|
||||
void PipelineCreator::AddDescriptorSetLayoutBinding(uint32_t set, uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stageFlags)
|
||||
{
|
||||
CP_ASSERT(set <= descriptorSetLayouts.size(), "AddDescriptorSetLayoutBinding : Cannot add descriptor set with set number greater than the current set count");
|
||||
descriptorSetLayouts[set].emplace_back(DescriptorSetBinding{binding, type, count, stageFlags});
|
||||
}
|
||||
|
||||
void PipelineCreator::SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology)
|
||||
{
|
||||
topology = primitiveTopology;
|
||||
}
|
||||
|
||||
void PipelineCreator::SetCullMode(VkCullModeFlags flags)
|
||||
{
|
||||
cullMode = flags;
|
||||
}
|
||||
|
||||
void PipelineCreator::SetCullFrontFace(VkFrontFace cullFrontFace)
|
||||
{
|
||||
frontFace = cullFrontFace;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/pipeline/VertexDescriptor.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class PipelineCreator
|
||||
{
|
||||
struct DescriptorSetBinding
|
||||
{
|
||||
uint32_t binding;
|
||||
VkDescriptorType type;
|
||||
uint32_t count;
|
||||
VkShaderStageFlags flags;
|
||||
};
|
||||
friend class Pipeline;
|
||||
private:
|
||||
std::map<uint32_t, std::vector<DescriptorSetBinding>> descriptorSetLayouts{};
|
||||
|
||||
std::string vertexShader;
|
||||
std::string fragmentShader;
|
||||
VertexDescriptor vertexDescriptor{};
|
||||
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
|
||||
public:
|
||||
PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader);
|
||||
|
||||
void SetVertexDescriptor(const VertexDescriptor& descriptor);
|
||||
void AddDescriptorSetLayoutBinding(uint32_t set, uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stageFlags);
|
||||
void SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology);
|
||||
void SetCullMode(VkCullModeFlags flags);
|
||||
void SetCullFrontFace(VkFrontFace cullFrontFace);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "Shader.h"
|
||||
|
||||
#include "copium/util/FileSystem.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
Shader::Shader(Instance& instance, Type type, const std::string& vertexInput, const std::string& fragmentInput)
|
||||
: instance{instance}
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::GlslCode:
|
||||
vertShaderModule = InitializeShaderModuleFromGlslCode(vertexInput, shaderc_vertex_shader);
|
||||
fragShaderModule = InitializeShaderModuleFromGlslCode(fragmentInput, shaderc_fragment_shader);
|
||||
break;
|
||||
case Type::GlslFile:
|
||||
vertShaderModule = InitializeShaderModuleFromGlslFile(vertexInput, shaderc_vertex_shader);
|
||||
fragShaderModule = InitializeShaderModuleFromGlslFile(fragmentInput, shaderc_fragment_shader);
|
||||
break;
|
||||
case Type::SpvCode:
|
||||
vertShaderModule = InitializeShaderModule(vertexInput);
|
||||
fragShaderModule = InitializeShaderModule(fragmentInput);
|
||||
break;
|
||||
case Type::SpvFile:
|
||||
vertShaderModule = InitializeShaderModule(FileSystem::ReadFile(vertexInput));
|
||||
fragShaderModule = InitializeShaderModule(FileSystem::ReadFile(fragmentInput));
|
||||
break;
|
||||
default:
|
||||
CP_ASSERT(false, "Shader : Unreachable switch case %d", (int)type);
|
||||
}
|
||||
|
||||
shaderStages.resize(2);
|
||||
shaderStages[0] = {};
|
||||
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
shaderStages[0].module = vertShaderModule;
|
||||
shaderStages[0].pName = "main";
|
||||
|
||||
shaderStages[1] = {};
|
||||
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
shaderStages[1].module = fragShaderModule;
|
||||
shaderStages[1].pName = "main";
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
vkDestroyShaderModule(instance.GetDevice(), vertShaderModule, nullptr);
|
||||
vkDestroyShaderModule(instance.GetDevice(), fragShaderModule, nullptr);
|
||||
}
|
||||
|
||||
const std::vector<VkPipelineShaderStageCreateInfo> Shader::GetShaderStages() const
|
||||
{
|
||||
return shaderStages;
|
||||
}
|
||||
|
||||
VkShaderModule Shader::InitializeShaderModule(const std::vector<uint32_t>& codeSpv)
|
||||
{
|
||||
return InitializeShaderModule(codeSpv.data(), codeSpv.size() * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
VkShaderModule Shader::InitializeShaderModule(const std::string& codeSpv)
|
||||
{
|
||||
return InitializeShaderModule(reinterpret_cast<const uint32_t*>(codeSpv.data()), codeSpv.size());
|
||||
}
|
||||
|
||||
VkShaderModule Shader::InitializeShaderModule(const std::vector<char>& codeSpv)
|
||||
{
|
||||
return InitializeShaderModule(reinterpret_cast<const uint32_t*>(codeSpv.data()), codeSpv.size());
|
||||
}
|
||||
|
||||
VkShaderModule Shader::InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind type)
|
||||
{
|
||||
std::string spvFilename = ".cache/" + filename + ".spv";
|
||||
try
|
||||
{
|
||||
if (FileSystem::FileExists(spvFilename))
|
||||
{
|
||||
if (FileSystem::DateModified(filename) < FileSystem::DateModified(spvFilename))
|
||||
{
|
||||
CP_DEBUG("InitializeShaderModuleFromGlslFile : Loading cached shader file: %s", filename.c_str());
|
||||
std::vector<char> data = FileSystem::ReadFile(spvFilename);
|
||||
CP_ASSERT(data.size() % 4 == 0, "Spv data size is not a factor of 4");
|
||||
return InitializeShaderModule((const uint32_t*)data.data(), data.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
CP_WARN("InitializeShaderModuleFromGlslFile : Cached shader file is invalid, recreating it");
|
||||
}
|
||||
CP_DEBUG("InitializeShaderModuleFromGlslFile : Compiling shader file: %s", filename.c_str());
|
||||
shaderc::Compiler compiler;
|
||||
shaderc::CompileOptions options;
|
||||
|
||||
options.SetOptimizationLevel(shaderc_optimization_level_size);
|
||||
|
||||
std::vector<char> glslCode = FileSystem::ReadFile(filename);
|
||||
shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(glslCode.data(), glslCode.size(), type, filename.c_str(), options);
|
||||
CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "InitializeShaderModuleFromGlslFile : Failed to compile shader: %s\n%s", filename.c_str(), result.GetErrorMessage().c_str());
|
||||
|
||||
std::vector<uint32_t> data{result.cbegin(), result.cend()};
|
||||
FileSystem::WriteFile(spvFilename, (const char*)data.data(), data.size() * sizeof(uint32_t));
|
||||
return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
VkShaderModule Shader::InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type)
|
||||
{
|
||||
shaderc::Compiler compiler;
|
||||
shaderc::CompileOptions options;
|
||||
|
||||
options.SetOptimizationLevel(shaderc_optimization_level_size);
|
||||
|
||||
shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(code.data(), type, "inline_shader_code", options);
|
||||
CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "InitializeShaderModuleFromGlslCode : Failed to compile inline shader code: %s", result.GetErrorMessage());
|
||||
|
||||
std::vector<uint32_t> data{result.cbegin(), result.cend()};
|
||||
return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
VkShaderModule Shader::InitializeShaderModule(const uint32_t* data, size_t size)
|
||||
{
|
||||
VkShaderModuleCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
createInfo.codeSize = size;
|
||||
createInfo.pCode = data;
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
CP_VK_ASSERT(vkCreateShaderModule(instance.GetDevice(), &createInfo, nullptr, &shaderModule), "InitializeShaderModule : Failed to initialize shader module");
|
||||
|
||||
return shaderModule;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/core/Instance.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <shaderc/shaderc.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class Shader final
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(Shader);
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
GlslFile, GlslCode, SpvFile, SpvCode
|
||||
};
|
||||
|
||||
private:
|
||||
Instance& instance;
|
||||
|
||||
VkShaderModule vertShaderModule;
|
||||
VkShaderModule fragShaderModule;
|
||||
std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
|
||||
public:
|
||||
Shader(Instance& instance, Type type, const std::string& vertexInput, const std::string& fragmentInput);
|
||||
~Shader();
|
||||
|
||||
const std::vector<VkPipelineShaderStageCreateInfo> GetShaderStages() const;
|
||||
private:
|
||||
VkShaderModule InitializeShaderModule(const std::vector<uint32_t>& codeSpv);
|
||||
VkShaderModule InitializeShaderModule(const std::string& codeSpv);
|
||||
VkShaderModule InitializeShaderModule(const std::vector<char>& codeSpv);
|
||||
VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind type);
|
||||
VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type);
|
||||
VkShaderModule InitializeShaderModule(const uint32_t* data, size_t size);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "copium/pipeline/VertexDescriptor.h"
|
||||
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
void VertexDescriptor::AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset, uint32_t size)
|
||||
{
|
||||
CP_ASSERT(binding <= bindings.size(), "AddAttribute : Attribute binding must less than or be equal to the amount of current bindings");
|
||||
|
||||
if (binding == bindings.size())
|
||||
AddLayout(binding, size);
|
||||
|
||||
VkVertexInputAttributeDescription description{};
|
||||
description.binding = binding;
|
||||
description.location = location;
|
||||
description.format = format;
|
||||
description.offset = offset;
|
||||
attributes.emplace_back(description);
|
||||
}
|
||||
|
||||
VkDeviceSize VertexDescriptor::GetVertexSize() const
|
||||
{
|
||||
VkDeviceSize bufferSize = 0;
|
||||
for (auto&& binding : bindings)
|
||||
{
|
||||
bufferSize += binding.stride;
|
||||
}
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
const std::vector<VkVertexInputAttributeDescription>& VertexDescriptor::GetAttributes() const
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
const std::vector<VkVertexInputBindingDescription>& VertexDescriptor::GetBindings() const
|
||||
{
|
||||
return bindings;
|
||||
}
|
||||
|
||||
uint32_t VertexDescriptor::AddLayout(uint32_t binding, uint32_t size)
|
||||
{
|
||||
VkVertexInputBindingDescription description{};
|
||||
description.binding = binding;
|
||||
description.stride = size;
|
||||
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
bindings.emplace_back(description);
|
||||
return description.binding;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class VertexDescriptor
|
||||
{
|
||||
private:
|
||||
uint32_t bindingIndex = 0;
|
||||
std::vector<VkVertexInputBindingDescription> bindings;
|
||||
std::vector<VkVertexInputAttributeDescription> attributes;
|
||||
|
||||
public:
|
||||
void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset, uint32_t size);
|
||||
VkDeviceSize GetVertexSize() const;
|
||||
const std::vector<VkVertexInputAttributeDescription>& GetAttributes() const;
|
||||
const std::vector<VkVertexInputBindingDescription>& GetBindings() const;
|
||||
|
||||
private:
|
||||
uint32_t AddLayout(uint32_t binding, uint32_t size);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user