From 20b5b1164066ea485e3a173fd67293bfec2f5e74 Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Mon, 5 Sep 2022 15:22:03 +0200 Subject: [PATCH] Get rid of attribute hack with sort to adjust their order Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- include/vkcv/VertexData.hpp | 8 ++- include/vkcv/VertexLayout.hpp | 11 +++- .../include/vkcv/asset/asset_loader.hpp | 30 +++++++--- .../src/vkcv/asset/asset_loader.cpp | 26 +++++++++ modules/scene/include/vkcv/scene/Mesh.hpp | 13 ++++- modules/scene/include/vkcv/scene/MeshPart.hpp | 12 ++++ modules/scene/include/vkcv/scene/Node.hpp | 19 ++++++- modules/scene/include/vkcv/scene/Scene.hpp | 27 +++++++-- modules/scene/src/vkcv/scene/Mesh.cpp | 6 +- modules/scene/src/vkcv/scene/MeshPart.cpp | 15 ++--- modules/scene/src/vkcv/scene/Node.cpp | 6 +- modules/scene/src/vkcv/scene/Scene.cpp | 6 +- projects/bindless_textures/src/main.cpp | 31 +++++------ projects/first_mesh/src/main.cpp | 28 ++++------ projects/first_scene/src/main.cpp | 12 +++- projects/head_demo/src/main.cpp | 11 +++- projects/indirect_dispatch/src/AppSetup.cpp | 23 ++++---- projects/indirect_draw/src/main.cpp | 55 ++++++++++--------- projects/mesh_shader/src/main.cpp | 48 +++++++++++----- projects/voxelization/src/main.cpp | 32 ++++------- src/vkcv/VertexLayout.cpp | 13 ++++- 21 files changed, 286 insertions(+), 146 deletions(-) diff --git a/include/vkcv/VertexData.hpp b/include/vkcv/VertexData.hpp index 8e69c85e..001dcfcf 100644 --- a/include/vkcv/VertexData.hpp +++ b/include/vkcv/VertexData.hpp @@ -22,6 +22,8 @@ namespace vkcv { VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, size_t offset = 0); + typedef std::vector<VertexBufferBinding> VertexBufferBindings; + /** * @brief Enum class to specify the size of indexes. */ @@ -33,13 +35,13 @@ namespace vkcv { class VertexData { private: - std::vector<VertexBufferBinding> m_bindings; + VertexBufferBindings m_bindings; BufferHandle m_indices; IndexBitCount m_indexBitCount; size_t m_count; public: - explicit VertexData(const std::vector<VertexBufferBinding> &bindings = {}); + explicit VertexData(const VertexBufferBindings &bindings = {}); VertexData(const VertexData& other) = default; VertexData(VertexData&& other) noexcept = default; @@ -50,7 +52,7 @@ namespace vkcv { VertexData& operator=(VertexData&& other) noexcept = default; [[nodiscard]] - const std::vector<VertexBufferBinding>& getVertexBufferBindings() const; + const VertexBufferBindings& getVertexBufferBindings() const; void setIndexBuffer(const BufferHandle& indices, IndexBitCount indexBitCount = IndexBitCount::Bit16); diff --git a/include/vkcv/VertexLayout.hpp b/include/vkcv/VertexLayout.hpp index 330be708..8e677d11 100644 --- a/include/vkcv/VertexLayout.hpp +++ b/include/vkcv/VertexLayout.hpp @@ -70,11 +70,20 @@ namespace vkcv { * * @param[in] bindingLocation Its entry in the buffers that make up the whole vertex buffer. * @param[in] attachments The vertex input attachments this specific buffer layout contains. - * @return Vertex buffer binding with calculated stride + * @return Vertex binding with calculated stride */ VertexBinding createVertexBinding(uint32_t bindingLocation, const VertexAttachments &attachments); typedef std::vector<VertexBinding> VertexBindings; + + /** + * Creates vertex bindings in a very simplified way with one vertex binding for + * each attachment. + * + * @param[in] attachments The vertex input attachments. + * @return Vertex bindings with calculated stride + */ + VertexBindings createVertexBindings(const VertexAttachments &attachments); /** * @brief Structure to store the details of a vertex layout. diff --git a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp index 2362e560..d6b5cf5d 100644 --- a/modules/asset_loader/include/vkcv/asset/asset_loader.hpp +++ b/modules/asset_loader/include/vkcv/asset/asset_loader.hpp @@ -11,6 +11,8 @@ #include <cstdint> #include <filesystem> +#include "vkcv/VertexData.hpp" + /* LOADING MESHES * The description of meshes is a hierarchy of structures with the Mesh at the * top. @@ -279,8 +281,8 @@ struct Scene { * Note that for URIs only (local) filesystem paths are supported, no * URLs using network protocols etc. * - * @param path must be the path to a glTF- or glb-file. - * @param scene is a reference to a Scene struct that will be filled with the + * @param[in] path must be the path to a glTF- or glb-file. + * @param[out] scene is a reference to a Scene struct that will be filled with the * meta-data of all objects described in the glTF file. * @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS */ @@ -295,8 +297,8 @@ int probeScene(const std::filesystem::path &path, Scene &scene); * Besides the mesh, this function will also add any associated data to the * Scene struct such as Materials and Textures required by the Mesh. * - * @param path must be the path to a glTF- or glb-file. - * @param scene is the scene struct to which the results will be written. + * @param[in,out] scene is the scene struct to which the results will be written. + * @param[in] mesh_index Index of the mesh to load * @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS */ int loadMesh(Scene &scene, int mesh_index); @@ -305,8 +307,8 @@ int loadMesh(Scene &scene, int mesh_index); * Load every mesh from the glTF file, as well as materials, textures and other * associated objects. * - * @param path must be the path to a glTF- or glb-file. - * @param scene is a reference to a Scene struct that will be filled with the + * @param[in] path must be the path to a glTF- or glb-file. + * @param[out] scene is a reference to a Scene struct that will be filled with the * content of the glTF file being loaded. * @return ASSET_ERROR on failure, otherwise ASSET_SUCCESS */ @@ -322,11 +324,25 @@ int loadScene(const std::filesystem::path &path, Scene &scene); * will be cleared to all 0 with path and data being empty; make sure to always * check that !data.empty() before using the struct. * - * @param path must be the path to an image file. + * @param[in] path must be the path to an image file. * @return Texture struct describing the loaded image. */ Texture loadTexture(const std::filesystem::path& path); +/** + * Loads up the vertex attributes and creates usable vertex buffer bindings + * to match the desired order of primitive types as used in the vertex + * shader. + * + * @param[in] attributes Vertex attributes + * @param[in] buffer Buffer handle + * @param[in] types Primitive type order + * @return Vertex buffer bindings + */ +VertexBufferBindings loadVertexBufferBindings(const std::vector<VertexAttribute> &attributes, + const BufferHandle &buffer, + const std::vector<PrimitiveType> &types); + /** @} */ } // end namespace vkcv::asset diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp index 110a941f..d8f2563d 100644 --- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp +++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp @@ -856,5 +856,31 @@ namespace vkcv::asset { } return texture; } + + VertexBufferBindings loadVertexBufferBindings(const std::vector<VertexAttribute> &attributes, + const BufferHandle &buffer, + const std::vector<PrimitiveType> &types) { + VertexBufferBindings bindings; + + for (const auto& type : types) { + const VertexAttribute* attribute = nullptr; + + for (const auto& attr : attributes) { + if (type == attr.type) { + attribute = &(attr); + break; + } + } + + if (!attribute) { + vkcv_log(LogLevel::ERROR, "Missing primitive type in vertex attributes"); + break; + } + + bindings.push_back(vkcv::vertexBufferBinding(buffer, attribute->offset)); + } + + return bindings; + } } diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp index 6235fa01..65cdb3a4 100644 --- a/modules/scene/include/vkcv/scene/Mesh.hpp +++ b/modules/scene/include/vkcv/scene/Mesh.hpp @@ -55,6 +55,7 @@ namespace vkcv::scene { /** * Constructor of a new mesh with a given scene as parent. + * * @param[in,out] scene Scene */ explicit Mesh(Scene& scene); @@ -62,14 +63,18 @@ namespace vkcv::scene { /** * Load mesh data from a scene structure from the asset loader * creating and loading all mesh parts being required. + * * @param[in] scene Scene structure from asset loader * @param[in] mesh Mesh structure from asset loader + * @param[in] types Primitive type order of vertex attributes */ void load(const asset::Scene& scene, - const asset::Mesh& mesh); + const asset::Mesh& mesh, + const std::vector<asset::PrimitiveType>& types); /** * Record drawcalls of the mesh, equally to all its visible parts. + * * @param[in] viewProjection View-transformation and projection as 4x4 matrix * @param[out] pushConstants Structure to store push constants per drawcall * @param[out] drawcalls List of drawcall structures @@ -83,6 +88,7 @@ namespace vkcv::scene { /** * Return the amount of drawcalls of the mesh * as sum of all its parts. + * * @return Amount of drawcalls */ [[nodiscard]] @@ -96,18 +102,21 @@ namespace vkcv::scene { /** * Copy-constructor of a mesh. + * * @param[in] other Other mesh instance */ Mesh(const Mesh& other) = default; /** * Move-constructor of a mesh. + * * @param[in,out] other Other mesh instance */ Mesh(Mesh&& other) = default; /** * Copy-operator of a mesh. + * * @param[in] other Other mesh instance * @return Reference to this mesh instance */ @@ -115,6 +124,7 @@ namespace vkcv::scene { /** * Move-operator of a mesh. + * * @param[in,out] other Other mesh instance * @return Reference to this mesh instance */ @@ -122,6 +132,7 @@ namespace vkcv::scene { /** * Return the axis aligned bounding box of the mesh. + * * @return Axis aligned bounding box of this mesh */ [[nodiscard]] diff --git a/modules/scene/include/vkcv/scene/MeshPart.hpp b/modules/scene/include/vkcv/scene/MeshPart.hpp index eef68a00..61ed8fc3 100644 --- a/modules/scene/include/vkcv/scene/MeshPart.hpp +++ b/modules/scene/include/vkcv/scene/MeshPart.hpp @@ -64,6 +64,7 @@ namespace vkcv::scene { /** * Constructor of a new mesh part with a given scene as parent. + * * @param[in,out] scene Scene */ explicit MeshPart(Scene& scene); @@ -71,12 +72,15 @@ namespace vkcv::scene { /** * Load vertex and index data from structures provided by the asset loader * and add a matching drawcall to the list if the loaded mesh part is valid. + * * @param[in] scene Scene structure from asset loader * @param[in] vertexGroup Vertex group structure from asset loader + * @param[in] types Primitive type order of vertex attributes * @param[out] drawcalls List of drawcalls */ void load(const asset::Scene& scene, const asset::VertexGroup& vertexGroup, + const std::vector<asset::PrimitiveType>& types, std::vector<InstanceDrawcall>& drawcalls); public: @@ -87,18 +91,21 @@ namespace vkcv::scene { /** * Copy-constructor of a mesh part. + * * @param[in] other Other mesh part */ MeshPart(const MeshPart& other); /** * Move-constructor of a mesh part. + * * @param[in,out] other Other mesh part */ MeshPart(MeshPart&& other) noexcept; /** * Copy-operator of a mesh part. + * * @param[in] other Other mesh part * @return Reference to this mesh part */ @@ -106,6 +113,7 @@ namespace vkcv::scene { /** * Move-operator of a mesh part. + * * @param[in,out] other Other mesh part * @return Reference to this mesh part */ @@ -114,6 +122,7 @@ namespace vkcv::scene { /** * Get the material used by this specific part of * the mesh for rendering. + * * @return Material */ [[nodiscard]] @@ -122,6 +131,7 @@ namespace vkcv::scene { /** * Return the axis aligned bounding box of this * specific part of the mesh. + * * @return Axis aligned bounding box of this mesh part */ [[nodiscard]] @@ -130,6 +140,7 @@ namespace vkcv::scene { /** * Return the status if this part of the mesh is valid * as boolean value. + * * @return true if the mesh part is valid, otherwise false */ explicit operator bool() const; @@ -137,6 +148,7 @@ namespace vkcv::scene { /** * Return the status if this part of the mesh is invalid * as boolean value. + * * @return true if the mesh part is invalid, otherwise false */ bool operator!() const; diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp index 3cd5083c..484e1c12 100644 --- a/modules/scene/include/vkcv/scene/Node.hpp +++ b/modules/scene/include/vkcv/scene/Node.hpp @@ -45,25 +45,32 @@ namespace vkcv::scene { /** * Constructor of a new node with a given scene as parent. + * * @param[in,out] scene Scene */ explicit Node(Scene& scene); /** * Add a given mesh to this node for drawcall recording. + * * @param[in] mesh Mesh */ void addMesh(const Mesh& mesh); /** * Load and add a mesh from a scene preloaded with the asset loader. + * * @param[in] asset_scene Scene structure from asset loader * @param[in] asset_mesh Mesh structure from asset loader + * @param[in] types Primitive type order of vertex attributes */ - void loadMesh(const asset::Scene& asset_scene, const asset::Mesh& asset_mesh); + void loadMesh(const asset::Scene& asset_scene, + const asset::Mesh& asset_mesh, + const std::vector<asset::PrimitiveType>& types); /** * Record drawcalls of all meshes of this node and its child nodes. + * * @param[in] viewProjection View-transformation and projection as 4x4 matrix * @param[out] pushConstants Structure to store push constants per drawcall * @param[out] drawcalls List of drawcall structures @@ -78,12 +85,14 @@ namespace vkcv::scene { * Splits child nodes into tree based graphs of nodes * until all nodes contain an amount of meshes below * a given maximum. + * * @param[in] maxMeshesPerNode Maximum amount of meshes per node */ void splitMeshesToSubNodes(size_t maxMeshesPerNode); /** * Return the sum of drawcalls in the graph of this node. + * * @return Amount of drawcalls */ [[nodiscard]] @@ -92,12 +101,14 @@ namespace vkcv::scene { /** * Add a new node as child to the scene graph with this node * as parent and return its index. + * * @return Index of the new node */ size_t addNode(); /** * Get a reference to the child node with a given index. + * * @param[in] index Valid index of a child node * @return Matching child node */ @@ -105,6 +116,7 @@ namespace vkcv::scene { /** * Get a const reference to the child node with a given index. + * * @param[in] index Valid index of a child node * @return Matching child node */ @@ -119,18 +131,21 @@ namespace vkcv::scene { /** * Copy-constructor of a scene node. + * * @param[in] other Other scene node */ Node(const Node& other) = default; /** * Move-constructor of a scene node. + * * @param[in,out] other Other scene node */ Node(Node&& other) = default; /** * Copy-operator of a scene node. + * * @param[in] other Other scene node * @return Reference of this node */ @@ -138,6 +153,7 @@ namespace vkcv::scene { /** * Move-operator of a scene node. + * * @param[in,out] other Other scene node * @return Reference of this node */ @@ -146,6 +162,7 @@ namespace vkcv::scene { /** * Return the axis aligned bounding box of the * scene node. + * * @return Axis aligned bounding box of this node */ [[nodiscard]] diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp index c482b464..74c5a50f 100644 --- a/modules/scene/include/vkcv/scene/Scene.hpp +++ b/modules/scene/include/vkcv/scene/Scene.hpp @@ -57,6 +57,7 @@ namespace vkcv::scene { /** * Constructor of a scene instance with a given Core instance. + * * @param[in,out] core Pointer to valid Core instance */ explicit Scene(Core* core); @@ -64,12 +65,14 @@ namespace vkcv::scene { /** * Add a new node to the first level of the scene graph with * this scene as parent and return its index. + * * @return Index of the new node */ size_t addNode(); /** * Get a reference to the first-level node with a given index. + * * @param[in] index Valid index of a first-level node * @return Matching first-level node */ @@ -77,6 +80,7 @@ namespace vkcv::scene { /** * Get a const reference to the first-level node with a given index. + * * @param[in] index Valid index of a first-level node * @return Matching first-level node */ @@ -85,12 +89,14 @@ namespace vkcv::scene { /** * Increase the amount of usages for a certain material via its index. + * * @param[in] index Index of a material */ void increaseMaterialUsage(size_t index); /** * Decrease the amount of usages for a certain material via its index. + * * @param[in] index Index of a material */ void decreaseMaterialUsage(size_t index); @@ -98,6 +104,7 @@ namespace vkcv::scene { /** * Load a material from a scene preloaded with the asset loader via * its index. + * * @param[in] index Valid index of a material * @param[in] scene Scene structure from asset loader * @param[in] material Material structure from asset loader @@ -113,18 +120,21 @@ namespace vkcv::scene { /** * Copy-constructor of a scene instance. + * * @param[in] other Other scene instance */ Scene(const Scene& other); /** * Move-constructor of a scene instance. + * * @param[in,out] other Other scene instance */ Scene(Scene&& other) noexcept; /** * Copy-operator of a scene instance. + * * @param[in] other Other scene instance * @return Reference to this scene */ @@ -132,6 +142,7 @@ namespace vkcv::scene { /** * Move-operator of a scene instance. + * * @param[in,out] other Other scene instance * @return Reference to this scene */ @@ -139,6 +150,7 @@ namespace vkcv::scene { /** * Return the amount of materials managed by this scene. + * * @return Amount of materials */ [[nodiscard]] @@ -147,6 +159,7 @@ namespace vkcv::scene { /** * Get the material data by its certain index. * The material can still be invalid if it was not loaded properly. + * * @param[in] index Valid index of material * @return Material */ @@ -155,6 +168,7 @@ namespace vkcv::scene { /** * Record drawcalls of all meshes of this scene with CPU-side frustum culling. + * * @param cmdStream Command stream handle * @param camera Scene viewing camera * @param pass Render pass handle @@ -175,7 +189,8 @@ namespace vkcv::scene { /** * Instantiation function to create a new scene instance. - * @param core Current Core instance + * + * @param[in,out] core Current Core instance * @return New scene instance */ static Scene create(Core& core); @@ -183,11 +198,15 @@ namespace vkcv::scene { /** * Load function to create a new scene instance with materials and meshes * loaded from a file using the asset loader. - * @param core Current Core instance - * @param path Path of a valid file to load via asset loader + * + * @param[in,out] core Current Core instance + * @param[in] path Path of a valid file to load via asset loader + * @param[in] types Primitive type order of vertex attributes * @return New scene instance */ - static Scene load(Core& core, const std::filesystem::path &path); + static Scene load(Core& core, + const std::filesystem::path &path, + const std::vector<asset::PrimitiveType>& types); }; diff --git a/modules/scene/src/vkcv/scene/Mesh.cpp b/modules/scene/src/vkcv/scene/Mesh.cpp index 5729ed6c..3c6249fb 100644 --- a/modules/scene/src/vkcv/scene/Mesh.cpp +++ b/modules/scene/src/vkcv/scene/Mesh.cpp @@ -20,7 +20,9 @@ namespace vkcv::scene { return matrix; } - void Mesh::load(const asset::Scene &scene, const asset::Mesh &mesh) { + void Mesh::load(const asset::Scene &scene, + const asset::Mesh &mesh, + const std::vector<asset::PrimitiveType>& types) { m_parts.clear(); m_drawcalls.clear(); @@ -32,7 +34,7 @@ namespace vkcv::scene { } MeshPart part (m_scene); - part.load(scene, scene.vertexGroups[vertexGroupIndex], m_drawcalls); + part.load(scene, scene.vertexGroups[vertexGroupIndex], types, m_drawcalls); if (!part) { continue; diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp index a3fc117f..d7ceacff 100644 --- a/modules/scene/src/vkcv/scene/MeshPart.cpp +++ b/modules/scene/src/vkcv/scene/MeshPart.cpp @@ -17,6 +17,7 @@ namespace vkcv::scene { void MeshPart::load(const asset::Scene& scene, const asset::VertexGroup &vertexGroup, + const std::vector<asset::PrimitiveType>& types, std::vector<InstanceDrawcall>& drawcalls) { Core& core = *(m_scene.m_core); @@ -27,15 +28,11 @@ namespace vkcv::scene { vertexBuffer.fill(vertexGroup.vertexBuffer.data); m_vertices = vertexBuffer.getHandle(); - auto attributes = vertexGroup.vertexBuffer.attributes; - - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - - for (const auto& attribute : attributes) { - m_vertexBindings.emplace_back(vertexBuffer.getHandle(), attribute.offset); - } + m_vertexBindings = asset::loadVertexBufferBindings( + vertexGroup.vertexBuffer.attributes, + vertexBuffer.getHandle(), + types + ); auto indexBuffer = buffer<uint8_t>( core, BufferType::INDEX, vertexGroup.indexBuffer.data.size() diff --git a/modules/scene/src/vkcv/scene/Node.cpp b/modules/scene/src/vkcv/scene/Node.cpp index 746fe180..f5234dd4 100644 --- a/modules/scene/src/vkcv/scene/Node.cpp +++ b/modules/scene/src/vkcv/scene/Node.cpp @@ -69,9 +69,11 @@ namespace vkcv::scene { m_meshes.push_back(mesh); } - void Node::loadMesh(const asset::Scene &asset_scene, const asset::Mesh &asset_mesh) { + void Node::loadMesh(const asset::Scene &asset_scene, + const asset::Mesh &asset_mesh, + const std::vector<asset::PrimitiveType>& types) { Mesh mesh (m_scene); - mesh.load(asset_scene, asset_mesh); + mesh.load(asset_scene, asset_mesh, types); addMesh(mesh); } diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp index e68de653..90d457c9 100644 --- a/modules/scene/src/vkcv/scene/Scene.cpp +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -316,7 +316,9 @@ namespace vkcv::scene { ); } - Scene Scene::load(Core& core, const std::filesystem::path &path) { + Scene Scene::load(Core& core, + const std::filesystem::path &path, + const std::vector<asset::PrimitiveType>& types) { asset::Scene asset_scene; if (!asset::loadScene(path.string(), asset_scene)) { @@ -335,7 +337,7 @@ namespace vkcv::scene { const size_t root = scene.addNode(); for (const auto& mesh : asset_scene.meshes) { - scene.getNode(root).loadMesh(asset_scene, mesh); + scene.getNode(root).loadMesh(asset_scene, mesh, types); } vkcv::SamplerHandle sampler = samplerLinear(core); diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp index 0a34bcb7..e4dd4916 100644 --- a/projects/bindless_textures/src/main.cpp +++ b/projects/bindless_textures/src/main.cpp @@ -125,18 +125,20 @@ int main(int argc, const char** argv) { { vkcv::ShaderStage::VERTEX, "resources/shaders/shader.vert" }, { vkcv::ShaderStage::FRAGMENT, "resources/shaders/shader.frag" } }, nullptr); - - auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - - const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments(); - std::vector<vkcv::VertexBinding> bindings; - for (size_t i = 0; i < vertexAttachments.size(); i++) { - bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] })); - } + const auto vertexBufferBindings = vkcv::asset::loadVertexBufferBindings( + mesh.vertexGroups[0].vertexBuffer.attributes, + vertexBuffer.getHandle(), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL, + vkcv::asset::PrimitiveType::TEXCOORD_0 + } + ); + + std::vector<vkcv::VertexBinding> bindings = vkcv::createVertexBindings( + firstMeshProgram.getVertexAttachments() + ); const vkcv::VertexLayout firstMeshLayout { bindings }; const std::unordered_map<uint32_t, vkcv::DescriptorBinding> &descriptorBindings = firstMeshProgram.getReflectedDescriptors().at(0); @@ -182,13 +184,6 @@ int main(int argc, const char** argv) { core.submitCommandStream(downsampleStream, false); vkcv::SamplerHandle sampler = vkcv::samplerLinear(core); - - const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[0].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[1].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[2].offset) - }; - vkcv::DescriptorWrites setWrites; for(uint32_t i = 0; i < 6; i++) diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index 2e28bd0f..88ab4b70 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -70,18 +70,20 @@ int main(int argc, const char** argv) { { vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" }, { vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" } }, nullptr); - - auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); + const auto vertexBufferBindings = vkcv::asset::loadVertexBufferBindings( + mesh.vertexGroups[0].vertexBuffer.attributes, + vertexBuffer.getHandle(), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL, + vkcv::asset::PrimitiveType::TEXCOORD_0 + } + ); - const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments(); - std::vector<vkcv::VertexBinding> bindings; - for (size_t i = 0; i < vertexAttachments.size(); i++) { - bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] })); - } + std::vector<vkcv::VertexBinding> bindings = vkcv::createVertexBindings( + firstMeshProgram.getVertexAttachments() + ); const vkcv::VertexLayout firstMeshLayout { bindings }; @@ -126,12 +128,6 @@ int main(int argc, const char** argv) { vkcv::SamplerHandle sampler = vkcv::samplerLinear(core); - const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[0].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[1].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[2].offset) - }; - vkcv::DescriptorWrites setWrites; setWrites.writeSampledImage(0, texture.getHandle()); setWrites.writeSampler(1, sampler); diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index 28a2f2d4..6b29b14b 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -45,9 +45,15 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); - vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path( - argc > 1 ? argv[1] : "assets/Sponza/Sponza.gltf" - )); + vkcv::scene::Scene scene = vkcv::scene::Scene::load( + core, + std::filesystem::path(argc > 1 ? argv[1] : "assets/Sponza/Sponza.gltf"), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL, + vkcv::asset::PrimitiveType::TEXCOORD_0 + } + ); vkcv::PassHandle scenePass = vkcv::passSwapchain( core, diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp index 2a0891f8..69daa8ba 100644 --- a/projects/head_demo/src/main.cpp +++ b/projects/head_demo/src/main.cpp @@ -38,9 +38,14 @@ int main(int argc, const char** argv) { cameraManager.getCamera(camIndex1).setNearFar(0.1f, 30.0f); - vkcv::scene::Scene scene = vkcv::scene::Scene::load(core, std::filesystem::path( - argc > 1 ? argv[1] : "assets/skull_scaled/scene.gltf" - )); + vkcv::scene::Scene scene = vkcv::scene::Scene::load( + core, + std::filesystem::path(argc > 1 ? argv[1] : "assets/skull_scaled/scene.gltf"), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL + } + ); vk::Format colorFormat = vk::Format::eR16G16B16A16Sfloat; diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp index fb542509..26cfbbc3 100644 --- a/projects/indirect_dispatch/src/AppSetup.cpp +++ b/projects/indirect_dispatch/src/AppSetup.cpp @@ -43,19 +43,16 @@ bool loadMesh(vkcv::Core& core, const std::filesystem::path& path, MeshResources outMesh->vertexBuffer = vertexBuffer.getHandle(); outMesh->indexBuffer = indexBuffer.getHandle(); - - auto& attributes = vertexData.attributes; - - std::sort(attributes.begin(), attributes.end(), - [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - - const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[0].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[1].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[2].offset) - }; + + const auto vertexBufferBindings = vkcv::asset::loadVertexBufferBindings( + vertexData.attributes, + vertexBuffer.getHandle(), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL, + vkcv::asset::PrimitiveType::TEXCOORD_0 + } + ); outMesh->mesh = vkcv::VertexData(vertexBufferBindings); outMesh->mesh.setIndexBuffer(indexBuffer.getHandle()); diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp index 4e852dbb..39c5621e 100644 --- a/projects/indirect_draw/src/main.cpp +++ b/projects/indirect_draw/src/main.cpp @@ -90,28 +90,33 @@ struct CompiledMaterial void interleaveScene(vkcv::asset::Scene scene, std::vector<std::vector<Vertex>> &interleavedVertexBuffers, - std::vector<glm::vec4> &boundingBoxBuffers) -{ - for(const auto &mesh : scene.meshes) - { - for(auto vertexGroupIndex : mesh.vertexGroups) - { - // Sort attributes to fix it! - auto& attributes = scene.vertexGroups[vertexGroupIndex].vertexBuffer.attributes; + std::vector<glm::vec4> &boundingBoxBuffers) { - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - + for(const auto &mesh : scene.meshes) { + for(auto vertexGroupIndex : mesh.vertexGroups) { const auto &vertexGroup = scene.vertexGroups[vertexGroupIndex]; - const vkcv::asset::VertexAttribute positionAttribute = vertexGroup.vertexBuffer.attributes[0]; - const vkcv::asset::VertexAttribute normalAttribute = vertexGroup.vertexBuffer.attributes[1]; - const vkcv::asset::VertexAttribute uvAttribute = vertexGroup.vertexBuffer.attributes[2]; - - assert(positionAttribute.type == vkcv::asset::PrimitiveType::POSITION); - assert(normalAttribute.type == vkcv::asset::PrimitiveType::NORMAL); - assert(uvAttribute.type == vkcv::asset::PrimitiveType::TEXCOORD_0); + const vkcv::asset::VertexAttribute* positionAttribute = nullptr; + const vkcv::asset::VertexAttribute* normalAttribute = nullptr; + const vkcv::asset::VertexAttribute* uvAttribute = nullptr; + + for (const auto& attribute : vertexGroup.vertexBuffer.attributes) { + switch (attribute.type) { + case vkcv::asset::PrimitiveType::POSITION: + positionAttribute = &attribute; + break; + case vkcv::asset::PrimitiveType::NORMAL: + normalAttribute = &attribute; + break; + case vkcv::asset::PrimitiveType::TEXCOORD_0: + uvAttribute = &attribute; + break; + default: + break; + } + } + + assert(positionAttribute && normalAttribute && uvAttribute); const uint64_t &verticesCount = vertexGroup.numVertices; const std::vector<uint8_t> &vertexData = vertexGroup.vertexBuffer.data; @@ -119,18 +124,18 @@ void interleaveScene(vkcv::asset::Scene scene, std::vector<Vertex> vertices; vertices.reserve(verticesCount); - const size_t positionStride = positionAttribute.stride == 0 ? sizeof(glm::vec3) : positionAttribute.stride; - const size_t normalStride = normalAttribute.stride == 0 ? sizeof(glm::vec3) : normalAttribute.stride; - const size_t uvStride = uvAttribute.stride == 0 ? sizeof(glm::vec2) : uvAttribute.stride; + const size_t positionStride = positionAttribute->stride == 0 ? sizeof(glm::vec3) : positionAttribute->stride; + const size_t normalStride = normalAttribute->stride == 0 ? sizeof(glm::vec3) : normalAttribute->stride; + const size_t uvStride = uvAttribute->stride == 0 ? sizeof(glm::vec2) : uvAttribute->stride; glm::vec3 max_pos(-std::numeric_limits<float>::max()); glm::vec3 min_pos(std::numeric_limits<float>::max()); for(size_t i = 0; i < verticesCount; i++) { - const size_t positionOffset = positionAttribute.offset + positionStride * i; - const size_t normalOffset = normalAttribute.offset + normalStride * i; - const size_t uvOffset = uvAttribute.offset + uvStride * i; + const size_t positionOffset = positionAttribute->offset + positionStride * i; + const size_t normalOffset = normalAttribute->offset + normalStride * i; + const size_t uvOffset = uvAttribute->offset + uvStride * i; Vertex v; diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 5fab2874..034ae3c0 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -120,22 +120,42 @@ int main(int argc, const char** argv) { vkcv::BufferMemoryType::DEVICE_LOCAL ); indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data); - - // format data for mesh shader - auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes; - - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); - - const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[0].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[1].offset), - vkcv::vertexBufferBinding(vertexBuffer.getHandle(), attributes[2].offset) - }; + + const auto vertexBufferBindings = vkcv::asset::loadVertexBufferBindings( + mesh.vertexGroups[0].vertexBuffer.attributes, + vertexBuffer.getHandle(), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL + } + ); + + const vkcv::asset::VertexAttribute* positionAttribute = nullptr; + const vkcv::asset::VertexAttribute* normalAttribute = nullptr; + + for (const auto& attribute : mesh.vertexGroups[0].vertexBuffer.attributes) { + switch (attribute.type) { + case vkcv::asset::PrimitiveType::POSITION: + positionAttribute = &attribute; + break; + case vkcv::asset::PrimitiveType::NORMAL: + normalAttribute = &attribute; + break; + default: + break; + } + } + + assert(positionAttribute && normalAttribute); const auto& bunny = mesh.vertexGroups[0]; - std::vector<vkcv::meshlet::Vertex> interleavedVertices = vkcv::meshlet::convertToVertices(bunny.vertexBuffer.data, bunny.numVertices, attributes[0], attributes[1]); + std::vector<vkcv::meshlet::Vertex> interleavedVertices = vkcv::meshlet::convertToVertices( + bunny.vertexBuffer.data, + bunny.numVertices, + *positionAttribute, + *normalAttribute + ); + // mesh shader buffers const auto& assetLoaderIndexBuffer = mesh.vertexGroups[0].indexBuffer; std::vector<uint32_t> indexBuffer32Bit = vkcv::meshlet::assetLoaderIndicesTo32BitIndices(assetLoaderIndexBuffer.data, assetLoaderIndexBuffer.type); diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 740de623..da2be34b 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -137,20 +137,11 @@ int main(int argc, const char** argv) { std::vector<std::vector<uint8_t>> vBuffers; std::vector<std::vector<uint8_t>> iBuffers; - std::vector<vkcv::VertexBufferBinding> vBufferBindings; std::vector<std::vector<vkcv::VertexBufferBinding>> vertexBufferBindings; - std::vector<vkcv::asset::VertexAttribute> vAttributes; for (size_t i = 0; i < scene.vertexGroups.size(); i++) { - vBuffers.push_back(scene.vertexGroups[i].vertexBuffer.data); iBuffers.push_back(scene.vertexGroups[i].indexBuffer.data); - - auto& attributes = scene.vertexGroups[i].vertexBuffer.attributes; - - std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { - return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); - }); } std::vector<vkcv::Buffer<uint8_t>> vertexBuffers; @@ -171,18 +162,17 @@ int main(int argc, const char** argv) { indexBuffers.back().fill(dataBuffer); } - int vertexBufferIndex = 0; - for (const auto& vertexGroup : scene.vertexGroups) { - for (const auto& attribute : vertexGroup.vertexBuffer.attributes) { - vAttributes.push_back(attribute); - vBufferBindings.push_back(vkcv::vertexBufferBinding( - vertexBuffers[vertexBufferIndex].getHandle(), - attribute.offset - )); - } - vertexBufferBindings.push_back(vBufferBindings); - vBufferBindings.clear(); - vertexBufferIndex++; + for (size_t i = 0; i < scene.vertexGroups.size(); i++) { + vertexBufferBindings.push_back(vkcv::asset::loadVertexBufferBindings( + scene.vertexGroups[i].vertexBuffer.attributes, + vertexBuffers[i].getHandle(), + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL, + vkcv::asset::PrimitiveType::TEXCOORD_0, + vkcv::asset::PrimitiveType::TANGENT + } + )); } const vk::Format colorBufferFormat = vk::Format::eB10G11R11UfloatPack32; diff --git a/src/vkcv/VertexLayout.cpp b/src/vkcv/VertexLayout.cpp index 73e3885b..1409fee0 100644 --- a/src/vkcv/VertexLayout.cpp +++ b/src/vkcv/VertexLayout.cpp @@ -43,5 +43,16 @@ namespace vkcv { binding.stride = offset; return binding; } - + + VertexBindings createVertexBindings(const VertexAttachments &attachments) { + VertexBindings bindings; + bindings.reserve(attachments.size()); + + for (uint32_t i = 0; i < attachments.size(); i++) { + bindings.push_back(createVertexBinding(i, { attachments[i] })); + } + + return bindings; + } + } \ No newline at end of file -- GitLab