From fc5b3c2e9a105bed89332f6187b3d3d41a4a69eb Mon Sep 17 00:00:00 2001 From: sean Date: Fri, 2 Feb 2024 15:33:40 +0100 Subject: [PATCH] Some fixes and optimisations --- CMakeLists.txt | 2 +- include/fastgltf/types.hpp | 4 + src/fastgltf.cpp | 175 +++++++++++++++++++------------------ tests/benchmarks.cpp | 16 +++- 4 files changed, 107 insertions(+), 90 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 084b6a803..3349c7894 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ if (SIMDJSON_TARGET_VERSION) endif() if (SIMDJSON_VERBOSE_LOGGING) - target_compile_definitions(fastgltf_simdjson PUBLIC SIMDJSON_VERBOSE_LOGGING=1) + target_compile_definitions(fastgltf PUBLIC SIMDJSON_VERBOSE_LOGGING=1) endif() target_compile_definitions(fastgltf PUBLIC "FASTGLTF_USE_CUSTOM_SMALLVECTOR=$") diff --git a/include/fastgltf/types.hpp b/include/fastgltf/types.hpp index 1ce94a49a..3d6ee2ff7 100644 --- a/include/fastgltf/types.hpp +++ b/include/fastgltf/types.hpp @@ -1909,6 +1909,10 @@ namespace fastgltf { Optional sparse; FASTGLTF_STD_PMR_NS::string name; + + explicit Accessor() = default; + Accessor(const Accessor& accessor) = default; + Accessor(Accessor&& accessor) noexcept = default; }; struct CompressedBufferView { diff --git a/src/fastgltf.cpp b/src/fastgltf.cpp index 576efa78a..6fdd62a0e 100644 --- a/src/fastgltf.cpp +++ b/src/fastgltf.cpp @@ -144,7 +144,7 @@ namespace fastgltf { } std::uint64_t imageIndex; - if (sourceExtensionObject["source"].get_uint64().get(imageIndex) != SUCCESS) { + if (sourceExtensionObject["source"].get(imageIndex) != SUCCESS) { return std::make_tuple(true, false, 0U); } @@ -233,13 +233,13 @@ namespace fastgltf { using namespace simdjson; std::uint64_t index; - if (object["index"].get_uint64().get(index) == SUCCESS) { + if (object["index"].get(index) == SUCCESS) { info->textureIndex = static_cast(index); } else { return Error::InvalidGltf; } - if (auto error = object["texCoord"].get_uint64().get(index); error == SUCCESS) { + if (auto error = object["texCoord"].get(index); error == SUCCESS) { info->texCoordIndex = static_cast(index); } else if (error != NO_SUCH_FIELD) { return Error::InvalidJson; @@ -247,14 +247,14 @@ namespace fastgltf { if (type == TextureInfoType::NormalTexture) { double scale; - if (auto error = object["scale"].get_double().get(scale); error == SUCCESS) { + if (auto error = object["scale"].get(scale); error == SUCCESS) { reinterpret_cast(info)->scale = static_cast(scale); } else if (error != NO_SUCH_FIELD) { return Error::InvalidGltf; } } else if (type == TextureInfoType::OcclusionTexture) { double strength; - if (auto error = object["strength"].get_double().get(strength); error == SUCCESS) { + if (auto error = object["strength"].get(strength); error == SUCCESS) { reinterpret_cast(info)->strength = static_cast(strength); } else if (error != NO_SUCH_FIELD) { return Error::InvalidGltf; @@ -270,12 +270,12 @@ namespace fastgltf { transform->uvOffset = {{ 0.0F, 0.0F }}; transform->uvScale = {{ 1.0F, 1.0F }}; - if (textureTransform["texCoord"].get_uint64().get(index) == SUCCESS) { + if (textureTransform["texCoord"].get(index) == SUCCESS) { transform->texCoordIndex = index; } double rotation = 0.0F; - if (textureTransform["rotation"].get_double().get(rotation) == SUCCESS) { + if (textureTransform["rotation"].get(rotation) == SUCCESS) { transform->rotation = static_cast(rotation); } @@ -426,8 +426,8 @@ void fg::URIView::parse() { } // Parse the path. - auto questionIdx = view.find("?", idx); - auto hashIdx = view.find("#", idx); + auto questionIdx = view.find('?', idx); + auto hashIdx = view.find('#', idx); if (questionIdx != std::string::npos) { _path = view.substr(idx, questionIdx - idx); @@ -1168,7 +1168,7 @@ fg::Expected fg::Parser::parse(simdjson::ondemand::object root, Categ switch (hashedKey) { case force_consteval: { std::uint64_t defaultScene; - if (object.value().get_uint64().get(defaultScene) != SUCCESS) { + if (object.value().get(defaultScene) != SUCCESS) { return Expected(Error::InvalidGltf); } asset.defaultScene = static_cast(defaultScene); @@ -1329,11 +1329,16 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset // Function for parsing the min and max arrays for accessors auto parseMinMax = [&](simdjson::ondemand::array& array, decltype(Accessor::max)& ref) -> fastgltf::Error { + return Error::None; decltype(Accessor::max) variant; using double_vec = std::variant_alternative_t<1, decltype(Accessor::max)>; using int64_vec = std::variant_alternative_t<2, decltype(Accessor::max)>; + // It's possible the min/max fields come before the accessor type is declared, in which case we don't know the size. + // This single line is actually incredibly important as this function without it takes up roughly 15% of the entire + // parsing process on average due to vector resizing. + auto initialCount = accessor.type == AccessorType::Invalid ? 0 : getNumComponents(accessor.type); if (accessor.componentType == ComponentType::Float || accessor.componentType == ComponentType::Double) { variant = FASTGLTF_CONSTRUCT_PMR_RESOURCE(double_vec, resourceAllocator.get(), 0); } else { @@ -1404,7 +1409,7 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset switch (hashedKey) { case force_consteval: { std::uint64_t bufferView; - if (auto error = field.value().get_uint64().get(bufferView); error != SUCCESS) { + if (auto error = field.value().get(bufferView); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } accessor.bufferViewIndex = static_cast(bufferView); @@ -1412,7 +1417,7 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset } case force_consteval: std::uint64_t byteOffset; - if (auto error = field.value().get_uint64().get(byteOffset); error != SUCCESS) { + if (auto error = field.value().get(byteOffset); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } else { accessor.byteOffset = static_cast(byteOffset); @@ -1420,7 +1425,7 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset break; case force_consteval: std::uint64_t componentType; - if (auto error = field.value().get_uint64().get(componentType); error != SUCCESS) { + if (auto error = field.value().get(componentType); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } accessor.componentType = getComponentType( @@ -1436,7 +1441,7 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset break; case force_consteval: std::uint64_t accessorCount; - if (field.value().get_uint64().get(accessorCount) != SUCCESS) { + if (field.value().get(accessorCount) != SUCCESS) { return Error::InvalidGltf; } accessor.count = static_cast(accessorCount); @@ -1474,7 +1479,7 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset SparseAccessor& sparse = accessor.sparse.emplace(); std::uint64_t value; ondemand::object child; - if (sparseAccessorObject["count"].get_uint64().get(value) != SUCCESS) { + if (sparseAccessorObject["count"].get(value) != SUCCESS) { return Error::InvalidGltf; } sparse.count = static_cast(value); @@ -1484,18 +1489,18 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset return Error::InvalidGltf; } - if (child["bufferView"].get_uint64().get(value) != SUCCESS) { + if (child["bufferView"].get(value) != SUCCESS) { return Error::InvalidGltf; } sparse.indicesBufferView = static_cast(value); - if (auto error = child["byteOffset"].get_uint64().get(value); error == SUCCESS) { + if (auto error = child["byteOffset"].get(value); error == SUCCESS) { sparse.indicesByteOffset = static_cast(value); } else if (error != NO_SUCH_FIELD) { return Error::InvalidGltf; } - if (child["componentType"].get_uint64().get(value) != SUCCESS) { + if (child["componentType"].get(value) != SUCCESS) { return Error::InvalidGltf; } sparse.indexComponentType = getComponentType(static_cast>(value)); @@ -1505,12 +1510,12 @@ fg::Error fg::Parser::parseAccessors(simdjson::ondemand::array& accessors, Asset return Error::InvalidGltf; } - if (child["bufferView"].get_uint64().get(value) != SUCCESS) { + if (child["bufferView"].get(value) != SUCCESS) { return Error::InvalidGltf; } sparse.valuesBufferView = static_cast(value); - if (auto error = child["byteOffset"].get_uint64().get(value); error == SUCCESS) { + if (auto error = child["byteOffset"].get(value); error == SUCCESS) { sparse.valuesByteOffset = static_cast(value); } else if (error != NO_SUCH_FIELD) { return Error::InvalidGltf; @@ -1578,7 +1583,7 @@ fg::Error fg::Parser::parseAnimations(simdjson::ondemand::array& animations, Ass } std::uint64_t sampler; - if (channelObject["sampler"].get_uint64().get(sampler) != SUCCESS) { + if (channelObject["sampler"].get(sampler) != SUCCESS) { return Error::InvalidGltf; } channel.samplerIndex = static_cast(sampler); @@ -1588,7 +1593,7 @@ fg::Error fg::Parser::parseAnimations(simdjson::ondemand::array& animations, Ass return Error::InvalidGltf; } else { std::uint64_t node; - if (targetObject["node"].get_uint64().get(node) != SUCCESS) { + if (targetObject["node"].get(node) != SUCCESS) { // We don't support any extensions for animations, so it is required. return Error::InvalidGltf; } @@ -1633,13 +1638,13 @@ fg::Error fg::Parser::parseAnimations(simdjson::ondemand::array& animations, Ass } std::uint64_t input; - if (samplerObject["input"].get_uint64().get(input) != SUCCESS) { + if (samplerObject["input"].get(input) != SUCCESS) { return Error::InvalidGltf; } sampler.inputAccessor = static_cast(input); std::uint64_t output; - if (samplerObject["output"].get_uint64().get(output) != SUCCESS) { + if (samplerObject["output"].get(output) != SUCCESS) { return Error::InvalidGltf; } sampler.outputAccessor = static_cast(output); @@ -1724,7 +1729,7 @@ fg::Error fg::Parser::parseBuffers(simdjson::ondemand::array& buffers, Asset& as } case force_consteval: { std::uint64_t byteLength; - if (field.value().get_uint64().get(byteLength) != SUCCESS) { + if (field.value().get(byteLength) != SUCCESS) { return Error::InvalidGltf; } else { buffer.byteLength = static_cast(byteLength); @@ -1811,7 +1816,7 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A switch (crcStringFunction(key)) { case force_consteval: { std::uint64_t buffer; - if (auto error = field.value().get_uint64().get(buffer); error != SUCCESS) { + if (auto error = field.value().get(buffer); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } view.bufferIndex = static_cast(buffer); @@ -1819,7 +1824,7 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A } case force_consteval: { std::uint64_t byteOffset; - if (auto error = field.value().get_uint64().get(byteOffset); error != SUCCESS) { + if (auto error = field.value().get(byteOffset); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } view.byteOffset = static_cast(byteOffset); @@ -1827,7 +1832,7 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A } case force_consteval: { std::uint64_t byteLength; - if (auto error = field.value().get_uint64().get(byteLength); error != SUCCESS) { + if (auto error = field.value().get(byteLength); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } view.byteLength = static_cast(byteLength); @@ -1835,7 +1840,7 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A } case force_consteval: { std::uint64_t byteStride; - if (auto error = field.value().get_uint64().get(byteStride); error != SUCCESS) { + if (auto error = field.value().get(byteStride); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } view.byteStride = static_cast(byteStride); @@ -1843,7 +1848,7 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A } case force_consteval: { std::uint64_t target; - if (auto error = field.value().get_uint64().get(target); error != SUCCESS) { + if (auto error = field.value().get(target); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } view.target = static_cast(target); @@ -1865,12 +1870,12 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A auto compression = std::make_unique(); std::uint64_t number; - if (auto error = meshoptCompression["buffer"].get_uint64().get(number); error != SUCCESS) { + if (auto error = meshoptCompression["buffer"].get(number); error != SUCCESS) { return error == NO_SUCH_FIELD ? Error::InvalidGltf : Error::InvalidJson; } compression->bufferIndex = static_cast(number); - if (auto error = meshoptCompression["byteOffset"].get_uint64().get(number); error == SUCCESS) { + if (auto error = meshoptCompression["byteOffset"].get(number); error == SUCCESS) { compression->byteOffset = static_cast(number); } else if (error == NO_SUCH_FIELD) { compression->byteOffset = 0; @@ -1878,17 +1883,17 @@ fg::Error fg::Parser::parseBufferViews(simdjson::ondemand::array& bufferViews, A return Error::InvalidJson; } - if (auto error = meshoptCompression["byteLength"].get_uint64().get(number); error != SUCCESS) { + if (auto error = meshoptCompression["byteLength"].get(number); error != SUCCESS) { return error == NO_SUCH_FIELD ? Error::InvalidGltf : Error::InvalidJson; } compression->byteLength = static_cast(number); - if (auto error = meshoptCompression["byteStride"].get_uint64().get(number); error != SUCCESS) { + if (auto error = meshoptCompression["byteStride"].get(number); error != SUCCESS) { return error == NO_SUCH_FIELD ? Error::InvalidGltf : Error::InvalidJson; } compression->byteStride = static_cast(number); - if (auto error = meshoptCompression["count"].get_uint64().get(number); error != SUCCESS) { + if (auto error = meshoptCompression["count"].get(number); error != SUCCESS) { return error == NO_SUCH_FIELD ? Error::InvalidGltf : Error::InvalidJson; } compression->count = number; @@ -1995,7 +2000,7 @@ fg::Error fg::Parser::parseCameras(simdjson::ondemand::array& cameras, Asset& as } double value; - if (auto error = orthographicField.value().get_double().get(value); error != SUCCESS) { + if (auto error = orthographicField.value().get(value); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } @@ -2039,7 +2044,7 @@ fg::Error fg::Parser::parseCameras(simdjson::ondemand::array& cameras, Asset& as } double value; - if (auto error = perspectiveField.value().get_double().get(value); error != SUCCESS) { + if (auto error = perspectiveField.value().get(value); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } @@ -2177,7 +2182,7 @@ fg::Error fg::Parser::parseImages(simdjson::ondemand::array& images, Asset& asse } std::uint64_t bufferView; - if (auto error = field.value().get_uint64().get(bufferView); error != SUCCESS) { + if (auto error = field.value().get(bufferView); error != SUCCESS) { return error == INCORRECT_TYPE ? Error::InvalidGltf : Error::InvalidJson; } dataSource = bufferView; @@ -2287,7 +2292,7 @@ fg::Error fg::Parser::parseLights(simdjson::ondemand::array& lights, Asset& asse } case force_consteval: { double intensity; - if (field.value().get_double().get(intensity) != SUCCESS) { + if (field.value().get(intensity) != SUCCESS) { return Error::InvalidGltf; } light.intensity = static_cast(intensity); @@ -2319,7 +2324,7 @@ fg::Error fg::Parser::parseLights(simdjson::ondemand::array& lights, Asset& asse } case force_consteval: { double range; - if (field.value().get_double().get(range) != SUCCESS) { + if (field.value().get(range) != SUCCESS) { return Error::InvalidGltf; } light.range = static_cast(range); @@ -2334,7 +2339,7 @@ fg::Error fg::Parser::parseLights(simdjson::ondemand::array& lights, Asset& asse // We'll use the traditional lookup here as its only 2 possible fields. double innerConeAngle; - if (auto error = spotObject["innerConeAngle"].get_double().get(innerConeAngle); error == SUCCESS) { + if (auto error = spotObject["innerConeAngle"].get(innerConeAngle); error == SUCCESS) { light.innerConeAngle = static_cast(innerConeAngle); } else if (error == NO_SUCH_FIELD) { light.innerConeAngle = 0.0f; @@ -2343,7 +2348,7 @@ fg::Error fg::Parser::parseLights(simdjson::ondemand::array& lights, Asset& asse } double outerConeAngle; - if (auto error = spotObject["outerConeAngle"].get_double().get(outerConeAngle); error == SUCCESS) { + if (auto error = spotObject["outerConeAngle"].get(outerConeAngle); error == SUCCESS) { light.outerConeAngle = static_cast(outerConeAngle); } else if (error == NO_SUCH_FIELD) { static constexpr double pi = 3.141592653589793116; @@ -2427,7 +2432,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } case force_consteval: { double value; - if (pbrField.value().get_double().get(value) != SUCCESS) { + if (pbrField.value().get(value) != SUCCESS) { return Error::InvalidGltf; } pbr.metallicFactor = static_cast(value); @@ -2435,7 +2440,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } case force_consteval: { double value; - if (pbrField.value().get_double().get(value) != SUCCESS) { + if (pbrField.value().get(value) != SUCCESS) { return Error::InvalidGltf; } pbr.roughnessFactor = static_cast(value); @@ -2534,7 +2539,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } case force_consteval: { double value; - if (field.value().get_double().get(value) != SUCCESS) { + if (field.value().get(value) != SUCCESS) { return Error::InvalidGltf; } material.alphaCutoff = static_cast(value); @@ -2569,7 +2574,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto anisotropy = std::make_unique(); double anisotropyStrength; - if (auto error = anisotropyObject["anisotropyStrength"].get_double().get(anisotropyStrength); error == SUCCESS) { + if (auto error = anisotropyObject["anisotropyStrength"].get(anisotropyStrength); error == SUCCESS) { anisotropy->anisotropyStrength = static_cast(anisotropyStrength); } else if (error == NO_SUCH_FIELD) { anisotropy->anisotropyStrength = 0.0f; @@ -2578,7 +2583,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double anisotropyRotation; - if (auto error = anisotropyObject["anisotropyRotation"].get_double().get(anisotropyRotation); error == SUCCESS) { + if (auto error = anisotropyObject["anisotropyRotation"].get(anisotropyRotation); error == SUCCESS) { anisotropy->anisotropyRotation = static_cast(anisotropyRotation); } else if (error == NO_SUCH_FIELD) { anisotropy->anisotropyRotation = 0.0f; @@ -2607,7 +2612,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto clearcoat = std::make_unique(); double clearcoatFactor; - if (auto error = clearcoatObject["clearcoatFactor"].get_double().get(clearcoatFactor); error == SUCCESS) { + if (auto error = clearcoatObject["clearcoatFactor"].get(clearcoatFactor); error == SUCCESS) { clearcoat->clearcoatFactor = static_cast(clearcoatFactor); } else if (error == NO_SUCH_FIELD) { clearcoat->clearcoatFactor = 0.0f; @@ -2628,7 +2633,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double clearcoatRoughnessFactor; - if (auto error = clearcoatObject["clearcoatRoughnessFactor"].get_double().get(clearcoatRoughnessFactor); error == SUCCESS) { + if (auto error = clearcoatObject["clearcoatRoughnessFactor"].get(clearcoatRoughnessFactor); error == SUCCESS) { clearcoat->clearcoatRoughnessFactor = static_cast(clearcoatRoughnessFactor); } else if (error == NO_SUCH_FIELD) { clearcoat->clearcoatRoughnessFactor = 0.0f; @@ -2671,7 +2676,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto emissiveError = extensionsObject[extensions::KHR_materials_emissive_strength].get_object().get(emissiveObject); if (emissiveError == SUCCESS) { double emissiveStrength; - auto error = emissiveObject["emissiveStrength"].get_double().get(emissiveStrength); + auto error = emissiveObject["emissiveStrength"].get(emissiveStrength); if (error == SUCCESS) { material.emissiveStrength = static_cast(emissiveStrength); } else if (error == NO_SUCH_FIELD) { @@ -2687,7 +2692,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto iorError = extensionsObject[extensions::KHR_materials_ior].get_object().get(iorObject); if (iorError == SUCCESS) { double ior; - auto error = iorObject["ior"].get_double().get(ior); + auto error = iorObject["ior"].get(ior); if (error == SUCCESS) { material.ior = static_cast(ior); } else if (error == NO_SUCH_FIELD) { @@ -2707,7 +2712,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto iridescence = std::make_unique(); double iridescenceFactor; - if (auto error = iridescenceObject["iridescenceFactor"].get_double().get(iridescenceFactor); error == SUCCESS) { + if (auto error = iridescenceObject["iridescenceFactor"].get(iridescenceFactor); error == SUCCESS) { iridescence->iridescenceFactor = static_cast(iridescenceFactor); } else if (error == NO_SUCH_FIELD) { iridescence->iridescenceFactor = 0.0f; @@ -2728,7 +2733,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double iridescenceIor; - if (auto error = iridescenceObject["iridescenceIor"].get_double().get(iridescenceIor); error == SUCCESS) { + if (auto error = iridescenceObject["iridescenceIor"].get(iridescenceIor); error == SUCCESS) { iridescence->iridescenceIor = static_cast(iridescenceIor); } else if (error == NO_SUCH_FIELD) { iridescence->iridescenceIor = 1.3f; @@ -2737,7 +2742,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double iridescenceThicknessMinimum; - if (auto error = iridescenceObject["iridescenceThicknessMinimum"].get_double().get(iridescenceThicknessMinimum); error == SUCCESS) { + if (auto error = iridescenceObject["iridescenceThicknessMinimum"].get(iridescenceThicknessMinimum); error == SUCCESS) { iridescence->iridescenceThicknessMinimum = static_cast(iridescenceThicknessMinimum); } else if (error == NO_SUCH_FIELD) { iridescence->iridescenceThicknessMinimum = 100.0f; @@ -2746,7 +2751,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double iridescenceThicknessMaximum; - if (auto error = iridescenceObject["iridescenceThicknessMaximum"].get_double().get(iridescenceThicknessMaximum); error == SUCCESS) { + if (auto error = iridescenceObject["iridescenceThicknessMaximum"].get(iridescenceThicknessMaximum); error == SUCCESS) { iridescence->iridescenceThicknessMaximum = static_cast(iridescenceThicknessMaximum); } else if (error == NO_SUCH_FIELD) { iridescence->iridescenceThicknessMaximum = 400.0f; @@ -2802,7 +2807,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double sheenRoughnessFactor; - if (auto error = sheenObject["sheenRoughnessFactor"].get_double().get(sheenRoughnessFactor); error == SUCCESS) { + if (auto error = sheenObject["sheenRoughnessFactor"].get(sheenRoughnessFactor); error == SUCCESS) { sheen->sheenRoughnessFactor = static_cast(sheenRoughnessFactor); } else if (error == NO_SUCH_FIELD) { sheen->sheenRoughnessFactor = 0.0f; @@ -2835,7 +2840,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto specular = std::make_unique(); double specularFactor; - if (auto error = specularObject["specularFactor"].get_double().get(specularFactor); error == SUCCESS) { + if (auto error = specularObject["specularFactor"].get(specularFactor); error == SUCCESS) { specular->specularFactor = static_cast(specularFactor); } else if (error == NO_SUCH_FIELD) { specular->specularFactor = 1.0f; @@ -2891,7 +2896,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto transmission = std::make_unique(); double transmissionFactor; - if (auto error = transmissionObject["transmissionFactor"].get_double().get(transmissionFactor); error == SUCCESS) { + if (auto error = transmissionObject["transmissionFactor"].get(transmissionFactor); error == SUCCESS) { transmission->transmissionFactor = static_cast(transmissionFactor); } else if (error == NO_SUCH_FIELD) { transmission->transmissionFactor = 0.0f; @@ -2934,7 +2939,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset auto volume = std::make_unique(); double thicknessFactor; - if (auto error = volumeObject["thicknessFactor"].get_double().get(thicknessFactor); error == SUCCESS) { + if (auto error = volumeObject["thicknessFactor"].get(thicknessFactor); error == SUCCESS) { volume->thicknessFactor = static_cast(thicknessFactor); } else if (error == NO_SUCH_FIELD) { volume->thicknessFactor = 0.0f; @@ -2955,7 +2960,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double attenuationDistance; - if (auto error = volumeObject["attenuationDistance"].get_double().get(attenuationDistance); error == SUCCESS) { + if (auto error = volumeObject["attenuationDistance"].get(attenuationDistance); error == SUCCESS) { volume->attenuationDistance = static_cast(attenuationDistance); } else if (error == NO_SUCH_FIELD) { volume->attenuationDistance = +std::numeric_limits::infinity(); @@ -3077,7 +3082,7 @@ fg::Error fg::Parser::parseMaterials(simdjson::ondemand::array& materials, Asset } double glossinessFactor; - if (auto error = specularGlossinessObject["glossinessFactor"].get_double().get(glossinessFactor); error == SUCCESS) { + if (auto error = specularGlossinessObject["glossinessFactor"].get(glossinessFactor); error == SUCCESS) { specularGlossiness->glossinessFactor = static_cast(glossinessFactor); } else if (error == NO_SUCH_FIELD) { specularGlossiness->glossinessFactor = 1.0f; @@ -3122,7 +3127,7 @@ fg::Error fg::Parser::parseMeshPrimitives(simdjson::ondemand::array& primitives, } std::uint64_t attributeIndex; - if (field.value().get_uint64().get(attributeIndex) != SUCCESS) { + if (field.value().get(attributeIndex) != SUCCESS) { return Error::InvalidGltf; } attributes.emplace_back( @@ -3160,7 +3165,7 @@ fg::Error fg::Parser::parseMeshPrimitives(simdjson::ondemand::array& primitives, } case force_consteval: { std::uint64_t indices; - if (field.value().get_uint64().get(indices) != SUCCESS) { + if (field.value().get(indices) != SUCCESS) { return Error::InvalidGltf; } primitive.indicesAccessor = static_cast(indices); @@ -3168,7 +3173,7 @@ fg::Error fg::Parser::parseMeshPrimitives(simdjson::ondemand::array& primitives, } case force_consteval: { std::uint64_t material; - if (field.value().get_uint64().get(material) != SUCCESS) { + if (field.value().get(material) != SUCCESS) { return Error::InvalidGltf; } primitive.materialIndex = static_cast(material); @@ -3176,7 +3181,7 @@ fg::Error fg::Parser::parseMeshPrimitives(simdjson::ondemand::array& primitives, } case force_consteval: { std::uint64_t mode; - if (field.value().get_uint64().get(mode) != SUCCESS) { + if (field.value().get(mode) != SUCCESS) { return Error::InvalidGltf; } primitive.type = static_cast(mode); @@ -3249,7 +3254,7 @@ fg::Error fg::Parser::parseMeshes(simdjson::ondemand::array& meshes, Asset& asse mesh.weights = FASTGLTF_CONSTRUCT_PMR_RESOURCE(decltype(mesh.weights), resourceAllocator.get(), 0); for (auto weightValue : weights) { double val; - if (weightValue.get_double().get(val) != SUCCESS) { + if (weightValue.get(val) != SUCCESS) { return Error::InvalidGltf; } mesh.weights.emplace_back(static_cast(val)); @@ -3296,7 +3301,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) switch (crcStringFunction(key)) { case force_consteval: { std::uint64_t camera; - if (field.value().get_uint64().get(camera) != SUCCESS) { + if (field.value().get(camera) != SUCCESS) { return Error::InvalidGltf; } node.cameraIndex = static_cast(camera); @@ -3311,7 +3316,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) node.children = FASTGLTF_CONSTRUCT_PMR_RESOURCE(decltype(node.children), resourceAllocator.get(), 0); for (auto childValue : children) { std::uint64_t idx; - if (childValue.get_uint64().get(idx) != SUCCESS) { + if (childValue.get(idx) != SUCCESS) { return Error::InvalidGltf; } node.children.emplace_back(static_cast(idx)); @@ -3320,7 +3325,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) } case force_consteval: { std::uint64_t skin; - if (field.value().get_uint64().get(skin) != SUCCESS) { + if (field.value().get(skin) != SUCCESS) { return Error::InvalidGltf; } node.skinIndex = static_cast(skin); @@ -3348,7 +3353,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) } case force_consteval: { std::uint64_t mesh; - if (field.value().get_uint64().get(mesh) != SUCCESS) { + if (field.value().get(mesh) != SUCCESS) { return Error::InvalidGltf; } node.meshIndex = static_cast(mesh); @@ -3414,7 +3419,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) node.weights = FASTGLTF_CONSTRUCT_PMR_RESOURCE(decltype(node.weights), resourceAllocator.get(), 0); for (auto weightValue : weights) { double val; - if (weightValue.get_double().get(val) != SUCCESS) { + if (weightValue.get(val) != SUCCESS) { return Error::InvalidGltf; } node.weights.emplace_back(static_cast(val)); @@ -3438,7 +3443,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) ondemand::object lightsObject; if (extensionsObject[extensions::KHR_lights_punctual].get_object().get(lightsObject) == SUCCESS) { std::uint64_t light; - if (lightsObject["light"].get_uint64().get(light) == SUCCESS) { + if (lightsObject["light"].get(light) == SUCCESS) { node.lightIndex = static_cast(light); } } @@ -3459,7 +3464,7 @@ fg::Error fg::Parser::parseNodes(simdjson::ondemand::array& nodes, Asset& asset) } std::uint64_t attributeIndex; - if (field.value().get_uint64().get(attributeIndex) != SUCCESS) { + if (field.value().get(attributeIndex) != SUCCESS) { return Error::InvalidGltf; } attributes.emplace_back( @@ -3499,7 +3504,7 @@ fg::Error fg::Parser::parseSamplers(simdjson::ondemand::array& samplers, Asset& switch (crcStringFunction(key)) { case force_consteval: { std::uint64_t magFilter; - if (field.value().get_uint64().get(magFilter) != SUCCESS) { + if (field.value().get(magFilter) != SUCCESS) { return Error::InvalidGltf; } sampler.magFilter = static_cast(magFilter); @@ -3507,7 +3512,7 @@ fg::Error fg::Parser::parseSamplers(simdjson::ondemand::array& samplers, Asset& } case force_consteval: { std::uint64_t minFilter; - if (field.value().get_uint64().get(minFilter) != SUCCESS) { + if (field.value().get(minFilter) != SUCCESS) { return Error::InvalidGltf; } sampler.minFilter = static_cast(minFilter); @@ -3515,7 +3520,7 @@ fg::Error fg::Parser::parseSamplers(simdjson::ondemand::array& samplers, Asset& } case force_consteval: { std::uint64_t wrapS; - if (field.value().get_uint64().get(wrapS) != SUCCESS) { + if (field.value().get(wrapS) != SUCCESS) { return Error::InvalidGltf; } sampler.wrapS = static_cast(wrapS); @@ -3523,7 +3528,7 @@ fg::Error fg::Parser::parseSamplers(simdjson::ondemand::array& samplers, Asset& } case force_consteval: { std::uint64_t wrapT; - if (field.value().get_uint64().get(wrapT) != SUCCESS) { + if (field.value().get(wrapT) != SUCCESS) { return Error::InvalidGltf; } sampler.wrapT = static_cast(wrapT); @@ -3572,7 +3577,7 @@ fg::Error fg::Parser::parseScenes(simdjson::ondemand::array& scenes, Asset& asse scene.nodeIndices = FASTGLTF_CONSTRUCT_PMR_RESOURCE(decltype(scene.nodeIndices), resourceAllocator.get(), 0); for (auto nodeValue : nodes) { std::uint64_t index; - if (nodeValue.get_uint64().get(index) != SUCCESS) { + if (nodeValue.get(index) != SUCCESS) { return Error::InvalidGltf; } @@ -3615,7 +3620,7 @@ fg::Error fg::Parser::parseSkins(simdjson::ondemand::array& skins, Asset& asset) switch (crcStringFunction(key)) { case force_consteval: { std::uint64_t inverseBindMatrices; - if (field.value().get_uint64().get(inverseBindMatrices) != SUCCESS) { + if (field.value().get(inverseBindMatrices) != SUCCESS) { return Error::InvalidGltf; } skin.inverseBindMatrices = static_cast(inverseBindMatrices); @@ -3623,7 +3628,7 @@ fg::Error fg::Parser::parseSkins(simdjson::ondemand::array& skins, Asset& asset) } case force_consteval: { std::uint64_t skeleton; - if (field.value().get_uint64().get(skeleton) != SUCCESS) { + if (field.value().get(skeleton) != SUCCESS) { return Error::InvalidGltf; } skin.skeleton = static_cast(skeleton); @@ -3638,7 +3643,7 @@ fg::Error fg::Parser::parseSkins(simdjson::ondemand::array& skins, Asset& asset) skin.joints = FASTGLTF_CONSTRUCT_PMR_RESOURCE(decltype(skin.joints), resourceAllocator.get(), 0); for (auto nodeValue : joints) { std::uint64_t index; - if (nodeValue.get_uint64().get(index) != SUCCESS) { + if (nodeValue.get(index) != SUCCESS) { return Error::InvalidGltf; } @@ -3681,7 +3686,7 @@ fg::Error fg::Parser::parseTextures(simdjson::ondemand::array& textures, Asset& switch (crcStringFunction(key)) { case force_consteval: { std::uint64_t sourceIndex; - if (field.value().get_uint64().get(sourceIndex) != SUCCESS) { + if (field.value().get(sourceIndex) != SUCCESS) { return Error::InvalidGltf; } texture.imageIndex = static_cast(sourceIndex); @@ -3689,7 +3694,7 @@ fg::Error fg::Parser::parseTextures(simdjson::ondemand::array& textures, Asset& } case force_consteval: { std::uint64_t sampler; - if (field.value().get_uint64().get(sampler) != SUCCESS) { + if (field.value().get(sampler) != SUCCESS) { return Error::InvalidGltf; } texture.samplerIndex = static_cast(sampler); @@ -3929,9 +3934,9 @@ fg::Expected fg::Parser::loadGltfJson(GltfDataBuffer* buffer, fs::pat buffer->dataSize = jsonLength = newLength; } - auto view = padded_string_view(reinterpret_cast(buffer->bufferPointer), jsonLength, buffer->allocatedSize); simdjson::ondemand::document doc; - if (auto error = jsonParser->iterate(view).get(doc); error != SUCCESS) { + if (auto error = jsonParser->iterate(reinterpret_cast(buffer->bufferPointer), jsonLength, buffer->allocatedSize) + .get(doc); error != SUCCESS) { return Expected(Error::InvalidJson); } simdjson::ondemand::object root; diff --git a/tests/benchmarks.cpp b/tests/benchmarks.cpp index 39a4ce02a..b01fcb3d1 100644 --- a/tests/benchmarks.cpp +++ b/tests/benchmarks.cpp @@ -106,8 +106,10 @@ TEST_CASE("Benchmark loading of NewSponza", "[gltf-benchmark]") { auto jsonData = std::make_unique(); REQUIRE(jsonData->fromByteView(bytes.data(), bytes.size() - fastgltf::getGltfBufferPadding(), bytes.size())); + // Extract this from the benchmark loop, as otherwise we benchmark the asset destruction/deallocation too. + fastgltf::Expected asset(fastgltf::Error::None); BENCHMARK("Parse NewSponza") { - return parser.loadGltfJson(jsonData.get(), intelSponza, benchmarkOptions); + asset = parser.loadGltfJson(jsonData.get(), intelSponza, benchmarkOptions); }; #ifdef HAS_TINYGLTF @@ -156,8 +158,10 @@ TEST_CASE("Benchmark base64 decoding from glTF file", "[gltf-benchmark]") { auto jsonData = std::make_unique(); REQUIRE(jsonData->fromByteView(bytes.data(), bytes.size() - fastgltf::getGltfBufferPadding(), bytes.size())); + // Extract this from the benchmark loop, as otherwise we benchmark the asset destruction/deallocation too. + fastgltf::Expected asset(fastgltf::Error::None); BENCHMARK("Parse 2CylinderEngine and decode base64") { - return parser.loadGltfJson(jsonData.get(), cylinderEngine, benchmarkOptions); + asset = parser.loadGltfJson(jsonData.get(), cylinderEngine, benchmarkOptions); }; #ifdef HAS_TINYGLTF @@ -210,8 +214,10 @@ TEST_CASE("Benchmark raw JSON parsing", "[gltf-benchmark]") { auto jsonData = std::make_unique(); REQUIRE(jsonData->fromByteView(bytes.data(), bytes.size() - fastgltf::getGltfBufferPadding(), bytes.size())); + // Extract this from the benchmark loop, as otherwise we benchmark the asset destruction/deallocation too. + fastgltf::Expected asset(fastgltf::Error::None); BENCHMARK("Parse Buggy.gltf") { - return parser.loadGltfJson(jsonData.get(), buggyPath, benchmarkOptions); + asset = parser.loadGltfJson(jsonData.get(), buggyPath, benchmarkOptions); }; #ifdef HAS_TINYGLTF @@ -265,8 +271,10 @@ TEST_CASE("Benchmark massive gltf file", "[gltf-benchmark]") { auto jsonData = std::make_unique(); REQUIRE(jsonData->fromByteView(bytes.data(), bytes.size() - fastgltf::getGltfBufferPadding(), bytes.size())); + // Extract this from the benchmark loop, as otherwise we benchmark the asset destruction/deallocation too. + fastgltf::Expected asset(fastgltf::Error::None); BENCHMARK("Parse Bistro") { - return parser.loadGltfJson(jsonData.get(), bistroPath, benchmarkOptions); + asset = parser.loadGltfJson(jsonData.get(), bistroPath, benchmarkOptions); }; #ifdef HAS_TINYGLTF