Browse Source

Refactoring

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
3eddecf540

+ 5 - 0
include/anki/core/App.h

@@ -75,6 +75,11 @@ public:
 		return m_threadpool;
 	}
 
+	HeapAllocator<U8>& getAllocator()
+	{
+		return m_heapAllocator;
+	}
+
 	/// TODO
 	void quit(int code);
 

+ 1 - 1
include/anki/resource/Animation.h

@@ -65,7 +65,7 @@ public:
 class Animation
 {
 public:
-	void load(const char* filename, ResourceAllocator<U8>& alloc);
+	void load(const char* filename, ResourceInitializer& init);
 
 	/// Get a vector of all animation channels
 	const ResourceVector<AnimationChannel>& getChannels() const

+ 39 - 0
include/anki/resource/Common.h

@@ -8,9 +8,14 @@
 
 #include "anki/util/Allocator.h"
 #include "anki/util/Vector.h"
+#include "anki/util/String.h"
 
 namespace anki {
 
+// Forward
+class GlDevice;
+class ResourceManager;
+
 /// @addtogroup resource
 /// @{
 
@@ -20,12 +25,46 @@ using ResourceAllocator = HeapAllocator<T>;
 template<typename T>
 using ResourceVector = Vector<T, ResourceAllocator<T>>;
 
+using ResourceString = BasicString<char, ResourceAllocator<char>>;
+
 template<typename T>
 using TempResourceAllocator = StackAllocator<T>;
 
 template<typename T>
 using TempResourceVector = Vector<T, TempResourceAllocator<T>>;
 
+using TempResourceString = BasicString<char, TempResourceAllocator<char>>;
+
+/// Contains initialization information for the resource classes.
+class ResourceInitializer
+{
+public:
+	ResourceAllocator<U8>& m_alloc;
+	TempResourceAllocator<U8>& m_tempAlloc;
+	const char* m_cacheDir;
+	GlDevice& m_gl;
+	U16 m_maxTextureSize;
+	U16 m_anisotropyLevel;
+	ResourceManager& m_resourceManager;
+
+	ResourceInitializer(
+		ResourceAllocator<U8>& alloc, 
+		TempResourceAllocator<U8>& tempAlloc,
+		const char* cacheDir,
+		GlDevice& gl,
+		U16 maxTextureSize,
+		U16 anisotropyLevel,
+		ResourceManager& resourceManager)
+	:	m_alloc(alloc),
+		m_tempAlloc(tempAlloc),
+		m_cacheDir(cacheDir),
+		m_gl(gl),
+		m_maxTextureSize(maxTextureSize),
+		m_anisotropyLevel(anisotropyLevel),
+		m_resourceManager(resourceManager)
+	{}
+};
+
 /// @}
 
 } // end namespace anki

+ 5 - 3
include/anki/resource/Image.h

@@ -70,8 +70,6 @@ public:
 	~Image()
 	{}
 
-	/// @name Accessors
-	/// @{
 	ColorFormat getColorFormat() const
 	{
 		ANKI_ASSERT(m_colorFormat != ColorFormat::NONE);
@@ -103,7 +101,11 @@ public:
 	}
 
 	const Surface& getSurface(U mipLevel, U layer) const;
-	/// @}
+
+	ResourceAllocator<U8> getAllocator() const
+	{
+		return m_surfaces.get_allocator();
+	}
 
 	/// Load an image file
 	/// @param[in] filename The file to load

+ 17 - 22
include/anki/resource/Material.h

@@ -43,21 +43,17 @@ typedef VisitableCommonBase<
 class MaterialVariable: public MateriaVariableVisitable, public NonCopyable
 {
 public:
-	typedef MateriaVariableVisitable Base;
+	using Base = MateriaVariableVisitable;
 
-	/// @name Constructors & destructor
-	/// @{
 	MaterialVariable(const GlProgramVariable* glvar, Bool instanced)
-		: m_progVar(glvar), m_instanced(instanced)
+	:	m_progVar(glvar), 
+		m_instanced(instanced)
 	{
 		ANKI_ASSERT(m_progVar);
 	}
 
 	virtual ~MaterialVariable();
-	/// @}
 
-	/// @name Accessors
-	/// @{
 	template<typename T>
 	const T* begin() const
 	{
@@ -65,6 +61,7 @@ public:
 		auto derived = static_cast<const MaterialVariableTemplate<T>*>(this);
 		return derived->begin();
 	}
+
 	template<typename T>
 	const T* end() const
 	{
@@ -98,7 +95,6 @@ public:
 	{
 		return m_instanced;
 	}
-	/// @}
 
 private:
 	/// Keep one program variable here for easy access of the common
@@ -118,9 +114,13 @@ public:
 	/// @name Constructors/Destructor
 	/// @{
 	MaterialVariableTemplate(
-		const GlProgramVariable* glvar, Bool instanced, 
-		const TData* x, U32 size)
-	:	MaterialVariable(glvar, instanced)
+		const GlProgramVariable* glvar, 
+		Bool instanced, 
+		const TData* x, 
+		U32 size,
+		ResourceAllocator<U8> alloc)
+	:	MaterialVariable(glvar, instanced),
+		m_data(alloc)
 	{
 		setupVisitable(this);
 
@@ -162,7 +162,7 @@ public:
 	/// @}
 
 private:
-	Vector<TData> m_data;
+	ResourceVector<TData> m_data;
 };
 
 /// Contains a few properties that other classes may use. For an explanation of
@@ -313,9 +313,6 @@ public:
 	Material();
 	~Material();
 
-	/// @name Accessors
-	/// @{
-
 	/// Access the base class just for copying in other classes
 	const MaterialProperties& getBaseClass() const
 	{
@@ -323,7 +320,7 @@ public:
 	}
 
 	// Variable accessors
-	const Vector<MaterialVariable*>& getVariables() const
+	const ResourceVector<MaterialVariable*>& getVariables() const
 	{
 		return m_vars;
 	}
@@ -332,10 +329,8 @@ public:
 	{
 		return m_shaderBlockSize;
 	}
-	/// @}
 
-	GlProgramPipelineHandle getProgramPipeline(
-		const RenderingKey& key);
+	GlProgramPipelineHandle getProgramPipeline(const RenderingKey& key);
 
 	/// Get by name
 	const MaterialVariable* findVariableByName(const char* name) const
@@ -354,11 +349,11 @@ public:
 	}
 
 private:
-	Vector<MaterialVariable*> m_vars;
+	ResourceVector<MaterialVariable*> m_vars;
 	Dictionary<MaterialVariable*> m_varDict;
 
-	Vector<ProgramResourcePointer> m_progs;
-	Vector<GlProgramPipelineHandle> m_pplines;
+	ResourceVector<ProgramResourcePointer> m_progs;
+	ResourceVector<GlProgramPipelineHandle> m_pplines;
 
 	U32 m_shaderBlockSize;
 

+ 8 - 17
include/anki/resource/Mesh.h

@@ -6,10 +6,10 @@
 #ifndef ANKI_RESOURCE_MESH_H
 #define ANKI_RESOURCE_MESH_H
 
+#include "anki/resource/Common.h"
 #include "anki/Math.h"
 #include "anki/Gl.h"
 #include "anki/collision/Obb.h"
-#include "anki/util/Vector.h"
 
 namespace anki {
 
@@ -34,11 +34,10 @@ enum class VertexAttribute: U8
 class Mesh
 {
 public:
-	/// Default constructor. Do nothing
+	/// Default constructor
 	Mesh()
 	{}
 
-	/// Does nothing
 	~Mesh()
 	{}
 
@@ -98,7 +97,7 @@ public:
 	Bool isCompatible(const Mesh& other) const;
 
 	/// Load from a .mesh file
-	void load(const char* filename);
+	void load(const char* filename, ResourceInitializer& init);
 
 protected:
 	/// Per sub mesh data
@@ -110,7 +109,7 @@ protected:
 		Obb m_obb;
 	};
 
-	Vector<SubMesh> m_subMeshes;
+	ResourceVector<SubMesh> m_subMeshes;
 	U32 m_indicesCount;
 	U32 m_vertsCount;
 	Obb m_obb;
@@ -121,32 +120,24 @@ protected:
 	GlBufferHandle m_indicesBuff;
 
 	/// Create the VBOs using the mesh data
-	void createBuffers(const MeshLoader& loader);
+	void createBuffers(const MeshLoader& loader, ResourceInitializer& init);
 
 	U32 calcVertexSize() const;
 };
 
-/// A mesh that behaves as a mesh and as a collection of separate meshes
+/// A mesh that behaves as a mesh and as a collection of separate meshes.
 class BucketMesh: public Mesh
 {
 public:
-	/// Default constructor. Do nothing
+	/// Default constructor.
 	BucketMesh()
 	{}
 
-	/// Load file
-	BucketMesh(const char* filename)
-	{
-		load(filename);
-	}
-	/// @}
-
-	/// Does nothing
 	~BucketMesh()
 	{}
 
 	/// Load from a .mmesh file
-	void load(const char* filename);
+	void load(const char* filename, ResourceInitializer& init);
 };
 
 } // end namespace anki

+ 39 - 39
include/anki/resource/MeshLoader.h

@@ -6,10 +6,10 @@
 #ifndef ANKI_RESOURCE_MESH_LOADER_H
 #define ANKI_RESOURCE_MESH_LOADER_H
 
+#include "anki/resource/Common.h"
 #include "anki/Math.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Array.h"
-#include <string>
 
 namespace anki {
 
@@ -47,73 +47,76 @@ namespace anki {
 class MeshLoader
 {
 public:
+	template<typename T>
+	using MLVector = TempResourceVector<T>;
+
 	/// If two vertices have the same position and normals under the angle 
 	/// specified by this constant then combine those normals
 	static constexpr F32 NORMALS_ANGLE_MERGE = getPi<F32>() / 6;
 
 	/// Vertex weight for skeletal animation
-	struct VertexWeight
+	class VertexWeight
 	{
+	public:
 		/// Dont change this or prepare to change the skinning code in
 		/// shader
 		static const U32 MAX_BONES_PER_VERT = 4;
 
-		U16 bonesNum;
-		Array<U16, MAX_BONES_PER_VERT> boneIds;
-		Array<F16, MAX_BONES_PER_VERT> weights;
+		U16 m_bonesCount;
+		Array<U16, MAX_BONES_PER_VERT> m_boneIds;
+		Array<F16, MAX_BONES_PER_VERT> m_weights;
 	};
 
 	/// Triangle
-	struct Triangle
+	class Triangle
 	{
+	public:
 		/// An array with the vertex indexes in the mesh class
-		Array<U32, 3> vertIds;
-		Vec3 normal;
+		Array<U32, 3> m_vertIds;
+		Vec3 m_normal;
 	};
 
-	MeshLoader()
-	{}
-	MeshLoader(const char* filename)
-	{
-		load(filename);
-	}
+	MeshLoader(TempResourceAllocator<U8>& alloc);
+
+	MeshLoader(const char* filename, TempResourceAllocator<U8>& alloc);
+
 	~MeshLoader()
 	{}
 
 	/// @name Accessors
 	/// @{
-	const Vector<Vec3>& getPositions() const
+	const MLVector<Vec3>& getPositions() const
 	{
-		return positions;
+		return m_positions;
 	}
 
-	const Vector<HVec3>& getNormals() const
+	const MLVector<HVec3>& getNormals() const
 	{
-		return normalsF16;
+		return m_normalsF16;
 	}
 
-	const Vector<HVec4>& getTangents() const
+	const MLVector<HVec4>& getTangents() const
 	{
-		return tangentsF16;
+		return m_tangentsF16;
 	}
 
-	const Vector<HVec2>& getTextureCoordinates(const U32 channel) const
+	const MLVector<HVec2>& getTextureCoordinates(const U32 channel) const
 	{
-		return texCoordsF16;
+		return m_texCoordsF16;
 	}
 	U getTextureChannelsCount() const
 	{
 		return 1;
 	}
 
-	const Vector<VertexWeight>& getWeights() const
+	const MLVector<VertexWeight>& getWeights() const
 	{
-		return weights;
+		return m_weights;
 	}
 
-	const Vector<U16>& getIndices() const
+	const MLVector<U16>& getIndices() const
 	{
-		return vertIndices;
+		return m_vertIndices;
 	}
 	/// @}
 
@@ -125,27 +128,24 @@ public:
 	void load(const char* filename);
 
 private:
-	/// @name Data
-	/// @{
-	Vector<Vec3> positions; ///< Loaded from file
+	MLVector<Vec3> m_positions; ///< Loaded from file
 
-	Vector<Vec3> normals; ///< Generated
-	Vector<HVec3> normalsF16;
+	MLVector<Vec3> m_normals; ///< Generated
+	MLVector<HVec3> m_normalsF16;
 
-	Vector<Vec4> tangents; ///< Generated
-	Vector<HVec4> tangentsF16;
+	MLVector<Vec4> m_tangents; ///< Generated
+	MLVector<HVec4> m_tangentsF16;
 
 	/// Optional. One for every vert so we can use vertex arrays & VBOs
-	Vector<Vec2> texCoords;
-	Vector<HVec2> texCoordsF16;
+	MLVector<Vec2> m_texCoords;
+	MLVector<HVec2> m_texCoordsF16;
 
-	Vector<VertexWeight> weights; ///< Optional
+	MLVector<VertexWeight> m_weights; ///< Optional
 
-	Vector<Triangle> tris; ///< Required
+	MLVector<Triangle> m_tris; ///< Required
 
 	/// Generated. Used for vertex arrays & VBOs
-	Vector<U16> vertIndices;
-	/// @}
+	MLVector<U16> m_vertIndices;
 
 	void createFaceNormals();
 	void createVertNormals();

+ 18 - 6
include/anki/resource/ProgramPrePreprocessor.h

@@ -6,6 +6,7 @@
 #ifndef ANKI_RESOURCE_PROGRAM_PRE_PREPROCESSOR_H
 #define ANKI_RESOURCE_PROGRAM_PRE_PREPROCESSOR_H
 
+#include "anki/resource/ResourceManager.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StringList.h"
 
@@ -36,10 +37,18 @@ enum class ShaderType
 /// - #pragma anki include "<filename>"
 class ProgramPrePreprocessor
 {
+private:
+	using PPPStringList = BasicStringList<char, TempResourceAllocator<char>>;
+	using PPPString = TempResourceString;
+
 public:
 	/// It loads a file and parses it
 	/// @param[in] filename The file to load
-	ProgramPrePreprocessor(const char* filename)
+	ProgramPrePreprocessor(
+		const char* filename, ResourceManager* manager)
+	:	m_shaderSource(manager->_getTempAllocator()),
+		m_sourceLines(manager->_getTempAllocator()),
+		m_manager(manager)
 	{
 		parseFile(filename);
 	}
@@ -49,7 +58,7 @@ public:
 
 	/// @name Accessors
 	/// @{
-	const String& getShaderSource()
+	const PPPString& getShaderSource()
 	{
 		ANKI_ASSERT(!m_shaderSource.empty());
 		return m_shaderSource;
@@ -64,14 +73,17 @@ public:
 
 protected:
 	/// The final program source
-	String m_shaderSource;
+	PPPString m_shaderSource;
 
 	/// The parseFileForPragmas fills this
-	StringList m_sourceLines;
+	PPPStringList m_sourceLines;
 
 	/// Shader type
 	ShaderType m_type = ShaderType::COUNT;
 
+	/// Keep the manager for some path conversions.
+	ResourceManager* m_manager;
+
 	/// Parse a PrePreprocessor formated GLSL file. Use the accessors to get 
 	/// the output
 	///
@@ -84,10 +96,10 @@ protected:
 	/// @param filename The file to parse
 	/// @param depth The #line in GLSL does not support filename so an
 	///              depth it being used. It also tracks the includance depth
-	void parseFileForPragmas(const String& filename, U32 depth = 0);
+	void parseFileForPragmas(const PPPString& filename, U32 depth);
 
 	/// Parse the type
-	Bool parseType(const String& line);
+	Bool parseType(const PPPString& line);
 
 	void printSourceLines() const;  ///< For debugging
 };

+ 6 - 3
include/anki/resource/ProgramResource.h

@@ -6,6 +6,7 @@
 #ifndef ANKI_RESOURCE_PROGRAM_RESOURCE_H
 #define ANKI_RESOURCE_PROGRAM_RESOURCE_H
 
+#include "anki/resource/Common.h"
 #include "anki/Gl.h"
 
 namespace anki {
@@ -19,6 +20,7 @@ class ProgramResource
 public:
 	ProgramResource()
 	{}
+
 	~ProgramResource()
 	{}
 
@@ -28,7 +30,7 @@ public:
 	}
 
 	/// Resource load
-	void load(const char* filename);
+	void load(const char* filename, ResourceInitializer& init);
 
 	/// Load and add extra code on top of the file
 	void load(const char* filename, const char* extraSrc);
@@ -42,10 +44,11 @@ public:
 	///        ways to identify the file in the cache
 	/// @return The file pathname of the new shader prog. Its
 	///         $HOME/.anki/cache/ + filenamePrefix + hash + .glsl
-	static std::string createSrcCodeToCache(
+	static String createSourceToCache(
 		const char* filename,
 		const char* preAppendedSrcCode,
-		const char* filenamePrefix);
+		const char* filenamePrefix,
+		ResourceManager& manager);
 
 private:
 	GlProgramHandle m_prog;

+ 23 - 10
include/anki/resource/ResourceManager.h

@@ -6,10 +6,11 @@
 #ifndef ANKI_RESOURCE_RESOURCE_MANAGER_H
 #define ANKI_RESOURCE_RESOURCE_MANAGER_H
 
+#include "anki/resource/Common.h"
+#include "anki/resource/ResourcePointer.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Functions.h"
 #include "anki/util/String.h"
-#include "anki/resource/ResourcePointer.h"
 
 namespace anki {
 
@@ -118,11 +119,11 @@ class ResourceManager:
 	public TypeResourceManager<TextureResource, ResourceManager>
 {
 public:
-	ResourceManager(const ConfigSet& config);
+	ResourceManager(App* app, const ConfigSet& config);
 
-	const String& getDataPath() const
+	const ResourceString& getDataDirectory() const
 	{
-		return m_dataPath;
+		return m_dataDir;
 	}
 
 	U32 getMaxTextureSize() const
@@ -135,15 +136,25 @@ public:
 		return m_textureAnisotropy;
 	}
 
-	HeapAllocator<U8>& _getAllocator()
+	TempResourceString fixResourceFilename(const char* filename) const;
+
+	/// @privatesection
+	/// @{
+	ResourceAllocator<U8>& _getAllocator()
 	{
 		return m_alloc;
 	}
 
-	String fixResourcePath(const char* filename) const;
+	TempResourceAllocator<U8>& _getTempAllocator()
+	{
+		return m_tmpAlloc;
+	}
+
+	App& _getApp()
+	{
+		return *m_app;
+	}
 
-	/// @privatesection
-	/// @{
 	template<typename T>
 	Bool _findLoadedResource(const char* filename, 
 		ResourcePointer<T, ResourceManager>& ptr)
@@ -166,8 +177,10 @@ public:
 	/// @}
 
 private:
-	HeapAllocator<U8> m_alloc;
-	String m_dataPath;
+	App* m_app;
+	ResourceAllocator<U8> m_alloc;
+	TempResourceAllocator<U8> m_tmpAlloc;
+	ResourceString m_dataDir;
 	U32 m_maxTextureSize;
 	U32 m_textureAnisotropy;
 };

+ 0 - 1
include/anki/resource/Skin.h

@@ -8,7 +8,6 @@
 
 #include "anki/resource/Resource.h"
 #include "anki/resource/Model.h"
-#include "anki/util/Vector.h"
 
 namespace anki {
 

+ 6 - 6
include/anki/resource/TextureResource.h

@@ -6,6 +6,7 @@
 #ifndef ANKI_RESOURCE_TEXTURE_RESOURCE_H
 #define ANKI_RESOURCE_TEXTURE_RESOURCE_H
 
+#include "anki/resource/Common.h"
 #include "anki/Gl.h"
 
 namespace anki {
@@ -13,19 +14,18 @@ namespace anki {
 // Forward
 class Image;
 
-/// @addtogroup Resource
+/// @addtogroup resource
 /// @{
 
-/// Texture resource class
+/// Texture resource class.
 ///
 /// It loads or creates an image and then loads it in the GPU. It supports 
-/// compressed and uncompressed TGAs and some of the formats of PNG 
-/// (PNG loading uses libpng)
+/// compressed and uncompressed TGAs and AnKi's texture format.
 class TextureResource
 {
 public:
 	/// Load a texture
-	void load(const char* filename);
+	void load(const char* filename, ResourceInitializer& init);
 
 	/// Get the GL texture
 	const GlTextureHandle& getGlTexture() const
@@ -43,7 +43,7 @@ private:
 	GlTextureHandle m_tex;
 
 	/// Load a texture
-	void loadInternal(const char* filename);
+	void loadInternal(const char* filename, ResourceInitializer& init);
 };
 /// @}
 

+ 12 - 8
include/anki/util/Dictionary.h

@@ -16,11 +16,12 @@ namespace anki {
 /// @{
 
 /// The hash function
-struct DictionaryHasher
+class DictionaryHasher
 {
-	size_t operator()(const char* str) const
+public:
+	PtrSize operator()(const char* str) const
 	{
-		size_t h = 0;
+		PtrSize h = 0;
 		for (; *str != '\0'; ++str)
 		{
 			h += *str;
@@ -30,25 +31,28 @@ struct DictionaryHasher
 };
 
 /// The collision evaluation function
-struct DictionaryEqual
+class DictionaryEqual
 {
-	bool operator()(const char* a, const char* b) const
+public:
+	Bool operator()(const char* a, const char* b) const
 	{
-		return strcmp(a, b) == 0;
+		return std::strcmp(a, b) == 0;
 	}
 };
 
 /// The hash map that has as key an old school C string. When inserting the
 /// char MUST NOT point to a temporary or the evaluation function will fail.
 /// Its template struct because C++ does not offer template typedefs
-template<typename T, typename Alloc = std::allocator<std::pair<const char*, T>>>
+template<
+	typename T, 
+	template <typename> class TAlloc = HeapAllocator>
 using Dictionary = 
 	std::unordered_map<
 		const char*,
 		T,
 		DictionaryHasher,
 		DictionaryEqual,
-		Alloc>;
+		TAlloc<std::pair<const char*, T>>>;
 
 /// @}
 

+ 3 - 3
include/anki/util/Memory.h

@@ -61,9 +61,9 @@ public:
 	}
 
 	/// The real constructor
-	/// @param alloc The allocation function callback
-	/// @param allocUserData The user data to pass to the allocation function
-	HeapMemoryPool(AllocAlignedCallback alloc, void* allocUserData);
+	/// @param allocCb The allocation function callback
+	/// @param allocCbUserData The user data to pass to the allocation function
+	HeapMemoryPool(AllocAlignedCallback allocCb, void* allocCbUserData);
 
 	/// Destroy
 	~HeapMemoryPool()

+ 2 - 2
include/anki/util/String.h

@@ -55,7 +55,7 @@ ANKI_DEPLOY_TO_STRING(F64, "%f")
 template<typename TChar, typename TAlloc>
 using BasicString = std::basic_string<TChar, std::char_traits<TChar>, TAlloc>;
 
-using String = BasicString<char, std::allocator<char>>;
+using String = BasicString<char, HeapAllocator<char>>;
 
 /// Trim a string
 /// Remove the @p what from the front and back of @p str
@@ -79,7 +79,7 @@ inline void replaceAllString(const TString& in,
 	}
 
 	out = in;
-	size_t start_pos = 0;
+	PtrSize start_pos = 0;
 	while((start_pos = out.find(from, start_pos)) != TString::npos) 
 	{
 		out.replace(start_pos, from.length(), to);

+ 2 - 2
src/resource/Animation.cpp

@@ -10,13 +10,13 @@
 namespace anki {
 
 //==============================================================================
-void Animation::load(const char* filename, ResourceAllocator<U8>& alloc)
+void Animation::load(const char* filename, ResourceInitializer& init)
 {
 	try
 	{
 		XmlDocument doc;
 		doc.loadFile(filename);
-		loadInternal(doc.getChildElement("animation"), alloc);
+		loadInternal(doc.getChildElement("animation"), init.m_alloc);
 	}
 	catch(const std::exception& e)
 	{

+ 11 - 10
src/resource/Mesh.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/resource/Mesh.h"
-#include "anki/resource/Material.h"
 #include "anki/resource/MeshLoader.h"
 #include "anki/util/Functions.h"
 #include "anki/misc/Xml.h"
@@ -23,11 +22,11 @@ Bool Mesh::isCompatible(const Mesh& other) const
 }
 
 //==============================================================================
-void Mesh::load(const char* filename)
+void Mesh::load(const char* filename, ResourceInitializer& init)
 {
 	try
 	{
-		MeshLoader loader(filename);
+		MeshLoader loader(filename, init.m_tempAlloc);
 
 		m_indicesCount = loader.getIndices().size();
 
@@ -44,7 +43,7 @@ void Mesh::load(const char* filename)
 		m_texChannelsCount = loader.getTextureChannelsCount();
 		m_weights = loader.getWeights().size() > 1;
 
-		createBuffers(loader);
+		createBuffers(loader, init);
 	}
 	catch(std::exception& e)
 	{
@@ -67,7 +66,8 @@ U32 Mesh::calcVertexSize() const
 }
 
 //==============================================================================
-void Mesh::createBuffers(const MeshLoader& loader)
+void Mesh::createBuffers(const MeshLoader& loader,
+	ResourceInitializer& init)
 {
 	ANKI_ASSERT(m_vertsCount == loader.getPositions().size()
 		&& m_vertsCount == loader.getNormals().size()
@@ -112,7 +112,7 @@ void Mesh::createBuffers(const MeshLoader& loader)
 	}
 
 	// Create GL buffers
-	GlDevice& gl = GlDeviceSingleton::get();
+	GlDevice& gl = init.m_gl;
 	GlCommandBufferHandle jobs(&gl);
 	
 	GlClientBufferHandle clientVertBuff(jobs, vbosize, &buff[0]);
@@ -224,7 +224,7 @@ void Mesh::getBufferInfo(const VertexAttribute attrib,
 //==============================================================================
 
 //==============================================================================
-void BucketMesh::load(const char* filename)
+void BucketMesh::load(const char* filename, ResourceInitializer& init)
 {
 	try
 	{
@@ -236,10 +236,11 @@ void BucketMesh::load(const char* filename)
 		XmlElement meshEl = meshesEl.getChildElement("mesh");
 
 		m_vertsCount = 0;
+		m_subMeshes = std::move(ResourceVector<SubMesh>(init.m_alloc));
 		m_subMeshes.reserve(4);
 		m_indicesCount = 0;
 
-		MeshLoader fullLoader;
+		MeshLoader fullLoader(init.m_tempAlloc);
 		U i = 0;
 		do
 		{
@@ -248,7 +249,7 @@ void BucketMesh::load(const char* filename)
 			// Load the submesh and if not the first load the append the 
 			// vertices to the fullMesh
 			MeshLoader* loader;
-			MeshLoader subLoader;
+			MeshLoader subLoader(init.m_tempAlloc);
 			if(i != 0)
 			{
 				// Sanity check
@@ -312,7 +313,7 @@ void BucketMesh::load(const char* filename)
 		} while(meshEl);
 
 		// Create the bucket mesh
-		createBuffers(fullLoader);
+		createBuffers(fullLoader, init);
 
 		const auto& positions = fullLoader.getPositions();
 		m_obb.setFromPointCloud(&positions[0], positions.size(),

+ 141 - 100
src/resource/MeshLoader.cpp

@@ -15,30 +15,65 @@ namespace anki {
 //==============================================================================
 
 /// The hash functor
-struct Hasher
+class Hasher
 {
-	size_t operator()(const Vec3& pos) const
+public:
+	PtrSize operator()(const Vec3& pos) const
 	{
 		F32 sum = pos.x() * 100.0 + pos.y() * 10.0 + pos.z();
-		size_t hash = 0;
-		memcpy(&hash, &sum, sizeof(F32));
+		PtrSize hash = 0;
+		std::memcpy(&hash, &sum, sizeof(F32));
 		return hash;
 	}
 };
 
+/// The collision evaluation function
+class Equal
+{
+public:
+	Bool operator()(const Vec3& a, const Vec3& b) const
+	{
+		return a == b;
+	}
+};
+
 /// The value of the hash map
-struct MapValue
+class MapValue
 {
-	U8 indicesCount = 0;
-	Array<U32, 16> indices;
+public:
+	U8 m_indicesCount = 0;
+	Array<U32, 16> m_indices;
 };
 
-typedef std::unordered_map<Vec3, MapValue, Hasher> FixNormalsMap;
+using FixNormalsMap = std::unordered_map<
+	Vec3, MapValue, Hasher, Equal, 
+	TempResourceAllocator<std::pair<Vec3, MapValue>>>;
 
 //==============================================================================
 // MeshLoader                                                                  =
 //==============================================================================
 
+//==============================================================================
+MeshLoader::MeshLoader(TempResourceAllocator<U8>& alloc)
+:	m_positions(alloc),
+	m_normals(alloc),
+	m_normalsF16(alloc),
+	m_tangents(alloc),
+	m_tangentsF16(alloc),
+	m_texCoords(alloc),
+	m_texCoordsF16(alloc),
+	m_weights(alloc),
+	m_tris(alloc),
+	m_vertIndices(alloc)
+{}
+
+//==============================================================================
+MeshLoader::MeshLoader(const char* filename, TempResourceAllocator<U8>& alloc)
+:	MeshLoader(filename, alloc)
+{
+	load(filename);
+}
+
 //==============================================================================
 void MeshLoader::load(const char* filename)
 {
@@ -53,7 +88,7 @@ void MeshLoader::load(const char* filename)
 		// Magic word
 		char magic[8];
 		file.read(magic, sizeof(magic));
-		if(memcmp(magic, "ANKIMESH", 8))
+		if(std::memcmp(magic, "ANKIMESH", 8))
 		{
 			throw ANKI_EXCEPTION("Incorrect magic word");
 		}
@@ -66,10 +101,10 @@ void MeshLoader::load(const char* filename)
 
 		// Verts num
 		U vertsNum = file.readU32();
-		positions.resize(vertsNum);
+		m_positions.resize(vertsNum);
 
 		// Vert coords
-		for(Vec3& vertCoord : positions)
+		for(Vec3& vertCoord : m_positions)
 		{
 			for(U j = 0; j < 3; j++)
 			{
@@ -79,17 +114,17 @@ void MeshLoader::load(const char* filename)
 
 		// Faces num
 		U facesNum = file.readU32();
-		tris.resize(facesNum);
+		m_tris.resize(facesNum);
 
 		// Faces IDs
-		for(Triangle& tri : tris)
+		for(Triangle& tri : m_tris)
 		{
 			for(U j = 0; j < 3; j++)
 			{
-				tri.vertIds[j] = file.readU32();
+				tri.m_vertIds[j] = file.readU32();
 
 				// a sanity check
-				if(tri.vertIds[j] >= positions.size())
+				if(tri.m_vertIds[j] >= m_positions.size())
 				{
 					throw ANKI_EXCEPTION("Vert index out of bounds");
 				}
@@ -98,10 +133,10 @@ void MeshLoader::load(const char* filename)
 
 		// Tex coords num
 		U texCoordsNum = file.readU32();
-		texCoords.resize(texCoordsNum);
+		m_texCoords.resize(texCoordsNum);
 
 		// Tex coords
-		for(Vec2& texCoord : texCoords)
+		for(Vec2& texCoord : m_texCoords)
 		{
 			for(U32 i = 0; i < 2; i++)
 			{
@@ -111,10 +146,10 @@ void MeshLoader::load(const char* filename)
 
 		// Vert weights num
 		U weightsNum = file.readU32();
-		weights.resize(weightsNum);
+		m_weights.resize(weightsNum);
 
 		// Vert weights
-		for(VertexWeight& vw : weights)
+		for(VertexWeight& vw : m_weights)
 		{
 			// get the bone connections num
 			U32 boneConnections = file.readU32();
@@ -132,18 +167,18 @@ void MeshLoader::load(const char* filename)
 				throw ANKI_EXCEPTION("Cannot have more than %d "
 					"bones per vertex", tmp);
 			}
-			vw.bonesNum = boneConnections;
+			vw.m_bonesCount = boneConnections;
 
 			// for all the weights of the current vertes
-			for(U32 i = 0; i < vw.bonesNum; i++)
+			for(U32 i = 0; i < vw.m_bonesCount; i++)
 			{
 				// read bone id
 				U32 boneId = file.readU32();
-				vw.boneIds[i] = boneId;
+				vw.m_boneIds[i] = boneId;
 
 				// read the weight of that bone
 				float weight = file.readF32();
-				vw.weights[i] = weight;
+				vw.m_weights[i] = weight;
 			}
 		} // end for all vert weights
 
@@ -160,17 +195,19 @@ void MeshLoader::load(const char* filename)
 void MeshLoader::doPostLoad()
 {
 	// Sanity checks
-	if(positions.size() < 1 || tris.size() < 1)
+	if(m_positions.size() < 1 || m_tris.size() < 1)
 	{
 		throw ANKI_EXCEPTION("Vert coords and tris must be filled");
 	}
-	if(texCoords.size() != 0 && texCoords.size() != positions.size())
+
+	if(m_texCoords.size() != 0 && m_texCoords.size() != m_positions.size())
 	{
 		throw ANKI_EXCEPTION("Tex coords num must be "
 			"zero or equal to the vertex "
 			"coords num");
 	}
-	if(weights.size() != 0 && weights.size() != positions.size())
+
+	if(m_weights.size() != 0 && m_weights.size() != m_positions.size())
 	{
 		throw ANKI_EXCEPTION("Vert weights num must be zero or equal to the "
 			"vertex coords num");
@@ -178,10 +215,12 @@ void MeshLoader::doPostLoad()
 
 	createAllNormals();
 	fixNormals();
-	if(texCoords.size() > 0)
+
+	if(m_texCoords.size() > 0)
 	{
 		createVertTangents();
 	}
+
 	createVertIndeces();
 	compressBuffers();
 }
@@ -189,13 +228,13 @@ void MeshLoader::doPostLoad()
 //==============================================================================
 void MeshLoader::createVertIndeces()
 {
-	vertIndices.resize(tris.size() * 3);
+	m_vertIndices.resize(m_tris.size() * 3);
 	U j = 0;
-	for(U i = 0; i < tris.size(); ++i)
+	for(U i = 0; i < m_tris.size(); ++i)
 	{
-		vertIndices[j + 0] = tris[i].vertIds[0];
-		vertIndices[j + 1] = tris[i].vertIds[1];
-		vertIndices[j + 2] = tris[i].vertIds[2];
+		m_vertIndices[j + 0] = m_tris[i].m_vertIds[0];
+		m_vertIndices[j + 1] = m_tris[i].m_vertIds[1];
+		m_vertIndices[j + 2] = m_tris[i].m_vertIds[2];
 
 		j += 3;
 	}
@@ -204,21 +243,21 @@ void MeshLoader::createVertIndeces()
 //==============================================================================
 void MeshLoader::createFaceNormals()
 {
-	for(Triangle& tri : tris)
+	for(Triangle& tri : m_tris)
 	{
-		const Vec3& v0 = positions[tri.vertIds[0]];
-		const Vec3& v1 = positions[tri.vertIds[1]];
-		const Vec3& v2 = positions[tri.vertIds[2]];
+		const Vec3& v0 = m_positions[tri.m_vertIds[0]];
+		const Vec3& v1 = m_positions[tri.m_vertIds[1]];
+		const Vec3& v2 = m_positions[tri.m_vertIds[2]];
 
-		tri.normal = (v1 - v0).cross(v2 - v0);
+		tri.m_normal = (v1 - v0).cross(v2 - v0);
 
-		if(tri.normal != Vec3(0.0))
+		if(tri.m_normal != Vec3(0.0))
 		{
 			//tri.normal.normalize();
 		}
 		else
 		{
-			tri.normal = Vec3(1.0, 0.0, 0.0);
+			tri.m_normal = Vec3(1.0, 0.0, 0.0);
 		}
 	}
 }
@@ -226,21 +265,21 @@ void MeshLoader::createFaceNormals()
 //==============================================================================
 void MeshLoader::createVertNormals()
 {
-	normals.resize(positions.size());
+	m_normals.resize(m_positions.size());
 
-	for(Vec3& vertNormal : normals)
+	for(Vec3& vertNormal : m_normals)
 	{
 		vertNormal = Vec3(0.0);
 	}
 
-	for(Triangle& tri : tris)
+	for(Triangle& tri : m_tris)
 	{
-		normals[tri.vertIds[0]] += tri.normal;
-		normals[tri.vertIds[1]] += tri.normal;
-		normals[tri.vertIds[2]] += tri.normal;
+		m_normals[tri.m_vertIds[0]] += tri.m_normal;
+		m_normals[tri.m_vertIds[1]] += tri.m_normal;
+		m_normals[tri.m_vertIds[2]] += tri.m_normal;
 	}
 
-	for(Vec3& vertNormal : normals)
+	for(Vec3& vertNormal : m_normals)
 	{
 		if(vertNormal != Vec3(0.0))
 		{
@@ -252,25 +291,27 @@ void MeshLoader::createVertNormals()
 //==============================================================================
 void MeshLoader::createVertTangents()
 {
-	tangents.resize(positions.size(), Vec4(0.0)); // alloc
-	Vector<Vec3> bitagents(positions.size(), Vec3(0.0));
+	m_tangents.resize(m_positions.size(), Vec4(0.0)); // alloc
+	MLVector<Vec3> bitagents(
+		m_positions.size(), Vec3(0.0), m_tangents.get_allocator());
 
-	for(U32 i = 0; i < tris.size(); i++)
+	for(U32 i = 0; i < m_tris.size(); i++)
 	{
-		const Triangle& tri = tris[i];
-		const I i0 = tri.vertIds[0];
-		const I i1 = tri.vertIds[1];
-		const I i2 = tri.vertIds[2];
-		const Vec3& v0 = positions[i0];
-		const Vec3& v1 = positions[i1];
-		const Vec3& v2 = positions[i2];
+		const Triangle& tri = m_tris[i];
+		const I i0 = tri.m_vertIds[0];
+		const I i1 = tri.m_vertIds[1];
+		const I i2 = tri.m_vertIds[2];
+		const Vec3& v0 = m_positions[i0];
+		const Vec3& v1 = m_positions[i1];
+		const Vec3& v2 = m_positions[i2];
 		Vec3 edge01 = v1 - v0;
 		Vec3 edge02 = v2 - v0;
-		Vec2 uvedge01 = texCoords[i1] - texCoords[i0];
-		Vec2 uvedge02 = texCoords[i2] - texCoords[i0];
+		Vec2 uvedge01 = m_texCoords[i1] - m_texCoords[i0];
+		Vec2 uvedge02 = m_texCoords[i2] - m_texCoords[i0];
 
 		F32 det = (uvedge01.y() * uvedge02.x()) -
 			(uvedge01.x() * uvedge02.y());
+
 		if(isZero(det))
 		{
 			det = 0.0001;
@@ -290,19 +331,19 @@ void MeshLoader::createVertTangents()
 		//t.normalize();
 		//b.normalize();
 
-		tangents[i0] += Vec4(t, 1.0);
-		tangents[i1] += Vec4(t, 1.0);
-		tangents[i2] += Vec4(t, 1.0);
+		m_tangents[i0] += Vec4(t, 1.0);
+		m_tangents[i1] += Vec4(t, 1.0);
+		m_tangents[i2] += Vec4(t, 1.0);
 
 		bitagents[i0] += b;
 		bitagents[i1] += b;
 		bitagents[i2] += b;
 	}
 
-	for(U i = 0; i < tangents.size(); i++)
+	for(U i = 0; i < m_tangents.size(); i++)
 	{
-		Vec3 t = tangents[i].xyz();
-		const Vec3& n = normals[i];
+		Vec3 t = m_tangents[i].xyz();
+		const Vec3& n = m_normals[i];
 		Vec3& b = bitagents[i];
 
 		t = t - n * n.dot(t);
@@ -319,20 +360,20 @@ void MeshLoader::createVertTangents()
 
 		F32 w = ((n.cross(t)).dot(b) < 0.0) ? 1.0 : -1.0;
 
-		tangents[i] = Vec4(t, w);
+		m_tangents[i] = Vec4(t, w);
 	}
 }
 
 //==============================================================================
 void MeshLoader::fixNormals()
 {
-	FixNormalsMap map;
+	FixNormalsMap map(10, Hasher(), Equal(), m_positions.get_allocator());
 
 	// For all verts
-	for(U i = 1; i < positions.size(); i++)
+	for(U i = 1; i < m_positions.size(); i++)
 	{
-		const Vec3& pos = positions[i];
-		Vec3& norm = normals[i];
+		const Vec3& pos = m_positions[i];
+		Vec3& norm = m_normals[i];
 
 		// Find pos
 		FixNormalsMap::iterator it = map.find(pos);
@@ -343,8 +384,8 @@ void MeshLoader::fixNormals()
 			// Not found
 
 			MapValue val;
-			val.indices[0] = i;
-			val.indicesCount = 1;
+			val.m_indices[0] = i;
+			val.m_indicesCount = 1;
 			map[pos] = val;
 		}
 		else
@@ -352,13 +393,13 @@ void MeshLoader::fixNormals()
 			// Found
 
 			MapValue& mapVal = it->second;
-			ANKI_ASSERT(mapVal.indicesCount > 0);
+			ANKI_ASSERT(mapVal.m_indicesCount > 0);
 
 			// Search the verts with the same position
-			for(U j = 0; j < mapVal.indicesCount; j++)
+			for(U j = 0; j < mapVal.m_indicesCount; j++)
 			{
-				const Vec3& posB = positions[mapVal.indices[j]];
-				Vec3& normB = normals[mapVal.indices[j]];
+				const Vec3& posB = m_positions[mapVal.m_indices[j]];
+				Vec3& normB = m_normals[mapVal.m_indices[j]];
 
 				ANKI_ASSERT(posB == pos);
 				(void)posB;
@@ -377,7 +418,7 @@ void MeshLoader::fixNormals()
 			}
 
 			// Update the map
-			mapVal.indices[mapVal.indicesCount++] = i;
+			mapVal.m_indices[mapVal.m_indicesCount++] = i;
 		}
 	}
 }
@@ -385,73 +426,73 @@ void MeshLoader::fixNormals()
 //==============================================================================
 void MeshLoader::append(const MeshLoader& other)
 {
-	positions.insert(
-		positions.end(), other.positions.begin(), other.positions.end());
+	m_positions.insert(
+		m_positions.end(), other.m_positions.begin(), other.m_positions.end());
 
 	//normals.insert(
 	//	normals.end(), other.normals.begin(), other.normals.end());
 
-	normalsF16.insert(
-		normalsF16.end(), other.normalsF16.begin(), other.normalsF16.end());
+	m_normalsF16.insert(m_normalsF16.end(), other.m_normalsF16.begin(), 
+		other.m_normalsF16.end());
 
 	//tangents.insert(
 	//	tangents.end(), other.tangents.begin(), other.tangents.end());
 
-	tangentsF16.insert(
-		tangentsF16.end(), other.tangentsF16.begin(), other.tangentsF16.end());
+	m_tangentsF16.insert(m_tangentsF16.end(), 
+		other.m_tangentsF16.begin(), other.m_tangentsF16.end());
 
 	//texCoords.insert(
 	//	texCoords.end(), other.texCoords.begin(), other.texCoords.end());
 
-	texCoordsF16.insert(
-		texCoordsF16.end(), other.texCoordsF16.begin(), 
-		other.texCoordsF16.end());
+	m_texCoordsF16.insert(
+		m_texCoordsF16.end(), other.m_texCoordsF16.begin(), 
+		other.m_texCoordsF16.end());
 
-	weights.insert(
-		weights.end(), other.weights.begin(), other.weights.end());
+	m_weights.insert(
+		m_weights.end(), other.m_weights.begin(), other.m_weights.end());
 
-	U16 bias = positions.size();
-	for(U16 index : other.vertIndices)
+	U16 bias = m_positions.size();
+	for(U16 index : other.m_vertIndices)
 	{
-		vertIndices.push_back(bias + index);
+		m_vertIndices.push_back(bias + index);
 	}
 }
 
 //==============================================================================
 void MeshLoader::compressBuffers()
 {
-	ANKI_ASSERT(positions.size() > 0);
+	ANKI_ASSERT(m_positions.size() > 0);
 
 	// Normals
-	normalsF16.resize(normals.size());
+	m_normalsF16.resize(m_normals.size());
 
-	for(U i = 0; i < normals.size(); i++)
+	for(U i = 0; i < m_normals.size(); i++)
 	{
 		for(U j = 0; j < 3; j++)
 		{
-			normalsF16[i][j] = F16(normals[i][j]);
+			m_normalsF16[i][j] = F16(m_normals[i][j]);
 		}
 	}
 
 	// Tangents
-	tangentsF16.resize(tangents.size());
+	m_tangentsF16.resize(m_tangents.size());
 
-	for(U i = 0; i < tangents.size(); i++)
+	for(U i = 0; i < m_tangents.size(); i++)
 	{
 		for(U j = 0; j < 4; j++)
 		{
-			tangentsF16[i][j] = F16(tangents[i][j]);
+			m_tangentsF16[i][j] = F16(m_tangents[i][j]);
 		}
 	}
 
 	// Texture coords
-	texCoordsF16.resize(texCoords.size());	
+	m_texCoordsF16.resize(m_texCoords.size());	
 
-	for(U i = 0; i < texCoords.size(); i++)
+	for(U i = 0; i < m_texCoords.size(); i++)
 	{
 		for(U j = 0; j < 2; j++)
 		{
-			texCoordsF16[i][j] = F16(texCoords[i][j]);
+			m_texCoordsF16[i][j] = F16(m_texCoords[i][j]);
 		}
 	}
 }

+ 22 - 16
src/resource/ProgramPrePreprocessor.cpp

@@ -31,10 +31,9 @@ const U32 MAX_DEPTH = 8;
 //==============================================================================
 void ProgramPrePreprocessor::printSourceLines() const
 {
-	for(U32 i = 0; i < m_sourceLines.size(); ++i)
+	for(U i = 0; i < m_sourceLines.size(); ++i)
 	{
-		std::cout << std::setw(3) << (i + 1) << ": " 
-			<< m_sourceLines[i] << std::endl;
+		printf("%4lu %s\n", i + 1, m_sourceLines[i].c_str());
 	}
 }
 
@@ -43,8 +42,12 @@ void ProgramPrePreprocessor::parseFile(const char* filename)
 {
 	try
 	{
+		auto alloc = m_shaderSource.get_allocator();	
+
 		// Parse files recursively
-		parseFileForPragmas(filename);
+		parseFileForPragmas(
+			PPPString(filename, alloc), 
+			0);
 
 		m_shaderSource = m_sourceLines.join("\n");
 	}
@@ -56,7 +59,7 @@ void ProgramPrePreprocessor::parseFile(const char* filename)
 
 //==============================================================================
 void ProgramPrePreprocessor::parseFileForPragmas(
-	const std::string& filename, U32 depth)
+	const PPPString& filename, U32 depth)
 {
 	// first check the depth
 	if(depth > MAX_DEPTH)
@@ -66,18 +69,19 @@ void ProgramPrePreprocessor::parseFileForPragmas(
 	}
 
 	// load file in lines
-	String txt;
-	StringList lines;
+	auto alloc = m_shaderSource.get_allocator();
+	PPPString txt(alloc);
+	PPPStringList lines(alloc);
 	File(filename.c_str(), File::OpenFlag::READ).readAllText(txt);
-	lines = StringList::splitString(txt.c_str(), '\n');
+	lines = PPPStringList::splitString(txt.c_str(), '\n', alloc);
 	if(lines.size() < 1)
 	{
 		throw ANKI_EXCEPTION("File is empty: %s", filename.c_str());
 	}
 
-	for(const std::string& line : lines)
+	for(const PPPString& line : lines)
 	{
-		std::string::size_type npos = 0;
+		PPPString::size_type npos = 0;
 		Bool expectPragmaAnki = false;
 		Bool gotPragmaAnki = true;
 
@@ -92,11 +96,13 @@ void ProgramPrePreprocessor::parseFileForPragmas(
 		}
 		else if((npos = line.find(commands[6])) == 0)
 		{
-			std::string filen = {line, strlen(commands[6]), std::string::npos};
+			// Include
+
+			PPPString filen(
+				line, std::strlen(commands[6]), PPPString::npos);
 			trimString(filen, " \"", filen);
 
-			filen = 
-				ResourceManagerSingleton::get().fixResourcePath(filen.c_str());
+			filen = m_manager->fixResourceFilename(filen.c_str());
 
 			parseFileForPragmas(filen, depth + 1);
 		}
@@ -121,12 +127,12 @@ void ProgramPrePreprocessor::parseFileForPragmas(
 }
 
 //==============================================================================
-Bool ProgramPrePreprocessor::parseType(const std::string& line)
+Bool ProgramPrePreprocessor::parseType(const PPPString& line)
 {
 	U i;
 	Bool found = false;
 
-	for(i = 0; i < (U)ShaderType::COUNT; i++)
+	for(i = 0; i < static_cast<U>(ShaderType::COUNT); i++)
 	{
 		if(line.find(commands[i]) == 0)
 		{
@@ -143,7 +149,7 @@ Bool ProgramPrePreprocessor::parseType(const std::string& line)
 				line.c_str());
 		}
 
-		m_type = (ShaderType)i;
+		m_type = static_cast<ShaderType>(i);
 	}
 
 	return found;

+ 14 - 10
src/resource/ProgramResource.cpp

@@ -14,7 +14,7 @@
 namespace anki {
 
 //==============================================================================
-void ProgramResource::load(const char* filename)
+void ProgramResource::load(const char* filename, ResourceInitializer& init)
 {
 	load(filename, "");
 }
@@ -38,24 +38,28 @@ void ProgramResource::load(const char* filename, const char* extraSrc)
 }
 
 //==============================================================================
-std::string ProgramResource::createSrcCodeToCache(
+String ProgramResource::createSourceToCache(
 	const char* filename, const char* preAppendedSrcCode, 
-	const char* filenamePrefix)
+	const char* filenamePrefix, App& app)
 {
 	ANKI_ASSERT(filename && preAppendedSrcCode && filenamePrefix);
 
-	if(strlen(preAppendedSrcCode) < 1)
+	auto& alloc = app.getAllocator();
+
+	if(std::strlen(preAppendedSrcCode) < 1)
 	{
-		return filename;
+		return String(filename, alloc);
 	}
 
 	// Create suffix
-	std::hash<std::string> stringHasher;
-	PtrSize h = stringHasher(std::string(filename) + preAppendedSrcCode);
-	std::string suffix = std::to_string(h);
+	std::hash<String> stringHasher;
+	PtrSize h = stringHasher(String(filename, alloc) + preAppendedSrcCode);
+
+	String suffix(alloc);
+	toString(h, suffix);
 
 	// Compose cached filename
-	std::string newFilename = AppSingleton::get().getCachePath()
+	String newFilename(app.getCachePath()
 		+ "/" + filenamePrefix + suffix + ".glsl";
 
 	if(File::fileExists(newFilename.c_str()))
@@ -64,7 +68,7 @@ std::string ProgramResource::createSrcCodeToCache(
 	}
 
 	// Read file and append code
-	std::string src;
+	String src(alloc);
 	File(ResourceManagerSingleton::get().fixResourcePath(filename).c_str(), 
 		File::OpenFlag::READ).readAllText(src);
 	src = preAppendedSrcCode + src;

+ 25 - 21
src/resource/ResourceManager.cpp

@@ -18,36 +18,42 @@
 namespace anki {
 
 //==============================================================================
-ResourceManager::ResourceManager(const ConfigSet& config)
+ResourceManager::ResourceManager(App* app, const ConfigSet& config)
+:	m_app(app),
+	m_alloc(HeapMemoryPool(
+		m_app->getAllocationCallback(), m_app->getAllocationCallbackData())),
+	m_tmpAlloc(StackMemoryPool(m_app->getAllocationCallback(), 
+		m_app->getAllocationCallbackData(), 1024 * 1024))
 {
+	// Init the data path
+	//
 	if(getenv("ANKI_DATA_PATH"))
 	{
-		m_dataPath = getenv("ANKI_DATA_PATH");
-#if ANKI_POSIX
-		m_dataPath += "/";
-#else
-		m_dataPath = "\\";
-#endif
-		ANKI_LOGI("Data path: %s", m_dataPath.c_str());
+		m_dataDir = ResourceString(getenv("ANKI_DATA_PATH"), m_alloc);
+		m_dataDir += "/";
+		ANKI_LOGI("Data path: %s", m_dataDir.c_str());
 	}
 	else
 	{
 		// Assume working directory
 #if ANKI_OS == ANKI_OS_ANDROID
-		m_dataPath = "$";
+		m_dataDir = ResourceString("$", m_alloc);
 #else
-#	if ANKI_POSIX
-		m_dataPath = "./";
-#	else
-		m_dataPath = ".\\";
-#	endif
+		m_dataDir = ResourceString("./", m_alloc);
 #endif
 	}
 
+	// Init cache dir
+	//
+	m_cacheDir = ResourceString(cacheDir, m_alloc);
+
+	// Init some constants
+	//
 	m_maxTextureSize = config.get("maxTextureSize");
 	m_textureAnisotropy = config.get("textureAnisotropy");
 
 	// Init type resource managers
+	//
 	TypeResourceManager<Animation, ResourceManager>::init(m_alloc);
 	TypeResourceManager<Material, ResourceManager>::init(m_alloc);
 	TypeResourceManager<Mesh, ResourceManager>::init(m_alloc);
@@ -59,21 +65,19 @@ ResourceManager::ResourceManager(const ConfigSet& config)
 }
 
 //==============================================================================
-String ResourceManager::fixResourcePath(const char* filename) const
+TempResourceString ResourceManager::fixResourceFilename(
+	const char* filename) const
 {
-	String newFname;
+	TempResourceString newFname(m_tmpAlloc);
 
 	// If the filename is in cache then dont append the data path
-	//const char* cachePath = AppSingleton::get().getCachePath().c_str();
-	const char* cachePath = nullptr;
-	ANKI_ASSERT(0 && "TODO");
-	if(std::strstr(filename, cachePath) != nullptr)
+	if(std::strstr(filename, m_cacheDir.c_str()) != nullptr)
 	{
 		newFname = filename;
 	}
 	else
 	{
-		newFname = m_dataPath + filename;
+		newFname = TempResourceString(m_dataDir.c_str(), m_tmpAlloc) + filename;
 	}
 
 	return newFname;

+ 34 - 34
src/resource/TextureResource.cpp

@@ -6,7 +6,6 @@
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/Image.h"
 #include "anki/util/Exception.h"
-#include "anki/renderer/MainRenderer.h"
 
 #if ANKI_GL == ANKI_GL_DESKTOP
 #	define DRIVER_CAN_COMPRESS 1
@@ -17,18 +16,19 @@
 namespace anki {
 
 //==============================================================================
-void deleteImageCallback(void* data)
+static void deleteImageCallback(void* data)
 {
-	Image* image = (Image*)data;
-	delete image;
+	Image* image = reinterpret_cast<Image*>(data);
+	auto alloc = image->getAllocator();
+	alloc.deleteInstance(image);
 }
 
 //==============================================================================
-void TextureResource::load(const char* filename)
+void TextureResource::load(const char* filename, ResourceInitializer& init)
 {
 	try
 	{
-		loadInternal(filename);
+		loadInternal(filename, init);
 	}
 	catch(std::exception& e)
 	{
@@ -37,28 +37,29 @@ void TextureResource::load(const char* filename)
 }
 
 //==============================================================================
-void TextureResource::loadInternal(const char* filename)
+void TextureResource::loadInternal(const char* filename, 
+	ResourceInitializer& rinit)
 {
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl); // Always first to avoid assertions (because of
-	                            // the check of the allocator)
+	GlDevice& gl = rinit.m_gl;
+	GlCommandBufferHandle jobs(&gl); // Always first to avoid assertions (
+	                                 // because of the check of the allocator)
 
 	GlTextureHandle::Initializer init;
 	U layers = 0;
 	Bool driverShouldGenMipmaps = false;
 
 	// Load image
-	Image* imgPtr = new Image;
+	Image* imgPtr = rinit.m_alloc.newInstance<Image>(rinit.m_alloc);
 	Image& img = *imgPtr;
-	img.load(filename, ResourceManagerSingleton::get().getMaxTextureSize());
+	img.load(filename, rinit.m_maxTextureSize);
 	
 	// width + height
-	init.m_width = img.getSurface(0, 0).width;
-	init.m_height = img.getSurface(0, 0).height;
+	init.m_width = img.getSurface(0, 0).m_width;
+	init.m_height = img.getSurface(0, 0).m_height;
 	
 	// depth
-	if(img.getTextureType() == Image::TT_2D_ARRAY 
-		|| img.getTextureType() == Image::TT_3D)
+	if(img.getTextureType() == Image::TextureType::_2D_ARRAY 
+		|| img.getTextureType() == Image::TextureType::_3D)
 	{
 		init.m_depth = img.getDepth();
 	}
@@ -70,19 +71,19 @@ void TextureResource::loadInternal(const char* filename)
 	// target
 	switch(img.getTextureType())
 	{
-	case Image::TT_2D:
+	case Image::TextureType::_2D:
 		init.m_target = GL_TEXTURE_2D;
 		layers = 1;
 		break;
-	case Image::TT_CUBE:
+	case Image::TextureType::CUBE:
 		init.m_target = GL_TEXTURE_CUBE_MAP;
 		layers = 6;
 		break;
-	case Image::TT_2D_ARRAY:
+	case Image::TextureType::_2D_ARRAY:
 		init.m_target = GL_TEXTURE_2D_ARRAY;
 		layers = init.m_depth;
 		break;
-	case Image::TT_3D:
+	case Image::TextureType::_3D:
 		init.m_target = GL_TEXTURE_3D;
 		layers = init.m_depth;
 	default:
@@ -90,11 +91,11 @@ void TextureResource::loadInternal(const char* filename)
 	}
 
 	// Internal format
-	if(img.getColorFormat() == Image::CF_RGB8)
+	if(img.getColorFormat() == Image::ColorFormat::RGB8)
 	{
 		switch(img.getCompression())
 		{
-		case Image::DC_RAW:
+		case Image::DataCompression::RAW:
 #if DRIVER_CAN_COMPRESS
 			init.m_internalFormat = GL_COMPRESSED_RGB;
 #else
@@ -103,11 +104,11 @@ void TextureResource::loadInternal(const char* filename)
 			driverShouldGenMipmaps = true;
 			break;
 #if ANKI_GL == ANKI_GL_DESKTOP
-		case Image::DC_S3TC:
+		case Image::DataCompression::S3TC:
 			init.m_internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
 			break;
 #else
-		case Image::DC_ETC:
+		case Image::DataCompression::ETC:
 			init.m_internalFormat = GL_COMPRESSED_RGB8_ETC2;
 			break;
 #endif
@@ -115,11 +116,11 @@ void TextureResource::loadInternal(const char* filename)
 			ANKI_ASSERT(0);
 		}
 	}
-	else if(img.getColorFormat() == Image::CF_RGBA8)
+	else if(img.getColorFormat() == Image::ColorFormat::RGBA8)
 	{
 		switch(img.getCompression())
 		{
-		case Image::DC_RAW:
+		case Image::DataCompression::RAW:
 #if DRIVER_CAN_COMPRESS
 			init.m_internalFormat = GL_COMPRESSED_RGBA;
 #else
@@ -128,11 +129,11 @@ void TextureResource::loadInternal(const char* filename)
 			driverShouldGenMipmaps = true;
 			break;
 #if ANKI_GL == ANKI_GL_DESKTOP
-		case Image::DC_S3TC:
+		case Image::DataCompression::S3TC:
 			init.m_internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
 			break;
 #else
-		case Image::DC_ETC:
+		case Image::DataCompression::ETC:
 			init.m_internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
 			break;
 #endif
@@ -148,10 +149,10 @@ void TextureResource::loadInternal(const char* filename)
 	// format
 	switch(img.getColorFormat())
 	{
-	case Image::CF_RGB8:
+	case Image::ColorFormat::RGB8:
 		init.m_format = GL_RGB;
 		break;
-	case Image::CF_RGBA8:
+	case Image::ColorFormat::RGBA8:
 		init.m_format = GL_RGBA;
 		break;
 	default:
@@ -171,8 +172,7 @@ void TextureResource::loadInternal(const char* filename)
 	init.m_repeat = true;
 
 	// anisotropyLevel
-	init.m_anisotropyLevel = 
-		ResourceManagerSingleton::get().getTextureAnisotropy();
+	init.m_anisotropyLevel = rinit.m_anisotropyLevel;
 
 	// genMipmaps
 	if(init.m_mipmapsCount == 1 || driverShouldGenMipmaps)
@@ -193,8 +193,8 @@ void TextureResource::loadInternal(const char* filename)
 
 			buff = GlClientBufferHandle(
 				jobs, 
-				img.getSurface(level, layer).data.size(), 
-				(void*)&img.getSurface(level, layer).data[0]);
+				img.getSurface(level, layer).m_data.size(), 
+				(void*)&img.getSurface(level, layer).m_data[0]);
 		}
 	}