libs/render/src/render/vertex_layout.cc
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "render/vertex_layout.h" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | |||
| 5 | #include "assert/assert.h" | ||
| 6 | |||
| 7 | namespace eu::render | ||
| 8 | { | ||
| 9 | |||
| 10 | |||
| 11 | ✗ | std::vector<VertexType> find_duplicates(const ShaderVertexAttributes& attributes) | |
| 12 | { | ||
| 13 | ✗ | std::vector<VertexType> ret; | |
| 14 | |||
| 15 | ✗ | std::set<VertexType> seen; | |
| 16 | ✗ | for (const auto& att : attributes) | |
| 17 | { | ||
| 18 | ✗ | if (seen.insert(att.type).second == false) | |
| 19 | { | ||
| 20 | ✗ | ret.emplace_back(att.type); | |
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | ✗ | return ret; | |
| 25 | ✗ | } | |
| 26 | |||
| 27 | /** A list of things we need to extract from the Geom when compiling */ | ||
| 28 | struct VertexTypeList | ||
| 29 | { | ||
| 30 | ✗ | explicit VertexTypeList(const std::vector<VertexType>& a_base_layout) | |
| 31 | ✗ | : base_layout(a_base_layout) | |
| 32 | { | ||
| 33 | ✗ | } | |
| 34 | |||
| 35 | ✗ | void add(const ShaderVertexAttributes& elements) | |
| 36 | { | ||
| 37 | ✗ | for (const auto& e: elements) | |
| 38 | { | ||
| 39 | ✗ | indices.insert(e.type); | |
| 40 | } | ||
| 41 | ✗ | } | |
| 42 | |||
| 43 | std::vector<VertexType> base_layout; | ||
| 44 | std::set<VertexType> indices; | ||
| 45 | }; | ||
| 46 | |||
| 47 | ✗ | CompiledShaderVertexAttributes compile_shader_layout( | |
| 48 | const CompiledVertexTypeList& l, | ||
| 49 | const ShaderVertexAttributes& elements, | ||
| 50 | std::optional<InstanceProp> instance_prop, | ||
| 51 | std::optional<int> start_index | ||
| 52 | ) | ||
| 53 | { | ||
| 54 | ✗ | std::vector<CompiledVertexElement> list; | |
| 55 | |||
| 56 | ✗ | for (const auto& e: elements) | |
| 57 | { | ||
| 58 | ✗ | const auto found = l.indices.find(e.type); | |
| 59 | ✗ | ASSERT(found != l.indices.end() && "layout wasn't added to the compilation list"); | |
| 60 | ✗ | if (found != l.indices.end()) | |
| 61 | { | ||
| 62 | ✗ | list.push_back({e.type, e.name, found->second}); | |
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | ✗ | if (instance_prop.has_value()) | |
| 67 | { | ||
| 68 | // if the value was provided, it can't be less than what we have already used | ||
| 69 | ✗ | ASSERT(start_index.has_value() == false || start_index.value() >= l.next_index); | |
| 70 | ✗ | list.push_back({instance_prop->type, instance_prop->name, start_index.value_or(l.next_index)}); | |
| 71 | } | ||
| 72 | |||
| 73 | ✗ | return {list, l.debug_types}; | |
| 74 | ✗ | } | |
| 75 | |||
| 76 | [[nodiscard]] | ||
| 77 | ✗ | CompiledGeomVertexAttributes get_geom_layout(const CompiledVertexTypeList& l) | |
| 78 | { | ||
| 79 | ✗ | std::vector<CompiledVertexElementNoName> list; | |
| 80 | ✗ | list.reserve(l.indices.size()); | |
| 81 | |||
| 82 | ✗ | for (const auto& [first, second]: l.indices) | |
| 83 | { | ||
| 84 | ✗ | list.push_back({first, second}); | |
| 85 | } | ||
| 86 | |||
| 87 | ✗ | std::sort( | |
| 88 | list.begin(), | ||
| 89 | list.end(), | ||
| 90 | ✗ | [](const CompiledVertexElementNoName& lhs, const CompiledVertexElementNoName& rhs) | |
| 91 | ✗ | { return lhs.index < rhs.index; } | |
| 92 | ); | ||
| 93 | |||
| 94 | // todo(Gustav): the index property is confusing and error-prone, just remove it | ||
| 95 | |||
| 96 | ✗ | return {list, l.debug_types}; | |
| 97 | ✗ | } | |
| 98 | |||
| 99 | ✗ | int calculate_shader_attribute_size(const VertexType&) | |
| 100 | { | ||
| 101 | ✗ | return 1; | |
| 102 | } | ||
| 103 | |||
| 104 | ✗ | CompiledVertexTypeList compile_vertex_type_list(const VertexTypeList& list) | |
| 105 | { | ||
| 106 | ✗ | std::map<VertexType, int> indices; | |
| 107 | |||
| 108 | ✗ | int next_index = 0; | |
| 109 | |||
| 110 | ✗ | for (const auto type: list.base_layout) | |
| 111 | { | ||
| 112 | ✗ | indices.insert({type, next_index}); | |
| 113 | ✗ | next_index += calculate_shader_attribute_size(type); | |
| 114 | } | ||
| 115 | |||
| 116 | ✗ | for (const auto type: list.indices) | |
| 117 | { | ||
| 118 | // already in base layout, don't add again | ||
| 119 | ✗ | if (indices.find(type) != indices.end()) | |
| 120 | { | ||
| 121 | ✗ | continue; | |
| 122 | } | ||
| 123 | |||
| 124 | ✗ | indices.insert({type, next_index}); | |
| 125 | ✗ | next_index += calculate_shader_attribute_size(type); | |
| 126 | } | ||
| 127 | |||
| 128 | ✗ | return {indices, {list.indices.begin(), list.indices.end()}, next_index}; | |
| 129 | ✗ | } | |
| 130 | |||
| 131 | ✗ | CompiledVertexTypeList compile_attribute_layouts( | |
| 132 | const std::vector<VertexType>& base_layout, const std::vector<ShaderVertexAttributes>& descriptions | ||
| 133 | ) | ||
| 134 | { | ||
| 135 | ✗ | auto list = VertexTypeList{base_layout}; | |
| 136 | |||
| 137 | ✗ | for (const auto& d: descriptions) | |
| 138 | { | ||
| 139 | ✗ | const auto duplicates = find_duplicates(d); | |
| 140 | ✗ | ASSERT(duplicates.empty() && "ShaderVertexAttributes has duplicate types"); | |
| 141 | ✗ | list.add(d); | |
| 142 | ✗ | } | |
| 143 | |||
| 144 | ✗ | return compile_vertex_type_list(list); | |
| 145 | ✗ | } | |
| 146 | |||
| 147 | ✗ | CompiledVertexTypeList compile_attribute_layouts(const std::vector<ShaderVertexAttributes>& descriptions) | |
| 148 | { | ||
| 149 | ✗ | return compile_attribute_layouts({}, descriptions); | |
| 150 | } | ||
| 151 | |||
| 152 | } // namespace klotter | ||
| 153 |