Add file structure to code

- Rename project to CopiumEngine
This commit is contained in:
Thraix
2023-02-07 21:43:47 +01:00
parent ef4eb7dd2f
commit 827572eada
494 changed files with 205 additions and 195 deletions
@@ -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);
};
}
+133
View File
@@ -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;
}
}
+38
View File
@@ -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);
};
}