diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-12-05 17:19:28 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-12-05 17:19:28 +0000 |
| commit | e3bad5a7fcedc170a10aed3ee644310ec8c982fe (patch) | |
| tree | 1ebedbfb4a1a415bc9615ded4f46fa1e8e694fc6 /AssetLoader/src | |
| parent | GLTF Loader: fixed names of Material::ALPHA_MODE enum members (diff) | |
| download | DiligentTools-e3bad5a7fcedc170a10aed3ee644310ec8c982fe.tar.gz DiligentTools-e3bad5a7fcedc170a10aed3ee644310ec8c982fe.zip | |
GLTF Resource manager: implemented texture array resizing
Diffstat (limited to 'AssetLoader/src')
| -rw-r--r-- | AssetLoader/src/GLTFLoader.cpp | 23 | ||||
| -rw-r--r-- | AssetLoader/src/GLTFResourceManager.cpp | 188 |
2 files changed, 153 insertions, 58 deletions
diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index addf01e..40b6f7d 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -699,6 +699,8 @@ void Model::LoadTextures(IRenderDevice* pDevice, TexInfo.UVScaleBias.y = static_cast<float>(gltf_image.height) / static_cast<float>(TexDesc.Height); TexInfo.UVScaleBias.z = static_cast<float>(Region.x) / static_cast<float>(TexDesc.Width); TexInfo.UVScaleBias.w = static_cast<float>(Region.y) / static_cast<float>(TexDesc.Height); + + TexInfo.Slice = static_cast<float>(TexInfo.pCacheAllocation->GetSlice()); } } else if (pTextureCache != nullptr) @@ -749,7 +751,7 @@ void Model::LoadTextures(IRenderDevice* pDevice, { if (CacheInfo.pResourceMgr != nullptr) { - TexInfo.pCacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(0, gltf_image.width, gltf_image.height); + TexInfo.pCacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(TEX_FORMAT_RGBA8_UNORM, gltf_image.width, gltf_image.height); if (TexInfo.pCacheAllocation) { const auto& TexDesc = TexInfo.pCacheAllocation->GetTexDesc(); @@ -761,6 +763,8 @@ void Model::LoadTextures(IRenderDevice* pDevice, TexInfo.UVScaleBias.y = static_cast<float>(gltf_image.height) / static_cast<float>(TexDesc.Height); TexInfo.UVScaleBias.z = static_cast<float>(Region.x) / static_cast<float>(TexDesc.Width); TexInfo.UVScaleBias.w = static_cast<float>(Region.y) / static_cast<float>(TexDesc.Height); + + TexInfo.Slice = static_cast<float>(TexInfo.pCacheAllocation->GetSlice()); } } else @@ -779,6 +783,7 @@ void Model::LoadTextures(IRenderDevice* pDevice, pDevice->CreateTexture(TexDesc, nullptr, &TexInfo.pTexture); TexInfo.pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)->SetSampler(pSampler); TexInfo.UVScaleBias = float4{1, 1, 0, 0}; + TexInfo.Slice = 0; TexInitData = PrepareGLTFTextureInitData(gltf_image, AlphaCutoff, 0, 0, 1); } @@ -860,7 +865,7 @@ void Model::PrepareGPUResources(IRenderDevice* pDevice, IDeviceContext* pCtx) const auto& Level = Levels[mip]; TextureSubResData SubresData{Level.Data.data(), Level.Stride}; - pCtx->UpdateTexture(pTexture, mip, 0, Level.UpdateBox, SubresData, RESOURCE_STATE_TRANSITION_MODE_NONE, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pCtx->UpdateTexture(pTexture, mip, static_cast<Uint32>(Textures[i].Slice), Level.UpdateBox, SubresData, RESOURCE_STATE_TRANSITION_MODE_NONE, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); } if (Levels.size() == 1 && pTexture->GetDesc().MipLevels > 1) @@ -993,17 +998,18 @@ void Model::LoadMaterials(const tinygltf::Model& gltf_model) const Material::TEXTURE_ID TextureId; float& UVSelector; float4& UVScaleBias; + float& Slice; const char* const TextureName; const tinygltf::ParameterMap& Params; }; // clang-format off std::array<TextureParameterInfo, 5> TextureParams = { - TextureParameterInfo{Material::TEXTURE_ID_BASE_COLOR, Mat.Attribs.BaseColorUVSelector, Mat.Attribs.BaseColorUVScaleBias, "baseColorTexture", gltf_mat.values}, - TextureParameterInfo{Material::TEXTURE_ID_PHYSICAL_DESC, Mat.Attribs.PhysicalDescriptorUVSelector, Mat.Attribs.PhysicalDescriptorUVScaleBias, "metallicRoughnessTexture", gltf_mat.values}, - TextureParameterInfo{Material::TEXTURE_ID_NORMAL_MAP, Mat.Attribs.NormalUVSelector, Mat.Attribs.NormalUVScaleBias, "normalTexture", gltf_mat.additionalValues}, - TextureParameterInfo{Material::TEXTURE_ID_OCCLUSION, Mat.Attribs.OcclusionUVSelector, Mat.Attribs.OcclusionUVScaleBias, "occlusionTexture", gltf_mat.additionalValues}, - TextureParameterInfo{Material::TEXTURE_ID_EMISSIVE, Mat.Attribs.EmissiveUVSelector, Mat.Attribs.EmissiveUVScaleBias, "emissiveTexture", gltf_mat.additionalValues} + TextureParameterInfo{Material::TEXTURE_ID_BASE_COLOR, Mat.Attribs.BaseColorUVSelector, Mat.Attribs.BaseColorUVScaleBias, Mat.Attribs.BaseColorSlice, "baseColorTexture", gltf_mat.values}, + TextureParameterInfo{Material::TEXTURE_ID_PHYSICAL_DESC, Mat.Attribs.PhysicalDescriptorUVSelector, Mat.Attribs.PhysicalDescriptorUVScaleBias, Mat.Attribs.PhysicalDescriptorSlice, "metallicRoughnessTexture", gltf_mat.values}, + TextureParameterInfo{Material::TEXTURE_ID_NORMAL_MAP, Mat.Attribs.NormalUVSelector, Mat.Attribs.NormalUVScaleBias, Mat.Attribs.NormalSlice, "normalTexture", gltf_mat.additionalValues}, + TextureParameterInfo{Material::TEXTURE_ID_OCCLUSION, Mat.Attribs.OcclusionUVSelector, Mat.Attribs.OcclusionUVScaleBias, Mat.Attribs.OcclusionSlice, "occlusionTexture", gltf_mat.additionalValues}, + TextureParameterInfo{Material::TEXTURE_ID_EMISSIVE, Mat.Attribs.EmissiveUVSelector, Mat.Attribs.EmissiveUVScaleBias, Mat.Attribs.EmissiveSlice, "emissiveTexture", gltf_mat.additionalValues} }; // clang-format on @@ -1125,7 +1131,10 @@ void Model::LoadMaterials(const tinygltf::Model& gltf_model) { auto TexIndex = Mat.TextureIds[Param.TextureId]; if (TexIndex >= 0) + { Param.UVScaleBias = GetUVScaleBias(TexIndex); + Param.Slice = GetSlice(TexIndex); + } } Materials.push_back(Mat); diff --git a/AssetLoader/src/GLTFResourceManager.cpp b/AssetLoader/src/GLTFResourceManager.cpp index dc4febf..fa1008b 100644 --- a/AssetLoader/src/GLTFResourceManager.cpp +++ b/AssetLoader/src/GLTFResourceManager.cpp @@ -91,71 +91,139 @@ GLTFResourceManager::TextureCache::TextureCache(GLTFResourceManager& Owner IRenderDevice* pDevice, const TextureCacheAttribs& CacheCI) : m_Owner{Owner}, - m_TexDesc{CacheCI.Desc}, - m_Mgr{CacheCI.Desc.Width / CacheCI.Granularity, CacheCI.Desc.Height / CacheCI.Granularity}, - m_Granularity{CacheCI.Granularity} + m_Attribs{CacheCI} { - m_TexDesc.Name = m_TexName.c_str(); + m_Attribs.Desc.Name = m_TexName.c_str(); - DEV_CHECK_ERR(IsPowerOfTwo(CacheCI.Granularity), "Granularity (", CacheCI.Granularity, ") must be a power of two"); - DEV_CHECK_ERR((CacheCI.Desc.Width % CacheCI.Granularity) == 0, "Atlas width (", CacheCI.Desc.Width, ") is not multiple of granularity (", CacheCI.Granularity, ")"); - DEV_CHECK_ERR((CacheCI.Desc.Height % CacheCI.Granularity) == 0, "Atlas height (", CacheCI.Desc.Height, ") is not multiple of granularity (", CacheCI.Granularity, ")"); + const auto& Desc = m_Attribs.Desc; + for (Uint32 slice = 0; slice < Desc.ArraySize; ++slice) + { + m_Slices.emplace_back(new SliceManager{Desc.Width / m_Attribs.Granularity, Desc.Height / m_Attribs.Granularity}); + } + + DEV_CHECK_ERR(IsPowerOfTwo(m_Attribs.Granularity), "Granularity (", m_Attribs.Granularity, ") must be a power of two"); + DEV_CHECK_ERR((Desc.Width % m_Attribs.Granularity) == 0, "Atlas width (", Desc.Width, ") is not multiple of granularity (", m_Attribs.Granularity, ")"); + DEV_CHECK_ERR((Desc.Height % m_Attribs.Granularity) == 0, "Atlas height (", Desc.Height, ") is not multiple of granularity (", m_Attribs.Granularity, ")"); - pDevice->CreateTexture(CacheCI.Desc, nullptr, &m_pTexture); + if (pDevice != nullptr) + { + pDevice->CreateTexture(Desc, nullptr, &m_pTexture); + } } ITexture* GLTFResourceManager::TextureCache::GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext) { - // TODO: handle resizes + RefCntAutoPtr<ITexture> pNewTexture; + { + std::lock_guard<std::mutex> Lock{m_SlicesMtx}; + if (!m_pTexture || m_pTexture->GetDesc().ArraySize < m_Slices.size()) + { + m_Attribs.Desc.ArraySize = static_cast<Uint32>(m_Slices.size()); + VERIFY_EXPR(pDevice != nullptr); + pDevice->CreateTexture(m_Attribs.Desc, nullptr, &pNewTexture); + } + if (pNewTexture) + { + if (m_pTexture) + { + const auto& OldDesc = m_pTexture->GetDesc(); + + CopyTextureAttribs CopyAttribs; + CopyAttribs.pSrcTexture = m_pTexture; + CopyAttribs.pDstTexture = pNewTexture; + CopyAttribs.SrcTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION; + CopyAttribs.DstTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION; + + for (Uint32 slice = 0; slice < OldDesc.ArraySize; ++slice) + { + for (Uint32 mip = 0; mip < OldDesc.MipLevels; ++mip) + { + CopyAttribs.SrcSlice = slice; + CopyAttribs.DstSlice = slice; + CopyAttribs.SrcMipLevel = mip; + CopyAttribs.DstMipLevel = mip; + pContext->CopyTexture(CopyAttribs); + } + } + } + m_pTexture = std::move(pNewTexture); + m_Owner.m_ResourceVersion.fetch_add(1); + } + } + return m_pTexture; } RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::TextureCache::Allocate(Uint32 Width, Uint32 Height) { VERIFY_EXPR(Width > 0 && Height > 0); - - std::lock_guard<std::mutex> Lock{m_Mtx}; - - auto Region = m_Mgr.Allocate((Width + m_Granularity - 1) / m_Granularity, (Height + m_Granularity - 1) / m_Granularity); - if (!Region.IsEmpty()) + const auto& TexDesc = m_Attribs.Desc; + if (Width > TexDesc.Width || Height > TexDesc.Height) { - Region.x *= m_Granularity; - Region.y *= m_Granularity; - Region.width *= m_Granularity; - Region.height *= m_Granularity; - - return RefCntAutoPtr<TextureAllocation>{ - MakeNewRCObj<TextureAllocation>()( - RefCntAutoPtr<GLTFResourceManager>{&m_Owner}, - *this, - Width, - Height, - std::move(Region) // - ) // - }; + LOG_ERROR_MESSAGE("Requested size ", Width, " x ", Height, " exceeds the texture size ", TexDesc.Width, " x ", TexDesc.Height); + return {}; } - else + + const auto Granularity = m_Attribs.Granularity; + for (Uint32 Slice = 0; Slice < m_Attribs.MaxSlices; ++Slice) { - // TODO: handle resize - return RefCntAutoPtr<TextureAllocation>{}; + SliceManager* pSliceMgr = nullptr; + { + std::lock_guard<std::mutex> Lock{m_SlicesMtx}; + if (Slice == m_Slices.size()) + { + for (Uint32 ExtraSlice = 0; ExtraSlice < m_Attribs.ExtraSliceCount && Slice + ExtraSlice < m_Attribs.MaxSlices; ++ExtraSlice) + { + m_Slices.emplace_back(new SliceManager{TexDesc.Width / Granularity, TexDesc.Height / Granularity}); + } + } + pSliceMgr = m_Slices[Slice].get(); + } + + auto Region = pSliceMgr->Allocate((Width + Granularity - 1) / Granularity, (Height + Granularity - 1) / Granularity); + if (!Region.IsEmpty()) + { + Region.x *= Granularity; + Region.y *= Granularity; + Region.width *= Granularity; + Region.height *= Granularity; + + return RefCntAutoPtr<TextureAllocation>{ + MakeNewRCObj<TextureAllocation>()( + RefCntAutoPtr<GLTFResourceManager>{&m_Owner}, + *this, + Width, + Height, + Slice, + std::move(Region) // + ) // + }; + } } + + return RefCntAutoPtr<TextureAllocation>{}; } -void GLTFResourceManager::TextureCache::FreeAllocation(DynamicAtlasManager::Region&& Allocation) +void GLTFResourceManager::TextureCache::FreeAllocation(Uint32 Slice, DynamicAtlasManager::Region&& Allocation) { - VERIFY((Allocation.x % m_Granularity) == 0, "Allocation x (", Allocation.x, ") is not multiple of granularity (", m_Granularity, ")"); - VERIFY((Allocation.y % m_Granularity) == 0, "Allocation y (", Allocation.y, ") is not multiple of granularity (", m_Granularity, ")"); - VERIFY((Allocation.width % m_Granularity) == 0, "Allocation width (", Allocation.width, ") is not multiple of granularity (", m_Granularity, ")"); - VERIFY((Allocation.height % m_Granularity) == 0, "Allocation height (", Allocation.height, ") is not multiple of granularity (", m_Granularity, ")"); - - Allocation.x /= m_Granularity; - Allocation.y /= m_Granularity; - Allocation.width /= m_Granularity; - Allocation.height /= m_Granularity; - - std::lock_guard<std::mutex> Lock{m_Mtx}; - m_Mgr.Free(std::move(Allocation)); + const auto Granularity = m_Attribs.Granularity; + VERIFY((Allocation.x % Granularity) == 0, "Allocation x (", Allocation.x, ") is not multiple of granularity (", Granularity, ")"); + VERIFY((Allocation.y % Granularity) == 0, "Allocation y (", Allocation.y, ") is not multiple of granularity (", Granularity, ")"); + VERIFY((Allocation.width % Granularity) == 0, "Allocation width (", Allocation.width, ") is not multiple of granularity (", Granularity, ")"); + VERIFY((Allocation.height % Granularity) == 0, "Allocation height (", Allocation.height, ") is not multiple of granularity (", Granularity, ")"); + + Allocation.x /= Granularity; + Allocation.y /= Granularity; + Allocation.width /= Granularity; + Allocation.height /= Granularity; + + SliceManager* pSliceMgr = nullptr; + { + std::lock_guard<std::mutex> Lock{m_SlicesMtx}; + pSliceMgr = m_Slices[Slice].get(); + } + pSliceMgr->Free(std::move(Allocation)); } @@ -169,7 +237,9 @@ RefCntAutoPtr<GLTFResourceManager> GLTFResourceManager::Create(IRenderDevice* GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters, IRenderDevice* pDevice, const CreateInfo& CI) : - TBase{pRefCounters} + TBase{pRefCounters}, + m_DefaultTexDesc{CI.DefaultTexDesc}, + m_DefaultExtraSliceCount{CI.DefaultExtraSliceCount} { m_Buffers.reserve(CI.NumBuffers); for (Uint32 i = 0; i < CI.NumBuffers; ++i) @@ -180,7 +250,7 @@ GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters, m_Textures.reserve(CI.NumTextures); for (Uint32 i = 0; i < CI.NumTextures; ++i) { - m_Textures.emplace_back(*this, pDevice, CI.Textures[i]); + m_Textures.emplace(CI.Textures[i].Desc.Format, TextureCache{*this, pDevice, CI.Textures[i]}); } } @@ -202,10 +272,10 @@ RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::FindA } RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::AllocateTextureSpace( - Uint32 TextureIndex, - Uint32 Width, - Uint32 Height, - const char* CacheId) + TEXTURE_FORMAT Fmt, + Uint32 Width, + Uint32 Height, + const char* CacheId) { RefCntAutoPtr<TextureAllocation> pAllocation; if (CacheId != nullptr && *CacheId != 0) @@ -215,7 +285,23 @@ RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::Alloc if (!pAllocation) { - pAllocation = m_Textures[TextureIndex].Allocate(Width, Height); + decltype(m_Textures)::iterator cache_it; // NB: can't initialize it without locking the mutex + { + std::lock_guard<std::mutex> Lock{m_TexturesMtx}; + cache_it = m_Textures.find(Fmt); + if (cache_it == m_Textures.end()) + { + TextureCacheAttribs NewCacheAttribs; + NewCacheAttribs.Desc = m_DefaultTexDesc; + + NewCacheAttribs.Desc.Name = "GLTF Texture cache"; + NewCacheAttribs.Desc.Format = Fmt; + + cache_it = m_Textures.emplace(Fmt, TextureCache{*this, nullptr, NewCacheAttribs}).first; + } + } + // Allocate outside of mutex + pAllocation = cache_it->second.Allocate(Width, Height); } if (CacheId != nullptr && *CacheId != 0) |
