Sfoglia il codice sorgente

Simplify resource management by introducing ResourceRegistry

Daniele Bartolini 12 anni fa
parent
commit
d7788743af

+ 23 - 7
engine/resource/Resource.h

@@ -48,13 +48,12 @@ const uint32_t TEXT_TYPE					= 0x9000BF0B;
 const uint32_t MATERIAL_TYPE				= 0x46807A92;
 const uint32_t SOUND_TYPE					= 0x8E128AA1;
 
-
 /// Enumerates the loading states of a resource
 enum ResourceState
 {
-	RS_UNLOADED		= 0,		//< The resource is not loaded, so it cannot be used
-	RS_LOADING		= 1,		//< The resource loader started to load the resource but it is yet not ready to use
-	RS_LOADED		= 2			//< The resource loader finished to load the texture meaning it can be used
+	RS_UNLOADED		= 0,		// The resource is not loaded, so it cannot be used
+	RS_LOADING		= 1,		// The resource loader started to load the resource but it is yet not ready to use
+	RS_LOADED		= 2			// The resource loader finished to load the texture meaning it can be used
 };
 
 /// ResourceId uniquely identifies a resource by its name and type.
@@ -62,11 +61,28 @@ enum ResourceState
 /// the index to the resource list where it is stored.
 struct ResourceId
 {
-	uint32_t		name;		// Hashed resource name
-	uint32_t		type;		// Hashed resource type
+	bool operator==(const ResourceId& b) { return name == b.name; }
+
+	uint32_t		name;
+	uint32_t		type;
 	uint32_t		index;		// Index into the ResourceManager internal list
+};
 
-	bool operator==(const ResourceId& b) { return name == b.name && type == b.type; }
+class Allocator;
+class Bundle;
+
+typedef void*	(*ResourceLoadCallback)(Allocator& a, Bundle& b, ResourceId id);
+typedef void	(*ResourceUnloadCallback)(Allocator& a, void* resource);
+typedef void	(*ResourceOnlineCallback)(void* resource);
+typedef void	(*ResourceOfflineCallback)(void);
+
+struct ResourceCallback
+{
+	uint32_t					type;
+	ResourceLoadCallback		on_load;
+	ResourceUnloadCallback		on_unload;
+	ResourceOnlineCallback		on_online;
+	ResourceOfflineCallback		on_offline;
 };
 
 } // namespace crown

+ 6 - 36
engine/resource/ResourceLoader.cpp

@@ -25,19 +25,18 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "ResourceLoader.h"
-#include "TextureResource.h"
-#include "MeshResource.h"
-#include "SoundResource.h"
+#include "ResourceRegistry.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-ResourceLoader::ResourceLoader(Bundle& bundle) :
+ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
 	Thread("resource-loader"),
 	m_bundle(bundle),
-	m_load_queue(m_allocator),
-	m_done_queue(m_allocator)
+	m_resource_heap(resource_heap),
+	m_load_queue(default_allocator()),
+	m_done_queue(default_allocator())
 {
 }
 
@@ -50,12 +49,6 @@ void ResourceLoader::load(ResourceId resource)
 	m_load_mutex.unlock();
 }
 
-//-----------------------------------------------------------------------------
-void ResourceLoader::unload(ResourceId resource, void* data)
-{
-	unload_by_type(resource, data);
-}
-
 //-----------------------------------------------------------------------------
 uint32_t ResourceLoader::remaining() const
 {
@@ -96,7 +89,7 @@ int32_t ResourceLoader::run()
 		m_load_queue.pop_front();
 		m_load_mutex.unlock();
 
-		void* data = load_by_type(resource);
+		void* data = resource_on_load(resource.type, m_resource_heap, m_bundle, resource);
 
 		m_done_mutex.lock();
 		m_done_queue.push_back(LoadedResource(resource, data));
@@ -106,27 +99,4 @@ int32_t ResourceLoader::run()
 	return 0;
 }
 
-//-----------------------------------------------------------------------------
-void* ResourceLoader::load_by_type(ResourceId name)
-{
-	switch (name.type)
-	{
-		case TEXTURE_TYPE: return TextureResource::load(m_resource_allocator, m_bundle, name);
-		case MESH_TYPE: return MeshResource::load(m_resource_allocator, m_bundle, name);
-		case SOUND_TYPE: return SoundResource::load(m_resource_allocator, m_bundle, name);
-		default: return NULL;
-	}
-}
-
-//-----------------------------------------------------------------------------
-void ResourceLoader::unload_by_type(ResourceId name, void* data)
-{
-	switch (name.type)
-	{
-		case TEXTURE_TYPE: return TextureResource::unload(m_resource_allocator, data);
-		case MESH_TYPE: return MeshResource::unload(m_resource_allocator, data);
-		case SOUND_TYPE: return SoundResource::unload(m_resource_allocator, data);
-	}
-}
-
 } // namespace crown

+ 8 - 16
engine/resource/ResourceLoader.h

@@ -27,9 +27,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
-#include "Thread.h"
 #include "Resource.h"
-#include "HeapAllocator.h"
+#include "Thread.h"
 #include "Queue.h"
 #include "List.h"
 #include "Mutex.h"
@@ -47,21 +46,20 @@ struct LoadedResource
 };
 
 class Bundle;
+class Allocator;
 
 /// Loads resources in a background thread.
 class ResourceLoader : public Thread
 {
 public:
 
-	/// Reads the resource data from the given @a bundle.
-				ResourceLoader(Bundle& bundle);
+	/// Reads the resources data from the given @a bundle using
+	/// @a resource_heap to allocate memory for them.
+				ResourceLoader(Bundle& bundle, Allocator& resource_heap);
 
 	/// Loads the @a resource in a background thread.
 	void		load(ResourceId resource);
 
-	/// Unloads the given @a resource @a data
-	void		unload(ResourceId resource, void* data);
-
 	/// Returns the number of resources still in the loading queue.
 	uint32_t	remaining() const;
 
@@ -76,18 +74,12 @@ public:
 
 private:
 
-	void*		load_by_type(ResourceId name);
-	void		unload_by_type(ResourceId name, void* data);
-
-private:
-
-	// Used to strore resource memory
-	HeapAllocator			m_allocator;
-	HeapAllocator			m_resource_allocator;
-
 	// Whether to look for resources
 	Bundle&					m_bundle;
 
+	// Used to strore resource memory
+	Allocator&				m_resource_heap;
+
 	Queue<ResourceId>		m_load_queue;
 	List<LoadedResource>	m_done_queue;
 	Mutex					m_load_mutex;

+ 9 - 27
engine/resource/ResourceManager.cpp

@@ -29,17 +29,15 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Types.h"
 #include "ResourceManager.h"
+#include "ResourceRegistry.h"
+#include "Allocator.h"
 #include "StringUtils.h"
 #include "Hash.h"
 #include "Path.h"
-#include "Log.h"
 #include "Device.h"
 #include "Filesystem.h"
 #include "TextReader.h"
 #include "DiskFile.h"
-#include "TextureResource.h"
-#include "MeshResource.h"
-#include "SoundResource.h"
 #include "TempAllocator.h"
 #include "List.h"
 
@@ -48,9 +46,10 @@ namespace crown
 
 //-----------------------------------------------------------------------------
 ResourceManager::ResourceManager(Bundle& bundle) :
-	m_loader(bundle),
+	m_resource_heap("resource", default_allocator()),
+	m_loader(bundle, m_resource_heap),
 	m_seed(0),
-	m_resources(m_allocator)
+	m_resources(default_allocator())
 {
 	DiskFile* seed_file = device()->filesystem()->open("seed.ini", FOM_READ);
 	TextReader reader(*seed_file);
@@ -97,7 +96,7 @@ void ResourceManager::unload(ResourceId name)
 	
 	if (entry.references == 0 && entry.state == RS_LOADED)
 	{
-		m_loader.unload(name, entry.resource);
+		resource_on_unload(name.type, m_resource_heap, entry.resource);
 
 		entry.state = RS_UNLOADED;
 		entry.resource = NULL;
@@ -144,7 +143,7 @@ void ResourceManager::flush()
 {
 	while (m_loader.remaining() > 0) ;
 
-	check_load_queue();
+	poll_resource_loader();
 }
 
 //-----------------------------------------------------------------------------
@@ -154,7 +153,7 @@ uint32_t ResourceManager::seed() const
 }
 
 //-----------------------------------------------------------------------------
-void ResourceManager::check_load_queue()
+void ResourceManager::poll_resource_loader()
 {
 	if (m_loader.num_loaded() != 0)
 	{
@@ -208,24 +207,7 @@ ResourceId ResourceManager::load(uint32_t name, uint32_t type)
 //-----------------------------------------------------------------------------
 void ResourceManager::online(ResourceId name, void* resource)
 {
-	switch (name.type)
-	{
-		case TEXTURE_TYPE:
-		{
-			TextureResource::online(resource);
-			break;
-		}
-		case MESH_TYPE:
-		{
-			MeshResource::online(resource);
-			break;
-		}
-		case SOUND_TYPE:
-		{
-			SoundResource::online(resource);
-			break;
-		}
-	}
+	resource_on_online(name.type, resource);
 
 	ResourceEntry& entry = m_resources[name.index];
 	entry.resource = resource;

+ 4 - 9
engine/resource/ResourceManager.h

@@ -29,7 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "List.h"
 #include "Resource.h"
-#include "HeapAllocator.h"
+#include "ProxyAllocator.h"
 #include "ResourceLoader.h"
 
 namespace crown
@@ -59,11 +59,7 @@ public:
 
 	/// Loads the resource by @a name and returns its ResourceId.
 	/// @note
-	/// The resource data may be not immediately available,
-	/// the resource gets pushed in a queue of load requests and loadead as
-	/// soon as possible by the ResourceLoader.
-	/// You have to explicitly call is_loaded() method to check if the
-	/// loading process is actually completed.
+	/// Call is_loaded() method to check if the loading process is actually completed.
 	ResourceId				load(const char* name);
 
 	/// Unloads the @a resource, freeing up all the memory associated by it
@@ -103,16 +99,15 @@ private:
 
 	// Checks the load queue and signal the backgroud about pending
 	// requests. It is normally called only by the Device.
-	void					check_load_queue();
+	void					poll_resource_loader();
 
 	// Loads the resource by name and type and returns its ResourceId.
 	ResourceId				load(uint32_t name, uint32_t type);
-	void					unload_by_type(ResourceId name, void* resource);
 	void					online(ResourceId name, void* resource);
 
 private:
 
-	HeapAllocator			m_allocator;
+	ProxyAllocator			m_resource_heap;
 	ResourceLoader			m_loader;
 	uint32_t				m_seed;
 	List<ResourceEntry>		m_resources;

+ 101 - 0
engine/resource/ResourceRegistry.cpp

@@ -0,0 +1,101 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "ResourceRegistry.h"
+#include "TextureResource.h"
+#include "MeshResource.h"
+#include "SoundResource.h"
+
+namespace crown
+{
+
+static const ResourceCallback RESOURCE_CALLBACK_REGISTRY[] =
+{
+	{ TEXTURE_TYPE, TextureResource::load, TextureResource::unload, TextureResource::online, TextureResource::offline },
+	{ MESH_TYPE, MeshResource::load, MeshResource::unload, MeshResource::online, MeshResource::offline },
+	{ SOUND_TYPE, SoundResource::load, SoundResource::unload, SoundResource::online, SoundResource::offline },
+	{ 0, NULL, NULL, NULL, NULL }
+};
+
+//-----------------------------------------------------------------------------
+static const ResourceCallback* find_callback(uint32_t type)
+{
+	const ResourceCallback* c = RESOURCE_CALLBACK_REGISTRY;
+
+	while (c->type != 0)
+	{
+		if (c->type == type)
+		{
+			return c;
+		}
+
+		c++;
+	}
+
+	return NULL;
+}
+
+//-----------------------------------------------------------------------------
+void* resource_on_load(uint32_t type, Allocator& allocator, Bundle& bundle, ResourceId id)
+{
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_load(allocator, bundle, id);
+}
+
+//-----------------------------------------------------------------------------
+void resource_on_unload(uint32_t type, Allocator& allocator, void* resource)
+{
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_unload(allocator, resource);
+}
+
+//-----------------------------------------------------------------------------
+void resource_on_online(uint32_t type, void* resource)
+{
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_online(resource);
+}
+
+//-----------------------------------------------------------------------------
+void resource_on_offline(uint32_t type)
+{
+	const ResourceCallback* c = find_callback(type);
+
+	CE_ASSERT_NOT_NULL(c);
+
+	return c->on_offline();
+}
+
+} // namespace crown

+ 39 - 0
engine/resource/ResourceRegistry.h

@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Resource.h"
+
+namespace crown
+{
+
+void* resource_on_load(uint32_t type, Allocator& allocator, Bundle& bundle, ResourceId id);
+void resource_on_online(uint32_t type, void* resource);
+void resource_on_offline(uint32_t type);
+void resource_on_unload(uint32_t type, Allocator& allocator, void* resource);
+
+} // namespace crown