git.s-ol.nu ~forks/DiligentTools / e3bad5a
GLTF Resource manager: implemented texture array resizing assiduous 11 months ago
4 changed file(s) with 257 addition(s) and 88 deletion(s). Raw diff Collapse all Expand all
6060 Uint8 IndexBufferIdx = 0;
6161 Uint8 VertexBuffer0Idx = 0;
6262 Uint8 VertexBuffer1Idx = 0;
63
64 TEXTURE_FORMAT BaseColorFormat = TEX_FORMAT_RGBA8_UNORM;
65 TEXTURE_FORMAT PhysicalDescFormat = TEX_FORMAT_RGBA8_UNORM;
66 TEXTURE_FORMAT NormalFormat = TEX_FORMAT_RGBA8_UNORM;
67 TEXTURE_FORMAT OcclusionFormat = TEX_FORMAT_RGBA8_UNORM;
68 TEXTURE_FORMAT EmissiveFormat = TEX_FORMAT_RGBA8_UNORM;
6369 };
6470
6571 struct Material
387393 return Textures[Index].UVScaleBias;
388394 }
389395
396 float GetSlice(Uint32 Index)
397 {
398 return Textures[Index].Slice;
399 }
400
390401 private:
391402 void LoadFromFile(IRenderDevice* pDevice,
392403 IDeviceContext* pContext,
432443 {
433444 RefCntAutoPtr<ITexture> pTexture;
434445 float4 UVScaleBias{1, 1, 0, 0};
446 float Slice = 0;
435447
436448 RefCntAutoPtr<GLTFResourceManager::TextureAllocation> pCacheAllocation;
437449
2929 #include <mutex>
3030 #include <vector>
3131 #include <unordered_map>
32 #include <atomic>
3233
3334 #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/RenderDevice.h"
3435 #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/DeviceContext.h"
9697 TextureCache& ParentCache,
9798 Uint32 Width,
9899 Uint32 Height,
100 Uint32 Slice,
99101 DynamicAtlasManager::Region&& Region) :
100102 // clang-format off
101103 ObjectBase<IObject>{pRefCounters},
103105 m_ParentCache {ParentCache},
104106 m_Width {Width},
105107 m_Height {Height},
108 m_Slice {Slice},
106109 m_Region {std::move(Region)}
107110 // clang-format on
108111 {
111114
112115 ~TextureAllocation()
113116 {
114 m_ParentCache.FreeAllocation(std::move(m_Region));
117 m_ParentCache.FreeAllocation(m_Slice, std::move(m_Region));
115118 }
116119
117120 ITexture* GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext) const
131134
132135 Uint32 GetWidth() const { return m_Width; }
133136 Uint32 GetHeight() const { return m_Height; }
137 Uint32 GetSlice() const { return m_Slice; }
134138
135139 private:
136140 RefCntAutoPtr<GLTFResourceManager> m_pResMgr;
137141 TextureCache& m_ParentCache;
138142 const Uint32 m_Width;
139143 const Uint32 m_Height;
144 const Uint32 m_Slice;
140145 DynamicAtlasManager::Region m_Region;
141146 };
142147
143148 struct TextureCacheAttribs
144149 {
145150 TextureDesc Desc;
146 Uint32 Granularity = 128;
151
152 Uint32 Granularity = 128;
153 Uint32 ExtraSliceCount = 2;
154 Uint32 MaxSlices = 2048;
147155 };
148156 struct CreateInfo
149157 {
152160
153161 const TextureCacheAttribs* Textures = nullptr; // [NumTextures]
154162 Uint32 NumTextures = 0;
163
164 TextureDesc DefaultTexDesc;
165
166 Uint32 DefaultExtraSliceCount = 1;
155167 };
156168
157169 static RefCntAutoPtr<GLTFResourceManager> Create(IRenderDevice* pDevice,
162174 return m_Buffers[BufferIndex].Allocate(Size, Alignment);
163175 }
164176
165 RefCntAutoPtr<TextureAllocation> AllocateTextureSpace(Uint32 TextureIndex, Uint32 Width, Uint32 Height, const char* CacheId = nullptr);
177 RefCntAutoPtr<TextureAllocation> AllocateTextureSpace(TEXTURE_FORMAT Fmt, Uint32 Width, Uint32 Height, const char* CacheId = nullptr);
166178
167179 RefCntAutoPtr<TextureAllocation> FindAllocation(const char* CacheId);
180
181 Uint32 GetResourceVersion() const
182 {
183 return m_ResourceVersion.load();
184 }
185
186 IBuffer* GetBuffer(Uint32 Index, IRenderDevice* pDevice, IDeviceContext* pContext)
187 {
188 return m_Buffers[Index].GetBuffer(pDevice, pContext);
189 }
190 ITexture* GetTexture(TEXTURE_FORMAT Fmt, IRenderDevice* pDevice, IDeviceContext* pContext)
191 {
192 decltype(m_Textures)::iterator cache_it; // NB: can't initialize it without locking the mutex
193 {
194 std::lock_guard<std::mutex> Lock{m_TexturesMtx};
195 cache_it = m_Textures.find(Fmt);
196 if (cache_it == m_Textures.end())
197 return nullptr;
198 }
199
200 return cache_it->second.GetTexture(pDevice, pContext);
201 }
168202
169203 private:
170204 template <typename AllocatorType, typename ObjectType>
226260
227261 TextureCache(TextureCache&& Cache) noexcept :
228262 // clang-format off
229 m_Owner {Cache.m_Owner},
230 m_TexDesc {m_TexDesc},
231 m_TexName {std::move(m_TexName)},
232 m_Granularity{Cache.m_Granularity},
233 m_Mgr {std::move(Cache.m_Mgr)},
234 m_pTexture {std::move(Cache.m_pTexture)}
235 // clang-format on
236 {
237 m_TexDesc.Name = m_TexName.c_str();
263 m_Owner {Cache.m_Owner},
264 m_Attribs {Cache.m_Attribs},
265 m_TexName {std::move(m_TexName)},
266 m_Slices {std::move(Cache.m_Slices)},
267 m_pTexture{std::move(Cache.m_pTexture)}
268 // clang-format on
269 {
270 m_Attribs.Desc.Name = m_TexName.c_str();
238271 }
239272
240273 ITexture* GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext);
241274
242275 const TextureDesc& GetTexDesc() const
243276 {
244 return m_TexDesc;
277 return m_Attribs.Desc;
245278 }
246279
247280 RefCntAutoPtr<TextureAllocation> Allocate(Uint32 Width, Uint32 Height);
248281
249 void FreeAllocation(DynamicAtlasManager::Region&& Allocation);
282 void FreeAllocation(Uint32 Slice, DynamicAtlasManager::Region&& Allocation);
250283
251284 private:
252285 GLTFResourceManager& m_Owner;
253286
254 TextureDesc m_TexDesc;
287 TextureCacheAttribs m_Attribs;
288
255289 std::string m_TexName;
256290
257 const Uint32 m_Granularity;
258
259 std::mutex m_Mtx;
260 DynamicAtlasManager m_Mgr;
291 struct SliceManager
292 {
293 SliceManager(Uint32 Width, Uint32 Height) :
294 Mgr{Width, Height}
295 {}
296
297 DynamicAtlasManager::Region Allocate(Uint32 Width, Uint32 Height)
298 {
299 std::lock_guard<std::mutex> Lock{Mtx};
300 return Mgr.Allocate(Width, Height);
301 }
302 void Free(DynamicAtlasManager::Region&& Region)
303 {
304 std::lock_guard<std::mutex> Lock{Mtx};
305 Mgr.Free(std::move(Region));
306 }
307
308 private:
309 std::mutex Mtx;
310 DynamicAtlasManager Mgr;
311 };
312 std::mutex m_SlicesMtx;
313 std::vector<std::unique_ptr<SliceManager>> m_Slices;
314
261315 RefCntAutoPtr<ITexture> m_pTexture;
262316 };
263 std::vector<TextureCache> m_Textures;
317
318 TextureDesc m_DefaultTexDesc;
319 const Uint32 m_DefaultExtraSliceCount;
320
321
322 std::mutex m_TexturesMtx;
323 std::unordered_map<TEXTURE_FORMAT, TextureCache> m_Textures;
264324
265325 std::mutex m_AllocationsMtx;
266326 std::unordered_map<std::string, RefCntWeakPtr<TextureAllocation>> m_Allocations;
327
328 std::atomic_uint32_t m_ResourceVersion = {};
267329 };
268330
269331 } // namespace Diligent
698698 TexInfo.UVScaleBias.y = static_cast<float>(gltf_image.height) / static_cast<float>(TexDesc.Height);
699699 TexInfo.UVScaleBias.z = static_cast<float>(Region.x) / static_cast<float>(TexDesc.Width);
700700 TexInfo.UVScaleBias.w = static_cast<float>(Region.y) / static_cast<float>(TexDesc.Height);
701
702 TexInfo.Slice = static_cast<float>(TexInfo.pCacheAllocation->GetSlice());
701703 }
702704 }
703705 else if (pTextureCache != nullptr)
748750 {
749751 if (CacheInfo.pResourceMgr != nullptr)
750752 {
751 TexInfo.pCacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(0, gltf_image.width, gltf_image.height);
753 TexInfo.pCacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(TEX_FORMAT_RGBA8_UNORM, gltf_image.width, gltf_image.height);
752754 if (TexInfo.pCacheAllocation)
753755 {
754756 const auto& TexDesc = TexInfo.pCacheAllocation->GetTexDesc();
760762 TexInfo.UVScaleBias.y = static_cast<float>(gltf_image.height) / static_cast<float>(TexDesc.Height);
761763 TexInfo.UVScaleBias.z = static_cast<float>(Region.x) / static_cast<float>(TexDesc.Width);
762764 TexInfo.UVScaleBias.w = static_cast<float>(Region.y) / static_cast<float>(TexDesc.Height);
765
766 TexInfo.Slice = static_cast<float>(TexInfo.pCacheAllocation->GetSlice());
763767 }
764768 }
765769 else
778782 pDevice->CreateTexture(TexDesc, nullptr, &TexInfo.pTexture);
779783 TexInfo.pTexture->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)->SetSampler(pSampler);
780784 TexInfo.UVScaleBias = float4{1, 1, 0, 0};
785 TexInfo.Slice = 0;
781786
782787 TexInitData = PrepareGLTFTextureInitData(gltf_image, AlphaCutoff, 0, 0, 1);
783788 }
859864 const auto& Level = Levels[mip];
860865
861866 TextureSubResData SubresData{Level.Data.data(), Level.Stride};
862 pCtx->UpdateTexture(pTexture, mip, 0, Level.UpdateBox, SubresData, RESOURCE_STATE_TRANSITION_MODE_NONE, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
867 pCtx->UpdateTexture(pTexture, mip, static_cast<Uint32>(Textures[i].Slice), Level.UpdateBox, SubresData, RESOURCE_STATE_TRANSITION_MODE_NONE, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
863868 }
864869
865870 if (Levels.size() == 1 && pTexture->GetDesc().MipLevels > 1)
992997 const Material::TEXTURE_ID TextureId;
993998 float& UVSelector;
994999 float4& UVScaleBias;
1000 float& Slice;
9951001 const char* const TextureName;
9961002 const tinygltf::ParameterMap& Params;
9971003 };
9981004 // clang-format off
9991005 std::array<TextureParameterInfo, 5> TextureParams =
10001006 {
1001 TextureParameterInfo{Material::TEXTURE_ID_BASE_COLOR, Mat.Attribs.BaseColorUVSelector, Mat.Attribs.BaseColorUVScaleBias, "baseColorTexture", gltf_mat.values},
1002 TextureParameterInfo{Material::TEXTURE_ID_PHYSICAL_DESC, Mat.Attribs.PhysicalDescriptorUVSelector, Mat.Attribs.PhysicalDescriptorUVScaleBias, "metallicRoughnessTexture", gltf_mat.values},
1003 TextureParameterInfo{Material::TEXTURE_ID_NORMAL_MAP, Mat.Attribs.NormalUVSelector, Mat.Attribs.NormalUVScaleBias, "normalTexture", gltf_mat.additionalValues},
1004 TextureParameterInfo{Material::TEXTURE_ID_OCCLUSION, Mat.Attribs.OcclusionUVSelector, Mat.Attribs.OcclusionUVScaleBias, "occlusionTexture", gltf_mat.additionalValues},
1005 TextureParameterInfo{Material::TEXTURE_ID_EMISSIVE, Mat.Attribs.EmissiveUVSelector, Mat.Attribs.EmissiveUVScaleBias, "emissiveTexture", gltf_mat.additionalValues}
1007 TextureParameterInfo{Material::TEXTURE_ID_BASE_COLOR, Mat.Attribs.BaseColorUVSelector, Mat.Attribs.BaseColorUVScaleBias, Mat.Attribs.BaseColorSlice, "baseColorTexture", gltf_mat.values},
1008 TextureParameterInfo{Material::TEXTURE_ID_PHYSICAL_DESC, Mat.Attribs.PhysicalDescriptorUVSelector, Mat.Attribs.PhysicalDescriptorUVScaleBias, Mat.Attribs.PhysicalDescriptorSlice, "metallicRoughnessTexture", gltf_mat.values},
1009 TextureParameterInfo{Material::TEXTURE_ID_NORMAL_MAP, Mat.Attribs.NormalUVSelector, Mat.Attribs.NormalUVScaleBias, Mat.Attribs.NormalSlice, "normalTexture", gltf_mat.additionalValues},
1010 TextureParameterInfo{Material::TEXTURE_ID_OCCLUSION, Mat.Attribs.OcclusionUVSelector, Mat.Attribs.OcclusionUVScaleBias, Mat.Attribs.OcclusionSlice, "occlusionTexture", gltf_mat.additionalValues},
1011 TextureParameterInfo{Material::TEXTURE_ID_EMISSIVE, Mat.Attribs.EmissiveUVSelector, Mat.Attribs.EmissiveUVScaleBias, Mat.Attribs.EmissiveSlice, "emissiveTexture", gltf_mat.additionalValues}
10061012 };
10071013 // clang-format on
10081014
11241130 {
11251131 auto TexIndex = Mat.TextureIds[Param.TextureId];
11261132 if (TexIndex >= 0)
1133 {
11271134 Param.UVScaleBias = GetUVScaleBias(TexIndex);
1135 Param.Slice = GetSlice(TexIndex);
1136 }
11281137 }
11291138
11301139 Materials.push_back(Mat);
9090 IRenderDevice* pDevice,
9191 const TextureCacheAttribs& CacheCI) :
9292 m_Owner{Owner},
93 m_TexDesc{CacheCI.Desc},
94 m_Mgr{CacheCI.Desc.Width / CacheCI.Granularity, CacheCI.Desc.Height / CacheCI.Granularity},
95 m_Granularity{CacheCI.Granularity}
96 {
97 m_TexDesc.Name = m_TexName.c_str();
98
99 DEV_CHECK_ERR(IsPowerOfTwo(CacheCI.Granularity), "Granularity (", CacheCI.Granularity, ") must be a power of two");
100 DEV_CHECK_ERR((CacheCI.Desc.Width % CacheCI.Granularity) == 0, "Atlas width (", CacheCI.Desc.Width, ") is not multiple of granularity (", CacheCI.Granularity, ")");
101 DEV_CHECK_ERR((CacheCI.Desc.Height % CacheCI.Granularity) == 0, "Atlas height (", CacheCI.Desc.Height, ") is not multiple of granularity (", CacheCI.Granularity, ")");
102
103 pDevice->CreateTexture(CacheCI.Desc, nullptr, &m_pTexture);
93 m_Attribs{CacheCI}
94 {
95 m_Attribs.Desc.Name = m_TexName.c_str();
96
97 const auto& Desc = m_Attribs.Desc;
98 for (Uint32 slice = 0; slice < Desc.ArraySize; ++slice)
99 {
100 m_Slices.emplace_back(new SliceManager{Desc.Width / m_Attribs.Granularity, Desc.Height / m_Attribs.Granularity});
101 }
102
103 DEV_CHECK_ERR(IsPowerOfTwo(m_Attribs.Granularity), "Granularity (", m_Attribs.Granularity, ") must be a power of two");
104 DEV_CHECK_ERR((Desc.Width % m_Attribs.Granularity) == 0, "Atlas width (", Desc.Width, ") is not multiple of granularity (", m_Attribs.Granularity, ")");
105 DEV_CHECK_ERR((Desc.Height % m_Attribs.Granularity) == 0, "Atlas height (", Desc.Height, ") is not multiple of granularity (", m_Attribs.Granularity, ")");
106
107 if (pDevice != nullptr)
108 {
109 pDevice->CreateTexture(Desc, nullptr, &m_pTexture);
110 }
104111 }
105112
106113
107114 ITexture* GLTFResourceManager::TextureCache::GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext)
108115 {
109 // TODO: handle resizes
116 RefCntAutoPtr<ITexture> pNewTexture;
117 {
118 std::lock_guard<std::mutex> Lock{m_SlicesMtx};
119 if (!m_pTexture || m_pTexture->GetDesc().ArraySize < m_Slices.size())
120 {
121 m_Attribs.Desc.ArraySize = static_cast<Uint32>(m_Slices.size());
122 VERIFY_EXPR(pDevice != nullptr);
123 pDevice->CreateTexture(m_Attribs.Desc, nullptr, &pNewTexture);
124 }
125 if (pNewTexture)
126 {
127 if (m_pTexture)
128 {
129 const auto& OldDesc = m_pTexture->GetDesc();
130
131 CopyTextureAttribs CopyAttribs;
132 CopyAttribs.pSrcTexture = m_pTexture;
133 CopyAttribs.pDstTexture = pNewTexture;
134 CopyAttribs.SrcTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
135 CopyAttribs.DstTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION;
136
137 for (Uint32 slice = 0; slice < OldDesc.ArraySize; ++slice)
138 {
139 for (Uint32 mip = 0; mip < OldDesc.MipLevels; ++mip)
140 {
141 CopyAttribs.SrcSlice = slice;
142 CopyAttribs.DstSlice = slice;
143 CopyAttribs.SrcMipLevel = mip;
144 CopyAttribs.DstMipLevel = mip;
145 pContext->CopyTexture(CopyAttribs);
146 }
147 }
148 }
149 m_pTexture = std::move(pNewTexture);
150 m_Owner.m_ResourceVersion.fetch_add(1);
151 }
152 }
153
110154 return m_pTexture;
111155 }
112156
113157 RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::TextureCache::Allocate(Uint32 Width, Uint32 Height)
114158 {
115159 VERIFY_EXPR(Width > 0 && Height > 0);
116
117 std::lock_guard<std::mutex> Lock{m_Mtx};
118
119 auto Region = m_Mgr.Allocate((Width + m_Granularity - 1) / m_Granularity, (Height + m_Granularity - 1) / m_Granularity);
120 if (!Region.IsEmpty())
121 {
122 Region.x *= m_Granularity;
123 Region.y *= m_Granularity;
124 Region.width *= m_Granularity;
125 Region.height *= m_Granularity;
126
127 return RefCntAutoPtr<TextureAllocation>{
128 MakeNewRCObj<TextureAllocation>()(
129 RefCntAutoPtr<GLTFResourceManager>{&m_Owner},
130 *this,
131 Width,
132 Height,
133 std::move(Region) //
134 ) //
135 };
136 }
137 else
138 {
139 // TODO: handle resize
140 return RefCntAutoPtr<TextureAllocation>{};
141 }
142 }
143
144 void GLTFResourceManager::TextureCache::FreeAllocation(DynamicAtlasManager::Region&& Allocation)
145 {
146 VERIFY((Allocation.x % m_Granularity) == 0, "Allocation x (", Allocation.x, ") is not multiple of granularity (", m_Granularity, ")");
147 VERIFY((Allocation.y % m_Granularity) == 0, "Allocation y (", Allocation.y, ") is not multiple of granularity (", m_Granularity, ")");
148 VERIFY((Allocation.width % m_Granularity) == 0, "Allocation width (", Allocation.width, ") is not multiple of granularity (", m_Granularity, ")");
149 VERIFY((Allocation.height % m_Granularity) == 0, "Allocation height (", Allocation.height, ") is not multiple of granularity (", m_Granularity, ")");
150
151 Allocation.x /= m_Granularity;
152 Allocation.y /= m_Granularity;
153 Allocation.width /= m_Granularity;
154 Allocation.height /= m_Granularity;
155
156 std::lock_guard<std::mutex> Lock{m_Mtx};
157 m_Mgr.Free(std::move(Allocation));
160 const auto& TexDesc = m_Attribs.Desc;
161 if (Width > TexDesc.Width || Height > TexDesc.Height)
162 {
163 LOG_ERROR_MESSAGE("Requested size ", Width, " x ", Height, " exceeds the texture size ", TexDesc.Width, " x ", TexDesc.Height);
164 return {};
165 }
166
167 const auto Granularity = m_Attribs.Granularity;
168 for (Uint32 Slice = 0; Slice < m_Attribs.MaxSlices; ++Slice)
169 {
170 SliceManager* pSliceMgr = nullptr;
171 {
172 std::lock_guard<std::mutex> Lock{m_SlicesMtx};
173 if (Slice == m_Slices.size())
174 {
175 for (Uint32 ExtraSlice = 0; ExtraSlice < m_Attribs.ExtraSliceCount && Slice + ExtraSlice < m_Attribs.MaxSlices; ++ExtraSlice)
176 {
177 m_Slices.emplace_back(new SliceManager{TexDesc.Width / Granularity, TexDesc.Height / Granularity});
178 }
179 }
180 pSliceMgr = m_Slices[Slice].get();
181 }
182
183 auto Region = pSliceMgr->Allocate((Width + Granularity - 1) / Granularity, (Height + Granularity - 1) / Granularity);
184 if (!Region.IsEmpty())
185 {
186 Region.x *= Granularity;
187 Region.y *= Granularity;
188 Region.width *= Granularity;
189 Region.height *= Granularity;
190
191 return RefCntAutoPtr<TextureAllocation>{
192 MakeNewRCObj<TextureAllocation>()(
193 RefCntAutoPtr<GLTFResourceManager>{&m_Owner},
194 *this,
195 Width,
196 Height,
197 Slice,
198 std::move(Region) //
199 ) //
200 };
201 }
202 }
203
204 return RefCntAutoPtr<TextureAllocation>{};
205 }
206
207 void GLTFResourceManager::TextureCache::FreeAllocation(Uint32 Slice, DynamicAtlasManager::Region&& Allocation)
208 {
209 const auto Granularity = m_Attribs.Granularity;
210 VERIFY((Allocation.x % Granularity) == 0, "Allocation x (", Allocation.x, ") is not multiple of granularity (", Granularity, ")");
211 VERIFY((Allocation.y % Granularity) == 0, "Allocation y (", Allocation.y, ") is not multiple of granularity (", Granularity, ")");
212 VERIFY((Allocation.width % Granularity) == 0, "Allocation width (", Allocation.width, ") is not multiple of granularity (", Granularity, ")");
213 VERIFY((Allocation.height % Granularity) == 0, "Allocation height (", Allocation.height, ") is not multiple of granularity (", Granularity, ")");
214
215 Allocation.x /= Granularity;
216 Allocation.y /= Granularity;
217 Allocation.width /= Granularity;
218 Allocation.height /= Granularity;
219
220 SliceManager* pSliceMgr = nullptr;
221 {
222 std::lock_guard<std::mutex> Lock{m_SlicesMtx};
223 pSliceMgr = m_Slices[Slice].get();
224 }
225 pSliceMgr->Free(std::move(Allocation));
158226 }
159227
160228
168236 GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters,
169237 IRenderDevice* pDevice,
170238 const CreateInfo& CI) :
171 TBase{pRefCounters}
239 TBase{pRefCounters},
240 m_DefaultTexDesc{CI.DefaultTexDesc},
241 m_DefaultExtraSliceCount{CI.DefaultExtraSliceCount}
172242 {
173243 m_Buffers.reserve(CI.NumBuffers);
174244 for (Uint32 i = 0; i < CI.NumBuffers; ++i)
179249 m_Textures.reserve(CI.NumTextures);
180250 for (Uint32 i = 0; i < CI.NumTextures; ++i)
181251 {
182 m_Textures.emplace_back(*this, pDevice, CI.Textures[i]);
252 m_Textures.emplace(CI.Textures[i].Desc.Format, TextureCache{*this, pDevice, CI.Textures[i]});
183253 }
184254 }
185255
201271 }
202272
203273 RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::AllocateTextureSpace(
204 Uint32 TextureIndex,
205 Uint32 Width,
206 Uint32 Height,
207 const char* CacheId)
274 TEXTURE_FORMAT Fmt,
275 Uint32 Width,
276 Uint32 Height,
277 const char* CacheId)
208278 {
209279 RefCntAutoPtr<TextureAllocation> pAllocation;
210280 if (CacheId != nullptr && *CacheId != 0)
214284
215285 if (!pAllocation)
216286 {
217 pAllocation = m_Textures[TextureIndex].Allocate(Width, Height);
287 decltype(m_Textures)::iterator cache_it; // NB: can't initialize it without locking the mutex
288 {
289 std::lock_guard<std::mutex> Lock{m_TexturesMtx};
290 cache_it = m_Textures.find(Fmt);
291 if (cache_it == m_Textures.end())
292 {
293 TextureCacheAttribs NewCacheAttribs;
294 NewCacheAttribs.Desc = m_DefaultTexDesc;
295
296 NewCacheAttribs.Desc.Name = "GLTF Texture cache";
297 NewCacheAttribs.Desc.Format = Fmt;
298
299 cache_it = m_Textures.emplace(Fmt, TextureCache{*this, nullptr, NewCacheAttribs}).first;
300 }
301 }
302 // Allocate outside of mutex
303 pAllocation = cache_it->second.Allocate(Width, Height);
218304 }
219305
220306 if (CacheId != nullptr && *CacheId != 0)