Parcourir la source

Merge branch 'master' into filesystem-mount-points

Conflicts:
	engine/resource/ResourceLoader.cpp
mikymod il y a 12 ans
Parent
commit
d51831de02

+ 2 - 2
BUILD.txt

@@ -59,8 +59,8 @@ engine on the currently supported platforms.
 
 	- Android
 
-		Building for Android is a bit involved process at the moment, we are working hard
-		to improve the system.
+		1. $ cd utils
+		2. $ ruby crown-android.rb --target <android-target> --name <project-name> --path <project-path>
 
 	You can also use the GUI front-end of CMake which can, less or more, simplify
 	the overall 'complexity' of building from the terminal.

+ 1 - 1
CMakeLists.txt

@@ -4,7 +4,7 @@ project(crown)
 
 set (CROWN_VERSION_MAJOR 0)
 set (CROWN_VERSION_MINOR 1)
-set (CROWN_VERSION_MICRO 9)
+set (CROWN_VERSION_MICRO 10)
 
 option (CROWN_BUILD_SAMPLES "Whether to build the samples" ON)
 option (CROWN_BUILD_TOOLS "Whether to build the tools" ON)

+ 1 - 0
engine/CMakeLists.txt

@@ -106,6 +106,7 @@ set (CONTAINERS_SRC
 
 set (CONTAINERS_HEADERS
 	core/containers/Queue.h
+	core/containers/PriorityQueue.h
 	core/containers/Map.h
 	core/containers/Generic.h
 	core/containers/List.h

+ 1 - 0
engine/Crown.h

@@ -62,6 +62,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "List.h"
 #include "Generic.h"
 #include "Queue.h"
+#include "PriorityQueue.h"
 #include "IdTable.h"
 
 // Core/Strings

+ 182 - 0
engine/core/containers/PriorityQueue.h

@@ -0,0 +1,182 @@
+/*
+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 <algorithm>
+#include "List.h"
+
+namespace crown
+{
+
+template <typename T>
+class PriorityQueue
+{
+public:
+
+	/// Does not allocate memory.
+					PriorityQueue(Allocator& a);
+					~PriorityQueue();
+
+	/// Returns whether the queue is empty.
+	bool			empty() const;
+
+	/// Returns the number of items in the queue.
+	uint32_t		size() const;
+
+	/// Returns the first item in the queue.
+	const T&		top() const;
+
+	/// Inserts @a item into the queue.
+	void			push(const T& item);
+
+	/// Removes the first item from the queue.
+	void			pop();
+
+	T*				begin();
+	const T*		begin() const;
+	T*				end();
+	const T*		end() const;
+
+	T&				front();
+	const T&		front() const;
+	T&				back();
+	const T&		back() const;
+
+private:
+
+	List<T>			m_queue;
+};
+
+//-----------------------------------------------------------------------------
+template <typename T>
+PriorityQueue<T>::PriorityQueue(Allocator& a) :
+	m_queue(a)
+{
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+PriorityQueue<T>::~PriorityQueue()
+{
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+bool PriorityQueue<T>::empty() const
+{
+	return m_queue.empty();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+uint32_t PriorityQueue<T>::size() const
+{
+	return m_queue.size();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+const T& PriorityQueue<T>::top() const
+{
+	return m_queue.front();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+void PriorityQueue<T>::push(const T& item)
+{
+	m_queue.push_back(item);
+
+	std::push_heap(begin(), end());
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+void PriorityQueue<T>::pop()
+{
+	std::pop_heap(begin(), end());
+
+	m_queue.pop_back();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+const T* PriorityQueue<T>::begin() const
+{
+	return m_queue.begin();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+T* PriorityQueue<T>::begin()
+{
+	return m_queue.begin();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+const T* PriorityQueue<T>::end() const
+{
+	return m_queue.end();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+T* PriorityQueue<T>::end()
+{
+	return m_queue.end();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+const T& PriorityQueue<T>::front() const
+{
+	return m_queue.front();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+T& PriorityQueue<T>::front()
+{
+	return m_queue.front();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+const T& PriorityQueue<T>::back() const
+{
+	return m_queue.back();
+}
+
+//-----------------------------------------------------------------------------
+template <typename T>
+T& PriorityQueue<T>::back()
+{
+	return m_queue.back();
+}
+
+} // namespace crown

+ 0 - 8
engine/resource/Resource.h

@@ -48,14 +48,6 @@ 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
-};
-
 /// ResourceId uniquely identifies a resource by its name and type.
 /// In order to speed up the lookup by the manager, it also keeps
 /// the index to the resource list where it is stored.

+ 55 - 40
engine/resource/ResourceLoader.cpp

@@ -26,6 +26,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "ResourceLoader.h"
 #include "ResourceRegistry.h"
+#include "Log.h"
 
 namespace crown
 {
@@ -35,69 +36,83 @@ ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
 	Thread("resource-loader"),
 	m_bundle(bundle),
 	m_resource_heap(resource_heap),
-	m_load_queue(default_allocator()),
-	m_done_queue(default_allocator())
+	m_num_requests(0),
+	m_requests(default_allocator())
 {
+	for (uint32_t i = 0; i < MAX_LOAD_REQUESTS; i++)
+	{
+		m_results[i].status = LRS_NO_INFORMATION;
+		m_results[i].data = NULL;
+	}
 }
 
 //-----------------------------------------------------------------------------
-void ResourceLoader::load(ResourceId resource)
+LoadResourceId ResourceLoader::load_resource(ResourceId resource)
 {
-	// m_load_mutex.lock();
-	// m_load_queue.push_back(resource);
-	// m_load_requests.signal();
-	// m_load_mutex.unlock();
 
-	void* data = resource_on_load(resource.type, m_resource_heap, m_bundle, resource);
-	m_done_queue.push_back(LoadedResource(resource, data));
-}
+	m_requests_mutex.lock();
 
-//-----------------------------------------------------------------------------
-uint32_t ResourceLoader::remaining() const
-{
-	return m_load_queue.size();
+	LoadResourceId lr_id = m_num_requests++;
+	LoadResource lr;
+	lr.id = lr_id;
+	lr.resource = resource;
+
+	m_requests.push_back(lr);
+
+	m_results[lr_id % MAX_LOAD_REQUESTS].status = LRS_QUEUED;
+
+	m_requests_mutex.unlock();
+
+	m_full.signal();
+
+	return lr_id;
 }
 
 //-----------------------------------------------------------------------------
-uint32_t ResourceLoader::num_loaded() const
+LoadResourceStatus ResourceLoader::load_resource_status(LoadResourceId id) const
 {
-	return m_done_queue.size();
+	if (m_num_requests - id > MAX_LOAD_REQUESTS)
+	{
+		return LRS_NO_INFORMATION;
+	}
+
+	return m_results[id % MAX_LOAD_REQUESTS].status;
 }
 
 //-----------------------------------------------------------------------------
-void ResourceLoader::get_loaded(List<LoadedResource>& l)
+void* ResourceLoader::load_resource_data(LoadResourceId id) const
 {
-	m_done_mutex.lock();
-	for (uint32_t i = 0; i < m_done_queue.size(); i++)
+	if (m_num_requests - id > MAX_LOAD_REQUESTS)
 	{
-		l.push_back(m_done_queue[i]);
+		return NULL;
 	}
 
-	m_done_queue.clear();
-	m_done_mutex.unlock();
+	return m_results[id % MAX_LOAD_REQUESTS].data;
 }
 
 //-----------------------------------------------------------------------------
 int32_t ResourceLoader::run()
 {
-	// while (!is_terminating())
-	// {
-	// 	m_load_mutex.lock();
-	// 	while (m_load_queue.size() == 0)
-	// 	{
-	// 		m_load_requests.wait(m_load_mutex);
-	// 	}
-
-	// 	ResourceId resource = m_load_queue.front();
-	// 	m_load_queue.pop_front();
-	// 	m_load_mutex.unlock();
-
-	// 	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));
-	// 	m_done_mutex.unlock();
-	// }
+	while (!is_terminating())
+	{
+		m_requests_mutex.lock();
+		while (m_requests.empty())
+		{
+			m_full.wait(m_requests_mutex);
+		}
+
+		LoadResource request = m_requests.front();
+		m_requests.pop_front();
+
+		m_requests_mutex.unlock();
+
+		m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADING;
+
+		void* data = resource_on_load(request.resource.type, m_resource_heap, m_bundle, request.resource);
+
+		m_results[request.id % MAX_LOAD_REQUESTS].data = data;
+		m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADED;
+	}
 
 	return 0;
 }

+ 35 - 21
engine/resource/ResourceLoader.h

@@ -37,16 +37,31 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-struct LoadedResource
+class Bundle;
+class Allocator;
+
+#define MAX_LOAD_REQUESTS 1024
+typedef uint32_t LoadResourceId;
+
+enum LoadResourceStatus
 {
-	LoadedResource(ResourceId r, void* d) : resource(r), data(d) {}
+	LRS_NO_INFORMATION,
+	LRS_QUEUED,
+	LRS_LOADING,
+	LRS_LOADED
+};
 
-	ResourceId	resource;
-	void*		data;
+struct LoadResource
+{
+	LoadResourceId id;
+	ResourceId resource;
 };
 
-class Bundle;
-class Allocator;
+struct LoadResourceData
+{
+	LoadResourceStatus status;
+	void* data;
+};
 
 /// Loads resources in a background thread.
 class ResourceLoader : public Thread
@@ -55,22 +70,19 @@ public:
 
 	/// Reads the resources data from the given @a bundle using
 	/// @a resource_heap to allocate memory for them.
-				ResourceLoader(Bundle& bundle, Allocator& resource_heap);
+							ResourceLoader(Bundle& bundle, Allocator& resource_heap);
 
 	/// Loads the @a resource in a background thread.
-	void		load(ResourceId resource);
-
-	/// Returns the number of resources still in the loading queue.
-	uint32_t	remaining() const;
+	LoadResourceId			load_resource(ResourceId resource);
 
-	/// Returns the number of resources already loaded.
-	uint32_t	num_loaded() const;
+	/// Returns the status of the given load request @a id.
+	LoadResourceStatus		load_resource_status(LoadResourceId id) const;
 
-	/// Returns a list of the last loaded resources.
-	void		get_loaded(List<LoadedResource>& l);
+	/// Returns the data which has been loaded for the given request @a id.
+	void*					load_resource_data(LoadResourceId id) const;
 
 	// Loads resources in the loading queue.
-	int32_t		run();
+	int32_t					run();
 
 private:
 
@@ -80,11 +92,13 @@ private:
 	// Used to strore resource memory
 	Allocator&				m_resource_heap;
 
-	Queue<ResourceId>		m_load_queue;
-	List<LoadedResource>	m_done_queue;
-	Mutex					m_load_mutex;
-	Mutex					m_done_mutex;
-	Cond					m_load_requests;
+	uint32_t				m_num_requests;
+	Queue<LoadResource>		m_requests;
+	LoadResourceData		m_results[MAX_LOAD_REQUESTS];
+
+	Mutex					m_requests_mutex;
+	Mutex					m_results_mutex;
+	Cond					m_full;
 };
 
 } // namespace crown

+ 20 - 17
engine/resource/ResourceManager.cpp

@@ -41,6 +41,7 @@ ResourceManager::ResourceManager(Bundle& bundle, uint32_t seed) :
 	m_resource_heap("resource", default_allocator()),
 	m_loader(bundle, m_resource_heap),
 	m_seed(seed),
+	m_pendings(default_allocator()),
 	m_resources(default_allocator())
 {
 	m_loader.start();
@@ -64,14 +65,12 @@ void ResourceManager::unload(ResourceId name)
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
 
 	ResourceEntry* entry = find(name);
-	
+
 	entry->references--;
 	
-	if (entry->references == 0 && entry->state == RS_LOADED)
+	if (entry->references == 0)
 	{
 		resource_on_unload(name.type, m_resource_heap, entry->resource);
-
-		entry->state = RS_UNLOADED;
 		entry->resource = NULL;
 	}
 }
@@ -97,7 +96,7 @@ bool ResourceManager::is_loaded(ResourceId name) const
 {
 	CE_ASSERT(has(name), "Resource not loaded: %.8X%.8X", name.name, name.type);
 
-	return find(name)->state == RS_LOADED;
+	return find(name)->resource != NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -111,9 +110,10 @@ uint32_t ResourceManager::references(ResourceId name) const
 //-----------------------------------------------------------------------------
 void ResourceManager::flush()
 {
-	while (m_loader.remaining() > 0) ;
-
-	poll_resource_loader();
+	while (!m_pendings.empty())
+	{
+		poll_resource_loader();
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -143,15 +143,16 @@ ResourceEntry* ResourceManager::find(ResourceId id) const
 //-----------------------------------------------------------------------------
 void ResourceManager::poll_resource_loader()
 {
-	if (m_loader.num_loaded() != 0)
+	if (!m_pendings.empty())
 	{
-		TempAllocator1024 alloc;
-		List<LoadedResource> loaded(alloc);
-		m_loader.get_loaded(loaded);
+		PendingRequest request = m_pendings.front();
 
-		for (uint32_t i = 0; i < loaded.size(); i++)
+		if (m_loader.load_resource_status(request.id) == LRS_LOADED)
 		{
-			online(loaded[i].resource, loaded[i].data);
+			m_pendings.pop_front();
+
+			void* data = m_loader.load_resource_data(request.id);
+			online(request.resource, data);
 		}
 	}
 }
@@ -168,14 +169,17 @@ ResourceId ResourceManager::load(ResourceId name)
 		ResourceEntry entry;
 
 		entry.id = name;
-		entry.state = RS_UNLOADED;
 		entry.references = 1;
 		entry.resource = NULL;
 
 		m_resources.push_back(entry);
 
 		// Issue request to resource loader
-		m_loader.load(name);
+		PendingRequest pr;
+		pr.resource = name;
+		pr.id = m_loader.load_resource(name);
+
+		m_pendings.push_back(pr);
 
 		return name;
 	}
@@ -193,7 +197,6 @@ void ResourceManager::online(ResourceId name, void* resource)
 
 	ResourceEntry* entry = find(name);
 	entry->resource = resource;
-	entry->state = RS_LOADED;
 }
 
 } // namespace crown

+ 8 - 1
engine/resource/ResourceManager.h

@@ -41,11 +41,16 @@ struct ResourceEntry
 	bool operator==(const ResourceEntry& b) const { return id == b.id; }
 
 	ResourceId		id;
-	ResourceState	state;
 	uint32_t		references;
 	void*			resource;
 };
 
+struct PendingRequest
+{
+	ResourceId resource;
+	LoadResourceId id;
+};
+
 class Bundle;
 
 /// Keeps track and manages resources loaded by ResourceLoader.
@@ -109,6 +114,8 @@ private:
 	ProxyAllocator			m_resource_heap;
 	ResourceLoader			m_loader;
 	uint32_t				m_seed;
+
+	Queue<PendingRequest>	m_pendings;
 	List<ResourceEntry>		m_resources;
 
 private: