Refactor UniformBuffers and DescriptorSets
- Refactor UniformBuffers to keep track of the uniforms it contains - Refactor DescriptorSets to initialize UniformsBuffers and keep track of all its bindings - DescriptorSets can now be created from the Pipeline - Add custom DescriptorSets to Renderer
This commit is contained in:
@@ -5,10 +5,22 @@
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
DescriptorSet::DescriptorSet(Vulkan& vulkan, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout)
|
||||
: vulkan{vulkan}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}
|
||||
DescriptorSet::DescriptorSet(Vulkan& vulkan, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout, const std::set<ShaderBinding>& bindings)
|
||||
: vulkan{vulkan}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}, bindings{bindings}
|
||||
{
|
||||
CP_ASSERT(!bindings.empty(), "DescriptorSet : cannot initialize DescriptorSet with empty ShaderBindings");
|
||||
|
||||
descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout);
|
||||
for (auto& binding : bindings)
|
||||
{
|
||||
if (binding.bindingType == BindingType::UniformBuffer)
|
||||
{
|
||||
std::unique_ptr<UniformBuffer> uniformBuffer = std::make_unique<UniformBuffer>(vulkan, binding);
|
||||
SetUniformBuffer(*uniformBuffer, binding.binding);
|
||||
uniformBuffers.emplace(binding.name, std::move(uniformBuffer));
|
||||
}
|
||||
}
|
||||
// TODO: Set default samplers and uniforms?
|
||||
}
|
||||
|
||||
DescriptorSet::~DescriptorSet()
|
||||
@@ -39,17 +51,27 @@ namespace Copium
|
||||
{
|
||||
for (size_t i = 0; i < descriptorSets.size(); ++i)
|
||||
{
|
||||
SetSampler(sampler, binding, i, arrayIndex);
|
||||
VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo(i);
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[i];
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = arrayIndex;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.pBufferInfo = nullptr;
|
||||
descriptorWrite.pImageInfo = &imageInfo;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
vkUpdateDescriptorSets(vulkan.GetDevice(), 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorSet::SetSampler(const Sampler& sampler, uint32_t binding, int index, int arrayIndex)
|
||||
void DescriptorSet::SetSamplerDynamic(const Sampler& sampler, uint32_t binding, int arrayIndex)
|
||||
{
|
||||
CP_ASSERT(index >= 0 && index < descriptorSets.size(), "AddSampler : index is out of range");
|
||||
VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo(index);
|
||||
VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo(vulkan.GetSwapChain().GetFlightIndex());
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[index];
|
||||
descriptorWrite.dstSet = descriptorSets[vulkan.GetSwapChain().GetFlightIndex()];
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = arrayIndex;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
@@ -81,6 +103,18 @@ namespace Copium
|
||||
}
|
||||
}
|
||||
|
||||
UniformBuffer& DescriptorSet::GetUniformBuffer(const std::string& uniformBuffer)
|
||||
{
|
||||
auto it = uniformBuffers.find(uniformBuffer);
|
||||
CP_ASSERT(it != uniformBuffers.end(), "GetUniformBuffer : UniformBuffer not found = %s", uniformBuffer.c_str());
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
uint32_t DescriptorSet::GetSetIndex() const
|
||||
{
|
||||
return bindings.begin()->set;
|
||||
}
|
||||
|
||||
DescriptorSet::operator VkDescriptorSet() const
|
||||
{
|
||||
return descriptorSets[vulkan.GetSwapChain().GetFlightIndex()];
|
||||
|
||||
@@ -2,11 +2,18 @@
|
||||
|
||||
#include "copium/buffer/UniformBuffer.h"
|
||||
#include "copium/pipeline/DescriptorPool.h"
|
||||
#include "copium/pipeline/ShaderBinding.h"
|
||||
#include "copium/pipeline/ShaderReflector.h"
|
||||
#include "copium/sampler/Sampler.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class DescriptorSet final
|
||||
@@ -17,16 +24,21 @@ namespace Copium
|
||||
DescriptorPool& descriptorPool;
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
|
||||
std::set<ShaderBinding> bindings;
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
std::map<std::string, std::unique_ptr<UniformBuffer>> uniformBuffers;
|
||||
|
||||
public:
|
||||
DescriptorSet(Vulkan& vulkan, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout);
|
||||
DescriptorSet(Vulkan& vulkan, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout, const std::set<ShaderBinding>& bindings);
|
||||
~DescriptorSet();
|
||||
|
||||
void SetUniformBuffer(const UniformBuffer& uniformBuffer, uint32_t binding);
|
||||
void SetSampler(const Sampler& sampler, uint32_t binding, int arrayIndex = 0);
|
||||
void SetSampler(const Sampler& sampler, uint32_t binding, int index, int arrayIndex = 0);
|
||||
void SetSamplerDynamic(const Sampler& sampler, uint32_t binding, int arrayIndex = 0);
|
||||
void SetSamplers(const std::vector<const Sampler*>& sampler, uint32_t binding);
|
||||
UniformBuffer& GetUniformBuffer(const std::string& uniformBuffer);
|
||||
uint32_t GetSetIndex() const;
|
||||
|
||||
operator VkDescriptorSet() const;
|
||||
};
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace Copium
|
||||
{
|
||||
Pipeline::Pipeline(Vulkan& vulkan, PipelineCreator creator)
|
||||
: vulkan{vulkan}
|
||||
: vulkan{vulkan}, shaderReflector{creator.shaderReflector}
|
||||
{
|
||||
InitializeDescriptorSetLayout(creator);
|
||||
InitializePipeline(creator);
|
||||
@@ -28,10 +28,10 @@ namespace Copium
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
|
||||
}
|
||||
|
||||
void Pipeline::SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet)
|
||||
void Pipeline::SetDescriptorSet(const DescriptorSet& descriptorSet)
|
||||
{
|
||||
CP_ASSERT(setIndex < boundDescriptorSets.size(), "SetDescriptorSet : DescriptorSet index is out of bounds");
|
||||
boundDescriptorSets[setIndex] = descriptorSet;
|
||||
CP_ASSERT(descriptorSet.GetSetIndex() < boundDescriptorSets.size(), "SetDescriptorSet : DescriptorSet index is out of bounds");
|
||||
boundDescriptorSets[descriptorSet.GetSetIndex()] = descriptorSet;
|
||||
}
|
||||
|
||||
void Pipeline::BindDescriptorSets(const CommandBuffer& commandBuffer)
|
||||
@@ -39,9 +39,17 @@ namespace Copium
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, boundDescriptorSets.size(), boundDescriptorSets.data(), 0, nullptr);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout Pipeline::GetDescriptorSetLayout(uint32_t setIndex) const
|
||||
std::unique_ptr<DescriptorSet> Pipeline::CreateDescriptorSet(DescriptorPool& descriptorPool, int setIndex) const
|
||||
{
|
||||
return descriptorSetLayouts[setIndex];
|
||||
std::set<ShaderBinding> bindings;
|
||||
for (auto& binding : shaderReflector.bindings)
|
||||
{
|
||||
if (binding.set != setIndex)
|
||||
continue;
|
||||
bindings.emplace(binding);
|
||||
}
|
||||
|
||||
return std::make_unique<DescriptorSet>(vulkan, descriptorPool, descriptorSetLayouts[setIndex], bindings);
|
||||
}
|
||||
|
||||
void Pipeline::InitializeDescriptorSetLayout(const PipelineCreator& creator)
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Copium
|
||||
private:
|
||||
Vulkan& vulkan;
|
||||
|
||||
ShaderReflector shaderReflector;
|
||||
std::vector<VkDescriptorSetLayout> descriptorSetLayouts{};
|
||||
std::vector<VkDescriptorSet> boundDescriptorSets;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
@@ -26,9 +27,10 @@ namespace Copium
|
||||
Pipeline(Vulkan& vulkan, PipelineCreator creator);
|
||||
~Pipeline();
|
||||
void Bind(const CommandBuffer& commandBuffer);
|
||||
void SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet);
|
||||
void SetDescriptorSet(const DescriptorSet& descriptorSet);
|
||||
void BindDescriptorSets(const CommandBuffer& commandBuffer);
|
||||
VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t setIndex) const;
|
||||
|
||||
std::unique_ptr<DescriptorSet> CreateDescriptorSet(DescriptorPool& descriptorPool, int setIndex) const;
|
||||
|
||||
private:
|
||||
void InitializeDescriptorSetLayout(const PipelineCreator& creator);
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Copium
|
||||
PipelineCreator::PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader)
|
||||
: vertexShader{vertexShader},
|
||||
fragmentShader{fragmentShader},
|
||||
shaderReflector{vertexShader, fragmentShader},
|
||||
renderPass{renderPass}
|
||||
{
|
||||
AddShaderDescription();
|
||||
@@ -39,8 +40,7 @@ namespace Copium
|
||||
|
||||
void PipelineCreator::AddShaderDescription()
|
||||
{
|
||||
ShaderReflector reflector{vertexShader, fragmentShader};
|
||||
for (auto& binding : reflector.bindings)
|
||||
for (auto& binding : shaderReflector.bindings)
|
||||
{
|
||||
descriptorSetLayouts[binding.set].emplace_back(DescriptorSetBinding{binding.binding, GetDescriptorType(binding.bindingType), binding.arraySize, GetShaderStageFlags(binding.shaderType)});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/pipeline/VertexDescriptor.h"
|
||||
#include "copium/util/ShaderReflector.h"
|
||||
#include "copium/pipeline/ShaderReflector.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@@ -24,6 +24,8 @@ namespace Copium
|
||||
|
||||
std::string vertexShader;
|
||||
std::string fragmentShader;
|
||||
|
||||
ShaderReflector shaderReflector;
|
||||
VertexDescriptor vertexDescriptor{};
|
||||
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
VkCullModeFlags cullMode = VK_CULL_MODE_FRONT_BIT;
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "copium/pipeline/ShaderBinding.h"
|
||||
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
bool ShaderBinding::operator<(const ShaderBinding& rhs) const
|
||||
{
|
||||
if (set != rhs.set)
|
||||
return set < rhs.set;
|
||||
return binding < rhs.binding;
|
||||
}
|
||||
|
||||
uint32_t ShaderBinding::GetUniformOffset(const std::string& uniform) const
|
||||
{
|
||||
// TODO: Caching?
|
||||
uint32_t offset = 0;
|
||||
for (auto& uniformElem : uniforms)
|
||||
{
|
||||
if (uniformElem.second == uniform)
|
||||
return offset;
|
||||
offset += GetUniformTypeOffset(uniformElem.first);
|
||||
}
|
||||
CP_ABORT("GetUniformOffset : Uniform not found=%s", uniform);
|
||||
}
|
||||
|
||||
uint32_t ShaderBinding::GetUniformSize(const std::string& uniform) const
|
||||
{
|
||||
for (auto& uniformElem : uniforms)
|
||||
{
|
||||
if (uniformElem.second == uniform)
|
||||
return GetUniformTypeSize(uniformElem.first);
|
||||
}
|
||||
CP_ABORT("GetUniformSize : Uniform not found=%s", uniform);
|
||||
}
|
||||
|
||||
UniformType ShaderBinding::GetUniformType(const std::string& uniform) const
|
||||
{
|
||||
for (auto& uniformElem : uniforms)
|
||||
{
|
||||
if (uniformElem.second == uniform)
|
||||
return uniformElem.first;
|
||||
}
|
||||
CP_ABORT("GetUniformType : Uniform not found=%s", uniform);
|
||||
}
|
||||
|
||||
uint32_t ShaderBinding::GetUniformBufferSize() const
|
||||
{
|
||||
CP_ASSERT(bindingType == BindingType::UniformBuffer, "GetUniformBufferSize : BindingType is not UniformBuffer");
|
||||
|
||||
uint32_t size = 0;
|
||||
for (auto& uniform : uniforms)
|
||||
{
|
||||
size += GetUniformTypeOffset(uniform.first);
|
||||
}
|
||||
|
||||
// alignas(64)
|
||||
if (size % 64 != 0)
|
||||
size += 64 - (size % 64);
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t ShaderBinding::GetUniformTypeSize(UniformType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case UniformType::Mat3:
|
||||
return 4 * 9; // glm::mat3
|
||||
case UniformType::Mat4:
|
||||
return 4 * 16; // glm::mat4
|
||||
case UniformType::Vec2:
|
||||
return 4 * 2; // glm::vec2
|
||||
case UniformType::Vec3:
|
||||
return 4 * 3; // glm::vec3
|
||||
case UniformType::Vec4:
|
||||
return 4 * 4; // glm::vec4
|
||||
case UniformType::Int:
|
||||
return 4; // int
|
||||
case UniformType::Float:
|
||||
return 4; // float
|
||||
default:
|
||||
CP_ABORT("GetUniformBufferSize : Unhandled switch case");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ShaderBinding::GetUniformTypeOffset(UniformType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case UniformType::Mat3:
|
||||
return 64; // alignas(16) glm::mat3
|
||||
case UniformType::Mat4:
|
||||
return 64; // alignas(16) glm::mat4
|
||||
case UniformType::Vec2:
|
||||
return 16; // alignas(16) glm::vec2
|
||||
case UniformType::Vec3:
|
||||
return 16; // alignas(16) glm::vec2
|
||||
case UniformType::Vec4:
|
||||
return 16; // alignas(16) glm::vec2
|
||||
case UniformType::Int:
|
||||
return 16; // alignas(16) glm::vec2
|
||||
case UniformType::Float:
|
||||
return 16; // alignas(16) glm::vec2
|
||||
default:
|
||||
CP_ABORT("GetUniformBufferSize : Unhandled switch case");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
enum class BindingType
|
||||
{
|
||||
Sampler2D, UniformBuffer
|
||||
};
|
||||
|
||||
enum class ShaderType
|
||||
{
|
||||
Vertex, Fragment
|
||||
};
|
||||
|
||||
enum class UniformType
|
||||
{
|
||||
Mat3, Mat4, Vec2, Vec3, Vec4, Float, Int
|
||||
};
|
||||
|
||||
struct ShaderBinding
|
||||
{
|
||||
std::string name;
|
||||
uint32_t set;
|
||||
uint32_t binding;
|
||||
uint32_t arraySize;
|
||||
BindingType bindingType;
|
||||
ShaderType shaderType;
|
||||
std::vector<std::pair<UniformType, std::string>> uniforms;
|
||||
|
||||
// TODO: Maybe store a cache mapping the std::string to the offset in the uniform buffer?
|
||||
|
||||
bool operator<(const ShaderBinding& rhs) const;
|
||||
|
||||
uint32_t GetUniformOffset (const std::string& uniform) const;
|
||||
uint32_t GetUniformSize(const std::string& uniform) const;
|
||||
UniformType GetUniformType(const std::string& uniform) const;
|
||||
uint32_t GetUniformBufferSize() const;
|
||||
private:
|
||||
uint32_t GetUniformTypeSize(UniformType type) const;
|
||||
uint32_t GetUniformTypeOffset(UniformType type) const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
#include "copium/pipeline/ShaderReflector.h"
|
||||
|
||||
#include "copium/util/FileSystem.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
|
||||
ShaderReflector::ShaderReflector(const std::string& vertexGlslFile, const std::string& fragmentGlslFile)
|
||||
{
|
||||
ParseGlslFile(vertexGlslFile, ShaderType::Vertex);
|
||||
ParseGlslFile(fragmentGlslFile, ShaderType::Fragment);
|
||||
}
|
||||
|
||||
void ShaderReflector::ParseGlslFile(const std::string& glslFile, ShaderType shaderType)
|
||||
{
|
||||
std::string str = FileSystem::ReadFileStr(glslFile);
|
||||
int index = 0;
|
||||
while (index < str.size())
|
||||
{
|
||||
ParseWhitespace(str, index);
|
||||
if (str[index] == '#')
|
||||
{
|
||||
ParseLine(str, index);
|
||||
continue;
|
||||
}
|
||||
if (std::string_view(&str[index], sizeof("layout") - 1) == "layout")
|
||||
{
|
||||
ParseLayout(str, index, shaderType);
|
||||
continue;
|
||||
}
|
||||
ParseLine(str, index);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderReflector::ParseLine(const std::string& str, int& index)
|
||||
{
|
||||
while(str[index] != '\n' && index < str.size()) index++;
|
||||
}
|
||||
|
||||
void ShaderReflector::ParseWhitespace(const std::string& str, int& index)
|
||||
{
|
||||
while ((str[index] == '\n' || str[index] == ' ' || str[index] == '\t' || str[index] == '\r') && index < str.size()) index++;
|
||||
}
|
||||
|
||||
void ShaderReflector::ParseLayout(const std::string& str, int& index, ShaderType shaderType)
|
||||
{
|
||||
// TODO: Make more robust, currently we might get a crash on the string if the glsl file is invalid
|
||||
index += sizeof("layout") - 1;
|
||||
ParseWhitespace(str, index);
|
||||
index++; // "("
|
||||
ParseWhitespace(str, index);
|
||||
if (std::string_view(&str[index], sizeof("set") - 1) != "set")
|
||||
{
|
||||
ParseLine(str, index);
|
||||
return;
|
||||
}
|
||||
ShaderBinding shaderBinding;
|
||||
shaderBinding.shaderType = shaderType;
|
||||
index += sizeof("set") - 1;
|
||||
ParseWhitespace(str, index);
|
||||
index++; // "="
|
||||
ParseWhitespace(str, index);
|
||||
char* end;
|
||||
shaderBinding.set = std::strtol(&str[index], &end, 10);
|
||||
index = end - str.c_str();
|
||||
ParseWhitespace(str, index);
|
||||
index++; // ","
|
||||
ParseWhitespace(str, index);
|
||||
index += sizeof("binding") - 1;
|
||||
ParseWhitespace(str, index);
|
||||
index++; // "="
|
||||
ParseWhitespace(str, index);
|
||||
shaderBinding.binding = std::strtol(&str[index], &end, 10);
|
||||
index = end - str.c_str();
|
||||
ParseWhitespace(str, index);
|
||||
index++; // ")
|
||||
ParseWhitespace(str, index);
|
||||
index += sizeof("uniform") - 1;
|
||||
ParseWhitespace(str, index);
|
||||
|
||||
std::string_view type = ParseWord(str, index);
|
||||
ParseWhitespace(str, index);
|
||||
if (str[index] == '{') ParseUniformBuffer(str, index, shaderBinding);
|
||||
ParseWhitespace(str, index);
|
||||
std::string_view name = ParseWord(str, index);
|
||||
shaderBinding.name = name;
|
||||
ParseWhitespace(str, index);
|
||||
|
||||
if (str[index] == '[')
|
||||
{
|
||||
index++;
|
||||
shaderBinding.arraySize = std::strtol(&str[index], &end, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
shaderBinding.arraySize = 1;
|
||||
}
|
||||
|
||||
ParseLine(str, index);
|
||||
if (type == "sampler2D")
|
||||
shaderBinding.bindingType = BindingType::Sampler2D;
|
||||
else
|
||||
shaderBinding.bindingType = BindingType::UniformBuffer;
|
||||
CP_ASSERT(bindings.emplace(shaderBinding).second, "ParseLayout : multiple layouts with the same binding");
|
||||
}
|
||||
|
||||
std::string_view ShaderReflector::ParseWord(const std::string& str, int& index)
|
||||
{
|
||||
int start = index;
|
||||
while (((str[index] >= 'a' && str[index] < 'z') ||
|
||||
(str[index] >= 'A' && str[index] < 'Z') ||
|
||||
(str[index] >= '0' && str[index] <= '9')) ||
|
||||
str[index] == '_' &&
|
||||
index < str.size()) index++;
|
||||
return std::string_view(&str[start], index - start);
|
||||
}
|
||||
|
||||
void ShaderReflector::ParseUniformBuffer(const std::string& str, int& index, ShaderBinding& binding)
|
||||
{
|
||||
index++;
|
||||
ParseWhitespace(str, index);
|
||||
while (str[index] != '}')
|
||||
{
|
||||
std::string_view type = ParseWord(str, index);
|
||||
ParseWhitespace(str, index);
|
||||
std::string_view name = ParseWord(str, index); // uniform name
|
||||
if (type == "mat3")
|
||||
binding.uniforms.emplace_back(UniformType::Mat3, std::string(name));
|
||||
else if (type == "mat4")
|
||||
binding.uniforms.emplace_back(UniformType::Mat4, std::string(name));
|
||||
else if (type == "vec2")
|
||||
binding.uniforms.emplace_back(UniformType::Vec2, std::string(name));
|
||||
else if (type == "vec3")
|
||||
binding.uniforms.emplace_back(UniformType::Vec3, std::string(name));
|
||||
else if (type == "vec4")
|
||||
binding.uniforms.emplace_back(UniformType::Vec4, std::string(name));
|
||||
else if (type == "float")
|
||||
binding.uniforms.emplace_back(UniformType::Float, std::string(name));
|
||||
else if (type == "int")
|
||||
binding.uniforms.emplace_back(UniformType::Int, std::string(name));
|
||||
else
|
||||
CP_ABORT("Unsupported uniform type=%s", std::string(type).c_str());
|
||||
ParseWhitespace(str, index);
|
||||
index++; // ";"
|
||||
ParseWhitespace(str, index);
|
||||
}
|
||||
if (index < str.size()) index++; // go past "}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/pipeline/ShaderBinding.h"
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class ShaderReflector
|
||||
{
|
||||
public:
|
||||
std::set<ShaderBinding> bindings;
|
||||
public:
|
||||
ShaderReflector(const std::string& vertexGlslFile, const std::string& fragmentGlslFile);
|
||||
|
||||
private:
|
||||
void ParseGlslFile(const std::string& glslFile, ShaderType type);
|
||||
void ParseLine(const std::string& str, int& index);
|
||||
void ParseWhitespace(const std::string& str, int& index);
|
||||
void ParseLayout(const std::string& str, int& index, ShaderType type);
|
||||
std::string_view ParseWord(const std::string& str, int& index);
|
||||
void ParseUniformBuffer(const std::string& str, int& index, ShaderBinding& binding);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user