git.s-ol.nu ~forks/DiligentTools / 3725eda
GLTFLoader: updated model initialization API; few minor improvements to loading assiduous 11 months ago
2 changed file(s) with 80 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
5353 namespace GLTF
5454 {
5555
56 struct GLTFCacheInfo
56 struct ResourceCacheUseInfo
5757 {
5858 ResourceManager* pResourceMgr = nullptr;
5959
334334 std::unordered_map<std::string, RefCntWeakPtr<ITexture>> Textures;
335335 };
336336
337 Model(IRenderDevice* pDevice,
338 IDeviceContext* pContext,
339 const std::string& filename,
340 TextureCacheType* pTextureCache = nullptr,
341 GLTFCacheInfo* pCache = nullptr);
337 /// Model create information
338 struct CreateInfo
339 {
340 /// File name
341 const char* FileName = nullptr;
342
343 /// Optional texture cache to use when loading the model.
344 /// The loader will try to find all the textures in the cache
345 /// and add all new textures to the cache.
346 TextureCacheType* pTextureCache = nullptr;
347
348 /// Optional resource cache usage info.
349 ResourceCacheUseInfo* pCacheInfo = nullptr;
350
351 /// Optional transform to apply to the model
352 const float4x4* pTransform = nullptr;
353 };
354 Model(IRenderDevice* pDevice,
355 IDeviceContext* pContext,
356 const CreateInfo& CI);
342357
343358 ~Model();
344359
377392 }
378393
379394 private:
380 void LoadFromFile(IRenderDevice* pDevice,
381 IDeviceContext* pContext,
382 const std::string& filename,
383 TextureCacheType* pTextureCache,
384 GLTFCacheInfo* pCache);
395 void LoadFromFile(IRenderDevice* pDevice,
396 IDeviceContext* pContext,
397 const CreateInfo& CI);
385398
386399 void LoadNode(IRenderDevice* pDevice,
387400 Node* parent,
394407 void LoadTextures(IRenderDevice* pDevice,
395408 const tinygltf::Model& gltf_model,
396409 const std::string& BaseDir,
397 TextureCacheType* pTextureCache);
410 TextureCacheType* pTextureCache,
411 ResourceManager* pResourceMgr);
398412
399413 void LoadTextureSamplers(IRenderDevice* pDevice, const tinygltf::Model& gltf_model);
400414 void LoadMaterials(const tinygltf::Model& gltf_model);
404418 Node* FindNode(Node* parent, Uint32 index);
405419 Node* NodeFromIndex(uint32_t index);
406420
407 GLTFCacheInfo CacheInfo;
408
409421 struct ResourceInitData;
410422 std::unique_ptr<ResourceInitData> InitData;
411423
246246
247247
248248
249 Model::Model(IRenderDevice* pDevice,
250 IDeviceContext* pContext,
251 const std::string& filename,
252 TextureCacheType* pTextureCache,
253 GLTFCacheInfo* pCache)
254 {
255 LoadFromFile(pDevice, pContext, filename, pTextureCache, pCache);
249 Model::Model(IRenderDevice* pDevice,
250 IDeviceContext* pContext,
251 const CreateInfo& CI)
252 {
253 LoadFromFile(pDevice, pContext, CI);
256254 }
257255
258256 Model::~Model()
259257 {
260 if (CacheInfo.pResourceMgr != nullptr)
261 {
262 CacheInfo.pResourceMgr->Release();
263 }
264258 }
265259
266260 void Model::LoadNode(IRenderDevice* pDevice,
674668 void Model::LoadTextures(IRenderDevice* pDevice,
675669 const tinygltf::Model& gltf_model,
676670 const std::string& BaseDir,
677 TextureCacheType* pTextureCache)
671 TextureCacheType* pTextureCache,
672 ResourceManager* pResourceMgr)
678673 {
679674 for (const tinygltf::Texture& gltf_tex : gltf_model.textures)
680675 {
686681 TextureInfo TexInfo;
687682 if (!CacheId.empty())
688683 {
689 if (CacheInfo.pResourceMgr != nullptr)
690 {
691 TexInfo.pAtlasSuballocation = CacheInfo.pResourceMgr->FindAllocation(CacheId.c_str());
684 if (pResourceMgr != nullptr)
685 {
686 TexInfo.pAtlasSuballocation = pResourceMgr->FindAllocation(CacheId.c_str());
692687 if (TexInfo.pAtlasSuballocation)
693688 {
694689 // Note that the texture may appear in the cache after the call to LoadImageData because
744739
745740 if (gltf_image.width > 0 && gltf_image.height > 0)
746741 {
747 if (CacheInfo.pResourceMgr != nullptr)
742 if (pResourceMgr != nullptr)
748743 {
749744 TexInfo.pAtlasSuballocation =
750 CacheInfo.pResourceMgr->AllocateTextureSpace(TEX_FORMAT_RGBA8_UNORM, gltf_image.width, gltf_image.height, CacheId.c_str());
745 pResourceMgr->AllocateTextureSpace(TEX_FORMAT_RGBA8_UNORM, gltf_image.width, gltf_image.height, CacheId.c_str());
751746 }
752747 else
753748 {
774769 RefCntAutoPtr<DataBlobImpl> pRawData(MakeNewRCObj<DataBlobImpl>()(gltf_image.image.size()));
775770 memcpy(pRawData->GetDataPtr(), gltf_image.image.data(), gltf_image.image.size());
776771 TextureLoadInfo LoadInfo;
777 if (CacheInfo.pResourceMgr != nullptr)
772 if (pResourceMgr != nullptr)
778773 {
779774 LoadInfo.Name = "Staging upload texture for compressed";
780775 LoadInfo.Usage = USAGE_STAGING;
784779 switch (gltf_image.pixel_type)
785780 {
786781 case IMAGE_FILE_FORMAT_DDS:
787 CreateTextureFromDDS(pRawData, LoadInfo, pDevice, CacheInfo.pResourceMgr != nullptr ? &TexInitData.pStagingTex : &TexInfo.pTexture);
782 CreateTextureFromDDS(pRawData, LoadInfo, pDevice, pResourceMgr != nullptr ? &TexInitData.pStagingTex : &TexInfo.pTexture);
788783 break;
789784
790785 case IMAGE_FILE_FORMAT_KTX:
794789 default:
795790 UNEXPECTED("Unknown raw image format");
796791 }
797 if (CacheInfo.pResourceMgr != nullptr && TexInitData.pStagingTex)
792 if (pResourceMgr != nullptr && TexInitData.pStagingTex)
798793 {
799794 const auto& TexDesc = TexInitData.pStagingTex->GetDesc();
800 TexInfo.pAtlasSuballocation = CacheInfo.pResourceMgr->AllocateTextureSpace(TexDesc.Format, TexDesc.Width, TexDesc.Height, CacheId.c_str());
795 TexInfo.pAtlasSuballocation = pResourceMgr->AllocateTextureSpace(TexDesc.Format, TexDesc.Width, TexDesc.Height, CacheId.c_str());
801796 }
802797 }
803798
13351330
13361331 struct ImageLoaderData
13371332 {
1338 using TexAllocationsVector = std::vector<RefCntAutoPtr<ITextureAtlasSuballocation>>;
1339 using TexturesVector = std::vector<RefCntAutoPtr<ITexture>>;
1340
13411333 Model::TextureCacheType* const pTextureCache;
1342 TexturesVector* const pTextureHold;
13431334 ResourceManager* const pResourceMgr;
1344 TexAllocationsVector* const pTextureAllocationsHold;
1335
1336 std::vector<RefCntAutoPtr<ITexture>> TextureHold;
1337 std::vector<RefCntAutoPtr<ITextureAtlasSuballocation>> TextureAllocationsHold;
13451338
13461339 std::string BaseDir;
13471340 };
13801373 gltf_image->pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
13811374
13821375 // Keep strong reference to ensure the allocation is alive (second time, but that's fine).
1383 pLoaderData->pTextureAllocationsHold->emplace_back(std::move(pAllocation));
1376 pLoaderData->TextureAllocationsHold.emplace_back(std::move(pAllocation));
13841377
13851378 return true;
13861379 }
14061399 gltf_image->pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
14071400
14081401 // Keep strong reference to ensure the texture is alive (second time, but that's fine).
1409 pLoaderData->pTextureHold->emplace_back(std::move(pTexture));
1402 pLoaderData->TextureHold.emplace_back(std::move(pTexture));
14101403
14111404 return true;
14121405 }
15481541 if (auto pAllocation = pLoaderData->pResourceMgr->FindAllocation(filepath.c_str()))
15491542 {
15501543 // Keep strong reference to ensure the allocation is alive.
1551 pLoaderData->pTextureAllocationsHold->emplace_back(std::move(pAllocation));
1544 pLoaderData->TextureAllocationsHold.emplace_back(std::move(pAllocation));
15521545 // Tiny GLTF checks the size of 'out', it can't be empty
15531546 out->resize(1);
15541547 return true;
15641557 if (auto pTexture = it->second.Lock())
15651558 {
15661559 // Keep strong reference to ensure the texture is alive.
1567 pLoaderData->pTextureHold->emplace_back(std::move(pTexture));
1560 pLoaderData->TextureHold.emplace_back(std::move(pTexture));
15681561 // Tiny GLTF checks the size of 'out', it can't be empty
15691562 out->resize(1);
15701563 return true;
16031596
16041597 } // namespace Callbacks
16051598
1606 void Model::LoadFromFile(IRenderDevice* pDevice,
1607 IDeviceContext* pContext,
1608 const std::string& filename,
1609 TextureCacheType* pTextureCache,
1610 GLTFCacheInfo* pCache)
1611 {
1612 if (pCache != nullptr)
1613 {
1614 CacheInfo = *pCache;
1615 CacheInfo.pResourceMgr->AddRef();
1616 }
1617
1618 tinygltf::Model gltf_model;
1619 tinygltf::TinyGLTF gltf_context;
1620
1621 Callbacks::ImageLoaderData::TexturesVector TextureHold;
1622 Callbacks::ImageLoaderData::TexAllocationsVector AllocationsHold;
1623
1624 Callbacks::ImageLoaderData LoaderData //
1625 {
1626 pTextureCache,
1627 &TextureHold,
1628 pCache ? pCache->pResourceMgr : nullptr,
1629 &AllocationsHold
1630 //
1631 };
1632
1599 void Model::LoadFromFile(IRenderDevice* pDevice,
1600 IDeviceContext* pContext,
1601 const CreateInfo& CI)
1602 {
1603 if (CI.FileName == nullptr || *CI.FileName == 0)
1604 LOG_ERROR_AND_THROW("File path must not be empty");
1605
1606 auto* const pTextureCache = CI.pTextureCache;
1607 auto* const pResourceMgr = CI.pCacheInfo != nullptr ? CI.pCacheInfo->pResourceMgr : nullptr;
1608 if (CI.pTextureCache != nullptr && pResourceMgr != nullptr)
1609 LOG_WARNING_MESSAGE("Texture cache is ignored when resource manager is used");
1610
1611 Callbacks::ImageLoaderData LoaderData{pTextureCache, pResourceMgr};
1612
1613 const std::string filename{CI.FileName};
16331614 if (filename.find_last_of("/\\") != std::string::npos)
16341615 LoaderData.BaseDir = filename.substr(0, filename.find_last_of("/\\"));
16351616 LoaderData.BaseDir += '/';
16361617
1618 tinygltf::TinyGLTF gltf_context;
16371619 gltf_context.SetImageLoader(Callbacks::LoadImageData, &LoaderData);
16381620 tinygltf::FsCallbacks fsCallbacks = {};
16391621 fsCallbacks.ExpandFilePath = tinygltf::ExpandFilePath;
16501632 binary = (filename.substr(extpos + 1, filename.length() - extpos) == "glb");
16511633 }
16521634
1653 std::string error;
1654 std::string warning;
1655
1656 bool fileLoaded;
1635 std::string error;
1636 std::string warning;
1637 tinygltf::Model gltf_model;
1638
1639 bool fileLoaded = false;
16571640 if (binary)
16581641 fileLoaded = gltf_context.LoadBinaryFromFile(&gltf_model, &error, &warning, filename.c_str());
16591642 else
16701653 InitData.reset(new ResourceInitData);
16711654
16721655 LoadTextureSamplers(pDevice, gltf_model);
1673 LoadTextures(pDevice, gltf_model, LoaderData.BaseDir, pTextureCache);
1656 LoadTextures(pDevice, gltf_model, LoaderData.BaseDir, pTextureCache, pResourceMgr);
16741657 LoadMaterials(gltf_model);
16751658
16761659 // TODO: scene handling with no default scene
17081691 {
17091692 auto& VertexData0 = InitData->VertexData0;
17101693 auto BufferSize = static_cast<Uint32>(VertexData0.size() * sizeof(VertexData0[0]));
1711 if (CacheInfo.pResourceMgr != nullptr)
1712 {
1713 Buffers[BUFFER_ID_VERTEX0].pSuballocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer0Idx, BufferSize, 1);
1694 if (pResourceMgr != nullptr)
1695 {
1696 Buffers[BUFFER_ID_VERTEX0].pSuballocation = pResourceMgr->AllocateBufferSpace(CI.pCacheInfo->VertexBuffer0Idx, BufferSize, 1);
17141697 }
17151698 else
17161699 {
17321715 {
17331716 auto& VertexData1 = InitData->VertexData1;
17341717 auto BufferSize = static_cast<Uint32>(VertexData1.size() * sizeof(VertexData1[0]));
1735 if (CacheInfo.pResourceMgr != nullptr)
1736 {
1737 Buffers[BUFFER_ID_VERTEX1].pSuballocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer1Idx, BufferSize, 1);
1718 if (pResourceMgr != nullptr)
1719 {
1720 Buffers[BUFFER_ID_VERTEX1].pSuballocation = pResourceMgr->AllocateBufferSpace(CI.pCacheInfo->VertexBuffer1Idx, BufferSize, 1);
17381721 }
17391722 else
17401723 {
17571740 {
17581741 auto& IndexBuffer = InitData->IndexData;
17591742 auto BufferSize = static_cast<Uint32>(IndexBuffer.size() * sizeof(IndexBuffer[0]));
1760 if (CacheInfo.pResourceMgr != nullptr)
1761 {
1762 Buffers[BUFFER_ID_INDEX].pSuballocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.IndexBufferIdx, BufferSize, 1);
1743 if (pResourceMgr != nullptr)
1744 {
1745 Buffers[BUFFER_ID_INDEX].pSuballocation = pResourceMgr->AllocateBufferSpace(CI.pCacheInfo->IndexBufferIdx, BufferSize, 1);
17631746 }
17641747 else
17651748 {