diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-03-23 23:23:18 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-03-23 23:23:18 +0000 |
| commit | 1a75815b391ab77002a264e3af9512d13e906420 (patch) | |
| tree | fb8f0419eb476c5d5fde36860557284253a526f3 /AssetLoader/src/GLTFLoader.cpp | |
| parent | Revert "Updated appveyor build URL" (diff) | |
| download | DiligentTools-1a75815b391ab77002a264e3af9512d13e906420.tar.gz DiligentTools-1a75815b391ab77002a264e3af9512d13e906420.zip | |
GLTF Loader: added optional texture cache
Diffstat (limited to 'AssetLoader/src/GLTFLoader.cpp')
| -rw-r--r-- | AssetLoader/src/GLTFLoader.cpp | 109 |
1 files changed, 93 insertions, 16 deletions
diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 81b050d..280e74b 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -171,9 +171,12 @@ void Node::Update() -Model::Model(IRenderDevice* pDevice, IDeviceContext* pContext, const std::string& filename) +Model::Model(IRenderDevice* pDevice, + IDeviceContext* pContext, + const std::string& filename, + TextureCacheType* pTextureCache) { - LoadFromFile(pDevice, pContext, filename); + LoadFromFile(pDevice, pContext, filename, pTextureCache); } void Model::LoadNode(IRenderDevice* pDevice, @@ -462,27 +465,53 @@ void Model::LoadSkins(const tinygltf::Model& gltf_model) void Model::LoadTextures(IRenderDevice* pDevice, IDeviceContext* pCtx, - const tinygltf::Model& gltf_model) + const tinygltf::Model& gltf_model, + TextureCacheType* pTextureCache) { + std::vector<ITexture*> NewTextures; for (const tinygltf::Texture& gltf_tex : gltf_model.textures) { - const tinygltf::Image& gltf_image = gltf_model.images[gltf_tex.source]; - RefCntAutoPtr<ISampler> pSampler; - if (gltf_tex.sampler == -1) + const tinygltf::Image& gltf_image = gltf_model.images[gltf_tex.source]; + + RefCntAutoPtr<ITexture> pTexture; + if (pTextureCache != nullptr) { - // No sampler specified, use a default one - pDevice->CreateSampler(Sam_LinearWrap, &pSampler); + auto it = pTextureCache->find(gltf_image.name); + if (it != pTextureCache->end()) + { + pTexture = it->second.Lock(); + VERIFY(pTexture, "Stale textures should not be found in the texture cache because we intentionally keep strong references. " + "This must be an unexpected effect of loading resources from multiple threads."); + } } - else + + if (!pTexture) { - pSampler = TextureSamplers[gltf_tex.sampler]; + RefCntAutoPtr<ISampler> pSampler; + if (gltf_tex.sampler == -1) + { + // No sampler specified, use a default one + pDevice->CreateSampler(Sam_LinearWrap, &pSampler); + } + else + { + pSampler = TextureSamplers[gltf_tex.sampler]; + } + + pTexture = TextureFromGLTFImage(pDevice, pCtx, gltf_image, pSampler); + NewTextures.push_back(pTexture); + + if (pTextureCache != nullptr) + { + pTextureCache->emplace(gltf_image.name, pTexture); + } } - auto pTexture = TextureFromGLTFImage(pDevice, pCtx, gltf_image, pSampler); + Textures.push_back(std::move(pTexture)); } std::vector<StateTransitionDesc> Barriers; - for (auto& Tex : Textures) + for (auto& Tex : NewTextures) { pCtx->GenerateMips(Tex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); @@ -858,6 +887,13 @@ namespace Callbacks namespace { +struct ImageLoaderData +{ + Model::TextureCacheType* pTextureCache; + std::vector<RefCntAutoPtr<ITexture>>* pTextureHold; +}; + + bool LoadImageData(tinygltf::Image* gltf_image, const int gltf_image_idx, std::string* error, @@ -868,9 +904,38 @@ bool LoadImageData(tinygltf::Image* gltf_image, int size, void* user_data) { - (void)user_data; (void)warning; + auto* pLoaderData = reinterpret_cast<ImageLoaderData*>(user_data); + if (pLoaderData != nullptr && pLoaderData->pTextureCache != nullptr) + { + auto it = pLoaderData->pTextureCache->find(gltf_image->name); + if (it != pLoaderData->pTextureCache->end()) + { + if (auto pTexture = it->second.Lock()) + { + const auto& TexDesc = pTexture->GetDesc(); + const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + + gltf_image->width = TexDesc.Width; + gltf_image->height = TexDesc.Height; + gltf_image->component = FmtAttribs.NumComponents; + gltf_image->bits = FmtAttribs.ComponentSize * 8; + gltf_image->pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE; + + // Keep strong reference to ensure the texture is alive. + pLoaderData->pTextureHold->emplace_back(std::move(pTexture)); + + return true; + } + else + { + // Texture is stale - remove it from the cache + pLoaderData->pTextureCache->erase(it); + } + } + } + ImageLoadInfo LoadInfo; LoadInfo.Format = Image::GetFileFormat(image_data, size); if (LoadInfo.Format == EImageFileFormat::unknown) @@ -1009,11 +1074,23 @@ bool ReadWholeFile(std::vector<unsigned char>* out, } // namespace Callbacks -void Model::LoadFromFile(IRenderDevice* pDevice, IDeviceContext* pContext, const std::string& filename) +void Model::LoadFromFile(IRenderDevice* pDevice, + IDeviceContext* pContext, + const std::string& filename, + TextureCacheType* pTextureCache) { tinygltf::Model gltf_model; tinygltf::TinyGLTF gltf_context; - gltf_context.SetImageLoader(Callbacks::LoadImageData, this); + + std::vector<RefCntAutoPtr<ITexture>> TextureHold; + + Callbacks::ImageLoaderData LoaderData // + { + pTextureCache, + &TextureHold // + }; + + gltf_context.SetImageLoader(Callbacks::LoadImageData, &LoaderData); tinygltf::FsCallbacks fsCallbacks = {}; fsCallbacks.ExpandFilePath = tinygltf::ExpandFilePath; fsCallbacks.FileExists = Callbacks::FileExists; @@ -1050,7 +1127,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, IDeviceContext* pContext, const std::vector<Vertex> VertexBuffer; LoadTextureSamplers(pDevice, gltf_model); - LoadTextures(pDevice, pContext, gltf_model); + LoadTextures(pDevice, pContext, gltf_model, pTextureCache); LoadMaterials(gltf_model); // TODO: scene handling with no default scene |
