From 03aeb4971f6fd97b152f742d55612072b07e720c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 24 Oct 2021 12:20:51 +0200 Subject: [PATCH] sceneconverter: add a --map option. Memory-maps the file and uses openMemory() instead of openFile(). For efficient data formats (such as glTF) can avoid reading the whole blob if only the metadata or a part of the file is needed (for example the peak usage for --info-materials with the Buggy.glb example model went from 8.5 MB to 991 kB, as it reads just the JSON at the start and never even pages in the buffer blobs at the end). This currently only works for standalone files, files that reference external images etc. would need to have file callbacks implemented. And it's Sunday and I'm lazy. --- doc/changelog.dox | 4 +++- src/Magnum/MeshTools/sceneconverter.cpp | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 7b27561ac..1b2133c24 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -230,7 +230,9 @@ See also: avoid accidentally clearing default flags potentially added in the future. - New @ref Trade::AbstractImporter::openMemory() function for passing non-temporary memory to the importer, allowing the implementations to avoid - allocating an internal copy + allocating an internal copy; for benchmarking and testing purposes it's + also exposed via a `--map` option in the + @ref magnum-sceneconverter "magnum-sceneconverter" utility - Ability to convert also 1D and 3D images with the @ref magnum-imageconverter "magnum-imageconverter" utility, as well as combining layers into images of one dimension more (or vice versa) and diff --git a/src/Magnum/MeshTools/sceneconverter.cpp b/src/Magnum/MeshTools/sceneconverter.cpp index 5d2e3d607..559b57273 100644 --- a/src/Magnum/MeshTools/sceneconverter.cpp +++ b/src/Magnum/MeshTools/sceneconverter.cpp @@ -77,8 +77,8 @@ information. @code{.sh} magnum-sceneconverter [-h|--help] [-I|--importer IMPORTER] - [-I|--converter CONVERTER]... [--plugin-dir DIR] [--remove-duplicates] - [--remove-duplicates-fuzzy EPSILON] + [-I|--converter CONVERTER]... [--plugin-dir DIR] [--map] + [--remove-duplicates] [--remove-duplicates-fuzzy EPSILON] [-i|--importer-options key=val,key2=val2,…] [-c|--converter-options key=val,key2=val2,…]... [--mesh MESH] [--level LEVEL] [--info-animations] [--info-images] [--info-lights] @@ -96,6 +96,8 @@ Arguments: @ref Trade::AnySceneImporter "AnySceneImporter") - `-C`, `--converter CONVERTER` --- scene converter plugin(s) - `--plugin-dir DIR` --- override base plugin dir +- `--map` --- memory-map the input for zero-copy import (works only for + standalone files) - `--only-attributes "i j …"` --- include only attributes of given IDs in the output - `--remove-duplicates` --- remove duplicate vertices using @@ -225,6 +227,9 @@ int main(int argc, char** argv) { .addOption('I', "importer", "AnySceneImporter").setHelp("importer", "scene importer plugin") .addArrayOption('C', "converter").setHelp("converter", "scene converter plugin(s)") .addOption("plugin-dir").setHelp("plugin-dir", "override base plugin dir", "DIR") + #if defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) + .addBooleanOption("map").setHelp("map", "memory-map the input for zero-copy import (works only for standalone files)") + #endif .addOption("only-attributes").setHelp("only-attributes", "include only attributes of given IDs in the output", "\"i j …\"") .addBooleanOption("remove-duplicates").setHelp("remove-duplicates", "remove duplicate vertices in the mesh after import") .addOption("remove-duplicates-fuzzy").setHelp("remove-duplicates-fuzzy", "remove duplicate vertices with fuzzy comparison in the mesh after import", "EPSILON") @@ -292,7 +297,17 @@ used.)") std::chrono::high_resolution_clock::duration importTime; - /* Open the file */ + /* Open the file or map it if requested */ + #if defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) + Containers::Array mapped; + if(args.isSet("map")) { + Duration d{importTime}; + if(!(mapped = Utility::Directory::mapRead(args.value("input"))) || !importer->openMemory(mapped)) { + Error() << "Cannot memory-map file" << args.value("input"); + return 3; + } + } else + #endif { Duration d{importTime}; if(!importer->openFile(args.value("input"))) {