diff --git a/doc/snippets/MagnumTrade.cpp b/doc/snippets/MagnumTrade.cpp index 5627ebc296..f2e4910bdd 100644 --- a/doc/snippets/MagnumTrade.cpp +++ b/doc/snippets/MagnumTrade.cpp @@ -180,6 +180,24 @@ importer->openFile("scene.gltf"); // memory-maps all files } #endif +#if defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) +{ +Containers::Pointer importer; +/* [AbstractImporter-usage-zerocopy] */ +importer->addFlags(Trade::ImporterFlag::ZeroCopy); + +Containers::Array memory; +if(!(memory = Utility::Directory::mapRead("huge-file.gltf")) || + !importer->openMemory(memory)) + Fatal{} << "Can't memory-map and open the file"; + +/* Depending on the importer, the actual vertex/index data will get paged from + the above file into the physical memory only once you actually access them */ +Containers::Optional mesh = importer->mesh("huge-cathedral"); +/* [AbstractImporter-usage-zerocopy] */ +} +#endif + { Containers::Pointer importer; Int materialIndex; diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index 369df8afc6..21ab1f081e 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -566,6 +566,41 @@ name doesn't exist. - Texture names using @ref textureName() & @ref textureForName(), imported with @ref texture(const std::string&) +@subsection Trade-AbstractImporter-usage-zerocopy Zero-copy data import + +Some file formats have the data structured in a way that allows them to be +loaded directly into memory or onto the GPU and used as-is. If you memory-map +such a a file and open it with a capable importer, it can give you a view on a +sub-range of the memory-mapped file instead of allocating a copy. Importers +advertise such capabilities with @ref ImporterFeature::ZeroCopyImages, +@relativeref{ImporterFeature,ZeroCopyMeshIndices}, +@relativeref{ImporterFeature,ZeroCopyMeshVertices} and related flags. Because +this puts additional constraints on data lifetime, you have to explicitly +enable the behavior with @ref ImporterFlag::ZeroCopy. Then use +@ref openMemory() to open the memory and ensure it stays in scope for as long +as you operate on the instances returned from the importer: + +@snippet MagnumTrade.cpp AbstractImporter-usage-zerocopy + +Returned instances that reference the original memory are indicated with a +presence of @ref DataFlag::ExternallyOwned. If you use the mutable +@ref openMemory(Containers::ArrayView) overload, the returned data will +have also @ref DataFlag::Mutable set, allowing you to do in-place modifications +on the original file. + +In some cases the importer might still need to process the data on import --- +for example converting image endianness or flipping image origin, and in that +case it'll still return a copy of the data, indicated with +@ref DataFlag::Owned instead. To enforce zero-copy behavior, enable one of the +@ref ImporterFlag::ForceZeroCopyImages, ... flags, providing the plugin +actually supports the corresponding feature. In that case import of particular +data will fail instead of returning a copy, which is useful when you want to, +for example, operate in-place on the imported file or when it's needed to avoid +accidental slowdowns. + +See documentation of a particular importer plugin for information about +provided zero-copy features and their limitations. + @subsection Trade-AbstractImporter-usage-state Internal importer state Some importers, especially ones that make use of well-known external libraries,