Skip to content

Commit

Permalink
gh-85: add shader reflection save load
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorOrachyov committed Oct 7, 2024
1 parent e33fdbb commit 8b5455d
Show file tree
Hide file tree
Showing 10 changed files with 341 additions and 112 deletions.
48 changes: 48 additions & 0 deletions engine/runtime/core/flat_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#pragma once

#include "io/stream.hpp"
#include "io/tree.hpp"

#include <robin_hood.hpp>
#include <unordered_set>
Expand All @@ -43,6 +44,53 @@ namespace wmoge {
*/
template<typename K>
using flat_set = robin_hood::unordered_flat_set<K>;

template<typename K>
Status stream_write(IoContext& context, IoStream& stream, const flat_set<K>& set) {
WG_ARCHIVE_WRITE(context, stream, set.size());
for (const auto& entry : set) {
WG_ARCHIVE_WRITE(context, stream, entry);
}
return WG_OK;
}

template<typename K>
Status stream_read(IoContext& context, IoStream& stream, flat_set<K>& set) {
assert(set.empty());
std::size_t size;
WG_ARCHIVE_READ(context, stream, size);
for (int i = 0; i < size; i++) {
K entry;
WG_ARCHIVE_READ(context, stream, entry);
set.insert(std::move(entry));
}
return WG_OK;
}

template<typename K>
Status tree_read(IoContext& context, IoTree& tree, flat_set<K>& set) {
assert(set.empty());
set.reserve(tree.node_num_children());
tree.node_find_first_child();
for (; tree.node_is_valid(); tree.node_next_sibling()) {
K entry;
WG_TREE_READ(context, tree, entry);
set.insert(std::move(entry));
}
return WG_OK;
}

template<typename K>
Status tree_write(IoContext& context, IoTree& tree, const flat_set<K>& set) {
WG_TREE_SEQ(tree, set.size());
for (const auto& entry : set) {
WG_CHECKED(tree.node_append_child());
WG_TREE_WRITE(context, tree, entry);
tree.node_pop();
}
return WG_OK;
}

#endif

}// namespace wmoge
2 changes: 2 additions & 0 deletions engine/runtime/grc/_rtti.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
#include "grc/shader.hpp"
#include "grc/shader_compiler.hpp"
#include "grc/shader_file.hpp"
#include "grc/shader_reflection.hpp"
#include "grc/texture.hpp"

namespace wmoge {

void rtti_grc() {
rtti_type<ShaderReflection>();
rtti_type<ShaderFileOption>();
rtti_type<ShaderFileParam>();
rtti_type<ShaderFileParamBlock>();
Expand Down
28 changes: 16 additions & 12 deletions engine/runtime/grc/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,11 @@ namespace wmoge {

assert(lang == GfxShaderLang::GlslVk450);

auto builder = compiler->make_builder();
std::function<void(const Ref<ShaderType>& struct_type)> visitor;
flat_set<Ref<ShaderType>> visited;
auto builder = compiler->make_builder();
std::function<void(const Ref<ShaderTypeStruct>& struct_type)> visitor;
flat_set<Ref<ShaderTypeStruct>> visited;

auto emit_struct = [&](const Ref<ShaderType>& struct_type) {
auto emit_struct = [&](const Ref<ShaderTypeStruct>& struct_type) {
for (const auto& field : struct_type->fields) {
if (field.is_array && field.elem_count == 0) {
builder->add_field(field.type->name, field.name, std::nullopt);
Expand All @@ -202,7 +202,9 @@ namespace wmoge {
}
};

visitor = [&](const Ref<ShaderType>& struct_type) {
visitor = [&](const Ref<ShaderTypeStruct>& struct_type) {
assert(struct_type);

if (visited.find(struct_type) != visited.end()) {
return;
}
Expand All @@ -211,7 +213,7 @@ namespace wmoge {

for (const auto& filed : struct_type->fields) {
if (filed.type->type == ShaderBaseType::Struct) {
visitor(filed.type);
visitor(filed.type.cast<ShaderTypeStruct>());
}
}

Expand All @@ -230,14 +232,16 @@ namespace wmoge {
switch (binding.binding) {
case ShaderBindingType::InlineUniformBuffer:
case ShaderBindingType::UniformBuffer:
case ShaderBindingType::StorageBuffer:
for (const auto& filed : binding.type->fields) {
case ShaderBindingType::StorageBuffer: {
auto s = binding.type.cast<ShaderTypeStruct>();
assert(s);
for (const auto& filed : s->fields) {
if (filed.type->type == ShaderBaseType::Struct) {
visitor(filed.type);
visitor(filed.type.cast<ShaderTypeStruct>());
}
}
break;

}
default:
break;
}
Expand All @@ -254,7 +258,7 @@ namespace wmoge {
case ShaderBindingType::InlineUniformBuffer:
case ShaderBindingType::UniformBuffer:
builder->begin_uniform_binding(space_idx, binding_idx, binding.name, binding.qualifiers);
emit_struct(binding.type);
emit_struct(binding.type.cast<ShaderTypeStruct>());
builder->end_uniform_binding();
break;

Expand All @@ -276,7 +280,7 @@ namespace wmoge {

case ShaderBindingType::StorageBuffer:
builder->begin_storage_binding(space_idx, binding_idx, binding.name, binding.qualifiers);
emit_struct(binding.type);
emit_struct(binding.type.cast<ShaderTypeStruct>());
builder->end_storage_binding();
break;

Expand Down
63 changes: 32 additions & 31 deletions engine/runtime/grc/shader_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,45 +35,45 @@

namespace wmoge {

ShaderBuilder::StructBuilder::StructBuilder(ShaderBuilder& owner, Ref<ShaderType> struct_type)
ShaderBuilder::StructBuilder::StructBuilder(ShaderBuilder& owner, Ref<ShaderTypeStruct> struct_type)
: m_owner(owner), m_struct_type(struct_type) {
}

ShaderBuilder::StructBuilder& ShaderBuilder::StructBuilder::add_field(Strid name, Strid struct_type) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_owner.m_reflection.declarations[struct_type];
field.offset = field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_owner.m_reflection.declarations[struct_type];
field.offset = field.type->byte_size;
return *this;
}

ShaderBuilder::StructBuilder& ShaderBuilder::StructBuilder::add_field(Strid name, Ref<ShaderType> type, Var value) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.offset = field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.offset = field.type->byte_size;
return *this;
}

ShaderBuilder::StructBuilder& ShaderBuilder::StructBuilder::add_field_array(Strid name, Strid struct_type, int n_elements) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_owner.m_reflection.declarations[struct_type];
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_owner.m_reflection.declarations[struct_type];
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
return *this;
}

ShaderBuilder::StructBuilder& ShaderBuilder::StructBuilder::add_field_array(Strid name, Ref<ShaderType> type, int n_elements, Var value) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
return *this;
}

Expand Down Expand Up @@ -268,26 +268,26 @@ namespace wmoge {
return *this;
}

ShaderBuilder& ShaderBuilder::add_struct(const Ref<ShaderType>& struct_type) {
ShaderBuilder& ShaderBuilder::add_struct(const Ref<ShaderTypeStruct>& struct_type) {
assert(struct_type);
assert(struct_type->type == ShaderBaseType::Struct);
m_reflection.declarations[struct_type->name] = struct_type;

for (const auto& field : struct_type->fields) {
if (field.type->type == ShaderBaseType::Struct) {
add_struct(field.type);
add_struct(field.type.cast<ShaderTypeStruct>());
}
}

return *this;
}

ShaderBuilder::StructBuilder ShaderBuilder::add_struct(Strid name, int byte_size) {
Ref<ShaderType> struct_type = make_ref<ShaderType>();
struct_type->name = name;
struct_type->type = ShaderBaseType::Struct;
struct_type->byte_size = byte_size;
m_reflection.declarations[name] = struct_type;
Ref<ShaderTypeStruct> struct_type = make_ref<ShaderTypeStruct>();
struct_type->name = name;
struct_type->type = ShaderBaseType::Struct;
struct_type->byte_size = byte_size;
m_reflection.declarations[name] = struct_type;
return StructBuilder(*this, struct_type);
}

Expand Down Expand Up @@ -347,7 +347,8 @@ namespace wmoge {

std::int16_t offset = 0;

for (const auto& field : binding.type->fields) {
auto s = binding.type.cast<ShaderTypeStruct>();
for (const auto& field : s->fields) {
if (field.is_array && field.elem_count == 0) {
WG_LOG_ERROR("no size array not allowed in "
<< " name=" << binding.name
Expand Down
8 changes: 4 additions & 4 deletions engine/runtime/grc/shader_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace wmoge {

class StructBuilder {
public:
StructBuilder(ShaderBuilder& owner, Ref<ShaderType> struct_type);
StructBuilder(ShaderBuilder& owner, Ref<ShaderTypeStruct> struct_type);

StructBuilder& add_field(Strid name, Strid struct_type);
StructBuilder& add_field(Strid name, Ref<ShaderType> type, Var value = Var());
Expand All @@ -55,8 +55,8 @@ namespace wmoge {
ShaderBuilder& end_struct();

private:
ShaderBuilder& m_owner;
Ref<ShaderType> m_struct_type;
ShaderBuilder& m_owner;
Ref<ShaderTypeStruct> m_struct_type;

friend class ShaderBuilder;
};
Expand Down Expand Up @@ -126,7 +126,7 @@ namespace wmoge {
ShaderBuilder& add_ui_info(const std::string& name, const std::string& hint);
ShaderBuilder& add_source(Strid file, GfxShaderModule module, GfxShaderLang lang);
ShaderBuilder& add_constant(Strid name, Var value);
ShaderBuilder& add_struct(const Ref<ShaderType>& struct_type);
ShaderBuilder& add_struct(const Ref<ShaderTypeStruct>& struct_type);
StructBuilder add_struct(Strid name, int byte_size);
SpaceBuilder add_space(Strid name, ShaderSpaceType type);
TechniqueBuilder add_technique(Strid name);
Expand Down
2 changes: 1 addition & 1 deletion engine/runtime/grc/shader_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ namespace wmoge {

auto type = qtype.value();
if (type->type == ShaderBaseType::Struct) {
builder.add_struct(type);
builder.add_struct(type.cast<ShaderTypeStruct>());
}

if (type->is_primitive) {
Expand Down
51 changes: 25 additions & 26 deletions engine/runtime/grc/shader_reflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

#include "core/crc32.hpp"
#include "grc/shader_manager.hpp"
#include "system/ioc_container.hpp"

namespace wmoge {

Expand Down Expand Up @@ -109,49 +108,49 @@ namespace wmoge {
IMAGE2D};
}

ShaderStructRegister::ShaderStructRegister(Strid name, std::size_t size) {
m_manager = IocContainer::iresolve_v<ShaderManager>();
m_struct_type = make_ref<ShaderType>();
ShaderStructRegister::ShaderStructRegister(Strid name, std::size_t size, ShaderManager* shader_manager) {
m_manager = shader_manager;
m_struct_type = make_ref<ShaderTypeStruct>();
m_struct_type->name = name;
m_struct_type->byte_size = std::int16_t(size);
m_struct_type->type = ShaderBaseType::Struct;
}

ShaderStructRegister& ShaderStructRegister::add_field(Strid name, Strid struct_type) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_manager->find_global_type(struct_type).value();
field.offset = field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_manager->find_global_type(struct_type).value();
field.offset = field.type->byte_size;
return *this;
}

ShaderStructRegister& ShaderStructRegister::add_field(Strid name, Ref<ShaderType> type, Var value) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.offset = field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.offset = field.type->byte_size;
return *this;
}

ShaderStructRegister& ShaderStructRegister::add_field_array(Strid name, Strid struct_type, int n_elements) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_manager->find_global_type(struct_type).value();
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = m_manager->find_global_type(struct_type).value();
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
return *this;
}

ShaderStructRegister& ShaderStructRegister::add_field_array(Strid name, Ref<ShaderType> type, int n_elements, Var value) {
ShaderType::Field& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
ShaderTypeField& field = m_struct_type->fields.emplace_back();
field.name = name;
field.type = type;
field.default_value = value;
field.is_array = true;
field.elem_count = n_elements;
field.offset = n_elements * field.type->byte_size;
return *this;
}

Expand Down
Loading

0 comments on commit 8b5455d

Please sign in to comment.