Skip to content
Snippets Groups Projects
Commit 887c6f2a authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Merge branch '36-shader-program-reflection' into 'develop'

Resolve "Shader Program Reflection"

Closes #36

See merge request !49
parents 84c7c24c 5027e837
No related branches found
No related tags found
1 merge request!49Resolve "Shader Program Reflection"
Pipeline #25630 passed
......@@ -32,7 +32,9 @@ set(vkcv_sources
${vkcv_include}/vkcv/SwapChain.hpp
${vkcv_source}/vkcv/SwapChain.cpp
${vkcv_include}/vkcv/ShaderStage.hpp
${vkcv_include}/vkcv/ShaderProgram.hpp
${vkcv_source}/vkcv/ShaderProgram.cpp
......
#pragma once
#include <vkcv/ShaderProgram.hpp>
#include <vkcv/Handles.hpp>
#include <vulkan/vulkan.hpp>
#include "vkcv/Handles.hpp"
#include "vkcv/ShaderStage.hpp"
namespace vkcv
{
struct DescriptorSet
......@@ -33,11 +35,13 @@ namespace vkcv
struct DescriptorBinding
{
DescriptorBinding(
uint32_t bindingID,
DescriptorType descriptorType,
uint32_t descriptorCount,
ShaderStage shaderStage
) noexcept;
uint32_t bindingID;
DescriptorType descriptorType;
uint32_t descriptorCount;
ShaderStage shaderStage;
......
......@@ -8,23 +8,16 @@
#include <unordered_map>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <filesystem>
#include <vulkan/vulkan.hpp>
#include <spirv_cross.hpp>
#include "vkcv/VertexLayout.hpp"
#include "vkcv/ShaderStage.hpp"
#include "vkcv/DescriptorConfig.hpp"
namespace vkcv {
enum class ShaderStage
{
VERTEX,
TESS_CONTROL,
TESS_EVAL,
GEOMETRY,
FRAGMENT,
COMPUTE
};
struct Shader
{
std::vector<char> shaderCode;
......@@ -60,10 +53,13 @@ namespace vkcv {
const VertexLayout &getVertexLayout() const;
size_t getPushConstantSize() const;
const std::vector<std::vector<DescriptorBinding>> getReflectedDescriptors() const;
private:
std::unordered_map<ShaderStage, Shader> m_Shaders;
VertexLayout m_VertexLayout;
std::vector<std::vector<DescriptorBinding>> m_DescriptorSets;
size_t m_pushConstantSize = 0;
};
}
#pragma once
namespace vkcv {
enum class ShaderStage
{
VERTEX,
TESS_CONTROL,
TESS_EVAL,
GEOMETRY,
FRAGMENT,
COMPUTE
};
}
......@@ -3,6 +3,7 @@
#include <unordered_map>
#include <vector>
#include <iostream>
#include <string>
namespace vkcv{
......@@ -38,10 +39,11 @@ namespace vkcv{
struct VertexInputAttachment{
VertexInputAttachment() = delete;
VertexInputAttachment(uint32_t location, uint32_t binding, VertexFormat format, uint32_t offset) noexcept;
VertexInputAttachment(uint32_t location, uint32_t binding, std::string name, VertexFormat format, uint32_t offset) noexcept;
uint32_t location;
uint32_t binding;
std::string name;
VertexFormat format;
uint32_t offset;
};
......
......@@ -102,13 +102,8 @@ int main(int argc, const char** argv) {
triangleShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/frag.spv"));
triangleShaderProgram.reflectShader(vkcv::ShaderStage::VERTEX);
triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT);
std::vector<vkcv::DescriptorBinding> descriptorBindings = {
vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT) ,
vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT) };
std::vector<vkcv::DescriptorBinding> descriptorBindings = { triangleShaderProgram.getReflectedDescriptors()[0] };
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
const vkcv::PipelineConfig trianglePipelineDefinition(
......
......@@ -94,9 +94,8 @@ int main(int argc, const char** argv) {
return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
});
std::vector<vkcv::DescriptorBinding> descriptorBindings = {
vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT) };
uint32_t setID = 0;
std::vector<vkcv::DescriptorBinding> descriptorBindings = { triangleShaderProgram.getReflectedDescriptors()[setID] };
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
const vkcv::PipelineConfig trianglePipelineDefinition(
......
......@@ -2,10 +2,12 @@
namespace vkcv {
DescriptorBinding::DescriptorBinding(
uint32_t bindingID,
DescriptorType descriptorType,
uint32_t descriptorCount,
ShaderStage shaderStage) noexcept
:
bindingID(bindingID),
descriptorType(descriptorType),
descriptorCount(descriptorCount),
shaderStage(shaderStage) {}
......
......@@ -40,7 +40,7 @@ namespace vkcv
//create each set's binding
for (uint32_t i = 0; i < bindings.size(); i++) {
vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(
i,
bindings[i].bindingID,
convertDescriptorTypeFlag(bindings[i].descriptorType),
bindings[i].descriptorCount,
convertShaderStageFlag(bindings[i].shaderStage));
......
......@@ -5,7 +5,6 @@
*/
#include "vkcv/ShaderProgram.hpp"
#include <algorithm>
namespace vkcv {
/**
......@@ -67,7 +66,8 @@ namespace vkcv {
ShaderProgram::ShaderProgram() noexcept :
m_Shaders{},
m_VertexLayout{}
m_VertexLayout{},
m_DescriptorSets{}
{}
bool ShaderProgram::addShader(ShaderStage shaderStage, const std::filesystem::path &shaderPath)
......@@ -111,6 +111,7 @@ namespace vkcv {
spirv_cross::Compiler comp(move(shaderCode));
spirv_cross::ShaderResources resources = comp.get_shader_resources();
//reflect vertex input
if (shaderStage == ShaderStage::VERTEX) {
std::vector<VertexInputAttachment> inputVec;
uint32_t offset = 0;
......@@ -118,17 +119,77 @@ namespace vkcv {
for (uint32_t i = 0; i < resources.stage_inputs.size(); i++) {
auto& u = resources.stage_inputs[i];
const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id);
VertexInputAttachment input = VertexInputAttachment(comp.get_decoration(u.id, spv::DecorationLocation),
0,
u.name,
convertFormat(base_type.basetype, base_type.vecsize),
offset);
inputVec.push_back(input);
offset += base_type.vecsize * base_type.width / 8;
}
m_VertexLayout = VertexLayout(inputVec);
}
//reflect descriptor sets (uniform buffer, storage buffer, sampler, sampled image, storage image)
std::vector<std::pair<uint32_t, DescriptorBinding>> bindings;
int32_t maxSetID = -1;
for (uint32_t i = 0; i < resources.uniform_buffers.size(); i++) {
auto& u = resources.uniform_buffers[i];
const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id);
std::pair descriptor(comp.get_decoration(u.id, spv::DecorationDescriptorSet),
DescriptorBinding(comp.get_decoration(u.id, spv::DecorationBinding), DescriptorType::UNIFORM_BUFFER, base_type.vecsize, shaderStage));
bindings.push_back(descriptor);
if (comp.get_decoration(u.id, spv::DecorationDescriptorSet) > maxSetID) maxSetID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
}
for (uint32_t i = 0; i < resources.storage_buffers.size(); i++) {
auto& u = resources.storage_buffers[i];
const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id);
std::pair descriptor(comp.get_decoration(u.id, spv::DecorationDescriptorSet),
DescriptorBinding(comp.get_decoration(u.id, spv::DecorationBinding), DescriptorType::STORAGE_BUFFER, base_type.vecsize, shaderStage));
bindings.push_back(descriptor);
if ((int32_t)comp.get_decoration(u.id, spv::DecorationDescriptorSet) > maxSetID)
maxSetID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
}
for (uint32_t i = 0; i < resources.separate_samplers.size(); i++) {
auto& u = resources.separate_samplers[i];
const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id);
std::pair descriptor(comp.get_decoration(u.id, spv::DecorationDescriptorSet),
DescriptorBinding(comp.get_decoration(u.id, spv::DecorationBinding), DescriptorType::SAMPLER, base_type.vecsize, shaderStage));
bindings.push_back(descriptor);
if ((int32_t)comp.get_decoration(u.id, spv::DecorationDescriptorSet) > maxSetID)
maxSetID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
}
for (uint32_t i = 0; i < resources.separate_images.size(); i++) {
auto& u = resources.separate_images[i];
const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id);
std::pair descriptor(comp.get_decoration(u.id, spv::DecorationDescriptorSet),
DescriptorBinding(comp.get_decoration(u.id, spv::DecorationBinding), DescriptorType::IMAGE_SAMPLED, base_type.vecsize, shaderStage));
bindings.push_back(descriptor);
if ((int32_t)comp.get_decoration(u.id, spv::DecorationDescriptorSet) > maxSetID)
maxSetID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
}
for (uint32_t i = 0; i < resources.storage_images.size(); i++) {
auto& u = resources.storage_images[i];
const spirv_cross::SPIRType& base_type = comp.get_type(u.base_type_id);
std::pair descriptor(comp.get_decoration(u.id, spv::DecorationDescriptorSet),
DescriptorBinding(comp.get_decoration(u.id, spv::DecorationBinding), DescriptorType::IMAGE_STORAGE, base_type.vecsize, shaderStage));
bindings.push_back(descriptor);
if ((int32_t)comp.get_decoration(u.id, spv::DecorationDescriptorSet) > maxSetID)
maxSetID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
}
if (maxSetID != -1) {
if((int32_t)m_DescriptorSets.size() <= maxSetID) m_DescriptorSets.resize(maxSetID + 1);
for (const auto &binding : bindings) {
m_DescriptorSets[binding.first].push_back(binding.second);
}
}
//reflect push constants
for (const auto &pushConstantBuffer : resources.push_constant_buffers) {
for (const auto &range : comp.get_active_buffer_ranges(pushConstantBuffer.id)) {
const size_t size = range.range + range.offset;
......@@ -141,6 +202,9 @@ namespace vkcv {
return m_VertexLayout;
}
const std::vector<std::vector<DescriptorBinding>> ShaderProgram::getReflectedDescriptors() const {
return m_DescriptorSets;
}
size_t ShaderProgram::getPushConstantSize() const {
return m_pushConstantSize;
}
......
......@@ -30,9 +30,10 @@ namespace vkcv {
return 0;
}
VertexInputAttachment::VertexInputAttachment(uint32_t location, uint32_t binding, VertexFormat format, uint32_t offset) noexcept:
VertexInputAttachment::VertexInputAttachment(uint32_t location, uint32_t binding, std::string name, VertexFormat format, uint32_t offset) noexcept:
location{location},
binding{binding},
name{name},
format{format},
offset{offset}
{}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment