From dbda70e3a0daf64c30dd70fde38d1d7c8c6a3ffd Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 20 Dec 2025 00:36:55 -0500 Subject: [PATCH] [BROKEN] This compiles if we use fastgltf 0.9.0, but it says Error::UnsupportedVersion for the file. Earlier versions can't compile because either simdjson has code errors, or the .a/.so is missing important functions. --- Makefile | 5 +- meson.build | 10 +++- vk_engine.cpp | 33 +++++++++++- vk_engine.h | 5 +- vk_loader.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++- wraps/fastgltf.wrap | 2 +- wraps/simdjson.wrap | 13 +++++ 7 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 wraps/simdjson.wrap diff --git a/Makefile b/Makefile index e3bb9fb..7536b9a 100644 --- a/Makefile +++ b/Makefile @@ -29,9 +29,12 @@ shaders: %.glb: %.glb.gz gunzip -k $< -build: basicmesh.glb +build: meson compile -j 10 -C $(ROOT_DIR)/builddir +meshes: basicmesh.glb + @echo "Meshes made" + release_build: meson --wipe builddir -Db_ndebug=true --buildtype release meson compile -j 10 -C builddir diff --git a/meson.build b/meson.build index 0346d16..054c8ef 100644 --- a/meson.build +++ b/meson.build @@ -78,7 +78,14 @@ imgui = subproject('imgui', ).get_variable('imgui_dep') sdl2 = subproject('sdl2').get_variable('sdl2_dep') -fastgltf = subproject('fastgltf').get_variable('fastgltf_dep') + +fastgltf_opts = cmake.subproject_options() +fastgltf_opts.add_cmake_defines({ + 'FASTGLTF_DOWNLOAD_SIMDJSON': false, +}) + +fastgltf_proj = cmake.subproject('fastgltf', options: fastgltf_opts) +fastgltf = fastgltf_proj.get_variable('fastgltf_dep') glm_opts = cmake.subproject_options() glm_opts.add_cmake_defines({ @@ -112,6 +119,7 @@ dependencies += [ glm, imgui, sdl2, + fastgltf, ] sources = [ diff --git a/vk_engine.cpp b/vk_engine.cpp index 8725787..cfcc16f 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -14,7 +14,7 @@ #define VMA_IMPLEMENTATION #include "vk_mem_alloc.h" -constexpr bool bUseValidationLayers = true; +constexpr bool bUseValidationLayers = false; VulkanEngine* loadedEngine = nullptr; @@ -202,6 +202,7 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) vkCmdDraw(cmd, 3, 1, 0, 0); + // draw rectangle vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _meshPipeline); GPUDrawPushConstants push_constants{ @@ -215,6 +216,30 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0); + + // draw monkey + size_t model_idx = 2; // 0 cube; 1 sphere; 2 monkey + + push_constants.vertexBuffer = testMeshes[model_idx]->meshBuffers.vertexBufferAddress; + + vkCmdPushConstants(cmd, + _meshPipelineLayout, + VK_SHADER_STAGE_VERTEX_BIT, + 0, + sizeof(GPUDrawPushConstants), + &push_constants); + + vkCmdBindIndexBuffer(cmd, + testMeshes[model_idx]->meshBuffers.indexBuffer.buffer, + 0, + VK_INDEX_TYPE_UINT32); + + vkCmdDrawIndexed(cmd, + testMeshes[model_idx]->surfaces[0].count, + 1, + testMeshes[model_idx]->surfaces[0].startIndex, + 0, 0); + vkCmdEndRendering(cmd); } @@ -711,7 +736,6 @@ void VulkanEngine::destroy_buffer(const AllocatedBuffer& buffer) vmaDestroyBuffer(_allocator, buffer.buffer, buffer.allocation); } - GPUMeshBuffers VulkanEngine::uploadMesh(std::span indices, std::span vertices) { const size_t vertexBufferSize = vertices.size() * sizeof(Vertex); @@ -796,6 +820,11 @@ void VulkanEngine::init_default_data() { rectangle = uploadMesh(rect_indices, rect_vertices); + auto basicmesh = loadGltfMeshes(this, "basicmesh.glb"); + assert(basicmesh != std::nullopt && "Failed to load basicmesh.glb"); + + testMeshes = *basicmesh; + _mainDeletionQueue.push_function([&](){ destroy_buffer(rectangle.indexBuffer); destroy_buffer(rectangle.vertexBuffer); diff --git a/vk_engine.h b/vk_engine.h index dcececa..1875146 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -6,6 +6,7 @@ #include #include #include "vk_gui.h" +#include "vk_loader.h" struct Transaction { VkCommandBuffer cmd; @@ -100,6 +101,7 @@ public: VkPipeline _meshPipeline; GPUMeshBuffers rectangle; + std::vector> testMeshes; // ZED's REFACTOR VkGUI _gui; @@ -123,6 +125,8 @@ public: Transaction begin_transaction(); void commit_transaction(Transaction& cmd); + GPUMeshBuffers uploadMesh(std::span indices, std::span vertices); + private: void init_vulkan(); void init_swapchain(); @@ -146,5 +150,4 @@ private: void draw_background(VkCommandBuffer cmd); void draw_geometry(VkCommandBuffer cmd); - GPUMeshBuffers uploadMesh(std::span indices, std::span vertices); }; diff --git a/vk_loader.cpp b/vk_loader.cpp index a5249f1..c978f60 100644 --- a/vk_loader.cpp +++ b/vk_loader.cpp @@ -11,9 +11,131 @@ #include #include +constexpr bool OverrideColors = true; std::optional>> loadGltfMeshes(VulkanEngine* engine, std::filesystem::path filePath) { + std::println("\nLoading GLTF: {}", filePath.string()); + auto data = fastgltf::GltfDataBuffer::FromPath(filePath); - return std::nullopt; + if(data.error() != fastgltf::Error::None) { + std::println("Failed to load glTF: {}={}\n", + typeid(data.error()).name(), + fastgltf::to_underlying(data.error())); + return std::nullopt; + } + + constexpr auto gltfOptions = fastgltf::Options::LoadExternalBuffers; + + fastgltf::Asset gltf{}; + fastgltf::Parser parser{}; + + auto load = parser.loadGltfBinary(data.get(), filePath.parent_path(), gltfOptions); + + switch(load.error()) { + case fastgltf::Error::None: + gltf = std::move(load.get()); + break; + case fastgltf::Error::InvalidGLB: + std::println("fastgltf says Error::InvalidGLB {}", filePath.string()); + return std::nullopt; + break; + case fastgltf::Error::UnsupportedVersion: + std::println("fastgltf says Error::UnsupportedVersion {}", filePath.string()); + return std::nullopt; + break; + case fastgltf::Error::InvalidPath: + std::println("fastgltf says Error::UnsupportedVersion {}", + filePath.string()); + return std::nullopt; + break; + default: + std::println("Unknown fastgltf error loading {}", filePath.string()); + break; + } + + std::vector> meshes; + // use the same vectors for all meshes + std::vector indices; + std::vector vertices; + + for(auto& mesh : gltf.meshes) { + MeshAsset newmesh; + newmesh.name = mesh.name; + + indices.clear(); + indices.clear(); + + for(auto&& p : mesh.primitives) { + auto& indexAccessor = gltf.accessors[p.indicesAccessor.value()]; + + GeoSurface newSurface { + .startIndex = (uint32_t)indices.size(), + .count = (uint32_t)indexAccessor.count, + }; + + size_t initial_vtx = vertices.size(); + + // load indices + { + indices.reserve(indices.size() + indexAccessor.count); + fastgltf::iterateAccessor( + gltf, indexAccessor, [&](std::uint32_t idx) { + indices.push_back(idx + initial_vtx); + }); + } + + // load vertex positions + { + fastgltf::Accessor& posAccessor = gltf.accessors[ + p.findAttribute("POSITIONS")->accessorIndex]; + vertices.resize(vertices.size() + posAccessor.count); + + fastgltf::iterateAccessorWithIndex( + gltf, posAccessor, [&](glm::vec3 v, size_t index) + { + vertices[initial_vtx + index] = { + .position = v, + .uv_x = 0, + .normal = {1, 0, 0}, + .uv_y = 0, + .color = glm::vec4{1.0f}, + }; + }); + } + + // load vertex normals + auto normals = p.findAttribute("NORMA:"); + if(normals != p.attributes.end()) { + fastgltf::iterateAccessorWithIndex( + gltf, gltf.accessors[(*normals).accessorIndex], + [&](glm::vec3 v, size_t index) + { + vertices[initial_vtx + index].normal = v; + }); + } + + auto uv = p.findAttribute("TEXCOORD_0"); + if(uv != p.attributes.end()) { + fastgltf::iterateAccessorWithIndex( + gltf, gltf.accessors[(*uv).accessorIndex], + [&](glm::vec2 v, size_t index) { + vertices[initial_vtx + index].uv_x = v.x; + vertices[initial_vtx + index].uv_y = v.y; + }); + } + + if(OverrideColors) { + for(Vertex& vtx : vertices) { + vtx.color = glm::vec4(vtx.normal, 1.0f); + } + } + + newmesh.meshBuffers = engine->uploadMesh(indices, vertices); + meshes.emplace_back(std::make_shared(std::move(newmesh))); + + } + } + + return meshes; } diff --git a/wraps/fastgltf.wrap b/wraps/fastgltf.wrap index abac338..db7da81 100644 --- a/wraps/fastgltf.wrap +++ b/wraps/fastgltf.wrap @@ -1,7 +1,7 @@ [wrap-git] directory=fastgltf url=https://github.com/spnda/fastgltf.git -revision=v0.9.x +revision=v0.9.0 depth=1 method=cmake diff --git a/wraps/simdjson.wrap b/wraps/simdjson.wrap new file mode 100644 index 0000000..a3e383c --- /dev/null +++ b/wraps/simdjson.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = simdjson-3.3.0 +source_url = https://github.com/simdjson/simdjson/archive/refs/tags/v3.3.0.tar.gz +source_filename = simdjson-3.3.0.tar.gz +source_hash = a8c9feff2f19c3ff281d42f0b6b4b18f02236513b99229756fa9a1b14787a58a +patch_filename = simdjson_3.3.0-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/simdjson_3.3.0-2/get_patch +patch_hash = 3c39f8a5abac17732b9599a416e6edb09f5f987bcf4e8b46808dbe88040eb40f +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/simdjson_3.3.0-2/simdjson-3.3.0.tar.gz +wrapdb_version = 3.3.0-2 + +[provide] +simdjson = simdjson_dep