Browse Source

Refactoring

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
1d6fbbba96
57 changed files with 826 additions and 890 deletions
  1. 1 0
      .gitignore
  2. 34 10
      include/anki/core/App.h
  3. 9 20
      include/anki/core/Logger.h
  4. 2 2
      include/anki/core/NativeWindow.h
  5. 2 2
      include/anki/core/StdinListener.h
  6. 1 1
      include/anki/gl/GlDevice.h
  7. 4 5
      include/anki/input/Input.h
  8. 11 1
      include/anki/input/InputSdl.h
  9. 19 12
      include/anki/renderer/Dbg.h
  10. 3 2
      include/anki/renderer/Drawer.h
  11. 1 1
      include/anki/renderer/Ez.h
  12. 9 9
      include/anki/renderer/Is.h
  13. 6 6
      include/anki/renderer/MainRenderer.h
  14. 3 5
      include/anki/renderer/Pps.h
  15. 39 23
      include/anki/renderer/Renderer.h
  16. 2 0
      include/anki/renderer/RenderingPass.h
  17. 4 4
      include/anki/renderer/Sm.h
  18. 1 1
      include/anki/renderer/Ssao.h
  19. 5 2
      include/anki/renderer/Sslr.h
  20. 1 1
      include/anki/resource/ProgramResource.h
  21. 4 1
      include/anki/resource/ResourceManager.h
  22. 7 0
      include/anki/resource/ResourcePointer.h
  23. 6 4
      include/anki/scene/SceneGraph.h
  24. 7 2
      include/anki/script/Common.h
  25. 10 1
      include/anki/script/ScriptManager.h
  26. 3 3
      include/anki/util/Bitset.h
  27. 1 1
      include/anki/util/Filesystem.h
  28. 1 1
      include/anki/util/String.h
  29. 102 68
      src/core/App.cpp
  30. 6 0
      src/core/Config.cpp
  31. 21 12
      src/core/Logger.cpp
  32. 1 1
      src/core/NativeWindowSdl.cpp
  33. 7 4
      src/core/StdinListener.cpp
  34. 1 1
      src/gl/GlDevice.cpp
  35. 5 2
      src/input/InputSdl.cpp
  36. 4 3
      src/renderer/Dbg.cpp
  37. 16 17
      src/renderer/Drawer.cpp
  38. 6 5
      src/renderer/Ez.cpp
  39. 5 8
      src/renderer/Hdr.cpp
  40. 101 99
      src/renderer/Is.cpp
  41. 48 53
      src/renderer/Lf.cpp
  42. 22 18
      src/renderer/MainRenderer.cpp
  43. 1 0
      src/renderer/Ms.cpp
  44. 45 40
      src/renderer/Pps.cpp
  45. 54 56
      src/renderer/Renderer.cpp
  46. 9 4
      src/renderer/RenderingPass.cpp
  47. 25 25
      src/renderer/Sm.cpp
  48. 45 48
      src/renderer/Ssao.cpp
  49. 37 37
      src/renderer/Sslr.cpp
  50. 17 14
      src/renderer/Tiler.cpp
  51. 2 1
      src/resource/Image.cpp
  52. 1 1
      src/resource/ProgramResource.cpp
  53. 3 12
      src/scene/SceneGraph.cpp
  54. 1 1
      src/script/ScriptManager.cpp
  55. 1 1
      src/util/CMakeLists.txt
  56. 42 238
      testapp/Main.cpp
  57. 2 1
      tests/Main.cpp

+ 1 - 0
.gitignore

@@ -1 +1,2 @@
 build/*
+*

+ 34 - 10
include/anki/core/App.h

@@ -19,7 +19,7 @@ extern android_app* gAndroidApp;
 #endif
 
 // Forward
-class Config;
+class ConfigSet;
 class Threadpool;
 class NativeWindow;
 class Input;
@@ -27,12 +27,16 @@ class GlDevice;
 class MainRenderer;
 class SceneGraph;
 class ScriptManager;
+class ResourceManager;
 
 /// The core class of the engine.
 class App
 {
 public:
-	App(const Config& config, 
+	using UserMainLoopCallback = void(*)(App& app, void* userData);
+
+	/// Create and initialize the application
+	App(const ConfigSet& config, 
 		AllocAlignedCallback allocCb, void* allocCbUserData);
 
 	~App()
@@ -52,12 +56,12 @@ public:
 
 	const String& getSettingsDirectory() const
 	{
-		return m_settingsPath;
+		return m_settingsDir;
 	}
 
 	const String& getCacheDirectory() const
 	{
-		return m_cachePath;
+		return m_cacheDir;
 	}
 
 	AllocAlignedCallback getAllocationCallback() const
@@ -84,7 +88,22 @@ public:
 	void quit(int code);
 
 	/// Run the main loop
-	void mainLoop();
+	void mainLoop(UserMainLoopCallback callback, void* userData);
+
+	Input& getInput()
+	{
+		return *m_input;
+	}
+
+	SceneGraph& getSceneGraph()
+	{
+		return *m_scene;
+	}
+
+	MainRenderer& getMainRenderer()
+	{
+		return *m_renderer;
+	}
 
 private:
 	// Allocation
@@ -93,25 +112,30 @@ private:
 	HeapAllocator<U8> m_heapAlloc;
 
 	// Sybsystems
-	GlDevice* m_gl = nullptr;
 	NativeWindow* m_window = nullptr;
 	Input* m_input = nullptr;
+	GlDevice* m_gl = nullptr;
+	ResourceManager* m_resources = nullptr;
 	MainRenderer* m_renderer = nullptr;
 	SceneGraph* m_scene = nullptr;
 	ScriptManager* m_script = nullptr;
 
 	// Misc
+	void* m_ctx = nullptr;
 	Threadpool* m_threadpool = nullptr;
-	String m_settingsPath; ///< The path that holds the configuration
-	String m_cachePath; ///< This is used as a cache
+	String m_settingsDir; ///< The path that holds the configuration
+	String m_cacheDir; ///< This is used as a cache
 	F32 m_timerTick;
 
 	/// Initialize the app
-	void init();
+	void init(const ConfigSet& config);
 
 	void initDirs();
 
-	static void printAppInfo();
+	void printAppInfo();
+
+	static void makeCurrent(void* data);
+	static void swapWindow(void* window);
 };
 
 } // end namespace anki

+ 9 - 20
include/anki/core/Logger.h

@@ -9,11 +9,12 @@
 #include "anki/Config.h"
 #include "anki/util/Singleton.h"
 #include "anki/util/File.h"
-#include <mutex>
+#include "anki/util/Thread.h"
+#include "anki/util/Enum.h"
 
 namespace anki {
 
-/// @addtogroup Core
+/// @addtogroup core
 /// @{
 
 /// The logger singleton class. The logger cannot print errors or throw
@@ -38,20 +39,7 @@ public:
 		WITH_SYSTEM_MESSAGE_HANDLER = 1 << 0,
 		WITH_LOG_FILE_MESSAGE_HANDLER  = 1 << 1
 	};
-
-	friend InitFlags operator|(InitFlags a, InitFlags b)
-	{
-		typedef std::underlying_type<InitFlags>::type Int;
-		return 
-			static_cast<InitFlags>(static_cast<Int>(a) | static_cast<Int>(b));
-	}
-
-	friend InitFlags operator&(InitFlags a, InitFlags b)
-	{
-		typedef std::underlying_type<InitFlags>::type Int;
-		return 
-			static_cast<InitFlags>(static_cast<Int>(a) & static_cast<Int>(b));
-	}
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(InitFlags, friend);
 
 	/// Used as parammeter when emitting the signal
 	class Info
@@ -68,7 +56,9 @@ public:
 	using MessageHandlerCallback = void (*)(void*, const Info& info);
 
 	/// Initialize the logger
-	Logger(InitFlags flags, HeapAllocator<U8>& alloc);
+	Logger(InitFlags flags, HeapAllocator<U8>& alloc, const char* cacheDir);
+
+	~Logger();
 
 	/// Add a new message handler
 	void addMessageHandler(void* data, MessageHandlerCallback callback);
@@ -82,8 +72,6 @@ public:
 		MessageType type, const char* fmt, ...);
 
 private:
-	std::mutex m_mutex; ///< For thread safety
-
 	class Handler
 	{
 	public:
@@ -91,9 +79,10 @@ private:
 		MessageHandlerCallback m_callback;
 	};
 
+	Mutex m_mutex; ///< For thread safety
 	Vector<Handler> m_handlers;
-
 	File m_logfile;
+	char* m_cacheDir = nullptr;
 	
 	static void defaultSystemMessageHandler(void*, const Info& info);
 	static void logfileMessageHandler(void* vlogger, const Info& info);

+ 2 - 2
include/anki/core/NativeWindow.h

@@ -44,7 +44,7 @@ public:
 		Bool8 m_debugContext = false; ///< Enables KHR_debug
 		/// @}
 
-		String m_title = "Untitled window";
+		const char* m_title = "Untitled window";
 	};
 
 	NativeWindow(Initializer& initializer, HeapAllocator<U8>& alloc)
@@ -94,7 +94,7 @@ private:
 
 	Bool isCreated() const
 	{
-		return m_impl.get() != nullptr;
+		return m_impl != nullptr;
 	}
 
 	void create(Initializer& initializer, HeapAllocator<U8>& alloc);

+ 2 - 2
include/anki/core/StdinListener.h

@@ -21,7 +21,7 @@ namespace anki {
 class StdinListener
 {
 public:
-	StdinListener();
+	StdinListener(HeapAllocator<String>& alloc);
 
 	~StdinListener();
 
@@ -29,7 +29,7 @@ public:
 	String getLine();
 
 private:
-	std::queue<String> m_q;
+	std::deque<String, HeapAllocator<String>> m_q;
 	Mutex m_mtx; ///< Protect the queue
 	Thread m_thrd; ///< The thread
 	Bool8 m_quit = false;

+ 1 - 1
include/anki/gl/GlDevice.h

@@ -39,7 +39,7 @@ public:
 	void swapBuffers();
 
 	/// Return the alignment of a buffer target
-	PtrSize getBufferOffsetAlignment(GLenum target);
+	PtrSize getBufferOffsetAlignment(GLenum target) const;
 
 	/// @privatesection
 	/// @{

+ 4 - 5
include/anki/input/Input.h

@@ -11,7 +11,6 @@
 #include "anki/util/Array.h"
 #include "anki/util/StdTypes.h"
 #include "anki/input/KeyCode.h"
-#include <memory>
 
 namespace anki {
 
@@ -26,9 +25,9 @@ class Input
 public:
 	enum class Event: U8
 	{
-		WINDOW_FOCUS_LOST_EVENT,
-		WINDOW_FOCUS_GAINED_EVENT,
-		WINDOW_CLOSED_EVENT,
+		WINDOW_FOCUS_LOST,
+		WINDOW_FOCUS_GAINED,
+		WINDOW_CLOSED,
 		COUNT
 	};
 
@@ -111,7 +110,7 @@ private:
 
 	Vec2 m_mousePosNdc = Vec2(2.0); ///< The coords are in the NDC space
 
-	Array<U8, EVENTS_COUNT> m_events;
+	Array<U8, static_cast<U>(Event::COUNT)> m_events;
 
 	Bool8 m_lockCurs = false;
 

+ 11 - 1
include/anki/input/InputSdl.h

@@ -16,7 +16,17 @@ namespace anki {
 class InputImpl
 {
 public:
-	std::unordered_map<SDL_Keycode, KeyCode> m_sdlToAnki;
+	std::unordered_map<
+		SDL_Keycode, 
+		KeyCode, 
+		std::hash<SDL_Keycode>,
+		std::equal_to<SDL_Keycode>,
+		HeapAllocator<std::pair<const SDL_Keycode, KeyCode>>> m_sdlToAnki;
+
+	InputImpl(HeapAllocator<std::pair<const SDL_Keycode, KeyCode>>& alloc)
+	:	m_sdlToAnki(10, std::hash<SDL_Keycode>(), std::equal_to<SDL_Keycode>(),
+			alloc)
+	{}
 };
 
 } // end namespace anki

+ 19 - 12
include/anki/renderer/Dbg.h

@@ -14,26 +14,33 @@
 
 namespace anki {
 
+namespace detail {
+
+/// Dbg flags. Define them first so they can be parameter to the bitset
+enum class DbgFlag
+{
+	NONE = 0,
+	SPATIAL = 1 << 0,
+	FRUSTUMABLE = 1 << 1,
+	SECTOR = 1 << 2,
+	OCTREE = 1 << 3,
+	PHYSICS = 1 << 4,
+	ALL = SPATIAL | FRUSTUMABLE | SECTOR | OCTREE | PHYSICS
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(DbgFlag, inline);
+
+} // end namespace detail
+
 /// @addtogroup renderer
 /// @{
 
 /// Debugging stage
-class Dbg: public RenderingPass, public Bitset<U8>
+class Dbg: public RenderingPass, public Bitset<detail::DbgFlag>
 {
 	friend class Renderer;
 
 public:
-	enum class Flag
-	{
-		NONE = 0,
-		SPATIAL = 1 << 0,
-		FRUSTUMABLE = 1 << 1,
-		SECTOR = 1 << 2,
-		OCTREE = 1 << 3,
-		PHYSICS = 1 << 4,
-		ALL = SPATIAL | FRUSTUMABLE | SECTOR | OCTREE | PHYSICS
-	};
-	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flag, friend);
+	using Flag = detail::DbgFlag;
 
 	Bool getDepthTestEnabled() const
 	{

+ 3 - 2
include/anki/renderer/Drawer.h

@@ -38,7 +38,8 @@ public:
 	/// The one and only constructor
 	RenderableDrawer(Renderer* r);
 
-	void prepareDraw(RenderingStage stage, Pass pass, GlCommandBufferHandle& jobs);
+	void prepareDraw(
+		RenderingStage stage, Pass pass, GlCommandBufferHandle& cmdBuff);
 
 	void render(
 		SceneNode& frsn,
@@ -52,7 +53,7 @@ private:
 
 	/// @name State
 	/// @{
-	GlCommandBufferHandle m_jobs;
+	GlCommandBufferHandle m_cmdBuff;
 	U8* m_uniformPtr;
 
 	/// Used to calc if the uni buffer is big enough. Zero it per swap buffers

+ 1 - 1
include/anki/renderer/Ez.h

@@ -27,7 +27,7 @@ private:
 	{}
 
 	void init(const ConfigSet& initializer);
-	void run(GlCommandBufferHandle& jobs);
+	void run(GlCommandBufferHandle& cmdBuff);
 };
 
 /// @}

+ 9 - 9
include/anki/renderer/Is.h

@@ -100,12 +100,12 @@ private:
 	/// @name Limits
 	/// @{
 	U16 m_maxPointLights;
-	U8 m_maxSpotLights;
-	U8 m_maxSpotTexLights;
+	U32 m_maxSpotLights;
+	U32 m_maxSpotTexLights;
 
-	U8 m_maxPointLightsPerTile;
-	U8 m_maxSpotLightsPerTile;
-	U8 m_maxSpotTexLightsPerTile;
+	U32 m_maxPointLightsPerTile;
+	U32 m_maxSpotLightsPerTile;
+	U32 m_maxSpotTexLightsPerTile;
 	/// @}
 
 	U32 m_tileSize; ///< Cache the value here
@@ -114,16 +114,16 @@ private:
 	~Is();
 
 	void init(const ConfigSet& initializer);
-	void run(GlCommandBufferHandle& jobs);
+	void run(GlCommandBufferHandle& cmdBuff);
 
 	/// Called by init
 	void initInternal(const ConfigSet& initializer);
 
 	/// Do the actual pass
-	void lightPass(GlCommandBufferHandle& jobs);
+	void lightPass(GlCommandBufferHandle& cmdBuff);
 
 	/// Prepare GL for rendering
-	void setState(GlCommandBufferHandle& jobs);
+	void setState(GlCommandBufferHandle& cmdBuff);
 
 	/// Calculate the size of the lights UBO
 	PtrSize calcLightsBufferSize() const;
@@ -131,7 +131,7 @@ private:
 	/// Calculate the size of the tile
 	PtrSize calcTileSize() const;
 
-	void updateCommonBlock(GlCommandBufferHandle& jobs);
+	void updateCommonBlock(GlCommandBufferHandle& cmdBuff);
 };
 
 /// @}

+ 6 - 6
include/anki/renderer/MainRenderer.h

@@ -7,13 +7,9 @@
 #define ANKI_RENDERER_MAIN_RENDERER_H
 
 #include "anki/renderer/Renderer.h"
-#include "anki/renderer/Deformer.h"
 
 namespace anki {
 
-// Forward
-class App;
-
 /// @addtogroup renderer
 /// @{
 
@@ -21,7 +17,12 @@ class App;
 class MainRenderer: public Renderer
 {
 public:
-	MainRenderer(App* app, const ConfigSet& initializer);
+	MainRenderer(
+		Threadpool* threadpool, 
+		ResourceManager* resources,
+		GlDevice* gl,
+		HeapAllocator<U8>& alloc,
+		const ConfigSet& config);
 
 	~MainRenderer();
 
@@ -33,7 +34,6 @@ public:
 	void takeScreenshot(const char* filename);
 
 private:
-	std::unique_ptr<Deformer> m_deformer;
 	ProgramResourcePointer m_blitFrag;
 	GlProgramPipelineHandle m_blitPpline;
 

+ 3 - 5
include/anki/renderer/Pps.h

@@ -75,6 +75,7 @@ public:
 		return m_sslr;
 	}
 
+	/// @privatesection
 	/// @{
 	const GlTextureHandle& _getRt() const
 	{
@@ -87,14 +88,11 @@ public:
 	/// @}
 
 private:
-	/// @name Passes
-	/// @{
 	Hdr m_hdr;
 	Ssao m_ssao;
 	Bl m_bl;
 	Lf m_lf;
 	Sslr m_sslr;
-	/// @}
 
 	GlFramebufferHandle m_fb;
 	ProgramResourcePointer m_frag;
@@ -104,10 +102,10 @@ private:
 	Pps(Renderer* r);
 	~Pps();
 
-	void init(const ConfigSet& initializer);
+	void init(const ConfigSet& config);
 	void run(GlCommandBufferHandle& jobs);
 
-	void initInternal(const ConfigSet& initializer);
+	void initInternal(const ConfigSet& config);
 };
 
 /// @}

+ 39 - 23
include/anki/renderer/Renderer.h

@@ -7,12 +7,11 @@
 #define ANKI_RENDERER_RENDERER_H
 
 #include "anki/Math.h"
+#include "anki/resource/ResourceManager.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/ProgramResource.h"
-#include "anki/resource/Resource.h"
 #include "anki/Gl.h"
 #include "anki/util/HighRezTimer.h"
-#include "anki/misc/ConfigSet.h"
 #include "anki/scene/Forward.h"
 
 #include "anki/renderer/Ms.h"
@@ -25,6 +24,9 @@
 
 namespace anki {
 
+// Forward
+class ConfigSet;
+
 /// @addtogroup renderer
 /// @{
 
@@ -37,7 +39,12 @@ public:
 	/// GL with a huge job chain
 	static const U32 JOB_CHAINS_COUNT = 2;
 		
-	Renderer(Threadpool* threadpool);
+	Renderer(
+		Threadpool* threadpool, 
+		ResourceManager* resources,
+		GlDevice* gl,
+		HeapAllocator<U8>& alloc,
+		const ConfigSet& config);
 
 	~Renderer();
 
@@ -180,18 +187,9 @@ public:
 		return m_defaultFb;
 	}
 
-	Threadpool& _getThreadpool() 
-	{
-		return *m_threadpool;
-	}
-
-	/// Init the renderer given an initialization class
-	/// @param initializer The initializer class
-	void init(const ConfigSet& initializer);
-
 	/// This function does all the rendering stages and produces a final FAI
 	void render(SceneGraph& scene, 
-		Array<GlCommandBufferHandle, JOB_CHAINS_COUNT>& jobs);
+		Array<GlCommandBufferHandle, JOB_CHAINS_COUNT>& cmdBuff);
 
 	/// My version of gluUnproject
 	/// @param windowCoords Window screen coords
@@ -205,9 +203,9 @@ public:
 
 	/// Draws a quad. Actually it draws 2 triangles because OpenGL will no
 	/// longer support quads
-	void drawQuad(GlCommandBufferHandle& jobs);
+	void drawQuad(GlCommandBufferHandle& cmdBuff);
 
-	void drawQuadInstanced(GlCommandBufferHandle& jobs, U32 primitiveCount);
+	void drawQuadInstanced(GlCommandBufferHandle& cmdBuff, U32 primitiveCount);
 
 	/// Get the LOD given the distance of an object from the camera
 	F32 calculateLod(F32 distance) const
@@ -224,16 +222,39 @@ public:
 	GlProgramPipelineHandle createDrawQuadProgramPipeline(
 		GlProgramHandle frag);
 
+	/// Init the renderer given an initialization class
+	/// @param initializer The initializer class
+	void init(const ConfigSet& initializer);
+
 	/// @privatesection
 	/// @{
-	GlDevice& _getGlDevice();
+	GlDevice& _getGlDevice()
+	{
+		return *m_gl;
+	}
+
+	HeapAllocator<U8>& _getAllocator()
+	{
+		return m_alloc;
+	}
 
-	HeapAllocator<U8>& _getAllocator();
+	ResourceManager& _getResourceManager()
+	{
+		return *m_resources;
+	}
 
-	ResourceManager& _getResourceManager();
+	Threadpool& _getThreadpool() 
+	{
+		return *m_threadpool;
+	}
 	/// @}
 
 private:
+	Threadpool* m_threadpool;
+	ResourceManager* m_resources;
+	GlDevice* m_gl;
+	HeapAllocator<U8> m_alloc;
+
 	/// @name Rendering stages
 	/// @{
 	Ms m_ms; ///< Material rendering stage
@@ -278,13 +299,8 @@ private:
 
 	U m_framesNum; ///< Frame number
 
-	/// String to pass to the material shaders
-	String m_shaderPostProcessorString;
-
 	GlFramebufferHandle m_defaultFb;
 
-	Threadpool* m_threadpool;
-
 	void computeProjectionParams(const Mat4& projMat);
 };
 

+ 2 - 0
include/anki/renderer/RenderingPass.h

@@ -16,6 +16,7 @@ namespace anki {
 // Forward
 class Renderer;
 class ResourceManager;
+class ConfigSet;
 
 /// @addtogroup renderer
 /// @{
@@ -47,6 +48,7 @@ protected:
 	HeapAllocator<U8>& getAllocator();
 
 	GlDevice& getGlDevice();
+	const GlDevice& getGlDevice() const;
 
 	ResourceManager& getResourceManager();
 };

+ 4 - 4
include/anki/renderer/Sm.h

@@ -72,7 +72,7 @@ private:
 
 	void init(const ConfigSet& initializer);
 	void run(Light* shadowCasters[], U32 shadowCastersCount, 
-		GlCommandBufferHandle& jobs);
+		GlCommandBufferHandle& cmdBuff);
 
 	/// Get max shadow casters
 	U32 getMaxLightsCount()
@@ -80,13 +80,13 @@ private:
 		return m_sms.size();
 	}
 
-	void prepareDraw(GlCommandBufferHandle& jobs);
-	void finishDraw(GlCommandBufferHandle& jobs);
+	void prepareDraw(GlCommandBufferHandle& cmdBuff);
+	void finishDraw(GlCommandBufferHandle& cmdBuff);
 
 	/// Find the best shadowmap for that light
 	Shadowmap& bestCandidate(Light& light);
 
-	Shadowmap* doLight(Light& light, GlCommandBufferHandle& jobs);
+	Shadowmap* doLight(Light& light, GlCommandBufferHandle& cmdBuff);
 };
 
 /// @}

+ 1 - 1
include/anki/renderer/Ssao.h

@@ -50,7 +50,7 @@ private:
 	{}
 
 	void init(const ConfigSet& initializer);
-	void run(GlCommandBufferHandle& jobs);
+	void run(GlCommandBufferHandle& cmdBuff);
 
 	GlTextureHandle& getRt()
 	{

+ 5 - 2
include/anki/renderer/Sslr.h

@@ -21,10 +21,13 @@ class Sslr: public BlurringRenderingPass
 	friend class Pps;
 
 public:
+	/// @privatesection
+	/// @{
 	GlTextureHandle& _getRt()
 	{
 		return m_dirs[(U)DirectionEnum::VERTICAL].m_rt;
 	}
+	/// @}
 
 private:
 	U32 m_width;
@@ -43,8 +46,8 @@ private:
 	:	BlurringRenderingPass(r)
 	{}
 
-	void init(const ConfigSet& initializer);
-	void run(GlCommandBufferHandle& jobs);
+	void init(const ConfigSet& config);
+	void run(GlCommandBufferHandle& cmdBuff);
 };
 
 /// @}

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

@@ -45,7 +45,7 @@ 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 String createSourceToCache(
+	static String createToCache(
 		const CString& filename,
 		const CString& preAppendedSrcCode,
 		const CString& filenamePrefix,

+ 4 - 1
include/anki/resource/ResourceManager.h

@@ -176,7 +176,10 @@ public:
 		return m_tmpAlloc;
 	}
 
-	GlDevice& _getGlDevice();
+	GlDevice& _getGlDevice()
+	{
+		return *m_gl;
+	}
 
 	const ResourceString& _getCacheDirectory() const
 	{

+ 7 - 0
include/anki/resource/ResourcePointer.h

@@ -128,6 +128,13 @@ public:
 	/// Load the resource using the resource manager
 	void load(const CString& filename, TResourceManager* resources);
 
+	template<typename... TArgs>
+	void loadToCache(TResourceManager* resources, TArgs&&... args)
+	{
+		auto fname = Type::createToCache(args..., *resources);
+		load(fname.toCString(), resources);
+	}
+
 	Bool isLoaded() const
 	{
 		return m_cb != nullptr;

+ 6 - 4
include/anki/scene/SceneGraph.h

@@ -38,13 +38,11 @@ public:
 	/// @name Constructors/Destructor
 	/// @{
 	SceneGraph(AllocAlignedCallback allocCb, void* allocCbData, 
-		Threadpool* threadpool);
+		Threadpool* threadpool, ResourceManager* resources);
 
 	~SceneGraph();
 	/// @}
 
-	void load(const char* filename);
-
 	/// @note Return a copy
 	SceneAllocator<U8> getAllocator() const
 	{
@@ -188,12 +186,16 @@ public:
 		return *m_resources;
 	}
 
-	GlDevice& _getGlDevice();
+	GlDevice& _getGlDevice()
+	{
+		return *m_gl;
+	}
 	/// @}
 
 private:
 	Threadpool* m_threadpool = nullptr;
 	ResourceManager* m_resources = nullptr;
+	GlDevice* m_gl = nullptr;
 
 	SceneAllocator<U8> m_alloc;
 	SceneAllocator<U8> m_frameAlloc;

+ 7 - 2
include/anki/script/Common.h

@@ -11,20 +11,25 @@
 
 #include "anki/script/LuaBinder.h"
 
+/// @addtogroup script
+/// @{
+
 /// Wrap a class
 #define ANKI_SCRIPT_WRAP(x) \
 	void ankiScriptWrap##x(LuaBinder& lb)
 
-/// XXX
+/// Call the function that wraps x
 #define ANKI_SCRIPT_CALL_WRAP(x) \
 	extern void ankiScriptWrap##x(LuaBinder&); \
 	ankiScriptWrap##x(*this);
 
-/// XXX
+/// Wrap a singleton class
 #define ANKI_SCRIPT_WRAP_SINGLETON(x) \
 	ANKI_SCRIPT_WRAP(x) { \
 	ANKI_LUA_CLASS_BEGIN_NO_DESTRUCTOR(lb, x)	\
 		ANKI_LUA_STATIC_METHOD("get", &x::get) \
 	ANKI_LUA_CLASS_END() }
 
+/// @}
+
 #endif

+ 10 - 1
include/anki/script/ScriptManager.h

@@ -11,6 +11,12 @@
 
 namespace anki {
 
+// Forward
+class App;
+
+/// @addtogroup script
+/// @{
+
 /// The scripting manager
 class ScriptManager: public LuaBinder
 {
@@ -18,9 +24,12 @@ public:
 	ScriptManager(HeapAllocator<U8>& alloc);
 
 	~ScriptManager();
+
+private:
+	App* m_app;
 };
 
-typedef SingletonInit<ScriptManager> ScriptManagerSingleton;
+/// @}
 
 } // end namespace anki
 

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

@@ -21,10 +21,10 @@ public:
 	typedef T Value;
 
 	Bitset()
-	:	m_bitmask(0)
+	:	m_bitmask(static_cast<Value>(0))
 	{}
 
-	Bitset(T bitmask)
+	Bitset(Value bitmask)
 	:	m_bitmask(bitmask)
 	{}
 
@@ -52,7 +52,7 @@ public:
 
 	Bool bitsEnabled(Value mask) const
 	{
-		return m_bitmask & mask;
+		return (m_bitmask & mask) != static_cast<Value>(0);
 	}
 
 	Value getBitmask() const

+ 1 - 1
include/anki/util/Filesystem.h

@@ -19,7 +19,7 @@ Bool fileExists(const CString& filename);
 /// Get file extension
 /// @param[in] filename The file to open
 /// @return nullptr on failure and if the dot is the last character
-CString getFileExtension(const CString& filename);
+String getFileExtension(const CString& filename, HeapAllocator<U8>& alloc);
 
 /// Return true if directory exists?
 Bool directoryExists(const CString& dir);

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

@@ -239,7 +239,7 @@ private:
 };
 
 /// User defined string literal for CStrings.
-CString operator"" _cstr(const char* str, unsigned long length)
+inline CString operator"" _cstr(const char* str, unsigned long length)
 {
 	return CString(str, length);
 }

+ 102 - 68
src/core/App.cpp

@@ -4,21 +4,20 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/core/App.h"
-#include "anki/Config.h"
+#include "anki/misc/ConfigSet.h"
 #include "anki/core/Logger.h"
 #include "anki/util/Exception.h"
 #include "anki/util/File.h"
+#include "anki/util/Filesystem.h"
 #include "anki/util/System.h"
+#include "anki/core/Counters.h"
+
+#include "anki/core/NativeWindow.h"
+#include "anki/input/Input.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/renderer/MainRenderer.h"
-#include "anki/input/Input.h"
-#include "anki/core/NativeWindow.h"
-#include "anki/core/Counters.h"
-#include <cstring>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-//#include <execinfo.h> XXX
+#include "anki/script/ScriptManager.h"
+
 #include <signal.h>
 #if ANKI_OS == ANKI_OS_ANDROID
 #	include <android_native_app_glue.h>
@@ -34,25 +33,40 @@ android_app* gAndroidApp = nullptr;
 #endif
 
 //==============================================================================
-App::App(AllocAlignedCallback allocCb, void* allocCbUserData)
+App::App(const ConfigSet& config, 
+	AllocAlignedCallback allocCb, void* allocCbUserData)
 :	m_allocCb(allocCb),
 	m_allocCbData(allocCbUserData),
-	m_heapAlloc(HeapMemoryPool(allocCbUserData, allocCb))
+	m_heapAlloc(HeapMemoryPool(allocCb, allocCbUserData))
 {
 	init(config);
 }
 
 //==============================================================================
-void App::init(const Config& config)
+void App::makeCurrent(void* data)
 {
-	printAppInfo();
-	initDirs();
+	App* app = reinterpret_cast<App*>(data);
+	app->m_window->contextMakeCurrent(app->m_ctx);
+}
 
-	timerTick = 1.0 / 60.0; // in sec. 1.0 / period
+//==============================================================================
+void App::swapWindow(void* window)
+{
+	reinterpret_cast<NativeWindow*>(window)->swapBuffers();
+}
 
+//==============================================================================
+void App::init(const ConfigSet& config)
+{
 	// Logger
 	LoggerSingleton::init(
-		Logger::InitFlags::WITH_SYSTEM_MESSAGE_HANDLER, m_heapAlloc);
+		Logger::InitFlags::WITH_SYSTEM_MESSAGE_HANDLER, m_heapAlloc,
+		&m_cacheDir[0]);
+
+	printAppInfo();
+	initDirs();
+
+	m_timerTick = 1.0 / 60.0; // in sec. 1.0 / period
 
 	// Window
 	NativeWindow::Initializer nwinit;
@@ -65,7 +79,7 @@ void App::init(const Config& config)
 	nwinit.m_fullscreenDesktopRez = config.get("fullscreen");
 	nwinit.m_debugContext = ANKI_DEBUG;
 	m_window = m_heapAlloc.newInstance<NativeWindow>(nwinit, m_heapAlloc);	
-	Context context = m_window->getCurrentContext();
+	m_ctx = m_window->getCurrentContext();
 	m_window->contextMakeCurrent(nullptr);
 
 	// Input
@@ -74,9 +88,37 @@ void App::init(const Config& config)
 	// Threadpool
 	m_threadpool = m_heapAlloc.newInstance<Threadpool>(getCpuCoresCount());
 
+	// GL
+	m_gl = m_heapAlloc.newInstance<GlDevice>(
+		makeCurrent, this,
+		swapWindow, m_window,
+		nwinit.m_debugContext,
+		m_allocCb, m_allocCbData,
+		m_cacheDir.toCString());
+
+	// Resources
+	ResourceManager::Initializer rinit;
+	rinit.m_gl = m_gl;
+	rinit.m_config = &config;
+	rinit.m_cacheDir = m_cacheDir.toCString();
+	rinit.m_allocCallback = m_allocCb;
+	rinit.m_allocCallbackData = m_allocCbData;
+	m_resources = m_heapAlloc.newInstance<ResourceManager>(rinit);
+
+	// Renderer
+	m_renderer = m_heapAlloc.newInstance<MainRenderer>(
+		m_threadpool,
+		m_resources,
+		m_gl,
+		m_heapAlloc,
+		config);
+
 	// Scene
 	m_scene = m_heapAlloc.newInstance<SceneGraph>(
-		m_allocCb, m_allocCbData, m_threadpool);
+		m_allocCb, m_allocCbData, m_threadpool, m_resources);
+
+	// Script
+	m_script = m_heapAlloc.newInstance<ScriptManager>(m_heapAlloc);
 }
 
 //==============================================================================
@@ -84,48 +126,47 @@ void App::initDirs()
 {
 #if ANKI_OS != ANKI_OS_ANDROID
 	// Settings path
-	Array<char, 512> home;
-	getHomeDirectory(sizeof(home), &home[0]);
-	String settingsPath = String(&home[0]) + "/.anki";
-	if(!directoryExists(settingsPath.c_str()))
+	String home = getHomeDirectory(m_heapAlloc);
+	String settingsDir = home + "/.anki";
+	if(!directoryExists(settingsDir.toCString()))
 	{
-		ANKI_LOGI("Creating settings dir: %s", settingsPath.c_str());
-		createDirectory(settingsPath.c_str());
+		ANKI_LOGI("Creating settings dir: %s", &settingsDir[0]);
+		createDirectory(settingsDir.toCString());
 	}
 
 	// Cache
-	cachePath = settingsPath + "/cache";
-	if(directoryExists(cachePath.c_str()))
+	m_cacheDir = settingsDir + "/cache";
+	if(directoryExists(m_cacheDir.toCString()))
 	{
-		ANKI_LOGI("Deleting dir: %s", cachePath.c_str());
-		removeDirectory(cachePath.c_str());
+		ANKI_LOGI("Deleting dir: %s", &m_cacheDir[0]);
+		removeDirectory(m_cacheDir.toCString());
 	}
 
-	ANKI_LOGI("Creating cache dir: %s", cachePath.c_str());
-	createDirectory(cachePath.c_str());
+	ANKI_LOGI("Creating cache dir: %s", &m_cacheDir[0]);
+	createDirectory(m_cacheDir.toCString());
 #else
 	//ANKI_ASSERT(gAndroidApp);
 	//ANativeActivity* activity = gAndroidApp->activity;
 
 	// Settings path
-	//settingsPath = String(activity->internalDataPath, alloc);
-	settingsPath = String("/sdcard/.anki/");
-	if(!directoryExists(settingsPath.c_str()))
+	//settingsDir = String(activity->internalDataDir, alloc);
+	settingsDir = String("/sdcard/.anki/");
+	if(!directoryExists(settingsDir.c_str()))
 	{
-		ANKI_LOGI("Creating settings dir: %s", settingsPath.c_str());
-		createDirectory(settingsPath.c_str());
+		ANKI_LOGI("Creating settings dir: %s", settingsDir.c_str());
+		createDirectory(settingsDir.c_str());
 	}
 
 	// Cache
-	cachePath = settingsPath + "/cache";
-	if(directoryExists(cachePath.c_str()))
+	cacheDir = settingsDir + "/cache";
+	if(directoryExists(cacheDir.c_str()))
 	{
-		ANKI_LOGI("Deleting dir: %s", cachePath.c_str());
-		removeDirectory(cachePath.c_str());
+		ANKI_LOGI("Deleting dir: %s", cacheDir.c_str());
+		removeDirectory(cacheDir.c_str());
 	}
 
-	ANKI_LOGI("Creating cache dir: %s", cachePath.c_str());
-	createDirectory(cachePath.c_str());
+	ANKI_LOGI("Creating cache dir: %s", cacheDir.c_str());
+	createDirectory(cacheDir.c_str());
 #endif
 }
 
@@ -136,40 +177,32 @@ void App::quit(int code)
 //==============================================================================
 void App::printAppInfo()
 {
-	std::stringstream msg;
-	msg << "App info: ";
-	msg << "AnKi " << ANKI_VERSION_MAJOR << "." << ANKI_VERSION_MINOR << ", ";
+	String msg(getAllocator());
+	msg.sprintf(
+		"App info: "
+		"version %u.%u, "
+		"build %s %s, "
+		"commit %s",
+		ANKI_VERSION_MAJOR, ANKI_VERSION_MINOR,
 #if !ANKI_DEBUG
-	msg << "Release";
+		"Release",
 #else
-	msg << "Debug";
+		"Debug",
 #endif
-	msg << " build,";
-
-	msg << " " << ANKI_CPU_ARCH_STR;
-	msg << " " << ANKI_GL_STR;
-	msg << " " << ANKI_WINDOW_BACKEND_STR;
-	msg << " CPU cores " << getCpuCoresCount();
-
-	msg << " build date " __DATE__ ", " << "rev " << ANKI_REVISION;
+		__DATE__,
+		ANKI_REVISION);
 
-	ANKI_LOGI(msg.str().c_str());
+	ANKI_LOGI(&msg[0]);
 }
 
 //==============================================================================
-void App::mainLoop()
+void App::mainLoop(UserMainLoopCallback callback, void* userData)
 {
-#if 0
 	ANKI_LOGI("Entering main loop");
 
 	HighRezTimer::Scalar prevUpdateTime = HighRezTimer::getCurrentTime();
 	HighRezTimer::Scalar crntTime = prevUpdateTime;
 
-	SceneGraph& scene = SceneGraphSingleton::get();
-	MainRenderer& renderer = MainRendererSingleton::get();
-	Input& input = InputSingleton::get();
-	NativeWindow& window = NativeWindowSingleton::get();
-
 	ANKI_COUNTER_START_TIMER(FPS);
 	while(true)
 	{
@@ -180,12 +213,14 @@ void App::mainLoop()
 		crntTime = HighRezTimer::getCurrentTime();
 
 		// Update
-		input.handleEvents();
-		scene.update(
-			prevUpdateTime, crntTime, MainRendererSingleton::get());
-		renderer.render(SceneGraphSingleton::get());
+		m_input->handleEvents();
+		m_scene->update(prevUpdateTime, crntTime, *m_renderer);
+		m_renderer->render(*m_scene);
+
+		// User update
+		callback(*this, userData);
 
-		window.swapBuffers();
+		m_gl->swapBuffers();
 		ANKI_COUNTERS_RESOLVE_FRAME();
 
 		// Sleep
@@ -202,7 +237,6 @@ void App::mainLoop()
 	// Counters end
 	ANKI_COUNTER_STOP_TIMER_INC(FPS);
 	ANKI_COUNTERS_FLUSH();
-#endif
 }
 
 } // end namespace anki

+ 6 - 0
src/core/Config.cpp

@@ -82,6 +82,12 @@ Config::Config()
 
 	newOption("maxTextureSize", 1024 * 1024);
 	newOption("textureAnisotropy", 8);
+
+	//
+	// Window
+	//
+	newOption("glminor", 4);
+	newOption("glmajor", 4);
 }
 
 //==============================================================================

+ 21 - 12
src/core/Logger.cpp

@@ -14,7 +14,8 @@
 namespace anki {
 
 //==============================================================================
-Logger::Logger(InitFlags flags, HeapAllocator<U8>& alloc)
+Logger::Logger(InitFlags flags, HeapAllocator<U8>& alloc, const char* cacheDir)
+:	m_handlers(alloc)
 {
 	if((flags & InitFlags::WITH_SYSTEM_MESSAGE_HANDLER) != InitFlags::NONE)
 	{
@@ -23,10 +24,24 @@ Logger::Logger(InitFlags flags, HeapAllocator<U8>& alloc)
 
 	if((flags & InitFlags::WITH_LOG_FILE_MESSAGE_HANDLER) != InitFlags::NONE)
 	{
+		U size = std::strlen(cacheDir) + 1;
+		m_cacheDir = reinterpret_cast<char*>(alloc.allocate(size));
+		std::memcpy(m_cacheDir, cacheDir, size);
+
 		addMessageHandler(this, &logfileMessageHandler);
 	}
 }
 
+//==============================================================================
+Logger::~Logger()
+{
+	if(m_cacheDir != nullptr)
+	{
+		HeapAllocator<char> alloc = m_handlers.get_allocator();
+		alloc.deallocate(m_cacheDir, 0);
+	}
+}
+
 //==============================================================================
 void Logger::addMessageHandler(void* data, MessageHandlerCallback callback)
 {
@@ -145,17 +160,11 @@ void Logger::logfileMessageHandler(void* vlogger, const Info& info)
 	// Init the file
 	if(!logger->m_logfile.isOpen())
 	{
-		const String& filename = AppSingleton::get().getSettingsPath();
-
-		if(!filename.empty())
-		{
-			logger->m_logfile.open((filename + "/anki.log").c_str(), 
-				File::OpenFlag::WRITE);
-		}
-		else
-		{
-			return;
-		}
+		String filename(logger->m_handlers.get_allocator());
+		filename = logger->m_cacheDir;
+		filename += "/anki.log";
+
+		logger->m_logfile.open(filename.toCString(), File::OpenFlag::WRITE);
 	}
 
 	const char* x = nullptr;

+ 1 - 1
src/core/NativeWindowSdl.cpp

@@ -62,7 +62,7 @@ void NativeWindow::create(Initializer& init, HeapAllocator<U8>& alloc)
 	}
 
 	m_impl->m_window = SDL_CreateWindow(
-    	init.m_title.c_str(),
+    	init.m_title,
 		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 
 		init.m_width, init.m_height, flags);
 

+ 7 - 4
src/core/StdinListener.cpp

@@ -11,8 +11,9 @@
 namespace anki {
 
 //==============================================================================
-StdinListener::StdinListener()
-:	m_thrd("anki_stdin")
+StdinListener::StdinListener(HeapAllocator<String>& alloc)
+:	m_q(alloc),
+	m_thrd("anki_stdin")
 {
 	m_thrd.start(this, workingFunc);	
 }
@@ -35,8 +36,10 @@ I StdinListener::workingFunc(Thread::Info& info)
 	{
 		I m = read(0, &buff[0], sizeof(buff));
 		buff[m] = '\0';
+
 		self.m_mtx.lock();
-		self.m_q.push(String(&buff[0]));
+		auto alloc = self.m_q.get_allocator();
+		self.m_q.emplace_back(&buff[0], alloc);
 		self.m_mtx.unlock();
 	}
 
@@ -52,7 +55,7 @@ String StdinListener::getLine()
 	if(!m_q.empty())
 	{
 		ret = m_q.front();
-		m_q.pop();
+		m_q.pop_front();
 	}
 
 	m_mtx.unlock();

+ 1 - 1
src/gl/GlDevice.cpp

@@ -63,7 +63,7 @@ void GlDevice::swapBuffers()
 }
 
 //==============================================================================
-PtrSize GlDevice::getBufferOffsetAlignment(GLenum target)
+PtrSize GlDevice::getBufferOffsetAlignment(GLenum target) const
 {
 	const GlState& state = m_queue->getState();
 

+ 5 - 2
src/input/InputSdl.cpp

@@ -18,7 +18,10 @@ void Input::init(NativeWindow* nativeWindow)
 	m_nativeWindow = nativeWindow;
 
 	// Init native
-	m_impl = m_nativeWindow->_getAllocator().newInstance<InputImpl>();
+	HeapAllocator<std::pair<const SDL_Keycode, KeyCode>> alloc = 
+		m_nativeWindow->_getAllocator();
+
+	m_impl = m_nativeWindow->_getAllocator().newInstance<InputImpl>(alloc);
 
 	//impl
 	m_impl->m_sdlToAnki[SDLK_RETURN] = KeyCode::RETURN;
@@ -319,7 +322,7 @@ void Input::handleEvents()
 				/ m_nativeWindow->getHeight() * 2.0 - 1.0);
 			break;
 		case SDL_QUIT:
-			addEvent(WINDOW_CLOSED_EVENT);
+			addEvent(Event::WINDOW_CLOSED);
 			break;
 		}
 	} // end while events

+ 4 - 3
src/renderer/Dbg.cpp

@@ -11,6 +11,7 @@
 #include "anki/scene/Light.h"
 #include "anki/core/Logger.h"
 #include "anki/util/Enum.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -32,7 +33,7 @@ Dbg::~Dbg()
 void Dbg::init(const ConfigSet& initializer)
 {
 	m_enabled = initializer.get("dbg.enabled");
-	enableBits(enumToValue(Flag::ALL));
+	enableBits(Flag::ALL);
 
 	try
 	{
@@ -53,7 +54,7 @@ void Dbg::init(const ConfigSet& initializer)
 				{m_r->getMs()._getDepthRt(), GL_DEPTH_ATTACHMENT}});
 		}
 
-		m_drawer = getAllocator().newInstance<DebugDrawer>();
+		m_drawer = getAllocator().newInstance<DebugDrawer>(m_r);
 		m_sceneDrawer = getAllocator().newInstance<SceneDebugDrawer>(m_drawer);
 
 		jobs.finish();
@@ -89,7 +90,7 @@ void Dbg::run(GlCommandBufferHandle& jobs)
 			return;
 		}
 
-		if(bitsEnabled(enumToValue(Flag::SPATIAL)) && sp)
+		if(bitsEnabled(Flag::SPATIAL) && sp)
 		{
 			m_sceneDrawer->draw(node);
 		}

+ 16 - 17
src/renderer/Drawer.cpp

@@ -30,7 +30,7 @@ public:
 	Ptr<const FrustumComponent> m_fr;
 	Ptr<RenderableDrawer> m_drawer;
 	U8 m_instanceCount;
-	GlCommandBufferHandle m_jobs;
+	GlCommandBufferHandle m_cmdBuff;
 
 	F32 m_flod;
 
@@ -201,7 +201,7 @@ public:
 			{
 				auto unit = glvar.getTextureUnit();
 
-				m_drawer->m_r->getMs()._getSmallDepthRt().bind(m_jobs, unit);
+				m_drawer->m_r->getMs()._getSmallDepthRt().bind(m_cmdBuff, unit);
 			}
 			break;
 		default:
@@ -221,24 +221,23 @@ void SetupRenderableVariableVisitor::uniSet<TextureResourcePointer>(
 	GlTextureHandle tex = (*values)->getGlTexture();
 	auto unit = uni.getTextureUnit();
 
-	tex.bind(m_jobs, unit);
+	tex.bind(m_cmdBuff, unit);
 }
 
 //==============================================================================
 RenderableDrawer::RenderableDrawer(Renderer* r)
-	: m_r(r)
+:	m_r(r)
 {
 	// Create the uniform buffer
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
-	m_uniformBuff = GlBufferHandle(jobs, GL_UNIFORM_BUFFER, 
+	GlCommandBufferHandle cmdBuff(&m_r->_getGlDevice());
+	m_uniformBuff = GlBufferHandle(cmdBuff, GL_UNIFORM_BUFFER, 
 		MAX_UNIFORM_BUFFER_SIZE,
 		GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
-	jobs.flush();
+	cmdBuff.flush();
 
 	m_uniformPtr = (U8*)m_uniformBuff.getPersistentMappingAddress();
 	ANKI_ASSERT(m_uniformPtr != nullptr);
-	ANKI_ASSERT(isAligned(gl.getBufferOffsetAlignment(
+	ANKI_ASSERT(isAligned(m_r->_getGlDevice().getBufferOffsetAlignment(
 		m_uniformBuff.getTarget()), m_uniformPtr));
 
 	// Set some other values
@@ -260,7 +259,7 @@ void RenderableDrawer::setupUniforms(
 	// Find a place to write the uniforms
 	//
 	U8* prevUniformPtr = m_uniformPtr;
-	alignRoundUp(GlDeviceSingleton::get().getBufferOffsetAlignment(
+	alignRoundUp(m_r->_getGlDevice().getBufferOffsetAlignment(
 		m_uniformBuff.getTarget()), m_uniformPtr);
 	U diff = m_uniformPtr - prevUniformPtr;
 
@@ -280,7 +279,7 @@ void RenderableDrawer::setupUniforms(
 	vis.m_fr = &fr;
 	vis.m_drawer = this;
 	vis.m_instanceCount = visibleNode.m_spatialsCount;
-	vis.m_jobs = m_jobs;
+	vis.m_cmdBuff = m_cmdBuff;
 	vis.m_flod = flod;
 
 	for(auto it = renderable.getVariablesBegin();
@@ -295,7 +294,7 @@ void RenderableDrawer::setupUniforms(
 	// Update the uniform descriptor
 	//
 	m_uniformBuff.bindShaderBuffer(
-		m_jobs, 
+		m_cmdBuff, 
 		m_uniformPtr - persistent,
 		mtl.getDefaultBlockSize(),
 		0);
@@ -347,7 +346,7 @@ void RenderableDrawer::render(SceneNode& frsn, VisibleNode& visibleNode)
 			return;
 		}
 
-		m_jobs.setBlendFunctions(
+		m_cmdBuff.setBlendFunctions(
 			mtl.getBlendingSfactor(), mtl.getBlendingDfactor());
 	}
 
@@ -361,19 +360,19 @@ void RenderableDrawer::render(SceneNode& frsn, VisibleNode& visibleNode)
 	// Enqueue vertex, program and drawcall
 	build.m_subMeshIndicesArray = &visibleNode.m_spatialIndices[0];
 	build.m_subMeshIndicesCount = visibleNode.m_spatialsCount;
-	build.m_jobs = m_jobs;
+	build.m_jobs = m_cmdBuff;
 
 	renderable.buildRendering(build);
 }
 
 //==============================================================================
 void RenderableDrawer::prepareDraw(RenderingStage stage, Pass pass,
-	GlCommandBufferHandle& jobs)
+	GlCommandBufferHandle& cmdBuff)
 {
 	// Set some numbers
 	m_stage = stage;
 	m_pass = pass;
-	m_jobs = jobs;
+	m_cmdBuff = cmdBuff;
 
 	if(m_r->getFramesCount() > m_uniformsUsedSizeFrame)
 	{
@@ -387,7 +386,7 @@ void RenderableDrawer::prepareDraw(RenderingStage stage, Pass pass,
 void RenderableDrawer::finishDraw()
 {
 	// Release the job chain
-	m_jobs = GlCommandBufferHandle();
+	m_cmdBuff = GlCommandBufferHandle();
 
 	if(m_uniformsUsedSize > MAX_UNIFORM_BUFFER_SIZE / 3)
 	{

+ 6 - 5
src/renderer/Ez.cpp

@@ -8,18 +8,19 @@
 #include "anki/core/App.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/Camera.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
 //==============================================================================
-void Ez::init(const ConfigSet& initializer)
+void Ez::init(const ConfigSet& config)
 {
-	m_enabled = initializer.get("ms.ez.enabled");
-	m_maxObjectsToDraw = initializer.get("ms.ez.maxObjectsToDraw");
+	m_enabled = config.get("ms.ez.enabled");
+	m_maxObjectsToDraw = config.get("ms.ez.maxObjectsToDraw");
 }
 
 //==============================================================================
-void Ez::run(GlCommandBufferHandle& jobs)
+void Ez::run(GlCommandBufferHandle& cmdBuff)
 {
 	ANKI_ASSERT(m_enabled);
 
@@ -29,7 +30,7 @@ void Ez::run(GlCommandBufferHandle& jobs)
 	VisibilityTestResults& vi = cam.getVisibilityTestResults();
 
 	m_r->getSceneDrawer().prepareDraw(
-		RenderingStage::MATERIAL, Pass::DEPTH, jobs);
+		RenderingStage::MATERIAL, Pass::DEPTH, cmdBuff);
 
 	U count = m_maxObjectsToDraw;
 	for(auto& it : vi.m_renderables)

+ 5 - 8
src/renderer/Hdr.cpp

@@ -5,6 +5,7 @@
 
 #include "anki/renderer/Hdr.h"
 #include "anki/renderer/Renderer.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -82,10 +83,8 @@ void Hdr::initInternal(const ConfigSet& initializer)
 		m_blurringDist, m_height, 
 		static_cast<U>(initializer.get("pps.hdr.samples")));
 
-	m_hblurFrag.load(ProgramResource::createSourceToCache(
-		SHADER_FILENAME, pps.toCString(), "r_", 
-		getResourceManager()).toCString(),
-		&getResourceManager());
+	m_hblurFrag.loadToCache(&getResourceManager(),
+		SHADER_FILENAME, pps.toCString(), "r_");
 
 	m_hblurPpline = 
 		m_r->createDrawQuadProgramPipeline(m_hblurFrag->getGlProgram());
@@ -98,10 +97,8 @@ void Hdr::initInternal(const ConfigSet& initializer)
 		m_blurringDist, m_width, 
 		static_cast<U>(initializer.get("pps.hdr.samples")));
 
-	m_vblurFrag.load(ProgramResource::createSourceToCache(
-		SHADER_FILENAME, pps.toCString(), "r_",
-		getResourceManager()).toCString(),
-		&getResourceManager());
+	m_vblurFrag.loadToCache(&getResourceManager(),
+		SHADER_FILENAME, pps.toCString(), "r_");
 
 	m_vblurPpline = 
 		m_r->createDrawQuadProgramPipeline(m_vblurFrag->getGlProgram());

+ 101 - 99
src/renderer/Is.cpp

@@ -10,7 +10,7 @@
 #include "anki/scene/Light.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Logger.h"
-#include <sstream>
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -82,11 +82,11 @@ public:
 	VisibilityTestResults::Container::const_iterator m_lightsBegin;
 	VisibilityTestResults::Container::const_iterator m_lightsEnd;
 
-	std::atomic<U32>* m_pointLightsCount = nullptr;
-	std::atomic<U32>* m_spotLightsCount = nullptr;
-	std::atomic<U32>* m_spotTexLightsCount = nullptr;
+	AtomicU32* m_pointLightsCount = nullptr;
+	AtomicU32* m_spotLightsCount = nullptr;
+	AtomicU32* m_spotTexLightsCount = nullptr;
 		
-	Array2d<std::atomic<U32>, 
+	Array2d<AtomicU32, 
 		ANKI_RENDERER_MAX_TILES_Y, 
 		ANKI_RENDERER_MAX_TILES_X>
 		* m_tilePointLightsCount = nullptr,
@@ -374,11 +374,11 @@ Is::~Is()
 {}
 
 //==============================================================================
-void Is::init(const ConfigSet& initializer)
+void Is::init(const ConfigSet& config)
 {
 	try
 	{
-		initInternal(initializer);
+		initInternal(config);
 	}
 	catch(const std::exception& e)
 	{
@@ -387,21 +387,21 @@ void Is::init(const ConfigSet& initializer)
 }
 
 //==============================================================================
-void Is::initInternal(const ConfigSet& initializer)
+void Is::initInternal(const ConfigSet& config)
 {
-	m_groundLightEnabled = initializer.get("is.groundLightEnabled");
-	m_maxPointLights = initializer.get("is.maxPointLights");
-	m_maxSpotLights = initializer.get("is.maxSpotLights");
-	m_maxSpotTexLights = initializer.get("is.maxSpotTexLights");
+	m_groundLightEnabled = config.get("is.groundLightEnabled");
+	m_maxPointLights = config.get("is.maxPointLights");
+	m_maxSpotLights = config.get("is.maxSpotLights");
+	m_maxSpotTexLights = config.get("is.maxSpotTexLights");
 
 	if(m_maxPointLights < 1 || m_maxSpotLights < 1 || m_maxSpotTexLights < 1)
 	{
 		throw ANKI_EXCEPTION("Incorrect number of max lights");
 	}
 
-	m_maxPointLightsPerTile = initializer.get("is.maxPointLightsPerTile");
-	m_maxSpotLightsPerTile = initializer.get("is.maxSpotLightsPerTile");
-	m_maxSpotTexLightsPerTile = initializer.get("is.maxSpotTexLightsPerTile");
+	m_maxPointLightsPerTile = config.get("is.maxPointLightsPerTile");
+	m_maxSpotLightsPerTile = config.get("is.maxSpotLightsPerTile");
+	m_maxSpotTexLightsPerTile = config.get("is.maxSpotTexLightsPerTile");
 
 	if(m_maxPointLightsPerTile < 1 
 		|| m_maxSpotLightsPerTile < 1 
@@ -418,51 +418,53 @@ void Is::initInternal(const ConfigSet& initializer)
 	//
 	// Init the passes
 	//
-	m_sm.init(initializer);
+	m_sm.init(config);
 
 	//
 	// Load the programs
 	//
-	std::stringstream pps;
-
-	pps << "\n#define TILES_X_COUNT " << m_r->getTilesCount().x()
-		<< "\n#define TILES_Y_COUNT " << m_r->getTilesCount().y()
-		<< "\n#define TILES_COUNT " 
-		<< (m_r->getTilesCount().x() * m_r->getTilesCount().y())
-		<< "\n#define RENDERER_WIDTH " << m_r->getWidth()
-		<< "\n#define RENDERER_HEIGHT " << m_r->getHeight()
-		<< "\n#define MAX_POINT_LIGHTS_PER_TILE " 
-		<< (U32)m_maxPointLightsPerTile
-		<< "\n#define MAX_SPOT_LIGHTS_PER_TILE " 
-		<< (U32)m_maxSpotLightsPerTile
-		<< "\n#define MAX_SPOT_TEX_LIGHTS_PER_TILE " 
-		<< (U32)m_maxSpotTexLightsPerTile
-		<< "\n#define MAX_POINT_LIGHTS " << (U32)m_maxPointLights
-		<< "\n#define MAX_SPOT_LIGHTS " << (U32)m_maxSpotLights 
-		<< "\n#define MAX_SPOT_TEX_LIGHTS " << (U32)m_maxSpotTexLights
-		<< "\n#define GROUND_LIGHT " << (U32)m_groundLightEnabled
-		<< "\n#define TILES_BLOCK_BINDING " << TILES_BLOCK_BINDING
-		<< "\n";
-
-	if(m_sm.getPoissonEnabled())
-	{
-		pps << "#define POISSON 1\n";
-	}
-	else
-	{
-		pps << "#define POISSON 0\n";
-	}
+	String pps(getAllocator());
+
+	pps.sprintf(
+		"\n#define TILES_X_COUNT %u\n"
+		"#define TILES_Y_COUNT %u\n"
+		"#define TILES_COUNT %u\n" 
+		"#define RENDERER_WIDTH %u\n"
+		"#define RENDERER_HEIGHT %u\n"
+		"#define MAX_POINT_LIGHTS_PER_TILE %u\n"
+		"#define MAX_SPOT_LIGHTS_PER_TILE %u\n"
+		"#define MAX_SPOT_TEX_LIGHTS_PER_TILE %u\n" 
+		"#define MAX_POINT_LIGHTS %u\n"
+		"#define MAX_SPOT_LIGHTS %u\n"
+		"#define MAX_SPOT_TEX_LIGHTS %u\n"
+		"#define GROUND_LIGHT %u\n"
+		"#define TILES_BLOCK_BINDING %u\n"
+		"#define POISSON %u\n",
+		m_r->getTilesCount().x(),
+		m_r->getTilesCount().y(),
+		(m_r->getTilesCount().x() * m_r->getTilesCount().y()),
+		m_r->getWidth(),
+		m_r->getHeight(),
+		m_maxPointLightsPerTile,
+		m_maxSpotLightsPerTile,
+		m_maxSpotTexLightsPerTile,
+		m_maxPointLights,
+		m_maxSpotLights,
+		m_maxSpotTexLights,
+		m_groundLightEnabled,
+		TILES_BLOCK_BINDING,
+		m_sm.getPoissonEnabled());
 
 	// point light
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl); // Job for initialization
+	GlCommandBufferHandle cmdBuff(&getGlDevice()); // Job for initialization
+
+	m_lightVert.loadToCache(&getResourceManager(),
+		"shaders/IsLp.vert.glsl", pps.toCString(), "r_");
 
-	m_lightVert.load(ProgramResource::createSrcCodeToCache(
-		"shaders/IsLp.vert.glsl", pps.str().c_str(), "r_").c_str());
-	m_lightFrag.load(ProgramResource::createSrcCodeToCache(
-		"shaders/IsLp.frag.glsl", pps.str().c_str(), "r_").c_str());
+	m_lightFrag.loadToCache(&getResourceManager(),
+		"shaders/IsLp.frag.glsl", pps.toCString(), "r_");
 
-	m_lightPpline = GlProgramPipelineHandle(jobs, 
+	m_lightPpline = GlProgramPipelineHandle(cmdBuff, 
 		{m_lightVert->getGlProgram(), m_lightFrag->getGlProgram()});
 
 	//
@@ -472,7 +474,7 @@ void Is::initInternal(const ConfigSet& initializer)
 	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGB8,
 			GL_RGB, GL_UNSIGNED_BYTE, 1, m_rt);
 
-	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}});
+	m_fb = GlFramebufferHandle(cmdBuff, {{m_rt, GL_COLOR_ATTACHMENT0}});
 
 	//
 	// Init the quad
@@ -480,10 +482,10 @@ void Is::initInternal(const ConfigSet& initializer)
 	static const F32 quadVertCoords[][2] = {{1.0, 1.0}, {0.0, 1.0},
 		{1.0, 0.0}, {0.0, 0.0}};
 
-	GlClientBufferHandle tempBuff(jobs, sizeof(quadVertCoords), 
+	GlClientBufferHandle tempBuff(cmdBuff, sizeof(quadVertCoords), 
 		(void*)&quadVertCoords[0][0]);
 
-	m_quadPositionsVertBuff = GlBufferHandle(jobs, GL_ARRAY_BUFFER,
+	m_quadPositionsVertBuff = GlBufferHandle(cmdBuff, GL_ARRAY_BUFFER,
 		tempBuff, 0);
 
 	//
@@ -491,22 +493,22 @@ void Is::initInternal(const ConfigSet& initializer)
 	//
 	const GLbitfield bufferBits = GL_DYNAMIC_STORAGE_BIT;
 
-	m_commonBuff = GlBufferHandle(jobs, GL_SHADER_STORAGE_BUFFER, 
+	m_commonBuff = GlBufferHandle(cmdBuff, GL_SHADER_STORAGE_BUFFER, 
 		sizeof(shader::CommonUniforms), bufferBits);
 
-	m_lightsBuff = GlBufferHandle(jobs, GL_SHADER_STORAGE_BUFFER, 
+	m_lightsBuff = GlBufferHandle(cmdBuff, GL_SHADER_STORAGE_BUFFER, 
 		calcLightsBufferSize(), bufferBits);
 
-	m_tilesBuff = GlBufferHandle(jobs, GL_SHADER_STORAGE_BUFFER,
+	m_tilesBuff = GlBufferHandle(cmdBuff, GL_SHADER_STORAGE_BUFFER,
 		m_r->getTilesCount().x() * m_r->getTilesCount().y() * m_tileSize,
 		bufferBits);
 
 	// Last thing to do
-	jobs.flush();
+	cmdBuff.flush();
 }
 
 //==============================================================================
-void Is::lightPass(GlCommandBufferHandle& jobs)
+void Is::lightPass(GlCommandBufferHandle& cmdBuff)
 {
 	Threadpool& threadPool = m_r->_getThreadpool();
 	m_cam = &m_r->getSceneGraph().getActiveCamera();
@@ -561,13 +563,13 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 	//
 	// Do shadows pass
 	//
-	m_sm.run(&shadowCasters[0], visibleSpotTexLightsCount, jobs);
+	m_sm.run(&shadowCasters[0], visibleSpotTexLightsCount, cmdBuff);
 
 	//
 	// Write the lights and tiles UBOs
 	//
-	GlDevice& gl = GlDeviceSingleton::get();
-	U32 blockAlignment = gl.getBufferOffsetAlignment(m_lightsBuff.getTarget());
+	U32 blockAlignment = 
+		getGlDevice().getBufferOffsetAlignment(m_lightsBuff.getTarget());
 
 	// Get the offsets and sizes of each uniform block
 	PtrSize pointLightsOffset = 0;
@@ -585,23 +587,23 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 	ANKI_ASSERT(
 		spotTexLightsOffset + spotTexLightsSize <= calcLightsBufferSize());
 
-	// Fire the super jobs
-	Array<WriteLightsJob, Threadpool::MAX_THREADS> tjobs;
+	// Fire the super cmdBuff
+	Array<WriteLightsJob, Threadpool::MAX_THREADS> tcmdBuff;
 
 	GlClientBufferHandle lightsClientBuff;
 	if(totalLightsCount > 0)
 	{
 		lightsClientBuff = GlClientBufferHandle(
-			jobs, spotTexLightsOffset + spotTexLightsSize, nullptr);
+			cmdBuff, spotTexLightsOffset + spotTexLightsSize, nullptr);
 	}
 
-	GlClientBufferHandle tilesClientBuff(jobs, m_tilesBuff.getSize(), nullptr);
+	GlClientBufferHandle tilesClientBuff(cmdBuff, m_tilesBuff.getSize(), nullptr);
 
-	std::atomic<U32> pointLightsAtomicCount(0);
-	std::atomic<U32> spotLightsAtomicCount(0);
-	std::atomic<U32> spotTexLightsAtomicCount(0);
+	AtomicU32 pointLightsAtomicCount(0);
+	AtomicU32 spotLightsAtomicCount(0);
+	AtomicU32 spotTexLightsAtomicCount(0);
 
-	Array2d<std::atomic<U32>, 
+	Array2d<AtomicU32, 
 		ANKI_RENDERER_MAX_TILES_Y, 
 		ANKI_RENDERER_MAX_TILES_X> 
 		tilePointLightsCount,
@@ -620,7 +622,7 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 
 	for(U i = 0; i < threadPool.getThreadsCount(); i++)
 	{
-		WriteLightsJob& job = tjobs[i];
+		WriteLightsJob& job = tcmdBuff[i];
 
 		if(i == 0)
 		{
@@ -655,16 +657,16 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 		}
 		else
 		{
-			// Just copy from the first job. All jobs have the same data
+			// Just copy from the first job. All cmdBuff have the same data
 
-			job = tjobs[0];
+			job = tcmdBuff[0];
 		}
 
 		threadPool.assignNewTask(i, &job);
 	}
 
 	// In the meantime set the state
-	setState(jobs);
+	setState(cmdBuff);
 
 	// Sync
 	threadPool.waitForAllThreadsToFinish();
@@ -696,10 +698,10 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 	// Write BOs
 	if(totalLightsCount > 0)
 	{
-		m_lightsBuff.write(jobs,
+		m_lightsBuff.write(cmdBuff,
 			lightsClientBuff, 0, 0, spotTexLightsOffset + spotTexLightsSize);
 	}
-	m_tilesBuff.write(jobs, tilesClientBuff, 0, 0, tilesClientBuff.getSize());
+	m_tilesBuff.write(cmdBuff, tilesClientBuff, 0, 0, tilesClientBuff.getSize());
 
 	//
 	// Setup uniforms
@@ -707,33 +709,33 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 
 	// shader prog
 
-	updateCommonBlock(jobs);
+	updateCommonBlock(cmdBuff);
 
-	m_commonBuff.bindShaderBuffer(jobs, COMMON_UNIFORMS_BLOCK_BINDING);
+	m_commonBuff.bindShaderBuffer(cmdBuff, COMMON_UNIFORMS_BLOCK_BINDING);
 
 	if(pointLightsSize > 0)
 	{
-		m_lightsBuff.bindShaderBuffer(jobs, 
+		m_lightsBuff.bindShaderBuffer(cmdBuff, 
 			pointLightsOffset, pointLightsSize, POINT_LIGHTS_BLOCK_BINDING);
 	}
 
 	if(spotLightsSize > 0)
 	{
-		m_lightsBuff.bindShaderBuffer(jobs, 
+		m_lightsBuff.bindShaderBuffer(cmdBuff, 
 			spotLightsOffset, spotLightsSize, SPOT_LIGHTS_BLOCK_BINDING);
 	}
 
 	if(spotTexLightsSize > 0)
 	{
-		m_lightsBuff.bindShaderBuffer(jobs,
+		m_lightsBuff.bindShaderBuffer(cmdBuff,
 			spotTexLightsOffset, spotTexLightsSize, 
 			SPOT_TEX_LIGHTS_BLOCK_BINDING);
 	}
 
-	m_tilesBuff.bindShaderBuffer(jobs, TILES_BLOCK_BINDING); 
+	m_tilesBuff.bindShaderBuffer(cmdBuff, TILES_BLOCK_BINDING); 
 
 	// The binding points should much the shader
-	jobs.bindTextures(0, {
+	cmdBuff.bindTextures(0, {
 		m_r->getMs()._getRt0(), 
 		m_r->getMs()._getRt1(), 
 		m_r->getMs()._getDepthRt(),
@@ -743,17 +745,17 @@ void Is::lightPass(GlCommandBufferHandle& jobs)
 	// Draw
 	//
 
-	m_lightPpline.bind(jobs);
+	m_lightPpline.bind(cmdBuff);
 
-	m_quadPositionsVertBuff.bindVertexBuffer(jobs, 
+	m_quadPositionsVertBuff.bindVertexBuffer(cmdBuff, 
 		2, GL_FLOAT, false, 0, 0, 0);
 
-	jobs.drawArrays(GL_TRIANGLE_STRIP, 4, 
+	cmdBuff.drawArrays(GL_TRIANGLE_STRIP, 4, 
 		m_r->getTilesCount().x() * m_r->getTilesCount().y());
 }
 
 //==============================================================================
-void Is::setState(GlCommandBufferHandle& jobs)
+void Is::setState(GlCommandBufferHandle& cmdBuff)
 {
 	Bool drawToDefaultFbo = !m_r->getPps().getEnabled() 
 		&& !m_r->getDbg().getEnabled() 
@@ -762,30 +764,30 @@ void Is::setState(GlCommandBufferHandle& jobs)
 
 	if(drawToDefaultFbo)
 	{
-		m_r->getDefaultFramebuffer().bind(jobs, true);
-		jobs.setViewport(0, 0, m_r->getWindowWidth(), m_r->getWindowHeight());
+		m_r->getDefaultFramebuffer().bind(cmdBuff, true);
+		cmdBuff.setViewport(0, 0, m_r->getWindowWidth(), m_r->getWindowHeight());
 	}
 	else
 	{
-		m_fb.bind(jobs, true);
+		m_fb.bind(cmdBuff, true);
 
-		jobs.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+		cmdBuff.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
 	}
 }
 
 //==============================================================================
-void Is::run(GlCommandBufferHandle& jobs)
+void Is::run(GlCommandBufferHandle& cmdBuff)
 {
 	// Do the light pass including the shadow passes
-	lightPass(jobs);
+	lightPass(cmdBuff);
 }
 
 //==============================================================================
-void Is::updateCommonBlock(GlCommandBufferHandle& jobs)
+void Is::updateCommonBlock(GlCommandBufferHandle& cmdBuff)
 {
 	SceneGraph& scene = m_r->getSceneGraph();
 
-	GlClientBufferHandle cbuff(jobs, sizeof(shader::CommonUniforms), nullptr);
+	GlClientBufferHandle cbuff(cmdBuff, sizeof(shader::CommonUniforms), nullptr);
 	shader::CommonUniforms& blk = 
 		*(shader::CommonUniforms*)cbuff.getBaseAddress();
 
@@ -801,14 +803,14 @@ void Is::updateCommonBlock(GlCommandBufferHandle& jobs)
 			Vec4(-m_cam->getViewMatrix().getColumn(1).xyz(), 1.0);
 	}
 
-	m_commonBuff.write(jobs, cbuff, 0, 0, cbuff.getSize());
+	m_commonBuff.write(cmdBuff, cbuff, 0, 0, cbuff.getSize());
 }
 
 //==============================================================================
 PtrSize Is::calcLightsBufferSize() const
 {
-	U32 buffAlignment = GlDeviceSingleton::get().getBufferOffsetAlignment(
-		GL_SHADER_STORAGE_BUFFER);
+	U32 buffAlignment = 
+		getGlDevice().getBufferOffsetAlignment(GL_SHADER_STORAGE_BUFFER);
 	PtrSize size;
 
 	size = getAlignedRoundUp(

+ 48 - 53
src/renderer/Lf.cpp

@@ -9,7 +9,7 @@
 #include "anki/scene/MoveComponent.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Light.h"
-#include <sstream>
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -55,11 +55,11 @@ Lf::~Lf()
 {}
 
 //==============================================================================
-void Lf::init(const ConfigSet& initializer)
+void Lf::init(const ConfigSet& config)
 {
 	try
 	{
-		initInternal(initializer);
+		initInternal(config);
 	}
 	catch(const std::exception& e)
 	{
@@ -68,47 +68,42 @@ void Lf::init(const ConfigSet& initializer)
 }
 
 //==============================================================================
-void Lf::initInternal(const ConfigSet& initializer)
+void Lf::initInternal(const ConfigSet& config)
 {
-	m_enabled = initializer.get("pps.lf.enabled") 
-		&& initializer.get("pps.hdr.enabled");
+	m_enabled = config.get("pps.lf.enabled") 
+		&& config.get("pps.hdr.enabled");
 	if(!m_enabled)
 	{
 		return;
 	}
 
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle cmdBuff(&getGlDevice());
 
-	m_maxFlaresPerLight = initializer.get("pps.lf.maxFlaresPerLight");
-	m_maxLightsWithFlares = initializer.get("pps.lf.maxLightsWithFlares");
+	m_maxFlaresPerLight = config.get("pps.lf.maxFlaresPerLight");
+	m_maxLightsWithFlares = config.get("pps.lf.maxLightsWithFlares");
 
 	// Load program 1
-	std::stringstream pps;
-	pps << "#define TEX_DIMENSIONS vec2(" 
-		<< (U)m_r->getPps().getHdr()._getRt().getWidth() << ".0, "
-		<< (U)m_r->getPps().getHdr()._getRt().getHeight() << ".0)\n";
-
-	std::string fname = ProgramResource::createSrcCodeToCache(
-		"shaders/PpsLfPseudoPass.frag.glsl", pps.str().c_str(), "r_");
-	m_pseudoFrag.load(fname.c_str());
+	String pps(getAllocator());
+	pps.sprintf("#define TEX_DIMENSIONS vec2(%u.0, %u.0)\n", 
+		m_r->getPps().getHdr()._getRt().getWidth(),
+		m_r->getPps().getHdr()._getRt().getHeight());
+
+	m_pseudoFrag.loadToCache(&getResourceManager(), 
+		"shaders/PpsLfPseudoPass.frag.glsl", pps.toCString(), "r_");
 	m_pseudoPpline = m_r->createDrawQuadProgramPipeline(
 		m_pseudoFrag->getGlProgram());
 
 	// Load program 2
-	pps.str("");
-	pps << "#define MAX_FLARES "
-		<< (U)(m_maxFlaresPerLight * m_maxLightsWithFlares) << "\n";
+	pps.sprintf("#define MAX_FLARES %u\n",
+		m_maxFlaresPerLight * m_maxLightsWithFlares);
 
-	fname = ProgramResource::createSrcCodeToCache(
-		"shaders/PpsLfSpritePass.vert.glsl", pps.str().c_str(), "r_");
-	m_realVert.load(fname.c_str());
+	m_realVert.loadToCache(&getResourceManager(), 
+		"shaders/PpsLfSpritePass.vert.glsl", pps.toCString(), "r_");
 
-	fname = ProgramResource::createSrcCodeToCache(
-		"shaders/PpsLfSpritePass.frag.glsl", pps.str().c_str(), "r_");
-	m_realFrag.load(fname.c_str());
+	m_realFrag.loadToCache(&getResourceManager(), 
+		"shaders/PpsLfSpritePass.frag.glsl", pps.toCString(), "r_");
 
-	m_realPpline = GlProgramPipelineHandle(jobs,
+	m_realPpline = GlProgramPipelineHandle(cmdBuff,
 		{m_realVert->getGlProgram(), m_realFrag->getGlProgram()});
 
 	PtrSize blockSize = 
@@ -121,28 +116,28 @@ void Lf::initInternal(const ConfigSet& initializer)
 
 	// Init buffer
 	m_flareDataBuff = GlBufferHandle(
-		jobs, GL_SHADER_STORAGE_BUFFER, blockSize, GL_DYNAMIC_STORAGE_BIT);
+		cmdBuff, GL_SHADER_STORAGE_BUFFER, blockSize, GL_DYNAMIC_STORAGE_BIT);
 
 	// Create the render target
 	m_r->createRenderTarget(m_r->getPps().getHdr()._getRt().getWidth(), 
 		m_r->getPps().getHdr()._getRt().getHeight(), 
 		GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 1, m_rt);
 
-	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}}); 
+	m_fb = GlFramebufferHandle(cmdBuff, {{m_rt, GL_COLOR_ATTACHMENT0}}); 
 	
 	// Textures
-	m_lensDirtTex.load("engine_data/lens_dirt.ankitex");
+	m_lensDirtTex.load("engine_data/lens_dirt.ankitex", &getResourceManager());
 
 	// Blit
-	m_blitFrag.load("shaders/Blit.frag.glsl");
+	m_blitFrag.load("shaders/Blit.frag.glsl", &getResourceManager());
 	m_blitPpline = m_r->createDrawQuadProgramPipeline(
 		m_blitFrag->getGlProgram());
 
-	jobs.finish();
+	cmdBuff.finish();
 }
 
 //==============================================================================
-void Lf::run(GlCommandBufferHandle& jobs)
+void Lf::run(GlCommandBufferHandle& cmdBuff)
 {
 	ANKI_ASSERT(m_enabled);
 
@@ -151,17 +146,17 @@ void Lf::run(GlCommandBufferHandle& jobs)
 	//
 
 	// Set the common state
-	m_fb.bind(jobs, true);
-	jobs.setViewport(0, 0, m_r->getPps().getHdr()._getRt().getWidth(), 
+	m_fb.bind(cmdBuff, true);
+	cmdBuff.setViewport(0, 0, m_r->getPps().getHdr()._getRt().getWidth(), 
 		m_r->getPps().getHdr()._getRt().getHeight());
 
-	m_pseudoPpline.bind(jobs);
+	m_pseudoPpline.bind(cmdBuff);
 
-	jobs.bindTextures(0, {
+	cmdBuff.bindTextures(0, {
 		m_r->getPps().getHdr()._getRt(), 
 		m_lensDirtTex->getGlTexture()});
 
-	m_r->drawQuad(jobs);
+	m_r->drawQuad(cmdBuff);
 
 	//
 	// Rest of the passes
@@ -203,7 +198,7 @@ void Lf::run(GlCommandBufferHandle& jobs)
 
 		// Write the UBO and get the groups
 		//
-		GlClientBufferHandle flaresCBuff(jobs,
+		GlClientBufferHandle flaresCBuff(cmdBuff,
 			sizeof(Flare) * lightsCount * m_maxFlaresPerLight, nullptr);
 		Flare* flares = (Flare*)flaresCBuff.getBaseAddress();
 		U flaresCount = 0;
@@ -295,13 +290,13 @@ void Lf::run(GlCommandBufferHandle& jobs)
 
 		// Write the buffer
 		m_flareDataBuff.write(
-			jobs, flaresCBuff, 0, 0, sizeof(Flare) * flaresCount);
+			cmdBuff, flaresCBuff, 0, 0, sizeof(Flare) * flaresCount);
 
 		// Set the common state
-		m_realPpline.bind(jobs);
+		m_realPpline.bind(cmdBuff);
 
-		jobs.enableBlend(true);
-		jobs.setBlendFunctions(GL_ONE, GL_ONE);
+		cmdBuff.enableBlend(true);
+		cmdBuff.setBlendFunctions(GL_ONE, GL_ONE);
 
 		PtrSize offset = 0;
 		for(U i = 0; i < groupsCount; i++)
@@ -310,10 +305,10 @@ void Lf::run(GlCommandBufferHandle& jobs)
 			U instances = groups[i];
 			PtrSize buffSize = sizeof(Flare) * instances;
 
-			tex.bind(jobs, 0);
-			m_flareDataBuff.bindShaderBuffer(jobs, offset, buffSize, 0);
+			tex.bind(cmdBuff, 0);
+			m_flareDataBuff.bindShaderBuffer(cmdBuff, offset, buffSize, 0);
 
-			m_r->drawQuadInstanced(jobs, instances);
+			m_r->drawQuadInstanced(cmdBuff, instances);
 
 			offset += buffSize;
 		}
@@ -322,17 +317,17 @@ void Lf::run(GlCommandBufferHandle& jobs)
 	{
 		// No lights
 
-		jobs.enableBlend(true);
-		jobs.setBlendFunctions(GL_ONE, GL_ONE);
+		cmdBuff.enableBlend(true);
+		cmdBuff.setBlendFunctions(GL_ONE, GL_ONE);
 	}
 
 	// Blit the HDR RT back to LF RT
 	//
-	m_r->getPps().getHdr()._getRt().bind(jobs, 0);
-	m_blitPpline.bind(jobs);
-	m_r->drawQuad(jobs);
+	m_r->getPps().getHdr()._getRt().bind(cmdBuff, 0);
+	m_blitPpline.bind(cmdBuff);
+	m_r->drawQuad(cmdBuff);
 
-	jobs.enableBlend(false);
+	cmdBuff.enableBlend(false);
 }
 
 } // end namespace anki

+ 22 - 18
src/renderer/MainRenderer.cpp

@@ -7,18 +7,23 @@
 #include "anki/core/Logger.h"
 #include "anki/renderer/Deformer.h"
 #include "anki/util/File.h"
+#include "anki/util/Filesystem.h"
 #include "anki/core/Counters.h"
 #include "anki/core/App.h"
-#include <cstdlib>
-#include <cstdio>
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
 //==============================================================================
-MainRenderer::MainRenderer(App* app, const ConfigSet& initializer)
-:	Renderer(&app->getThreadpool())
+MainRenderer::MainRenderer(
+	Threadpool* threadpool, 
+	ResourceManager* resources,
+	GlDevice* gl,
+	HeapAllocator<U8>& alloc,
+	const ConfigSet& config)
+:	Renderer(threadpool, resources, gl, alloc, config)
 {
-	init(initializer);
+	init(config);
 }
 
 //==============================================================================
@@ -26,23 +31,22 @@ MainRenderer::~MainRenderer()
 {}
 
 //==============================================================================
-void MainRenderer::init(const ConfigSet& initializer_)
+void MainRenderer::init(const ConfigSet& config_)
 {
 	ANKI_LOGI("Initializing main renderer...");
 
-	ConfigSet initializer = initializer_;
-	initializer.set("offscreen", false);
-	initializer.set("width", 
-		initializer.get("width") * initializer.get("renderingQuality"));
-	initializer.set("height", 
-		initializer.get("height") * initializer.get("renderingQuality"));
+	ConfigSet config = config_;
+	config.set("offscreen", false);
+	config.set("width", 
+		config.get("width") * config.get("renderingQuality"));
+	config.set("height", 
+		config.get("height") * config.get("renderingQuality"));
 
 	initGl();
 
-	Renderer::init(initializer);
-	m_deformer.reset(new Deformer);
+	Renderer::init(config);
 
-	m_blitFrag.load("shaders/Final.frag.glsl");
+	m_blitFrag.load("shaders/Final.frag.glsl", &_getResourceManager());
 	m_blitPpline = createDrawQuadProgramPipeline(
 		m_blitFrag->getGlProgram());
 
@@ -55,7 +59,7 @@ void MainRenderer::render(SceneGraph& scene)
 {
 	ANKI_COUNTER_START_TIMER(MAIN_RENDERER_TIME);
 
-	GlDevice& gl = GlDeviceSingleton::get();
+	GlDevice& gl = _getGlDevice();
 	Array<GlCommandBufferHandle, JOB_CHAINS_COUNT> jobs;
 	GlCommandBufferHandle& lastJobs = jobs[JOB_CHAINS_COUNT - 1];
 
@@ -113,7 +117,7 @@ void MainRenderer::render(SceneGraph& scene)
 void MainRenderer::initGl()
 {
 	// get max texture units
-	GlDevice& gl = GlDeviceSingleton::get();
+	GlDevice& gl = _getGlDevice();
 	GlCommandBufferHandle jobs(&gl);
 
 	jobs.enableCulling(true);
@@ -185,7 +189,7 @@ void MainRenderer::takeScreenshotTga(const char* filename)
 //==============================================================================
 void MainRenderer::takeScreenshot(const char* filename)
 {
-	std::string ext = File::getFileExtension(filename);
+	String ext = getFileExtension(filename, _getAllocator());
 
 	// exec from this extension
 	if(ext == "tga")

+ 1 - 0
src/renderer/Ms.cpp

@@ -10,6 +10,7 @@
 #include "anki/core/Logger.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/SceneGraph.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 

+ 45 - 40
src/renderer/Pps.cpp

@@ -8,6 +8,7 @@
 #include "anki/renderer/Hdr.h"
 #include "anki/renderer/Ssao.h"
 #include "anki/core/Logger.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -26,9 +27,9 @@ Pps::~Pps()
 {}
 
 //==============================================================================
-void Pps::initInternal(const ConfigSet& initializer)
+void Pps::initInternal(const ConfigSet& config)
 {
-	m_enabled = initializer.get("pps.enabled");
+	m_enabled = config.get("pps.enabled");
 	if(!m_enabled)
 	{
 		return;
@@ -36,46 +37,50 @@ void Pps::initInternal(const ConfigSet& initializer)
 
 	ANKI_ASSERT("Initializing PPS");
 
-	m_ssao.init(initializer);
-	m_hdr.init(initializer);
-	m_lf.init(initializer);
-	m_sslr.init(initializer);
+	m_ssao.init(config);
+	m_hdr.init(config);
+	m_lf.init(config);
+	m_sslr.init(config);
 
 	// FBO
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle cmdBuff(&getGlDevice());
 
 	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGB8, GL_RGB,
 		GL_UNSIGNED_BYTE, 1, m_rt);
 
-	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}});
+	m_fb = GlFramebufferHandle(cmdBuff, {{m_rt, GL_COLOR_ATTACHMENT0}});
 
 	// SProg
-	std::stringstream pps;
-
-	pps << "#define SSAO_ENABLED " << (U)m_ssao.getEnabled() << "\n"
-		<< "#define HDR_ENABLED " << (U)m_hdr.getEnabled() << "\n"
-		<< "#define SHARPEN_ENABLED " << (U)initializer.get("pps.sharpen") 
-			<< "\n"
-		<< "#define GAMMA_CORRECTION_ENABLED " 
-			<< (U)initializer.get("pps.gammaCorrection") << "\n"
-		<< "#define FBO_WIDTH " << (U)m_r->getWidth() << "\n"
-		<< "#define FBO_HEIGHT " << (U)m_r->getHeight() << "\n";
-
-	m_frag.load(ProgramResource::createSrcCodeToCache(
-		"shaders/Pps.frag.glsl", pps.str().c_str(), "r_").c_str());
+	String pps(getAllocator());
+
+	pps.sprintf(
+		"#define SSAO_ENABLED %u\n"
+		"#define HDR_ENABLED %u\n"
+		"#define SHARPEN_ENABLED %u\n"
+		"#define GAMMA_CORRECTION_ENABLED %u\n"
+		"#define FBO_WIDTH %u\n"
+		"#define FBO_HEIGHT %u\n",
+		m_ssao.getEnabled(), 
+		m_hdr.getEnabled(), 
+		static_cast<U>(config.get("pps.sharpen")),
+		static_cast<U>(config.get("pps.gammaCorrection")),
+		m_r->getWidth(),
+		m_r->getHeight());
+
+	m_frag.loadToCache(&getResourceManager(),
+		"shaders/Pps.frag.glsl", pps.toCString(), "r_");
 
 	m_ppline = m_r->createDrawQuadProgramPipeline(m_frag->getGlProgram());
 
-	jobs.finish();
+	cmdBuff.finish();
 }
 
 //==============================================================================
-void Pps::init(const ConfigSet& initializer)
+void Pps::init(const ConfigSet& config)
 {
 	try
 	{
-		initInternal(initializer);
+		initInternal(config);
 	}
 	catch(const std::exception& e)
 	{
@@ -84,30 +89,30 @@ void Pps::init(const ConfigSet& initializer)
 }
 
 //==============================================================================
-void Pps::run(GlCommandBufferHandle& jobs)
+void Pps::run(GlCommandBufferHandle& cmdBuff)
 {
 	ANKI_ASSERT(m_enabled);
 
 	// First SSAO because it depends on MS where HDR depends on IS
 	if(m_ssao.getEnabled())
 	{
-		m_ssao.run(jobs);
+		m_ssao.run(cmdBuff);
 	}
 
 	// Then SSLR because HDR depends on it
 	if(m_sslr.getEnabled())
 	{
-		m_sslr.run(jobs);
+		m_sslr.run(cmdBuff);
 	}
 
 	if(m_hdr.getEnabled())
 	{
-		m_hdr.run(jobs);
+		m_hdr.run(cmdBuff);
 	}
 
 	if(m_lf.getEnabled())
 	{
-		m_lf.run(jobs);
+		m_lf.run(cmdBuff);
 	}
 
 	Bool drawToDefaultFbo = 
@@ -117,34 +122,34 @@ void Pps::run(GlCommandBufferHandle& jobs)
 
 	if(drawToDefaultFbo)
 	{
-		m_r->getDefaultFramebuffer().bind(jobs, true);
-		jobs.setViewport(0, 0, m_r->getWindowWidth(), m_r->getWindowHeight());
+		m_r->getDefaultFramebuffer().bind(cmdBuff, true);
+		cmdBuff.setViewport(0, 0, m_r->getWindowWidth(), m_r->getWindowHeight());
 	}
 	else
 	{
-		m_fb.bind(jobs, true);
-		jobs.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+		m_fb.bind(cmdBuff, true);
+		cmdBuff.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
 	}
 
-	m_ppline.bind(jobs);
+	m_ppline.bind(cmdBuff);
 
-	m_r->getIs()._getRt().bind(jobs, 0);
+	m_r->getIs()._getRt().bind(cmdBuff, 0);
 
 	if(m_ssao.getEnabled())
 	{
-		m_ssao.getRt().bind(jobs, 1);
+		m_ssao.getRt().bind(cmdBuff, 1);
 	}
 
 	if(m_lf.getEnabled())
 	{
-		m_lf._getRt().bind(jobs, 2);
+		m_lf._getRt().bind(cmdBuff, 2);
 	}
 	else if(m_hdr.getEnabled())
 	{
-		m_hdr._getRt().bind(jobs, 2);
+		m_hdr._getRt().bind(cmdBuff, 2);
 	}
 
-	m_r->drawQuad(jobs);
+	m_r->drawQuad(cmdBuff);
 }
 
 } // end namespace anki

+ 54 - 56
src/renderer/Renderer.cpp

@@ -8,19 +8,27 @@
 #include "anki/scene/Camera.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/core/Counters.h"
-#include <sstream>
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
 //==============================================================================
-Renderer::Renderer(Threadpool* threadpool)
-:	m_ms(this), 
+Renderer::Renderer(
+	Threadpool* threadpool, 
+	ResourceManager* resources,
+	GlDevice* gl,
+	HeapAllocator<U8>& alloc,
+	const ConfigSet& config)
+:	m_threadpool(threadpool),
+	m_resources(resources),
+	m_gl(gl),
+	m_alloc(alloc),
+	m_ms(this), 
 	m_is(this),
 	m_pps(this),
 	m_bs(this),
 	m_dbg(this), 
-	m_sceneDrawer(this),
-	m_threadpool(threadpool)
+	m_sceneDrawer(this)
 {}
 
 //==============================================================================
@@ -28,20 +36,20 @@ Renderer::~Renderer()
 {}
 
 //==============================================================================
-void Renderer::init(const ConfigSet& initializer)
+void Renderer::init(const ConfigSet& config)
 {
-	// Set from the initializer
-	m_width = initializer.get("width");
-	m_height = initializer.get("height");
-	m_lodDistance = initializer.get("lodDistance");
+	// Set from the config
+	m_width = config.get("width");
+	m_height = config.get("height");
+	m_lodDistance = config.get("lodDistance");
 	m_framesNum = 0;
-	m_samples = initializer.get("samples");
-	m_isOffscreen = initializer.get("offscreen");
-	m_renderingQuality = initializer.get("renderingQuality");
-	m_tilesCount.x() = initializer.get("tilesXCount");
-	m_tilesCount.y() = initializer.get("tilesYCount");
+	m_samples = config.get("samples");
+	m_isOffscreen = config.get("offscreen");
+	m_renderingQuality = config.get("renderingQuality");
+	m_tilesCount.x() = config.get("tilesXCount");
+	m_tilesCount.y() = config.get("tilesYCount");
 
-	m_tessellation = initializer.get("tessellation");
+	m_tessellation = config.get("tessellation");
 
 	// A few sanity checks
 	if(m_samples != 1 && m_samples != 4 && m_samples != 8 && m_samples != 16
@@ -59,42 +67,34 @@ void Renderer::init(const ConfigSet& initializer)
 	static const F32 quadVertCoords[][2] = {{1.0, 1.0}, {-1.0, 1.0}, 
 		{1.0, -1.0}, {-1.0, -1.0}};
 
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle cmdBuff(m_gl);
 
-	GlClientBufferHandle tmpBuff = GlClientBufferHandle(jobs, 
+	GlClientBufferHandle tmpBuff = GlClientBufferHandle(cmdBuff, 
 		sizeof(quadVertCoords), (void*)&quadVertCoords[0][0]);
 
-	m_quadPositionsBuff = GlBufferHandle(jobs, GL_ARRAY_BUFFER, 
+	m_quadPositionsBuff = GlBufferHandle(cmdBuff, GL_ARRAY_BUFFER, 
 		tmpBuff, 0);
 
-	m_drawQuadVert.load("shaders/Quad.vert.glsl");
+	m_drawQuadVert.load("shaders/Quad.vert.glsl", m_resources);
 
 	// Init the stages. Careful with the order!!!!!!!!!!
 	m_tiler.init(this);
 
-	m_ms.init(initializer);;
-	m_is.init(initializer);
-	m_bs.init(initializer);
-	m_pps.init(initializer);
-	m_dbg.init(initializer);
-
-	// Init the shaderPostProcessorString
-	std::stringstream ss;
-	ss << "#define RENDERING_WIDTH " << m_width << "\n"
-		<< "#define RENDERING_HEIGHT " << m_height << "\n";
-
-	m_shaderPostProcessorString = ss.str();
+	m_ms.init(config);
+	m_is.init(config);
+	m_bs.init(config);
+	m_pps.init(config);
+	m_dbg.init(config);
 
 	// Default FB
-	m_defaultFb = GlFramebufferHandle(jobs, {});
+	m_defaultFb = GlFramebufferHandle(cmdBuff, {});
 
-	jobs.finish();
+	cmdBuff.finish();
 }
 
 //==============================================================================
 void Renderer::render(SceneGraph& scene, 
-	Array<GlCommandBufferHandle, JOB_CHAINS_COUNT>& jobs)
+	Array<GlCommandBufferHandle, JOB_CHAINS_COUNT>& cmdBuff)
 {
 	m_scene = &scene;
 	Camera& cam = m_scene->getActiveCamera();
@@ -113,47 +113,47 @@ void Renderer::render(SceneGraph& scene,
 	}
 
 	ANKI_COUNTER_START_TIMER(RENDERER_MS_TIME);
-	m_ms.run(jobs[0]);
-	ANKI_ASSERT(jobs[0].getReferenceCount() == 1);
-	jobs[0].flush();
+	m_ms.run(cmdBuff[0]);
+	ANKI_ASSERT(cmdBuff[0].getReferenceCount() == 1);
+	cmdBuff[0].flush();
 	ANKI_COUNTER_STOP_TIMER_INC(RENDERER_MS_TIME);
 
 	m_tiler.runMinMax(m_ms._getDepthRt());
 
 	ANKI_COUNTER_START_TIMER(RENDERER_IS_TIME);
-	m_is.run(jobs[1]);
+	m_is.run(cmdBuff[1]);
 	ANKI_COUNTER_STOP_TIMER_INC(RENDERER_IS_TIME);
 
-	m_bs.run(jobs[1]);
+	m_bs.run(cmdBuff[1]);
 
 	ANKI_COUNTER_START_TIMER(RENDERER_PPS_TIME);
 	if(m_pps.getEnabled())
 	{
-		m_pps.run(jobs[1]);
+		m_pps.run(cmdBuff[1]);
 	}
 	ANKI_COUNTER_STOP_TIMER_INC(RENDERER_PPS_TIME);
 
 	if(m_dbg.getEnabled())
 	{
-		m_dbg.run(jobs[1]);
+		m_dbg.run(cmdBuff[1]);
 	}
 
 	++m_framesNum;
 }
 
 //==============================================================================
-void Renderer::drawQuad(GlCommandBufferHandle& jobs)
+void Renderer::drawQuad(GlCommandBufferHandle& cmdBuff)
 {
-	drawQuadInstanced(jobs, 1);
+	drawQuadInstanced(cmdBuff, 1);
 }
 
 //==============================================================================
 void Renderer::drawQuadInstanced(
-	GlCommandBufferHandle& jobs, U32 primitiveCount)
+	GlCommandBufferHandle& cmdBuff, U32 primitiveCount)
 {
-	m_quadPositionsBuff.bindVertexBuffer(jobs, 2, GL_FLOAT, false, 0, 0, 0);
+	m_quadPositionsBuff.bindVertexBuffer(cmdBuff, 2, GL_FLOAT, false, 0, 0, 0);
 
-	dc.drawArrays(GL_TRIANGLE_STRIP, 4, primitiveCount);
+	cmdBuff.drawArrays(GL_TRIANGLE_STRIP, 4, primitiveCount);
 }
 
 //==============================================================================
@@ -227,23 +227,21 @@ void Renderer::createRenderTarget(U32 w, U32 h, GLenum internalFormat,
 	init.m_genMipmaps = false;
 	init.m_samples = samples;
 
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
-	rt = GlTextureHandle(jobs, init);
-	jobs.finish();
+	GlCommandBufferHandle cmdBuff(m_gl);
+	rt = GlTextureHandle(cmdBuff, init);
+	cmdBuff.finish();
 }
 
 //==============================================================================
 GlProgramPipelineHandle Renderer::createDrawQuadProgramPipeline(
 	GlProgramHandle frag)
 {
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle cmdBuff(m_gl);
 
 	Array<GlProgramHandle, 2> progs = {{m_drawQuadVert->getGlProgram(), frag}};
 
-	GlProgramPipelineHandle ppline(jobs, &progs[0], &progs[0] + 2);
-	jobs.finish();
+	GlProgramPipelineHandle ppline(cmdBuff, &progs[0], &progs[0] + 2);
+	cmdBuff.finish();
 
 	return ppline;
 }

+ 9 - 4
src/renderer/RenderingPass.cpp

@@ -12,7 +12,13 @@ namespace anki {
 //==============================================================================
 GlDevice& RenderingPass::getGlDevice()
 {
-	return m_r->getGlDevice();
+	return m_r->_getGlDevice();
+}
+
+//==============================================================================
+const GlDevice& RenderingPass::getGlDevice() const
+{
+	return m_r->_getGlDevice();
 }
 
 //==============================================================================
@@ -65,10 +71,9 @@ void BlurringRenderingPass::initBlurring(
 		dir.m_fb = GlFramebufferHandle(
 			jobs, {{dir.m_rt, GL_COLOR_ATTACHMENT0}});
 
-		dir.m_frag.load(ProgramResource::createSourceToCache(
+		dir.m_frag.loadToCache(&getResourceManager(),
 			"shaders/VariableSamplingBlurGeneric.frag.glsl", 
-			pps[i].toCString(), "r_", getResourceManager()).toCString(),
-			&getResourceManager());
+			pps[i].toCString(), "r_");
 
 		dir.m_ppline = 
 			r.createDrawQuadProgramPipeline(dir.m_frag->getGlProgram());

+ 25 - 25
src/renderer/Sm.cpp

@@ -10,6 +10,7 @@
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Light.h"
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -54,14 +55,13 @@ void Sm::init(const ConfigSet& initializer)
 		sminit.m_filterType = GlTextureHandle::Filter::NEAREST;
 	}
 
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle cmdBuff(&getGlDevice());
 
-	m_sm2DArrayTex = GlTextureHandle(jobs, sminit);
+	m_sm2DArrayTex = GlTextureHandle(cmdBuff, sminit);
 
-	m_sm2DArrayTex.setParameter(jobs, 
+	m_sm2DArrayTex.setParameter(cmdBuff, 
 		GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
-	m_sm2DArrayTex.setParameter(jobs, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+	m_sm2DArrayTex.setParameter(cmdBuff, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
 
 	// Init sms
 	U32 layer = 0;
@@ -69,58 +69,58 @@ void Sm::init(const ConfigSet& initializer)
 	for(Shadowmap& sm : m_sms)
 	{
 		sm.m_layerId = layer;
-		sm.m_fb = GlFramebufferHandle(jobs, 
+		sm.m_fb = GlFramebufferHandle(cmdBuff, 
 			{{m_sm2DArrayTex, GL_DEPTH_ATTACHMENT, (U32)layer}});
 
 		++layer;
 	}
 
-	jobs.flush();
+	cmdBuff.flush();
 }
 
 //==============================================================================
-void Sm::prepareDraw(GlCommandBufferHandle& jobs)
+void Sm::prepareDraw(GlCommandBufferHandle& cmdBuff)
 {
 	// disable color & blend & enable depth test
 
-	jobs.enableDepthTest(true);
-	jobs.setColorWriteMask(false, false, false, false);
+	cmdBuff.enableDepthTest(true);
+	cmdBuff.setColorWriteMask(false, false, false, false);
 
 	// for artifacts
-	jobs.setPolygonOffset(2.0, 2.0); // keep both as low as possible!!!!
-	jobs.enablePolygonOffset(true);
+	cmdBuff.setPolygonOffset(2.0, 2.0); // keep both as low as possible!!!!
+	cmdBuff.enablePolygonOffset(true);
 
 	m_r->getSceneDrawer().prepareDraw(
-		RenderingStage::MATERIAL, Pass::DEPTH, jobs);
+		RenderingStage::MATERIAL, Pass::DEPTH, cmdBuff);
 }
 
 //==============================================================================
-void Sm::finishDraw(GlCommandBufferHandle& jobs)
+void Sm::finishDraw(GlCommandBufferHandle& cmdBuff)
 {
 	m_r->getSceneDrawer().finishDraw();
 
-	jobs.enableDepthTest(false);
-	jobs.enablePolygonOffset(false);
-	jobs.setColorWriteMask(true, true, true, true);
+	cmdBuff.enableDepthTest(false);
+	cmdBuff.enablePolygonOffset(false);
+	cmdBuff.setColorWriteMask(true, true, true, true);
 }
 
 //==============================================================================
 void Sm::run(Light* shadowCasters[], U32 shadowCastersCount, 
-	GlCommandBufferHandle& jobs)
+	GlCommandBufferHandle& cmdBuff)
 {
 	ANKI_ASSERT(m_enabled);
 
-	prepareDraw(jobs);
+	prepareDraw(cmdBuff);
 
 	// render all
 	for(U32 i = 0; i < shadowCastersCount; i++)
 	{
-		Shadowmap* sm = doLight(*shadowCasters[i], jobs);
+		Shadowmap* sm = doLight(*shadowCasters[i], cmdBuff);
 		ANKI_ASSERT(sm != nullptr);
 		(void)sm;
 	}
 
-	finishDraw(jobs);
+	finishDraw(cmdBuff);
 }
 
 //==============================================================================
@@ -162,7 +162,7 @@ Sm::Shadowmap& Sm::bestCandidate(Light& light)
 }
 
 //==============================================================================
-Sm::Shadowmap* Sm::doLight(Light& light, GlCommandBufferHandle& jobs)
+Sm::Shadowmap* Sm::doLight(Light& light, GlCommandBufferHandle& cmdBuff)
 {
 	Shadowmap& sm = bestCandidate(light);
 
@@ -210,9 +210,9 @@ Sm::Shadowmap* Sm::doLight(Light& light, GlCommandBufferHandle& jobs)
 	//
 	// Render
 	//
-	sm.m_fb.bind(jobs, true);
-	jobs.setViewport(0, 0, m_resolution, m_resolution);
-	jobs.clearBuffers(GL_DEPTH_BUFFER_BIT);
+	sm.m_fb.bind(cmdBuff, true);
+	cmdBuff.setViewport(0, 0, m_resolution, m_resolution);
+	cmdBuff.clearBuffers(GL_DEPTH_BUFFER_BIT);
 
 	for(auto& it : vi.m_renderables)
 	{

+ 45 - 48
src/renderer/Ssao.cpp

@@ -8,7 +8,7 @@
 #include "anki/scene/Camera.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/util/Functions.h"
-#include <sstream>
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
@@ -69,25 +69,23 @@ public:
 //==============================================================================
 void Ssao::createFb(GlFramebufferHandle & fb, GlTextureHandle& rt)
 {
-	GlDevice& gl = GlDeviceSingleton::get();
-
 	m_r->createRenderTarget(m_width, m_height, GL_RED, GL_RED, 
 		GL_UNSIGNED_BYTE, 1, rt);
 
 	// Set to bilinear because the blurring techniques take advantage of that
-	GlCommandBufferHandle jobs(&gl);
-	rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
+	GlCommandBufferHandle cmdBuff(&getGlDevice());
+	rt.setFilter(cmdBuff, GlTextureHandle::Filter::LINEAR);
 
 	// create FB
-	fb = GlFramebufferHandle(jobs, {{rt, GL_COLOR_ATTACHMENT0}});
+	fb = GlFramebufferHandle(cmdBuff, {{rt, GL_COLOR_ATTACHMENT0}});
 
-	jobs.flush();
+	cmdBuff.flush();
 }
 
 //==============================================================================
-void Ssao::initInternal(const ConfigSet& initializer)
+void Ssao::initInternal(const ConfigSet& config)
 {
-	m_enabled = initializer.get("pps.ssao.enabled");
+	m_enabled = config.get("pps.ssao.enabled");
 
 	if(!m_enabled)
 	{
@@ -95,12 +93,12 @@ void Ssao::initInternal(const ConfigSet& initializer)
 	}
 
 	m_blurringIterationsCount = 
-		initializer.get("pps.ssao.blurringIterationsCount");
+		config.get("pps.ssao.blurringIterationsCount");
 
 	//
 	// Init the widths/heights
 	//
-	const F32 quality = initializer.get("pps.ssao.renderingQuality");
+	const F32 quality = config.get("pps.ssao.renderingQuality");
 
 	m_width = quality * (F32)m_r->getWidth();
 	alignRoundUp(16, m_width);
@@ -116,8 +114,7 @@ void Ssao::initInternal(const ConfigSet& initializer)
 	//
 	// noise texture
 	//
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle jobs(&getGlDevice());
 
 	GlClientBufferHandle noise(
 		jobs, sizeof(Vec3) * NOISE_TEX_SIZE * NOISE_TEX_SIZE, nullptr);
@@ -142,24 +139,20 @@ void Ssao::initInternal(const ConfigSet& initializer)
 	//
 	// Kernel
 	//
-	std::stringstream kernelStr;
+	String kernelStr(getAllocator());
 	Array<Vec3, KERNEL_SIZE> kernel;
 
 	genKernel(kernel.begin(), kernel.end());
-	kernelStr << "vec3[](";
+	kernelStr = "vec3[](";
 	for(U i = 0; i < kernel.size(); i++)
 	{
-		kernelStr << "vec3(" << kernel[i].x() << ", " << kernel[i].y()
-			<< ", " << kernel[i].z() << ")";
+		String tmp(getAllocator());
 
-		if(i != kernel.size() - 1)
-		{
-			kernelStr << ", ";
-		}
-		else
-		{
-			kernelStr << ")";
-		}
+		tmp.sprintf("vec3(%f, %f, %f) %s",
+			kernel[i].x(), kernel[i].y(), kernel[i].z(),
+			(i != kernel.size() - 1) ? ", " : ")");
+
+		kernelStr += tmp;
 	}
 
 	//
@@ -168,18 +161,20 @@ void Ssao::initInternal(const ConfigSet& initializer)
 	m_uniformsBuff = GlBufferHandle(jobs, GL_SHADER_STORAGE_BUFFER, 
 		sizeof(ShaderCommonUniforms), GL_DYNAMIC_STORAGE_BIT);
 
-	std::stringstream pps;
+	String pps(getAllocator());
 
 	// main pass prog
-	pps << "#define NOISE_MAP_SIZE " << NOISE_TEX_SIZE
-		<< "\n#define WIDTH " << m_width
-		<< "\n#define HEIGHT " << m_height
-		<< "\n#define KERNEL_SIZE " << KERNEL_SIZE << "U"
-		<< "\n#define KERNEL_ARRAY " << kernelStr.str() 
-		<< "\n";
+	pps.sprintf(
+		"#define NOISE_MAP_SIZE %u\n"
+		"#define WIDTH %u\n"
+		"#define HEIGHT %u\n"
+		"#define KERNEL_SIZE %u\n"
+		"#define KERNEL_ARRAY %s\n",
+		NOISE_TEX_SIZE, m_width, m_height, KERNEL_SIZE, &kernelStr[0]);
+
+	m_ssaoFrag.loadToCache(&getResourceManager(),
+		"shaders/PpsSsao.frag.glsl", pps.toCString(), "r_");
 
-	m_ssaoFrag.load(ProgramResource::createSrcCodeToCache(
-		"shaders/PpsSsao.frag.glsl", pps.str().c_str(), "r_").c_str());
 
 	m_ssaoPpline = m_r->createDrawQuadProgramPipeline(
 		m_ssaoFrag->getGlProgram());
@@ -188,26 +183,28 @@ void Ssao::initInternal(const ConfigSet& initializer)
 	const char* SHADER_FILENAME = 
 		"shaders/VariableSamplingBlurGeneric.frag.glsl";
 
-	pps.str("");
-	pps << "#define HPASS\n"
+	pps.sprintf(
+		"#define HPASS\n"
 		"#define COL_R\n"
-		"#define IMG_DIMENSION " << m_height << "\n"
-		"#define SAMPLES 7\n";
+		"#define IMG_DIMENSION %u\n"
+		"#define SAMPLES 7\n", 
+		m_height);
 
-	m_hblurFrag.load(ProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.str().c_str(), "r_").c_str());
+	m_hblurFrag.loadToCache(&getResourceManager(),
+		SHADER_FILENAME, pps.toCString(), "r_");
 
 	m_hblurPpline = m_r->createDrawQuadProgramPipeline(
 		m_hblurFrag->getGlProgram());
 
-	pps.str("");
-	pps << "#define VPASS\n"
+	pps.sprintf(
+		"#define VPASS\n"
 		"#define COL_R\n"
-		"#define IMG_DIMENSION " << m_width << "\n"
-		"#define SAMPLES 7\n";
+		"#define IMG_DIMENSION %u\n"
+		"#define SAMPLES 7\n", 
+		m_width);
 
-	m_vblurFrag.load(ProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.str().c_str(), "r_").c_str());
+	m_vblurFrag.loadToCache(&getResourceManager(),
+		SHADER_FILENAME, pps.toCString(), "r_");
 
 	m_vblurPpline = m_r->createDrawQuadProgramPipeline(
 		m_vblurFrag->getGlProgram());
@@ -216,11 +213,11 @@ void Ssao::initInternal(const ConfigSet& initializer)
 }
 
 //==============================================================================
-void Ssao::init(const ConfigSet& initializer)
+void Ssao::init(const ConfigSet& config)
 {
 	try
 	{
-		initInternal(initializer);
+		initInternal(config);
 	}
 	catch(const std::exception& e)
 	{

+ 37 - 37
src/renderer/Sslr.cpp

@@ -5,14 +5,14 @@
 
 #include "anki/renderer/Sslr.h"
 #include "anki/renderer/Renderer.h"
-#include <sstream>
+#include "anki/misc/ConfigSet.h"
 
 namespace anki {
 
 //==============================================================================
-void Sslr::init(const ConfigSet& initializer)
+void Sslr::init(const ConfigSet& config)
 {
-	m_enabled = initializer.get("pps.sslr.enabled");
+	m_enabled = config.get("pps.sslr.enabled");
 
 	if(!m_enabled)
 	{
@@ -20,9 +20,9 @@ void Sslr::init(const ConfigSet& initializer)
 	}
 
 	// Size
-	const F32 quality = initializer.get("pps.sslr.renderingQuality");
+	const F32 quality = config.get("pps.sslr.renderingQuality");
 	m_blurringIterationsCount = 
-		initializer.get("pps.sslr.blurringIterationsCount");
+		config.get("pps.sslr.blurringIterationsCount");
 
 	m_width = quality * (F32)m_r->getWidth();
 	alignRoundUp(16, m_width);
@@ -30,26 +30,26 @@ void Sslr::init(const ConfigSet& initializer)
 	alignRoundUp(16, m_height);
 
 	// Programs
-	std::stringstream pps;
+	String pps(getAllocator());
 
-	pps << "#define WIDTH " << m_width 
-		<< "\n#define HEIGHT " << m_height
-		<< "\n";
+	pps.sprintf(
+		"#define WIDTH %u\n"
+		"#define HEIGHT %u\n",
+		m_width, m_height);
 
-	m_reflectionFrag.load(ProgramResource::createSrcCodeToCache(
-		"shaders/PpsSslr.frag.glsl", pps.str().c_str(), "r_").c_str());
+	m_reflectionFrag.loadToCache(&getResourceManager(),
+		"shaders/PpsSslr.frag.glsl", pps.toCString(), "r_");
 
 	m_reflectionPpline = m_r->createDrawQuadProgramPipeline(
 		m_reflectionFrag->getGlProgram());
 
 	// Sampler
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
-	m_depthMapSampler = GlSamplerHandle(jobs);
-	m_depthMapSampler.setFilter(jobs, GlSamplerHandle::Filter::NEAREST);
+	GlCommandBufferHandle cmdBuff(&getGlDevice());
+	m_depthMapSampler = GlSamplerHandle(cmdBuff);
+	m_depthMapSampler.setFilter(cmdBuff, GlSamplerHandle::Filter::NEAREST);
 
 	// Blit
-	m_blitFrag.load("shaders/Blit.frag.glsl");
+	m_blitFrag.load("shaders/Blit.frag.glsl", &getResourceManager());
 	m_blitPpline = m_r->createDrawQuadProgramPipeline(
 		m_blitFrag->getGlProgram());
 
@@ -67,61 +67,61 @@ void Sslr::init(const ConfigSet& initializer)
 
 		// Set to bilinear because the blurring techniques take advantage of 
 		// that
-		dir.m_rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
+		dir.m_rt.setFilter(cmdBuff, GlTextureHandle::Filter::LINEAR);
 
 		// Create FB
 		dir.m_fb = GlFramebufferHandle(
-			jobs, {{dir.m_rt, GL_COLOR_ATTACHMENT0}});
+			cmdBuff, {{dir.m_rt, GL_COLOR_ATTACHMENT0}});
 	}
 
-	jobs.finish();
+	cmdBuff.finish();
 }
 
 //==============================================================================
-void Sslr::run(GlCommandBufferHandle& jobs)
+void Sslr::run(GlCommandBufferHandle& cmdBuff)
 {
 	ANKI_ASSERT(m_enabled);
 
 	// Compute the reflection
 	//
-	m_dirs[(U)DirectionEnum::VERTICAL].m_fb.bind(jobs, true);
-	jobs.setViewport(0, 0, m_width, m_height);
+	m_dirs[(U)DirectionEnum::VERTICAL].m_fb.bind(cmdBuff, true);
+	cmdBuff.setViewport(0, 0, m_width, m_height);
 
-	m_reflectionPpline.bind(jobs);
+	m_reflectionPpline.bind(cmdBuff);
 
-	jobs.bindTextures(0	, {
+	cmdBuff.bindTextures(0	, {
 		m_r->getIs()._getRt(), // 0 
 		m_r->getMs()._getSmallDepthRt(), // 1
 		m_r->getMs()._getRt1()}); // 2
 
-	m_depthMapSampler.bind(jobs, 1);
-	m_r->getPps().getSsao().m_uniformsBuff.bindShaderBuffer(jobs, 0);
+	m_depthMapSampler.bind(cmdBuff, 1);
+	m_r->getPps().getSsao().m_uniformsBuff.bindShaderBuffer(cmdBuff, 0);
 
-	m_r->drawQuad(jobs);
+	m_r->drawQuad(cmdBuff);
 
-	GlSamplerHandle::bindDefault(jobs, 1); // Unbind the sampler
+	GlSamplerHandle::bindDefault(cmdBuff, 1); // Unbind the sampler
 
 	// Blurring
 	//
 	if(m_blurringIterationsCount > 0)
 	{
-		runBlurring(*m_r, jobs);
+		runBlurring(*m_r, cmdBuff);
 	}
 
 	// Write the reflection back to IS RT
 	//
-	m_r->getIs().m_fb.bind(jobs, false);
-	jobs.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
+	m_r->getIs().m_fb.bind(cmdBuff, false);
+	cmdBuff.setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
 
-	jobs.enableBlend(true);
-	jobs.setBlendFunctions(GL_ONE, GL_ONE);
+	cmdBuff.enableBlend(true);
+	cmdBuff.setBlendFunctions(GL_ONE, GL_ONE);
 
-	m_dirs[(U)DirectionEnum::VERTICAL].m_rt.bind(jobs, 0);
+	m_dirs[(U)DirectionEnum::VERTICAL].m_rt.bind(cmdBuff, 0);
 
-	m_blitPpline.bind(jobs);
-	m_r->drawQuad(jobs);
+	m_blitPpline.bind(cmdBuff);
+	m_r->drawQuad(cmdBuff);
 
-	jobs.enableBlend(false);
+	cmdBuff.enableBlend(false);
 }
 
 } // end namespace anki

+ 17 - 14
src/renderer/Tiler.cpp

@@ -7,7 +7,6 @@
 #include "anki/renderer/Renderer.h"
 #include "anki/resource/ProgramResource.h"
 #include "anki/scene/Camera.h"
-#include <sstream>
 
 // Default should be 0
 #define ANKI_TILER_ENABLE_GPU 0
@@ -227,14 +226,19 @@ void Tiler::initInternal(Renderer* r)
 	m_r = r;
 
 	// Load the program
-	std::stringstream pps;
-	pps << "#define TILES_X_COUNT " << m_r->getTilesCount().x() << "\n"
-		<< "#define TILES_Y_COUNT " << m_r->getTilesCount().y() << "\n"
-		<< "#define RENDERER_WIDTH " << m_r->getWidth() << "\n"
-		<< "#define RENDERER_HEIGHT " << m_r->getHeight() << "\n";
-
-	m_frag.load(ProgramResource::createSrcCodeToCache(
-		"shaders/TilerMinMax.frag.glsl", pps.str().c_str(), "r_").c_str());
+	String pps(r->_getAllocator());
+	pps.sprintf(
+		"#define TILES_X_COUNT %u\n"
+		"#define TILES_Y_COUNT %u\n"
+		"#define RENDERER_WIDTH %u\n"
+		"#define RENDERER_HEIGHT %u\n",
+		m_r->getTilesCount().x(),
+		m_r->getTilesCount().y(),
+		m_r->getWidth(),
+		m_r->getHeight());
+
+	m_frag.loadToCache(&m_r->_getResourceManager(),
+		"shaders/TilerMinMax.frag.glsl", pps.toCString(), "r_");
 
 	m_ppline = m_r->createDrawQuadProgramPipeline(m_frag->getGlProgram());
 
@@ -242,16 +246,15 @@ void Tiler::initInternal(Renderer* r)
 	m_r->createRenderTarget(m_r->getTilesCount().x(), m_r->getTilesCount().y(),
 		GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, 1, m_rt);
 
-	GlDevice& gl = GlDeviceSingleton::get();
-	GlCommandBufferHandle jobs(&gl);
+	GlCommandBufferHandle cmdBuff(&m_r->_getGlDevice());
 
-	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}});
+	m_fb = GlFramebufferHandle(cmdBuff, {{m_rt, GL_COLOR_ATTACHMENT0}});
 
 	// Create PBO
 	U pixelBuffSize = m_r->getTilesCount().x() * m_r->getTilesCount().y();
 	pixelBuffSize *= 2 * sizeof(F32); // The pixel size
 	pixelBuffSize *= 4; // Because it will be always mapped
-	m_pixelBuff = GlBufferHandle(jobs, GL_PIXEL_PACK_BUFFER, pixelBuffSize,
+	m_pixelBuff = GlBufferHandle(cmdBuff, GL_PIXEL_PACK_BUFFER, pixelBuffSize,
 		GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
 
 	// Init planes. One plane for each direction, plus near/far plus the world
@@ -275,7 +278,7 @@ void Tiler::initInternal(Renderer* r)
 	ANKI_ASSERT(m_farPlanesW + m_r->getTilesCount().x() 
 		* m_r->getTilesCount().y() ==  &m_allPlanes[0] + m_allPlanes.size());
 
-	jobs.flush();
+	cmdBuff.flush();
 }
 
 //==============================================================================

+ 2 - 1
src/resource/Image.cpp

@@ -464,7 +464,8 @@ static void loadAnkiTexture(
 void Image::load(const CString& filename, U32 maxTextureSize)
 {
 	// get the extension
-	CString ext = getFileExtension(filename);
+	HeapAllocator<U8> alloc = m_surfaces.get_allocator();
+	String ext = getFileExtension(filename, alloc);
 	
 	if(ext == nullptr)
 	{

+ 1 - 1
src/resource/ProgramResource.cpp

@@ -40,7 +40,7 @@ void ProgramResource::load(const CString& filename, const CString& extraSrc,
 }
 
 //==============================================================================
-String ProgramResource::createSourceToCache(
+String ProgramResource::createToCache(
 	const CString& filename, const CString& preAppendedSrcCode, 
 	const CString& filenamePrefix, ResourceManager& manager)
 {

+ 3 - 12
src/scene/SceneGraph.cpp

@@ -78,7 +78,7 @@ struct UpdateSceneNodesJob: Threadpool::Task
 
 //==============================================================================
 SceneGraph::SceneGraph(AllocAlignedCallback allocCb, void* allocCbData, 
-	Threadpool* threadpool)
+	Threadpool* threadpool, ResourceManager* resources)
 :	m_alloc(StackMemoryPool(allocCb, allocCbData, ANKI_SCENE_ALLOCATOR_SIZE)),
 	m_frameAlloc(StackMemoryPool(allocCb, allocCbData, 
 		ANKI_SCENE_FRAME_ALLOCATOR_SIZE)),
@@ -87,7 +87,8 @@ SceneGraph::SceneGraph(AllocAlignedCallback allocCb, void* allocCbData,
 	m_physics(),
 	m_sectorGroup(this),
 	m_events(this),
-	m_threadpool(threadpool)
+	m_threadpool(threadpool),
+	m_resources(resources)
 {
 	m_nodes.reserve(ANKI_SCENE_OPTIMAL_SCENE_NODES_COUNT);
 
@@ -256,14 +257,4 @@ void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	ANKI_COUNTER_STOP_TIMER_INC(SCENE_UPDATE_TIME);
 }
 
-//==============================================================================
-void SceneGraph::load(const char* filename)
-{}
-
-//==============================================================================
-GlDevice& SceneGraph::_getGlDevice()
-{
-	return m_resources->_getGlDevice();
-}
-
 } // end namespace anki

+ 1 - 1
src/script/ScriptManager.cpp

@@ -43,7 +43,7 @@ ANKI_SCRIPT_WRAP(Anki)
 
 //==============================================================================
 ScriptManager::ScriptManager(HeapAllocator<U8>& alloc)
-	: LuaBinder(alloc)
+:	LuaBinder(alloc)
 {
 	ANKI_LOGI("Initializing scripting engine...");
 

+ 1 - 1
src/util/CMakeLists.txt

@@ -1,4 +1,4 @@
-set(ANKI_UTIL_SOURCES Assert.cpp Exception.cpp Functions.cpp File.cpp Memory.cpp System.cpp HighRezTimer.cpp Thread.cpp Hash.cpp)
+set(ANKI_UTIL_SOURCES Assert.cpp Exception.cpp Functions.cpp File.cpp Filesystem.cpp Memory.cpp System.cpp HighRezTimer.cpp Thread.cpp Hash.cpp)
 
 if(LINUX OR ANDROID OR MACOS)
 	set(ANKI_UTIL_SOURCES ${ANKI_UTIL_SOURCES} HighRezTimerPosix.cpp FilesystemPosix.cpp ThreadPosix.cpp)

+ 42 - 238
testapp/Main.cpp

@@ -31,88 +31,19 @@
 
 using namespace anki;
 
+App* app;
+
 ModelNode* horse;
 PerspectiveCamera* cam;
-NativeWindow* win;
-HeapAllocator<U8> globAlloc;
-
-//==============================================================================
-void initPhysics()
-{
-#if 0
-	SceneGraph& scene = SceneGraphSingleton::get();
-
-	btCollisionShape* groundShape = new btBoxShape(
-	    btVector3(btScalar(50.), btScalar(50.), btScalar(50.)));
-
-	Transform groundTransform;
-	groundTransform.setIdentity();
-	groundTransform.setOrigin(Vec4(0, -50, 0, 0));
-
-	RigidBody::Initializer init;
-	init.mass = 0.0;
-	init.shape = groundShape;
-	init.startTrf = groundTransform;
-	init.group = PhysicsWorld::CG_MAP;
-	init.mask = PhysicsWorld::CG_ALL;
-
-	new RigidBody(&SceneGraphSingleton::get().getPhysics(), init);
-
-	btCollisionShape* colShape = new btBoxShape(
-	    btVector3(1, 1, 1));
-
-	init.startTrf.setOrigin(Vec3(0.0, 15.0, 0.0));
-	init.mass = 20;
-	init.shape = colShape;
-	init.group = PhysWorld::CG_PARTICLE;
-	init.mask = PhysWorld::CG_MAP | PhysWorld::CG_PARTICLE;
-
-	const I ARRAY_SIZE_X = 5;
-	const I ARRAY_SIZE_Y = 5;
-	const I ARRAY_SIZE_Z = 5;
-	const I START_POS_X = -5;
-	const I START_POS_Y = 35;
-	const I START_POS_Z = -3;
-
-	float start_x = START_POS_X - ARRAY_SIZE_X / 2;
-	float start_y = START_POS_Y;
-	float start_z = START_POS_Z - ARRAY_SIZE_Z / 2;
-
-	for(I k = 0; k < ARRAY_SIZE_Y; k++)
-	{
-		for(I i = 0; i < ARRAY_SIZE_X; i++)
-		{
-			for(I j = 0; j < ARRAY_SIZE_Z; j++)
-			{
-				std::string name = std::string("crate0") + std::to_string(i)
-					+ std::to_string(j) + std::to_string(k);
-
-				ModelNode* mnode = new ModelNode(
-					name.c_str(), &SceneGraphSingleton::get(), nullptr,
-					MoveComponent::MF_NONE, "models/crate0/crate0.mdl");
-
-				init.movable = mnode;
-				ANKI_ASSERT(init.movable);
-
-				Transform trf(
-					Vec3(2.0 * i + start_x, 2.0 * k + start_y,
-						2.0 * j + start_z), Mat3::getIdentity(), 1.0);
-
-				init.startTrf = trf;
-
-				new RigidBody(&SceneGraphSingleton::get().getPhysics(), init);
-			}
-		}
-	}
-#endif
-}
 
 //==============================================================================
 void init()
 {
 	ANKI_LOGI("Other init...");
 
-	SceneGraph& scene = SceneGraphSingleton::get();
+	SceneGraph& scene = app->getSceneGraph();
+	MainRenderer& renderer = app->getMainRenderer();
+
 	scene.setAmbientColor(Vec4(0.1, 0.05, 0.05, 0.0) * 3);
 
 #if 0
@@ -125,7 +56,7 @@ void init()
 	cam = scene.newSceneNode<PerspectiveCamera>("main-camera");
 	const F32 ang = 45.0;
 	cam->setAll(
-		MainRendererSingleton::get().getAspectRatio() * toRad(ang),
+		renderer.getAspectRatio() * toRad(ang),
 		toRad(ang), 0.5, 500.0);
 	cam->setLocalTransform(Transform(Vec4(17.0, 5.2, 0.0, 0),
 		Mat3x4(Euler(toRad(-10.0), toRad(90.0), toRad(0.0))),
@@ -287,8 +218,6 @@ void init()
 	}
 #endif
 
-	initPhysics();
-
 	/*AnimationResourcePointer anim;
 	anim.load("maps/sponza/unnamed_0.ankianim");
 	AnimationEvent* event;
@@ -339,6 +268,7 @@ void init()
 }
 
 //==============================================================================
+#if 0
 /// The func pools the stdinListener for string in the console, if
 /// there are any it executes them with scriptingEngine
 void execStdinScpripts()
@@ -362,47 +292,51 @@ void execStdinScpripts()
 		}
 	}
 }
+#endif
 
 //==============================================================================
-void mainLoopExtra()
+void mainLoopExtra(App& app, void*)
 {
 	F32 dist = 0.1;
 	F32 ang = toRad(1.5);
 	F32 scale = 0.01;
 	F32 mouseSensivity = 9.0;
 
+	SceneGraph& scene = app.getSceneGraph();
+	Input& in = app.getInput();
+	MainRenderer& renderer = app.getMainRenderer();
+
 	// move the camera
 	static MoveComponent* mover = 
-		&SceneGraphSingleton::get().getActiveCamera().getComponent<MoveComponent>();
-	Input& in = InputSingleton::get();
+		&scene.getActiveCamera().getComponent<MoveComponent>();
 
 	if(in.getKey(KeyCode::_1))
 	{
-		mover = &SceneGraphSingleton::get().getActiveCamera();
+		mover = &scene.getActiveCamera();
 	}
 	if(in.getKey(KeyCode::_2))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("horse").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("horse").getComponent<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_3))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("spot0").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("spot0").getComponent<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_4))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("spot1").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("spot1").getComponent<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_5))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("pe").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("pe").getComponent<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_6))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("shape0").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("shape0").getComponent<MoveComponent>();
 	}
 	if(in.getKey(KeyCode::_7))
 	{
-		mover = &SceneGraphSingleton::get().findSceneNode("shape1").getComponent<MoveComponent>();
+		mover = &scene.findSceneNode("shape1").getComponent<MoveComponent>();
 	}
 
 	/*if(in.getKey(KeyCode::L) == 1)
@@ -418,36 +352,31 @@ void mainLoopExtra()
 
 	if(in.getKey(KeyCode::F1) == 1)
 	{
-		MainRendererSingleton::get().getDbg().setEnabled(
-			!MainRendererSingleton::get().getDbg().getEnabled());
+		renderer.getDbg().setEnabled(!renderer.getDbg().getEnabled());
 	}
 	if(in.getKey(KeyCode::F2) == 1)
 	{
-		MainRendererSingleton::get().getDbg().switchBits(
-			Dbg::DF_SPATIAL);
+		renderer.getDbg().switchBits(Dbg::Flag::SPATIAL);
 	}
 	if(in.getKey(KeyCode::F3) == 1)
 	{
-		MainRendererSingleton::get().getDbg().switchBits(
-			Dbg::DF_PHYSICS);
+		renderer.getDbg().switchBits(Dbg::Flag::PHYSICS);
 	}
 	if(in.getKey(KeyCode::F4) == 1)
 	{
-		MainRendererSingleton::get().getDbg().switchBits(
-			Dbg::DF_SECTOR);
+		renderer.getDbg().switchBits(Dbg::Flag::SECTOR);
 	}
 	if(in.getKey(KeyCode::F5) == 1)
 	{
-		MainRendererSingleton::get().getDbg().switchBits(
-			Dbg::DF_OCTREE);
+		renderer.getDbg().switchBits(Dbg::Flag::OCTREE);
 	}
 	if(in.getKey(KeyCode::F6) == 1)
 	{
-		MainRendererSingleton::get().getDbg().switchDepthTestEnabled();
+		renderer.getDbg().switchDepthTestEnabled();
 	}
 	if(in.getKey(KeyCode::F12) == 1)
 	{
-		MainRendererSingleton::get().takeScreenshot("screenshot.tga");
+		renderer.takeScreenshot("screenshot.tga");
 	}
 
 	if(in.getKey(KeyCode::UP)) mover->rotateLocalX(ang);
@@ -471,6 +400,7 @@ void mainLoopExtra()
 	{
 		mover->scale(-scale);
 	}
+#if 0
 	if(in.getKey(KeyCode::P) == 1)
 	{
 		std::cout << "{Vec3(" 
@@ -479,7 +409,9 @@ void mainLoopExtra()
 			<< Quat(mover->getWorldTransform().getRotation()).toString()
 			<< ")}," << std::endl;
 	}
+#endif
 
+#if 0
 	if(in.getKey(KeyCode::L) == 1)
 	{
 		try
@@ -498,139 +430,23 @@ end)");
 			ANKI_LOGE(e.what());
 		}
 	}
-
+#endif
 
 	if(in.getMousePosition() != Vec2(0.0))
 	{
 		F32 angY = -ang * in.getMousePosition().x() * mouseSensivity *
-			MainRendererSingleton::get().getAspectRatio();
+			renderer.getAspectRatio();
 
 		mover->rotateLocalY(angY);
 		mover->rotateLocalX(ang * in.getMousePosition().y() * mouseSensivity);
 	}
 
-	execStdinScpripts();
-}
-
-//==============================================================================
-void mainLoop()
-{
-	ANKI_LOGI("Entering main loop");
-
-	HighRezTimer::Scalar prevUpdateTime = HighRezTimer::getCurrentTime();
-	HighRezTimer::Scalar crntTime = prevUpdateTime;
-
-	ANKI_COUNTER_START_TIMER(FPS);
-
-	while(1)
-	{
-		HighRezTimer timer;
-		timer.start();
-
-		prevUpdateTime = crntTime;
-		crntTime = HighRezTimer::getCurrentTime();
-
-		// Update
-		//
-		InputSingleton::get().handleEvents();
-		mainLoopExtra();
-
-		SceneGraphSingleton::get().update(
-			prevUpdateTime, crntTime, MainRendererSingleton::get());
-		//EventManagerSingleton::get().updateAllEvents(prevUpdateTime, crntTime);
-		MainRendererSingleton::get().render(SceneGraphSingleton::get());
-
-		if(InputSingleton::get().getKey(KeyCode::ESCAPE))
-		{
-			break;
-		}
-
-		GlManagerSingleton::get().swapBuffers();
-		ANKI_COUNTERS_RESOLVE_FRAME();
-
-		// Sleep
-		//
-#if 1
-		timer.stop();
-		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
-		{
-			HighRezTimer::sleep(AppSingleton::get().getTimerTick()
-				- timer.getElapsedTime());
-		}
-#else
-		if(MainRendererSingleton::get().getFramesCount() == 2000)
-		{
-			break;
-		}
-#endif
-		increaseGlobTimestamp();
-	}
-
-	
-	GlManagerSingleton::destroy();
-	ANKI_COUNTER_STOP_TIMER_INC(FPS);
-
-	ANKI_COUNTERS_FLUSH();
-
-#if 0
-	MainRendererSingleton::get().takeScreenshot("screenshot.tga");
-#endif
+	//execStdinScpripts();
 }
 
 //==============================================================================
-// initSubsystems                                                              =
-//==============================================================================
-
-void makeCurrent(void* ctx)
-{
-	win->contextMakeCurrent(ctx);
-}
-
-void swapBuffers(void* wind)
-{
-	NativeWindow* win = (NativeWindow*)wind;
-	win->swapBuffers();
-}
-
 void initSubsystems(int argc, char* argv[])
 {
-#if ANKI_GL == ANKI_GL_DESKTOP
-	U32 glmajor = 4;
-	U32 glminor = 4;
-#else
-	U32 glmajor = 3;
-	U32 glminor = 0;
-#endif
-
-	globAlloc = HeapAllocator<U8>(HeapMemoryPool(allocAligned, nullptr));
-
-	// Logger
-	LoggerSingleton::init(
-		Logger::InitFlags::WITH_SYSTEM_MESSAGE_HANDLER, globAlloc);
-
-	// App
-	AppSingleton::get().init();
-
-	// Window
-	NativeWindowInitializer nwinit;
-	nwinit.m_width = 1280;
-	nwinit.m_height = 720;
-	nwinit.m_majorVersion = glmajor;
-	nwinit.m_minorVersion = glminor;
-	nwinit.m_depthBits = 0;
-	nwinit.m_stencilBits = 0;
-	nwinit.m_fullscreenDesktopRez = false;
-	nwinit.m_debugContext = ANKI_DEBUG;
-	win = new NativeWindow;	
-	win->create(nwinit);
-	void* context = win->getCurrentContext();
-	win->contextMakeCurrent(nullptr);
-
-	// GL stuff
-	GlManagerSingleton::init(makeCurrent, context,
-		swapBuffers, win, nwinit.m_debugContext,
-		allocAligned, nullptr);
-
 	// Config
 	Config config;
 	config.set("ms.ez.enabled", false);
@@ -660,31 +476,20 @@ void initSubsystems(int argc, char* argv[])
 	config.set("pps.lf.enabled", true);
 	config.set("pps.sharpen", true);
 	config.set("renderingQuality", 1.0);
-	config.set("width", win->getWidth());
-	config.set("height", win->getHeight());
+	config.set("width", 1280);
+	config.set("height", 720);
 	config.set("lodDistance", 20.0);
 	config.set("samples", 1);
 	config.set("tessellation", false);
 	config.set("tilesXCount", 16);
 	config.set("tilesYCount", 16);
 
-	// Input
-	InputSingleton::get().init(win);
-	InputSingleton::get().lockCursor(true);
-	InputSingleton::get().hideCursor(true);
-	InputSingleton::get().moveCursor(Vec2(0.0));
-
-	ResourceManagerSingleton::init(config);
+	app = new App(config, allocAligned, nullptr);
 
-	MainRendererSingleton::init(config);
-
-	ScriptManagerSingleton::init(globAlloc);
-
-	SceneGraphSingleton::init(allocAligned, nullptr);
-
-	StdinListenerSingleton::get().start();
-
-	ThreadpoolSingleton::get().init(getCpuCoresCount());
+	// Input
+	app->getInput().lockCursor(true);
+	app->getInput().hideCursor(true);
+	app->getInput().moveCursor(Vec2(0.0));
 }
 
 //==============================================================================
@@ -697,10 +502,9 @@ int main(int argc, char* argv[])
 		initSubsystems(argc, argv);
 		init();
 
-		mainLoop();
+		app->mainLoop(mainLoopExtra, nullptr);
 
 		ANKI_LOGI("Exiting...");
-		AppSingleton::get().quit(EXIT_SUCCESS);
 		exitCode = 0;
 	}
 	catch(std::exception& e)

+ 2 - 1
tests/Main.cpp

@@ -5,6 +5,7 @@
 
 #include "tests/framework/Framework.h"
 #include "anki/core/Logger.h"
+#include "anki/util/Filesystem.h"
 
 using namespace anki;
 
@@ -15,7 +16,7 @@ int main(int argc, char** argv)
 	// Call a few singletons to avoid memory leak confusion
 	LoggerSingleton::init(
 		Logger::InitFlags::WITH_SYSTEM_MESSAGE_HANDLER,
-		alloc);
+		alloc, &(getHomeDirectory(alloc) + ".anki/tests.log")[0]);
 
 	int exitcode = getTesterSingleton().run(argc, argv);