ezEngine  Milestone 7
ResourceManager_inl.h
1 #pragma once
2 
3 #include <Foundation/Logging/Log.h>
4 
5 template<typename ResourceType>
6 ResourceType* ezResourceManager::GetResource(const char* szResourceID, bool bIsReloadable)
7 {
8  ezResourceBase* pResource = NULL;
9 
10  const ezTempHashedString sResourceHash(szResourceID);
11 
12  EZ_LOCK(s_ResourceMutex);
13 
14  if (m_LoadedResources.TryGetValue(sResourceHash, pResource))
15  return (ResourceType*) pResource;
16 
17  const ezRTTI* pRtti = ezGetStaticRTTI<ResourceType>();
18  EZ_ASSERT_DEV(pRtti != NULL, "There is no RTTI information available for the given resource type '%s'", EZ_STRINGIZE(ResourceType));
19  EZ_ASSERT_DEV(pRtti->GetAllocator() != NULL, "There is no RTTI allocator available for the given resource type '%s'", EZ_STRINGIZE(ResourceType));
20 
21  ResourceType* pNewResource = static_cast<ResourceType*>(pRtti->GetAllocator()->Allocate());
22  pNewResource->SetUniqueID(szResourceID, bIsReloadable);
23 
24  m_LoadedResources.Insert(sResourceHash, pNewResource);
25 
26  return (ResourceType*) pNewResource;
27 }
28 
29 template<typename ResourceType>
30 ezResourceHandle<ResourceType> ezResourceManager::LoadResource(const char* szResourceID)
31 {
32  return ezResourceHandle<ResourceType>(GetResource<ResourceType>(szResourceID, true));
33 }
34 
35 template<typename ResourceType>
36 ezResourceHandle<ResourceType> ezResourceManager::LoadResource(const char* szResourceID, ezResourcePriority Priority, ezResourceHandle<ResourceType> hFallbackResource)
37 {
38  ezResourceHandle<ResourceType> hResource(GetResource<ResourceType>(szResourceID, true));
39 
40  ResourceType* pResource = ezResourceManager::BeginAcquireResource(hResource, ezResourceAcquireMode::PointerOnly, ezResourceHandle<ResourceType>(), Priority);
41 
42  if (hFallbackResource.IsValid())
43  {
44  pResource->SetFallbackResource(hFallbackResource);
45  }
46 
47  ezResourceManager::EndAcquireResource(pResource);
48 
49  return hResource;
50 }
51 
52 template<typename ResourceType>
53 ezResourceHandle<ResourceType> ezResourceManager::GetExistingResource(const char* szResourceID)
54 {
55  ezResourceBase* pResource = NULL;
56 
57  const ezTempHashedString sResourceHash(szResourceID);
58 
59  EZ_LOCK(s_ResourceMutex);
60 
61  if (m_LoadedResources.TryGetValue(sResourceHash, pResource))
62  return (ResourceType*) pResource;
63 
65 }
66 
67 template<typename ResourceType>
68 ezResourceHandle<ResourceType> ezResourceManager::CreateResource(const char* szResourceID, const typename ResourceType::DescriptorType& descriptor, const char* szResourceDescription)
69 {
70  EZ_LOG_BLOCK("ezResourceManager::CreateResource", szResourceID);
71 
72  EZ_LOCK(s_ResourceMutex);
73 
74  ezResourceHandle<ResourceType> hResource(GetResource<ResourceType>(szResourceID, false));
75 
76  ResourceType* pResource = BeginAcquireResource(hResource, ezResourceAcquireMode::PointerOnly);
77  pResource->SetResourceDescription(szResourceDescription);
78 
79  EZ_ASSERT_DEV(pResource->GetLoadingState() == ezResourceState::Unloaded, "CreateResource was called on a resource that is already created");
80 
81  // If this does not compile, you have forgotten to make ezResourceManager a friend of your resource class.
82  // which probably means that you did not derive from ezResource, which you should do!
83  static_cast<ezResource<ResourceType, typename ResourceType::DescriptorType>*>(pResource)->CallCreateResource(descriptor);
84 
85  EZ_ASSERT_DEV(pResource->GetLoadingState() != ezResourceState::Unloaded, "CreateResource did not set the loading state properly.");
86 
87  EndAcquireResource(pResource);
88 
89  return hResource;
90 }
91 
92 template<typename ResourceType>
93 ResourceType* ezResourceManager::BeginAcquireResource(const ezResourceHandle<ResourceType>& hResource, ezResourceAcquireMode mode, const ezResourceHandle<ResourceType>& hFallbackResource, ezResourcePriority Priority)
94 {
95  //EZ_LOCK(s_ResourceMutex);
96 
97  EZ_ASSERT_DEV(hResource.IsValid(), "Cannot acquire a resource through an invalid handle!");
98 
99  ResourceType* pResource = (ResourceType*) hResource.m_pResource;
100 
101  EZ_ASSERT_DEV(pResource->m_iLockCount < 20, "You probably forgot somewhere to call 'EndAcquireResource' in sync with 'BeginAcquireResource'.");
102  EZ_ASSERT_DEBUG(pResource->GetDynamicRTTI() == ezGetStaticRTTI<ResourceType>(), "The requested resource does not have the same type ('%s') as the resource handle ('%s').", pResource->GetDynamicRTTI()->GetTypeName(), ezGetStaticRTTI<ResourceType>()->GetTypeName());
103 
104  if (mode == ezResourceAcquireMode::PointerOnly ||
105  (mode == ezResourceAcquireMode::MetaInfo && pResource->GetLoadingState() >= ezResourceState::UnloadedMetaInfoAvailable))
106  {
107  pResource->m_iLockCount.Increment();
108  return pResource;
109  }
110 
111  // only set the last accessed time stamp, if it is actually needed, pointer-only access might not mean that the resource is used productively
112  pResource->m_LastAcquire = m_LastFrameUpdate;
113 
114  if (pResource->GetLoadingState() != ezResourceState::LoadedResourceMissing)
115  {
116  if (pResource->GetLoadingState() != ezResourceState::Loaded)
117  {
118  // only modify the priority, if the resource is not yet loaded
119  if (Priority != ezResourcePriority::Unchanged)
120  pResource->SetPriority(Priority);
121 
122  // will append this at the preload array, thus will be loaded immediately
123  // even after recalculating priorities, it will end up as top priority
124  InternalPreloadResource(pResource, true);
125 
126  if (mode == ezResourceAcquireMode::AllowFallback && (pResource->m_hFallback.IsValid() || hFallbackResource.IsValid() || ResourceType::GetTypeFallbackResource().IsValid()))
127  {
128  // return the fallback resource for now, if there is one
129 
130  // Fallback order is as follows:
131  // 1) Prefer any resource specific fallback resource
132  // 2) If not available, use the fallback that is given to BeginAcquireResource, as that is at least specific to the situation
133  // 3) If nothing else is available, take the fallback for the whole resource type
134 
135  if (pResource->m_hFallback.IsValid())
136  return (ResourceType*) BeginAcquireResource(pResource->m_hFallback, ezResourceAcquireMode::NoFallback);
137  else if (hFallbackResource.IsValid())
138  return (ResourceType*) BeginAcquireResource(hFallbackResource, ezResourceAcquireMode::NoFallback);
139  else
140  return (ResourceType*) BeginAcquireResource(ResourceType::GetTypeFallbackResource(), ezResourceAcquireMode::NoFallback);
141  }
142 
143  const ezResourceState RequestedState = (mode == ezResourceAcquireMode::MetaInfo) ? ezResourceState::UnloadedMetaInfoAvailable : ezResourceState::Loaded;
144 
145  // help loading until the requested resource is available
146  while ((ezInt32) pResource->GetLoadingState() < (ezInt32) RequestedState && (pResource->GetLoadingState() != ezResourceState::LoadedResourceMissing))
147  {
148  if (!m_WorkerTask[m_iCurrentWorker].IsTaskFinished())
149  ezTaskSystem::WaitForTask(&m_WorkerTask[m_iCurrentWorker]);
150  else
151  {
152  for (ezInt32 i = 0; i < 16; ++i)
153  {
154  // get the 'oldest' GPU task in the queue and try to finish that first
155  const ezInt32 iWorkerGPU = (ezResourceManager::m_iCurrentWorkerGPU + i) % 16;
156 
157  if (!m_WorkerGPU[iWorkerGPU].IsTaskFinished())
158  {
159  ezTaskSystem::WaitForTask(&m_WorkerGPU[iWorkerGPU]);
160  break; // we waited for one of them, that's enough for this round
161  }
162  }
163  }
164  }
165  }
166  else
167  {
168  // as long as there are more quality levels available, schedule the resource for more loading
169  if (pResource->m_Flags.IsSet(ezResourceFlags::IsPreloading) == false && pResource->GetNumQualityLevelsLoadable() > 0)
170  InternalPreloadResource(pResource, false);
171  }
172  }
173 
174  if (pResource->GetLoadingState() == ezResourceState::LoadedResourceMissing)
175  {
176  if (/*mode == ezResourceAcquireMode::AllowFallback && (hFallbackResource.IsValid() || */ResourceType::GetTypeMissingResource().IsValid())//)
177  {
178  // prefer the fallback given for this situation (might e.g. be a default normal map)
179  // use the type specific missing resource otherwise
180 
181  //if (hFallbackResource.IsValid())
182  // return (ResourceType*) BeginAcquireResource(hFallbackResource, ezResourceAcquireMode::NoFallback);
183  //else
184  return (ResourceType*) BeginAcquireResource(ResourceType::GetTypeMissingResource(), ezResourceAcquireMode::NoFallback);
185  }
186 
187  EZ_REPORT_FAILURE("The resource '%s' of type '%s' is missing and no fallback is available", pResource->GetResourceID().GetData(), ezGetStaticRTTI<ResourceType>()->GetTypeName());
188  return nullptr;
189  }
190 
191  pResource->m_iLockCount.Increment();
192  return pResource;
193 }
194 
195 template<typename ResourceType>
196 void ezResourceManager::EndAcquireResource(ResourceType* pResource)
197 {
198  EZ_ASSERT_DEV(pResource != NULL, "Resource Pointer cannot be NULL.");
199  EZ_ASSERT_DEV(pResource->m_iLockCount > 0, "The resource lock counter is incorrect: %i", (ezInt32) pResource->m_iLockCount);
200 
201  pResource->m_iLockCount.Decrement();
202 }
203 
204 template<typename ResourceType>
205 void ezResourceManager::PreloadResource(const ezResourceHandle<ResourceType>& hResource, ezTime tShouldBeAvailableIn)
206 {
207  ResourceType* pResource = BeginAcquireResource(hResource, ezResourceAcquireMode::PointerOnly);
208 
209  PreloadResource(pResource, tShouldBeAvailableIn);
210 
211  EndAcquireResource(pResource);
212 }
213 
214 template<typename ResourceType>
215 void ezResourceManager::ReloadResource(const ezResourceHandle<ResourceType>& hResource)
216 {
217  ResourceType* pResource = BeginAcquireResource(hResource, ezResourceAcquireMode::PointerOnly);
218 
219  ReloadResource(pResource);
220 
221  EndAcquireResource(pResource);
222 }
223 
224 template<typename ResourceType>
225 void ezResourceManager::ReloadResourcesOfType()
226 {
227  ReloadResourcesOfType(ezGetStaticRTTI<ResourceType>());
228 }
229 
230 template<typename ResourceType>
231 void ezResourceManager::SetResourceTypeLoader(ezResourceTypeLoader* creator)
232 {
233  EZ_LOCK(s_ResourceMutex);
234 
235  m_ResourceTypeLoader[ezGetStaticRTTI<ResourceType>()->GetTypeName()] = creator;
236 }
237 
238 inline void ezResourceManager::SetDefaultResourceLoader(ezResourceTypeLoader* pDefaultLoader)
239 {
240  EZ_LOCK(s_ResourceMutex);
241 
242  m_pDefaultResourceLoader = pDefaultLoader;
243 }
244