Bladeren bron

Mega refactoring. It will not compile

Panagiotis Christopoulos Charitos 11 jaren geleden
bovenliggende
commit
25d171f127
100 gewijzigde bestanden met toevoegingen van 2022 en 1817 verwijderingen
  1. 6 4
      CMakeLists.txt
  2. 2 129
      docs/drafts/physics.md
  3. 2 2
      include/anki/Gl.h
  4. 63 35
      include/anki/core/App.h
  5. 1 1
      include/anki/core/Counters.h
  6. 50 46
      include/anki/core/NativeWindow.h
  7. 9 12
      include/anki/core/StdinListener.h
  8. 2 9
      include/anki/gl/GlBuffer.h
  9. 12 15
      include/anki/gl/GlBufferHandle.h
  10. 4 8
      include/anki/gl/GlClientBuffer.h
  11. 3 3
      include/anki/gl/GlClientBufferHandle.h
  12. 170 0
      include/anki/gl/GlCommandBuffer.h
  13. 31 33
      include/anki/gl/GlCommandBufferHandle.h
  14. 5 5
      include/anki/gl/GlCommon.h
  15. 2 2
      include/anki/gl/GlContainerHandle.h
  16. 13 13
      include/anki/gl/GlDevice.h
  17. 6 9
      include/anki/gl/GlFramebufferHandle.h
  18. 10 10
      include/anki/gl/GlHandle.h
  19. 10 10
      include/anki/gl/GlHandleDeferredDeleter.h
  20. 0 169
      include/anki/gl/GlJobChain.h
  21. 6 6
      include/anki/gl/GlOperations.h
  22. 1 1
      include/anki/gl/GlProgramHandle.h
  23. 6 6
      include/anki/gl/GlProgramPipelineHandle.h
  24. 21 21
      include/anki/gl/GlQueue.h
  25. 4 4
      include/anki/gl/GlSyncHandles.h
  26. 12 10
      include/anki/gl/GlTextureHandle.h
  27. 22 18
      include/anki/input/Input.h
  28. 2 2
      include/anki/math/Functions.h
  29. 1 1
      include/anki/renderer/Bs.h
  30. 1 1
      include/anki/renderer/Dbg.h
  31. 3 3
      include/anki/renderer/DebugDrawer.h
  32. 2 2
      include/anki/renderer/Drawer.h
  33. 1 1
      include/anki/renderer/Ez.h
  34. 2 2
      include/anki/renderer/Hdr.h
  35. 4 4
      include/anki/renderer/Is.h
  36. 1 1
      include/anki/renderer/Lf.h
  37. 5 5
      include/anki/renderer/MainRenderer.h
  38. 1 1
      include/anki/renderer/Ms.h
  39. 1 1
      include/anki/renderer/Pps.h
  40. 12 5
      include/anki/renderer/Renderer.h
  41. 1 1
      include/anki/renderer/RenderingPass.h
  42. 4 4
      include/anki/renderer/Sm.h
  43. 1 1
      include/anki/renderer/Ssao.h
  44. 1 1
      include/anki/renderer/Sslr.h
  45. 36 30
      include/anki/resource/Animation.h
  46. 28 0
      include/anki/resource/Common.h
  47. 48 42
      include/anki/resource/Image.h
  48. 1 1
      include/anki/resource/Material.h
  49. 24 10
      include/anki/resource/MaterialProgramCreator.h
  50. 3 3
      include/anki/resource/Model.h
  51. 4 9
      include/anki/resource/Resource.h
  52. 117 63
      include/anki/resource/ResourceManager.h
  53. 66 61
      include/anki/resource/ResourcePointer.h
  54. 90 0
      include/anki/resource/ResourcePointer.inl.h
  55. 1 1
      include/anki/scene/RenderComponent.h
  56. 10 6
      include/anki/scene/SceneGraph.h
  57. 4 5
      include/anki/scene/Visibility.h
  58. 12 9
      include/anki/util/Allocator.h
  59. 27 0
      include/anki/util/Enum.h
  60. 18 17
      include/anki/util/Memory.h
  61. 152 156
      include/anki/util/Thread.h
  62. 39 20
      src/core/App.cpp
  63. 1 1
      src/core/Counters.cpp
  64. 5 8
      src/core/NativeWindowSdl.cpp
  65. 29 15
      src/core/StdinListener.cpp
  66. 68 52
      src/gl/GlBufferHandle.cpp
  67. 5 5
      src/gl/GlClientBufferHandle.cpp
  68. 117 0
      src/gl/GlCommandBuffer.cpp
  69. 118 116
      src/gl/GlCommandBufferHandle.cpp
  70. 14 14
      src/gl/GlDevice.cpp
  71. 35 27
      src/gl/GlFramebufferHandle.cpp
  72. 0 116
      src/gl/GlJobChain.cpp
  73. 10 10
      src/gl/GlOperations.cpp
  74. 12 12
      src/gl/GlProgramHandle.cpp
  75. 17 17
      src/gl/GlProgramPipelineHandle.cpp
  76. 45 45
      src/gl/GlQueue.cpp
  77. 11 11
      src/gl/GlSyncHandles.cpp
  78. 70 68
      src/gl/GlTextureHandle.cpp
  79. 4 4
      src/input/Input.cpp
  80. 10 5
      src/input/InputSdl.cpp
  81. 1 1
      src/renderer/Bs.cpp
  82. 3 3
      src/renderer/Dbg.cpp
  83. 2 2
      src/renderer/DebugDrawer.cpp
  84. 6 6
      src/renderer/Drawer.cpp
  85. 1 1
      src/renderer/Ez.cpp
  86. 6 6
      src/renderer/Hdr.cpp
  87. 11 12
      src/renderer/Is.cpp
  88. 3 3
      src/renderer/Lf.cpp
  89. 9 7
      src/renderer/MainRenderer.cpp
  90. 5 5
      src/renderer/Ms.cpp
  91. 3 3
      src/renderer/Pps.cpp
  92. 17 16
      src/renderer/Renderer.cpp
  93. 3 3
      src/renderer/RenderingPass.cpp
  94. 6 6
      src/renderer/Sm.cpp
  95. 5 5
      src/renderer/Ssao.cpp
  96. 3 3
      src/renderer/Sslr.cpp
  97. 5 6
      src/renderer/Tiler.cpp
  98. 52 51
      src/resource/Animation.cpp
  99. 109 100
      src/resource/Image.cpp
  100. 5 2
      src/resource/Material.cpp

+ 6 - 4
CMakeLists.txt

@@ -115,10 +115,12 @@ endif()
 set(CXX_FLAGS "${CXX_FLAGS} -static-libstdc++ ")
 set(CXX_FLAGS "${CXX_FLAGS} -static-libstdc++ ")
 
 
 # SSE
 # SSE
-if(LINUX OR MACOS OR WINDOWS)
-	set(COMPILER_FLAGS "${COMPILER_FLAGS} -msse4 ")
-else()
-	set(COMPILER_FLAGS "${COMPILER_FLAGS} -mfpu=neon ")
+if(ANKI_ENABLE_SIMD)
+	if(LINUX OR MACOS OR WINDOWS)
+		set(COMPILER_FLAGS "${COMPILER_FLAGS} -msse4 ")
+	else()
+		set(COMPILER_FLAGS "${COMPILER_FLAGS} -mfpu=neon ")
+	endif()
 endif()
 endif()
 
 
 if(${ANKI_BUILD_TYPE} STREQUAL "Debug")
 if(${ANKI_BUILD_TYPE} STREQUAL "Debug")

+ 2 - 129
docs/drafts/physics.md

@@ -2,135 +2,8 @@
 Physics engine spec
 Physics engine spec
 ===================
 ===================
 
 
-This is a spec for a physics implementation based on ODE.
-
-Plan
-----
-
-1. Make changes to collision
-2. Test that all is working
-
-Changes to collision
---------------------
-
-1. Add compound functionality
-2. Remove frustums to another level of functionality
-3. Remove Ray and rename LineSegment to Ray
-4. Add capsule shape
-5. Add trimesh shape
-6. Change the collision matrix to support penetration
-
-### Add compound functionality
-
-Every shape has 2 pointers pointing to previous and next shape. 
-
-Some methods
-(testPlane, transform, computeAabb, accept) will have to propagade to the next
-shape and so on. The pure virtuals will have to change names everywhere to
-xxxSingle (eg testPlaneSingle) and the CollisionShape will have the xxx names.
-The CollisionShape::testPlane for example will propagade to _this_ and the 
-children.
-
-Assertions will make sure that the methods start from the root shape.
-
-Add copy constructor and call this in derived classes. Assert if trying to 
-copy compound.
-
-### Remove frustums to another level of functionality
-
-The Frustum will look like:
-
-```
-virtual CollisionShape& getCollisionShape() = 0;
-Bool insideFrustum(const CollisionShape& b) const;
-virtual void computeProjectionMatrix(Mat4& m) const = 0;
-virtual void setTransform(const Transform& trf) = 0;
-
-void transformPlanes(const Transform& trf);
-
-Transform m_trf;
-F32 m_near;
-F32 m_far;
-Plane m_planes[6];
-```
-
-The PerspectiveFrustum will look like:
-
-```
-F32 m_fovX;
-F32 m_fovY;
-Ray m_rays[4]; // Compound
-```
-
-Optimize setTransform(). There is no need to recalculate.
-
-
-ODE physics
------------
-
-dxGeom:
-- type
-- flags
-- data: used defined void*
-- body: the body
-- final_posr: pointer to position
-- offset_posr: pointer to position relative to the body
-- body_next: pointer to dxGeom
-- [other pointers to dxGeom]
-- parent_space: pointer to space
-- category_bits & collide_bits: some flags
-- aabb: cached AABB
-
-dxConvex:
-- planes
-- positions
-- indices for the above positions
-- saabb: A static AABB
-- edges: Array of edges
-
-dxSphere:
-- radius
-
-dxBox:
-- side: Same as extend
-
-dxPlane
-- p: 4 plane numbers
-
-dxCylinded:
-- radius: Along Z axis
-- lz: Length along Z axis
-
-Class diagram of physics
-------------------------
-
-The source tree is:
-```
--- src
-   |-- math
-   |-- collision
-   |-- physics
-```
-
-### Collision shape
-
-```
-PhysicsWorld
-init
-destroy
-castRay
-```
-
-RigidBody
-<constructor>: type, init_data_union
-setPosition
-setRotation
-getPosition
-getRotation
-getMoveUpdateTimestamp
-addForce
-
-CharacterController
+This is the spec for physics engine
 
 
+## 
 
 
 
 

+ 2 - 2
include/anki/Gl.h

@@ -33,7 +33,7 @@
 
 
 #include "anki/gl/GlOperations.h"
 #include "anki/gl/GlOperations.h"
 
 
-#include "anki/gl/GlJobChainHandle.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlCommandBufferHandle.h"
+#include "anki/gl/GlDevice.h"
 
 
 #endif
 #endif

+ 63 - 35
include/anki/core/App.h

@@ -6,9 +6,8 @@
 #ifndef ANKI_CORE_APP_H
 #ifndef ANKI_CORE_APP_H
 #define ANKI_CORE_APP_H
 #define ANKI_CORE_APP_H
 
 
-#include "anki/Config.h"
-#include "anki/util/Singleton.h"
-#include "anki/util/StringList.h"
+#include "anki/util/Allocator.h"
+#include "anki/util/String.h"
 #if ANKI_OS == ANKI_OS_ANDROID
 #if ANKI_OS == ANKI_OS_ANDROID
 #	include <android_native_app_glue.h>
 #	include <android_native_app_glue.h>
 #endif
 #endif
@@ -19,69 +18,98 @@ namespace anki {
 extern android_app* gAndroidApp;
 extern android_app* gAndroidApp;
 #endif
 #endif
 
 
+// Forward
+class Config;
+class Threadpool;
+class NativeWindow;
+class Input;
+class GlDevice;
+class MainRenderer;
+class SceneManager;
+class ScriptManager;
+
 /// The core class of the engine.
 /// The core class of the engine.
-///
-/// - It initializes the window
-/// - it holds the global state and thus it parses the command line arguments
-/// - It manipulates the main loop timer
 class App
 class App
 {
 {
 public:
 public:
-	App()
-	{}
-	~App()
-	{}
+	App(const Config& config, 
+		AllocAlignedCallback allocCb, void* allocCbUserData);
 
 
-	/// Initialize the app
-	void init();
-
-	/// @name Accessors
-	/// @{
-	F32 getTimerTick() const
+	~App()
 	{
 	{
-		return timerTick;
+		// TODO
 	}
 	}
-	F32& getTimerTick()
+
+	F32 getTimerTick() const
 	{
 	{
-		return timerTick;
+		return m_timerTick;
 	}
 	}
+
 	void setTimerTick(const F32 x)
 	void setTimerTick(const F32 x)
 	{
 	{
-		timerTick = x;
+		m_timerTick = x;
 	}
 	}
 
 
 	const String& getSettingsPath() const
 	const String& getSettingsPath() const
 	{
 	{
-		return settingsPath;
+		return m_settingsPath;
 	}
 	}
 
 
 	const String& getCachePath() const
 	const String& getCachePath() const
 	{
 	{
-		return cachePath;
+		return m_cachePath;
+	}
+
+	AllocAlignedCallback getAllocationCallback() const
+	{
+		return m_allocCb;
 	}
 	}
-	/// @}
 
 
-	/// What it does:
-	/// - Destroy the window
-	/// - call exit()
+	void* getAllocationCallbackData() const
+	{
+		return m_allocCbData;
+	}
+
+	Threadpool& getThreadpool()
+	{
+		return m_threadpool;
+	}
+
+	/// TODO
 	void quit(int code);
 	void quit(int code);
 
 
 	/// Run the main loop
 	/// Run the main loop
 	void mainLoop();
 	void mainLoop();
 
 
-	static void printAppInfo();
-
 private:
 private:
-	/// The path that holds the configuration
-	String settingsPath;
-	/// This is used as a cache
-	String cachePath;
-	F32 timerTick;
+	// Allocation
+	AllocAlignedCallback m_allocCb;
+	void* m_allocCbData;
+	HeapAllocator<U8> m_heapAlloc;
+
+	// Sybsystems
+	GlDevice* m_gl = nullptr;
+	NativeWindow* m_window = nullptr;
+	Input* m_input = nullptr;
+	MainRenderer* m_renderer = nullptr;
+	SceneGraph* m_scene = nullptr;
+	ScriptManager* m_script = nullptr;
+
+	// Misc
+	Threadpool* m_threadpool = nullptr;
+	String m_settingsPath; ///< The path that holds the configuration
+	String m_cachePath; ///< This is used as a cache
+	F32 m_timerTick;
+
+	/// Initialize the app
+	void init();
 
 
 	void initDirs();
 	void initDirs();
+
+	static void printAppInfo();
 };
 };
 
 
-typedef Singleton<App> AppSingleton;
+using AppSingleton = SingletonInit<App>;
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 1 - 1
include/anki/core/Counters.h

@@ -26,7 +26,7 @@ enum class Counter
 	GL_SERVER_WAIT_TIME,
 	GL_SERVER_WAIT_TIME,
 	GL_DRAWCALLS_COUNT,
 	GL_DRAWCALLS_COUNT,
 	GL_VERTICES_COUNT,
 	GL_VERTICES_COUNT,
-	GL_JOB_CHAINS_SIZE,
+	GL_QUEUES_SIZE,
 	GL_CLIENT_BUFFERS_SIZE,
 	GL_CLIENT_BUFFERS_SIZE,
 
 
 	COUNT
 	COUNT

+ 50 - 46
include/anki/core/NativeWindow.h

@@ -8,53 +8,55 @@
 
 
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"
-#include "anki/util/Singleton.h"
 #include "anki/util/String.h"
 #include "anki/util/String.h"
-#include <string>
-#include <memory>
+#include "anki/util/Allocator.h"
 
 
 namespace anki {
 namespace anki {
 
 
 class NativeWindowImpl;
 class NativeWindowImpl;
-typedef void* Context;
-
-/// Window initializer
-struct NativeWindowInitializer
-{
-	U32 m_width = 640;
-	U32 m_height = 768;
-	Array<U32, 4> m_rgbaBits = {{8, 8, 8, 0}};
-	U32 m_depthBits = 0;
-	U32 m_stencilBits = 0;
-	U32 m_samplesCount = 0;
-	static const Bool m_doubleBuffer = true;
-	/// Create a fullscreen window with the desktop's resolution
-	Bool8 m_fullscreenDesktopRez = false;
-
-	/// @name GL context properties
-	/// @{
-
-	/// Minor OpenGL version. Used to create core profile context
-	U32 m_minorVersion = 0;
-	/// Major OpenGL version. Used to create core profile context
-	U32 m_majorVersion = 0;
-	Bool8 m_useGles = false; ///< Use OpenGL ES
-	Bool8 m_debugContext = false; ///< Enables KHR_debug
-	/// @}
-
-	String m_title = "Untitled window";
-};
+using Context = void*;
 
 
 /// Native window with GL context
 /// Native window with GL context
 class NativeWindow
 class NativeWindow
 {
 {
 public:
 public:
-	NativeWindow()
-	{}
-	~NativeWindow();
+	/// Window initializer
+	struct Initializer
+	{
+		U32 m_width = 640;
+		U32 m_height = 768;
+		Array<U32, 4> m_rgbaBits = {{8, 8, 8, 0}};
+		U32 m_depthBits = 0;
+		U32 m_stencilBits = 0;
+		U32 m_samplesCount = 0;
+		static const Bool m_doubleBuffer = true;
+		/// Create a fullscreen window with the desktop's resolution
+		Bool8 m_fullscreenDesktopRez = false;
+
+		/// @name GL context properties
+		/// @{
+
+		/// Minor OpenGL version. Used to create core profile context
+		U32 m_minorVersion = 0;
+		/// Major OpenGL version. Used to create core profile context
+		U32 m_majorVersion = 0;
+		Bool8 m_useGles = false; ///< Use OpenGL ES
+		Bool8 m_debugContext = false; ///< Enables KHR_debug
+		/// @}
+
+		String m_title = "Untitled window";
+	};
+
+	NativeWindow(Initializer& initializer, HeapAllocator<U8>& alloc)
+	{
+		create(initializer, alloc);
+	}
+
+	~NativeWindow()
+	{
+		destroy();
+	}
 
 
-	/// @name Accessors
-	/// @{
 	NativeWindowImpl& getNative()
 	NativeWindowImpl& getNative()
 	{
 	{
 		ANKI_ASSERT(isCreated());
 		ANKI_ASSERT(isCreated());
@@ -69,33 +71,35 @@ public:
 	{
 	{
 		return m_height;
 		return m_height;
 	}
 	}
-	/// @}
 
 
-	/// @name Public interface
-	/// Don't implement them in .h files
-	/// @{
-	void create(NativeWindowInitializer& initializer);
-	void destroy();
 	void swapBuffers();
 	void swapBuffers();
 	Context createSharedContext();
 	Context createSharedContext();
 	Context getCurrentContext();
 	Context getCurrentContext();
 	void contextMakeCurrent(Context ctx);
 	void contextMakeCurrent(Context ctx);
+
+	/// @privatesector
+	/// @{
+	HeapAllocator<U8>& _getAllocator()
+	{
+		return m_alloc;
+	}
 	/// @}
 	/// @}
 
 
 private:
 private:
 	U32 m_width;
 	U32 m_width;
 	U32 m_height;
 	U32 m_height;
 
 
-	std::shared_ptr<NativeWindowImpl> m_impl;
+	NativeWindowImpl* m_impl;
+	HeapAllocator<U8> m_alloc;
 
 
 	Bool isCreated() const
 	Bool isCreated() const
 	{
 	{
 		return m_impl.get() != nullptr;
 		return m_impl.get() != nullptr;
 	}
 	}
-};
 
 
-/// Native window singleton
-typedef Singleton<NativeWindow> NativeWindowSingleton;
+	void create(Initializer& initializer, HeapAllocator<U8>& alloc);
+	void destroy();
+};
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 9 - 12
include/anki/core/StdinListener.h

@@ -6,10 +6,8 @@
 #ifndef ANKI_CORE_STDIN_LISTENER_H
 #ifndef ANKI_CORE_STDIN_LISTENER_H
 #define ANKI_CORE_STDIN_LISTENER_H
 #define ANKI_CORE_STDIN_LISTENER_H
 
 
-#include "anki/util/Singleton.h"
 #include "anki/util/String.h"
 #include "anki/util/String.h"
-#include <thread>
-#include <mutex>
+#include "anki/util/Thread.h"
 #include <queue>
 #include <queue>
 
 
 namespace anki {
 namespace anki {
@@ -23,23 +21,22 @@ namespace anki {
 class StdinListener
 class StdinListener
 {
 {
 public:
 public:
+	StdinListener();
+
+	~StdinListener();
+
 	/// Get line from the queue or return an empty string
 	/// Get line from the queue or return an empty string
 	String getLine();
 	String getLine();
 
 
-	/// Start reading
-	void start();
-
 private:
 private:
 	std::queue<String> m_q;
 	std::queue<String> m_q;
-	std::mutex m_mtx; ///< Protect the queue
-	std::thread m_thrd; ///< The thread
+	Mutex m_mtx; ///< Protect the queue
+	Thread m_thrd; ///< The thread
+	Bool8 m_quit = false;
 
 
-	void workingFunc(); ///< The thread function
+	static I workingFunc(Thread::Info& info); ///< The thread function
 };
 };
 
 
-/// Singleton
-typedef Singleton<StdinListener> StdinListenerSingleton;
-
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 2 - 9
include/anki/gl/GlBuffer.h

@@ -18,10 +18,7 @@ namespace anki {
 class GlBuffer: public GlObject
 class GlBuffer: public GlObject
 {
 {
 public:
 public:
-	typedef GlObject Base;
-
-	/// @name Constructors/Destructor
-	/// @{
+	using Base = GlObject;
 
 
 	/// Default
 	/// Default
 	GlBuffer()
 	GlBuffer()
@@ -51,13 +48,10 @@ public:
 	{
 	{
 		destroy();
 		destroy();
 	}
 	}
-	/// @}
-
+	
 	/// Move
 	/// Move
 	GlBuffer& operator=(GlBuffer&& b);
 	GlBuffer& operator=(GlBuffer&& b);
 
 
-	/// @name Accessors
-	/// @{
 	GLenum getTarget() const
 	GLenum getTarget() const
 	{
 	{
 		ANKI_ASSERT(isCreated());
 		ANKI_ASSERT(isCreated());
@@ -84,7 +78,6 @@ public:
 		ANKI_ASSERT(m_persistentMapping);
 		ANKI_ASSERT(m_persistentMapping);
 		return m_persistentMapping;
 		return m_persistentMapping;
 	}
 	}
-	/// @}
 
 
 	/// Bind
 	/// Bind
 	void bind() const
 	void bind() const

+ 12 - 15
include/anki/gl/GlBufferHandle.h

@@ -13,7 +13,7 @@ namespace anki {
 // Forward
 // Forward
 class GlBuffer;
 class GlBuffer;
 class GlClientBufferHandle;
 class GlClientBufferHandle;
-class GlJobChainHandle;
+class GlCommandBufferHandle;
 
 
 /// @addtogroup opengl_containers
 /// @addtogroup opengl_containers
 /// @{
 /// @{
@@ -22,22 +22,19 @@ class GlJobChainHandle;
 class GlBufferHandle: public GlContainerHandle<GlBuffer>
 class GlBufferHandle: public GlContainerHandle<GlBuffer>
 {
 {
 public:
 public:
-	typedef GlContainerHandle<GlBuffer> Base;
+	using Base = GlContainerHandle<GlBuffer>;
 
 
-	/// @name Constructors/Destructor
-	/// @{
 	GlBufferHandle();
 	GlBufferHandle();
 
 
 	/// Create the buffer with data
 	/// Create the buffer with data
-	explicit GlBufferHandle(GlJobChainHandle& jobs, GLenum target, 
+	explicit GlBufferHandle(GlCommandBufferHandle& commands, GLenum target, 
 		GlClientBufferHandle& data, GLbitfield flags);
 		GlClientBufferHandle& data, GLbitfield flags);
 
 
 	/// Create the buffer without data
 	/// Create the buffer without data
-	explicit GlBufferHandle(GlJobChainHandle& jobs, GLenum target, 
+	explicit GlBufferHandle(GlCommandBufferHandle& commands, GLenum target, 
 		PtrSize size, GLbitfield flags);
 		PtrSize size, GLbitfield flags);
 
 
 	~GlBufferHandle();
 	~GlBufferHandle();
-	/// @}
 
 
 	/// Get buffer size. It may serialize 
 	/// Get buffer size. It may serialize 
 	PtrSize getSize() const;
 	PtrSize getSize() const;
@@ -50,26 +47,26 @@ public:
 
 
 	/// Write data to the buffer
 	/// Write data to the buffer
 	void write(
 	void write(
-		GlJobChainHandle& jobs, 
+		GlCommandBufferHandle& commands, 
 		GlClientBufferHandle& data, PtrSize readOffset,
 		GlClientBufferHandle& data, PtrSize readOffset,
 		PtrSize writeOffset, PtrSize size);
 		PtrSize writeOffset, PtrSize size);
 
 
 	/// Bind to the state as uniform/shader storage buffer
 	/// Bind to the state as uniform/shader storage buffer
-	void bindShaderBuffer(GlJobChainHandle& jobs, U32 bindingPoint)
+	void bindShaderBuffer(GlCommandBufferHandle& commands, U32 bindingPoint)
 	{
 	{
-		bindShaderBufferInternal(jobs, -1, -1, bindingPoint);
+		bindShaderBufferInternal(commands, -1, -1, bindingPoint);
 	}
 	}
 
 
 	/// Bind to the state as uniform/shader storage buffer
 	/// Bind to the state as uniform/shader storage buffer
-	void bindShaderBuffer(GlJobChainHandle& jobs,
+	void bindShaderBuffer(GlCommandBufferHandle& commands,
 		U32 offset, U32 size, U32 bindingPoint)
 		U32 offset, U32 size, U32 bindingPoint)
 	{
 	{
-		bindShaderBufferInternal(jobs, offset, size, bindingPoint);
+		bindShaderBufferInternal(commands, offset, size, bindingPoint);
 	}
 	}
 
 
 	/// Bind to the state as vertex buffer
 	/// Bind to the state as vertex buffer
 	void bindVertexBuffer(
 	void bindVertexBuffer(
-		GlJobChainHandle& jobs, 
+		GlCommandBufferHandle& commands, 
 		U32 elementSize,
 		U32 elementSize,
 		GLenum type,
 		GLenum type,
 		Bool normalized,
 		Bool normalized,
@@ -78,10 +75,10 @@ public:
 		U32 attribLocation);
 		U32 attribLocation);
 
 
 	/// Bind to the state as index buffer
 	/// Bind to the state as index buffer
-	void bindIndexBuffer(GlJobChainHandle& jobs);
+	void bindIndexBuffer(GlCommandBufferHandle& commands);
 
 
 private:
 private:
-	void bindShaderBufferInternal(GlJobChainHandle& jobs,
+	void bindShaderBufferInternal(GlCommandBufferHandle& commands,
 		I32 offset, I32 size, U32 bindingPoint);
 		I32 offset, I32 size, U32 bindingPoint);
 };
 };
 
 

+ 4 - 8
include/anki/gl/GlClientBuffer.h

@@ -18,15 +18,12 @@ namespace anki {
 class GlClientBuffer: public NonCopyable
 class GlClientBuffer: public NonCopyable
 {
 {
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
-
 	/// Default constructor
 	/// Default constructor
 	GlClientBuffer()
 	GlClientBuffer()
 	{}
 	{}
 
 
 	/// Create the buffer and allocate memory for the chain's allocator
 	/// Create the buffer and allocate memory for the chain's allocator
-	GlClientBuffer(const GlJobChainAllocator<U8>& chainAlloc, PtrSize size)
+	GlClientBuffer(const GlCommandBufferAllocator<U8>& chainAlloc, PtrSize size)
 		: m_alloc(chainAlloc)
 		: m_alloc(chainAlloc)
 	{
 	{
 		ANKI_ASSERT(size > 0);
 		ANKI_ASSERT(size > 0);
@@ -54,7 +51,6 @@ public:
 	{
 	{
 		destroy();
 		destroy();
 	}
 	}
-	/// @}
 
 
 	/// Move
 	/// Move
 	GlClientBuffer& operator=(GlClientBuffer&& b)
 	GlClientBuffer& operator=(GlClientBuffer&& b)
@@ -70,7 +66,7 @@ public:
 		if(!m_preallocated)
 		if(!m_preallocated)
 		{
 		{
 			m_alloc = b.m_alloc;
 			m_alloc = b.m_alloc;
-			b.m_alloc = GlJobChainAllocator<U8>();
+			b.m_alloc = GlCommandBufferAllocator<U8>();
 		}
 		}
 		return *this;
 		return *this;
 	}
 	}
@@ -90,7 +86,7 @@ public:
 	}
 	}
 
 
 	/// Return the allocator
 	/// Return the allocator
-	GlJobChainAllocator<U8> getAllocator() const
+	GlCommandBufferAllocator<U8> getAllocator() const
 	{
 	{
 		ANKI_ASSERT(!m_preallocated);
 		ANKI_ASSERT(!m_preallocated);
 		return m_alloc;
 		return m_alloc;
@@ -99,7 +95,7 @@ public:
 private:
 private:
 	void* m_ptr = nullptr;
 	void* m_ptr = nullptr;
 	U32 m_size = 0;
 	U32 m_size = 0;
-	GlJobChainAllocator<U8> m_alloc;
+	GlCommandBufferAllocator<U8> m_alloc;
 	Bool8 m_preallocated;
 	Bool8 m_preallocated;
 
 
 	void destroy()
 	void destroy()

+ 3 - 3
include/anki/gl/GlClientBufferHandle.h

@@ -12,7 +12,7 @@ namespace anki {
 
 
 // Forward
 // Forward
 class GlClientBuffer;
 class GlClientBuffer;
-class GlJobChainHandle;
+class GlCommandBufferHandle;
 
 
 /// @addtogroup opengl_other
 /// @addtogroup opengl_other
 /// @{
 /// @{
@@ -28,12 +28,12 @@ public:
 	GlClientBufferHandle();
 	GlClientBufferHandle();
 
 
 	/// Create the buffer using preallocated memory or memory from the chain
 	/// Create the buffer using preallocated memory or memory from the chain
-	/// @param chain The job chain this client memory belongs to
+	/// @param chain The command buffer this client memory belongs to
 	/// @param size The size of the buffer
 	/// @param size The size of the buffer
 	/// @param preallocatedMem Preallocated memory. Can be nullptr
 	/// @param preallocatedMem Preallocated memory. Can be nullptr
 	/// @return The address of the new memory
 	/// @return The address of the new memory
 	GlClientBufferHandle(
 	GlClientBufferHandle(
-		GlJobChainHandle& chain, PtrSize size, void* preallocatedMem);
+		GlCommandBufferHandle& chain, PtrSize size, void* preallocatedMem);
 
 
 	~GlClientBufferHandle();
 	~GlClientBufferHandle();
 	/// @}
 	/// @}

+ 170 - 0
include/anki/gl/GlCommandBuffer.h

@@ -0,0 +1,170 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#ifndef ANKI_GL_GL_COMMAND_BUFFER_H
+#define ANKI_GL_GL_COMMAND_BUFFER_H
+
+#include "anki/gl/GlCommon.h"
+#include "anki/util/Assert.h"
+#include "anki/util/Allocator.h"
+
+namespace anki {
+
+// Forward 
+class GlQueue;
+class GlCommandBuffer;
+
+/// @addtogroup opengl_private
+/// @{
+
+/// The base of all GL commands
+class GlCommand
+{
+public:
+	GlCommand* m_nextCommand = nullptr;
+
+	virtual ~GlCommand()
+	{}
+
+	/// Execute command
+	virtual void operator()(GlCommandBuffer*) = 0;
+};
+
+/// A common command that deletes an object
+template<typename T, typename TAlloc>
+class GlDeleteObjectCommand: public GlCommand
+{
+public:
+	T* m_ptr;
+	TAlloc m_alloc;
+
+	GlDeleteObjectCommand(T* ptr, TAlloc alloc)
+		: m_ptr(ptr), m_alloc(alloc)
+	{
+		ANKI_ASSERT(m_ptr);
+	}
+
+	void operator()(GlCommandBuffer*)
+	{
+		m_alloc.deleteInstance(m_ptr);
+	}
+};
+
+/// Command buffer initialization hints. They are used to optimize the allocators
+/// of a command buffer
+class GlCommandBufferInitHints
+{
+	friend class GlCommandBuffer;
+
+private:
+	static const PtrSize m_maxChunkSize = 4 * 1024 * 1024; // 1MB
+
+	PtrSize m_chunkSize = 1024;
+};
+
+/// A number of GL commands organized in a chain
+class GlCommandBuffer: public NonCopyable
+{
+public:
+	/// Default constructor
+	/// @param server The command buffers server
+	/// @param hints Hints to optimize the command's allocator
+	GlCommandBuffer(GlQueue* server, 
+		const GlCommandBufferInitHints& hints);
+
+	/// Move
+	GlCommandBuffer(GlCommandBuffer&& b)
+	{
+		*this = std::move(b);
+	}
+
+	~GlCommandBuffer()
+	{
+		destroy();
+	}
+
+	/// Move
+	GlCommandBuffer& operator=(GlCommandBuffer&& b);
+
+	/// Get he allocator
+	GlCommandBufferAllocator<U8> getAllocator() const
+	{
+		return m_alloc;
+	}
+
+	GlGlobalHeapAllocator<U8> getGlobalAllocator() const;
+
+	GlQueue& getQueue()
+	{
+		return *m_server;
+	}
+
+	const GlQueue& getQueue() const
+	{
+		return *m_server;
+	}
+
+	/// Compute initialization hints
+	GlCommandBufferInitHints computeInitHints() const;
+
+	/// Create a new command and add it to the chain
+	template<typename TCommand, typename... TArgs>
+	void pushBackNewCommand(TArgs&&... args)
+	{
+		ANKI_ASSERT(m_immutable == false);
+		TCommand* newCommand = 
+			m_alloc.template newInstance<TCommand>(std::forward<TArgs>(args)...);
+
+		if(m_firstCommand != nullptr)
+		{
+			ANKI_ASSERT(m_lastCommand != nullptr);
+			ANKI_ASSERT(m_lastCommand->m_nextCommand == nullptr);
+			m_lastCommand->m_nextCommand = newCommand;
+			m_lastCommand = newCommand;
+		}
+		else
+		{
+			m_firstCommand = newCommand;
+			m_lastCommand = newCommand;
+		}
+	}
+
+	/// Execute all commands
+	void executeAllCommands();
+
+	/// Fake that it's been executed
+	void makeExecuted()
+	{
+#if ANKI_DEBUG
+		m_executed = true;
+#endif
+	}
+
+	/// Make immutable
+	void makeImmutable()
+	{
+		m_immutable = true;
+	}
+
+private:
+	GlQueue* m_server;
+	GlCommand* m_firstCommand = nullptr;
+	GlCommand* m_lastCommand = nullptr;
+	GlCommandBufferAllocator<U8> m_alloc;
+	Bool8 m_immutable = false;
+
+#if ANKI_DEBUG
+	Bool8 m_executed = false;
+#endif
+
+	void destroy();
+};
+
+/// @}
+
+} // end namespace anki
+
+#endif
+

+ 31 - 33
include/anki/gl/GlJobChainHandle.h → include/anki/gl/GlCommandBufferHandle.h

@@ -3,53 +3,50 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#ifndef ANKI_GL_GL_JOB_CHAIN_HANDLE_H
-#define ANKI_GL_GL_JOB_CHAIN_HANDLE_H
+#ifndef ANKI_GL_GL_COMMAND_BUFFER_HANDLE_H
+#define ANKI_GL_GL_COMMAND_BUFFER_HANDLE_H
 
 
 #include "anki/gl/GlHandle.h"
 #include "anki/gl/GlHandle.h"
-#include "anki/gl/GlJobChain.h"
+#include "anki/gl/GlCommandBuffer.h"
 
 
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class GlManager;
+class GlDevice;
 class GlTextureHandle;
 class GlTextureHandle;
 
 
 /// @addtogroup opengl_other
 /// @addtogroup opengl_other
 /// @{
 /// @{
 
 
-/// Job chain handle
-class GlJobChainHandle: public GlHandle<GlJobChain>
+/// Command buffer handle
+class GlCommandBufferHandle: public GlHandle<GlCommandBuffer>
 {
 {
 public:
 public:
-	typedef GlHandle<GlJobChain> Base;
+	using Base = GlHandle<GlCommandBuffer>;
 	using UserCallback = void(*)(void*);
 	using UserCallback = void(*)(void*);
 
 
-	/// @name Constructors/Destructor
-	/// @{
-	GlJobChainHandle();
+	GlCommandBufferHandle();
 
 
-	/// Create job chain
-	explicit GlJobChainHandle(GlManager* gl, 
-		GlJobChainInitHints hints = GlJobChainInitHints());
+	/// Create command buffer
+	explicit GlCommandBufferHandle(GlDevice* gl, 
+		GlCommandBufferInitHints hints = GlCommandBufferInitHints());
 
 
-	~GlJobChainHandle();
-	/// @}
+	~GlCommandBufferHandle();
 
 
-	/// Add a user job at the end of the chain
-	void pushBackUserJob(UserCallback callback, void* data);
+	/// Add a user command at the end of the command buffer
+	void pushBackUserCommand(UserCallback callback, void* data);
 
 
-	/// Add another job chain for execution
-	void pushBackOtherJobChain(GlJobChainHandle& jobs);
+	/// Add another command buffer for execution
+	void pushBackOtherCommandBuffer(GlCommandBufferHandle& commands);
 
 
-	/// Flush chain for deffered deletion
+	/// Flush command buffer for deffered deletion
 	void flush();
 	void flush();
 
 
 	/// Flush and wait to finish
 	/// Flush and wait to finish
 	void finish();
 	void finish();
 
 
 	/// Compute initialization hints
 	/// Compute initialization hints
-	GlJobChainInitHints computeInitHints() const
+	GlCommandBufferInitHints computeInitHints() const
 	{
 	{
 		return _get().computeInitHints();
 		return _get().computeInitHints();
 	}
 	}
@@ -137,7 +134,7 @@ public:
 
 
 	/// @privatesection
 	/// @privatesection
 	/// @{
 	/// @{
-	GlJobChainAllocator<U8> _getAllocator() const
+	GlCommandBufferAllocator<U8> _getAllocator() const
 	{
 	{
 		return _get().getAllocator();
 		return _get().getAllocator();
 	}
 	}
@@ -147,27 +144,28 @@ public:
 		return _get().getGlobalAllocator();
 		return _get().getGlobalAllocator();
 	}
 	}
 
 
-	GlJobManager& _getJobManager()
+	GlQueue& _getQueue()
 	{
 	{
-		return _get().getJobManager();
+		return _get().getQueue();
 	}
 	}
 
 
-	const GlJobManager& _getJobManager() const
+	const GlQueue& _getQueue() const
 	{
 	{
-		return _get().getJobManager();
+		return _get().getQueue();
 	}
 	}
 
 
-	/// Add a new job to the list
-	template<typename TJob, typename... TArgs>
-	void _pushBackNewJob(TArgs&&... args)
+	/// Add a new command to the list
+	template<typename TCommand, typename... TArgs>
+	void _pushBackNewCommand(TArgs&&... args)
 	{
 	{
-		_get().template pushBackNewJob<TJob>(std::forward<TArgs>(args)...);
+		_get().template pushBackNewCommand<TCommand>(
+			std::forward<TArgs>(args)...);
 	}
 	}
 
 
-	/// Execute all jobs
-	void _executeAllJobs()
+	/// Execute all commands
+	void _executeAllCommands()
 	{
 	{
-		_get().executeAllJobs();
+		_get().executeAllCommands();
 	}
 	}
 	/// @}
 	/// @}
 };
 };

+ 5 - 5
include/anki/gl/GlCommon.h

@@ -31,7 +31,7 @@
 #	error "See file"
 #	error "See file"
 #endif
 #endif
 
 
-#define ANKI_JOB_MANAGER_DISABLE_ASYNC 0
+#define ANKI_QUEUE_DISABLE_ASYNC 0
 
 
 namespace anki {
 namespace anki {
 
 
@@ -42,9 +42,9 @@ class GlProgramBlock;
 /// @addtogroup opengl_private
 /// @addtogroup opengl_private
 /// @{
 /// @{
 
 
-/// The type of the allocator of GlJobChain
+/// The type of the allocator of GlCommandBuffer
 template<typename T>
 template<typename T>
-using GlJobChainAllocator = ChainAllocator<T>;
+using GlCommandBufferAllocator = ChainAllocator<T>;
 
 
 /// The type of the allocator for heap allocations
 /// The type of the allocator for heap allocations
 template<typename T>
 template<typename T>
@@ -203,12 +203,12 @@ private:
 	void writeClientMemorySanityChecks(void* buffBase, U32 buffSize,
 	void writeClientMemorySanityChecks(void* buffBase, U32 buffSize,
 		const T arr[], U32 size) const;
 		const T arr[], U32 size) const;
 
 
-	/// Do the actual job of setClientMemory
+	/// Do the actual command of setClientMemory
 	template<typename T>
 	template<typename T>
 	void writeClientMemoryInternal(
 	void writeClientMemoryInternal(
 		void* buff, U32 buffSize, const T arr[], U32 size) const;
 		void* buff, U32 buffSize, const T arr[], U32 size) const;
 
 
-	/// Do the actual job of setClientMemory for matrices
+	/// Do the actual command of setClientMemory for matrices
 	template<typename Mat, typename Vec>
 	template<typename Mat, typename Vec>
 	void writeClientMemoryInternalMatrix(void* buff, U32 buffSize,
 	void writeClientMemoryInternalMatrix(void* buff, U32 buffSize,
 		const Mat arr[], U32 size) const;
 		const Mat arr[], U32 size) const;

+ 2 - 2
include/anki/gl/GlContainerHandle.h

@@ -7,7 +7,7 @@
 #define ANKI_GL_GL_CONTAINER_HANDLE_H
 #define ANKI_GL_GL_CONTAINER_HANDLE_H
 
 
 #include "anki/gl/GlHandle.h"
 #include "anki/gl/GlHandle.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlDevice.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -30,7 +30,7 @@ protected:
 
 
 		if(state == GlHandleState::TO_BE_CREATED)
 		if(state == GlHandleState::TO_BE_CREATED)
 		{
 		{
-			Base::_getManager()._getJobManager().syncClientServer();
+			Base::_getManager()._getQueue().syncClientServer();
 			ANKI_ASSERT(Base::_getState() > GlHandleState::TO_BE_CREATED);
 			ANKI_ASSERT(Base::_getState() > GlHandleState::TO_BE_CREATED);
 		}
 		}
 	}
 	}

+ 13 - 13
include/anki/gl/GlManager.h → include/anki/gl/GlDevice.h

@@ -3,12 +3,12 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#ifndef ANKI_GL_GL_MANAGER_H
-#define ANKI_GL_GL_MANAGER_H
+#ifndef ANKI_GL_GL_DEVICE_H
+#define ANKI_GL_GL_DEVICE_H
 
 
 #include "anki/gl/GlCommon.h"
 #include "anki/gl/GlCommon.h"
 #include "anki/util/Singleton.h"
 #include "anki/util/Singleton.h"
-#include "anki/gl/GlJobManager.h"
+#include "anki/gl/GlQueue.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -16,17 +16,17 @@ namespace anki {
 /// @{
 /// @{
 
 
 /// Common stuff for all GL contexts
 /// Common stuff for all GL contexts
-class GlManager
+class GlDevice
 {
 {
 public:
 public:
-	/// @see GlJobManager::start
-	GlManager(
+	/// @see GlQueue::start
+	GlDevice(
 		GlCallback makeCurrentCallback, void* context,
 		GlCallback makeCurrentCallback, void* context,
 		GlCallback swapBuffersCallback, void* swapBuffersCbData,
 		GlCallback swapBuffersCallback, void* swapBuffersCbData,
 		Bool registerDebugMessages,
 		Bool registerDebugMessages,
 		AllocAlignedCallback alloc, void* allocUserData);
 		AllocAlignedCallback alloc, void* allocUserData);
 
 
-	~GlManager()
+	~GlDevice()
 	{
 	{
 		destroy();
 		destroy();
 	}
 	}
@@ -47,26 +47,26 @@ public:
 		return m_alloc;
 		return m_alloc;
 	}
 	}
 
 
-	GlJobManager& _getJobManager() 
+	GlQueue& _getQueue() 
 	{
 	{
-		return *m_jobManager;
+		return *m_queue;
 	}
 	}
 
 
-	const GlJobManager& _getJobManager() const
+	const GlQueue& _getQueue() const
 	{
 	{
-		return *m_jobManager;
+		return *m_queue;
 	}
 	}
 	/// @}
 	/// @}
 
 
 private:
 private:
-	GlJobManager* m_jobManager;
+	GlQueue* m_queue;
 	HeapAllocator<U8> m_alloc; ///< Keep it last to be deleted last
 	HeapAllocator<U8> m_alloc; ///< Keep it last to be deleted last
 
 
 	void destroy();
 	void destroy();
 };
 };
 
 
 /// Singleton for common GL stuff
 /// Singleton for common GL stuff
-typedef SingletonInit<GlManager> GlManagerSingleton;
+typedef SingletonInit<GlDevice> GlDeviceSingleton;
 
 
 /// @}
 /// @}
 
 

+ 6 - 9
include/anki/gl/GlFramebufferHandle.h

@@ -12,7 +12,7 @@
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class GlJobChainHandle;
+class GlCommandBufferHandle;
 
 
 /// @addtogroup opengl_other
 /// @addtogroup opengl_other
 /// @{
 /// @{
@@ -24,31 +24,28 @@ public:
 	using Base = GlContainerHandle<GlFramebuffer>;
 	using Base = GlContainerHandle<GlFramebuffer>;
 	using Attachment = GlFramebuffer::Attachment;
 	using Attachment = GlFramebuffer::Attachment;
 
 
-	/// @name Contructors/Destructor
-	/// @{
 	GlFramebufferHandle();
 	GlFramebufferHandle();
 
 
 	/// Create a framebuffer
 	/// Create a framebuffer
 	explicit GlFramebufferHandle(
 	explicit GlFramebufferHandle(
-		GlJobChainHandle& jobs,
+		GlCommandBufferHandle& commands,
 		const std::initializer_list<Attachment>& attachments);
 		const std::initializer_list<Attachment>& attachments);
 
 
 	~GlFramebufferHandle();
 	~GlFramebufferHandle();
-	/// @}
 
 
 	/// Bind it to the state
 	/// Bind it to the state
-	/// @param jobs The job chain
+	/// @param commands The command buffer
 	/// @param invalidate If true invalidate the FB after binding it
 	/// @param invalidate If true invalidate the FB after binding it
-	void bind(GlJobChainHandle& jobs, Bool invalidate);
+	void bind(GlCommandBufferHandle& commands, Bool invalidate);
 
 
 	/// Blit another framebuffer to this
 	/// Blit another framebuffer to this
-	/// @param[in, out] jobs The job chain
+	/// @param[in, out] commands The command buffer
 	/// @param[in] b The sorce framebuffer
 	/// @param[in] b The sorce framebuffer
 	/// @param[in] sourceRect The source rectangle
 	/// @param[in] sourceRect The source rectangle
 	/// @param[in] destRect The destination rectangle
 	/// @param[in] destRect The destination rectangle
 	/// @param attachmentMask The attachments to blit
 	/// @param attachmentMask The attachments to blit
 	/// @param linear Perform linean filtering
 	/// @param linear Perform linean filtering
-	void blit(GlJobChainHandle& jobs,
+	void blit(GlCommandBufferHandle& commands,
 		const GlFramebufferHandle& b, 
 		const GlFramebufferHandle& b, 
 		const Array<U32, 4>& sourceRect,
 		const Array<U32, 4>& sourceRect,
 		const Array<U32, 4>& destRect, 
 		const Array<U32, 4>& destRect, 

+ 10 - 10
include/anki/gl/GlHandle.h

@@ -11,7 +11,7 @@
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class GlManager;
+class GlDevice;
 
 
 /// @addtogroup opengl_private
 /// @addtogroup opengl_private
 /// @{
 /// @{
@@ -31,7 +31,7 @@ template<typename T, typename TAlloc>
 class GlHandleDefaultDeleter
 class GlHandleDefaultDeleter
 {
 {
 public:
 public:
-	void operator()(T* ptr, TAlloc alloc, GlManager*)
+	void operator()(T* ptr, TAlloc alloc, GlDevice*)
 	{
 	{
 		alloc.deleteInstance(ptr);
 		alloc.deleteInstance(ptr);
 	}
 	}
@@ -51,7 +51,7 @@ public:
 	/// @name Constructor/Destructor
 	/// @name Constructor/Destructor
 	/// @{
 	/// @{
 	GlHandle()
 	GlHandle()
-		: m_cb(nullptr)
+	:	m_cb(nullptr)
 	{}
 	{}
 
 
 	/// Create an object and initialize the handle with that
 	/// Create an object and initialize the handle with that
@@ -64,7 +64,7 @@ public:
 	///                deleters
 	///                deleters
 	/// @param args The arguments to pass to the object's constructor
 	/// @param args The arguments to pass to the object's constructor
 	template<typename TAlloc, typename TDeleter, typename... TArgs>
 	template<typename TAlloc, typename TDeleter, typename... TArgs>
-	GlHandle(GlManager* manager, TAlloc alloc, TDeleter del, TArgs&&... args)
+	GlHandle(GlDevice* manager, TAlloc alloc, TDeleter del, TArgs&&... args)
 	{
 	{
 		// Create the object
 		// Create the object
 		T* ptr = alloc.template newInstance<T>(std::forward<TArgs>(args)...);
 		T* ptr = alloc.template newInstance<T>(std::forward<TArgs>(args)...);
@@ -104,13 +104,13 @@ public:
 	}
 	}
 
 
 	GlHandle(const GlHandle& b)
 	GlHandle(const GlHandle& b)
-		: GlHandle()
+	:	GlHandle()
 	{
 	{
 		*this = b;
 		*this = b;
 	}
 	}
 
 
 	GlHandle(GlHandle&& b)
 	GlHandle(GlHandle&& b)
-		: GlHandle()
+	:	GlHandle()
 	{
 	{
 		*this = std::move(b);
 		*this = std::move(b);
 	}
 	}
@@ -229,7 +229,7 @@ public:
 		return m_cb->getStateAtomically(&newVal);
 		return m_cb->getStateAtomically(&newVal);
 	}
 	}
 
 
-	GlManager& _getManager() const
+	GlDevice& _getManager() const
 	{
 	{
 		ANKI_ASSERT(m_cb != nullptr && m_cb->getManager() != nullptr);
 		ANKI_ASSERT(m_cb != nullptr && m_cb->getManager() != nullptr);
 		return *m_cb->getManager(); 
 		return *m_cb->getManager(); 
@@ -255,7 +255,7 @@ private:
 		virtual void deleteSelf() = 0;
 		virtual void deleteSelf() = 0;
 
 
 		/// The container handles want the manager
 		/// The container handles want the manager
-		virtual GlManager* getManager() const
+		virtual GlDevice* getManager() const
 		{
 		{
 			return nullptr;
 			return nullptr;
 		}
 		}
@@ -309,7 +309,7 @@ private:
 		YDeleter m_del;
 		YDeleter m_del;
 
 
 		/// @note Its mutable because we want read/write access to it
 		/// @note Its mutable because we want read/write access to it
-		mutable GlManager* m_manager; 
+		mutable GlDevice* m_manager; 
 
 
 		std::atomic<GlHandleState> m_state;
 		std::atomic<GlHandleState> m_state;
 		
 		
@@ -325,7 +325,7 @@ private:
 			m_alloc.deleteInstance(this);
 			m_alloc.deleteInstance(this);
 		}
 		}
 
 
-		GlManager* getManager() const override
+		GlDevice* getManager() const override
 		{
 		{
 			return m_manager;
 			return m_manager;
 		}
 		}

+ 10 - 10
include/anki/gl/GlHandleDeferredDeleter.h

@@ -6,8 +6,8 @@
 #ifndef ANKI_GL_GL_HANDLE_DEFERRED_DELETER_H
 #ifndef ANKI_GL_GL_HANDLE_DEFERRED_DELETER_H
 #define ANKI_GL_GL_HANDLE_DEFERRED_DELETER_H
 #define ANKI_GL_GL_HANDLE_DEFERRED_DELETER_H
 
 
-#include "anki/gl/GlManager.h"
-#include "anki/gl/GlJobChainHandle.h"
+#include "anki/gl/GlDevice.h"
+#include "anki/gl/GlCommandBufferHandle.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -17,24 +17,24 @@ namespace anki {
 /// Common deleter for objects that require deferred deletion. Some handles
 /// Common deleter for objects that require deferred deletion. Some handles
 /// might get releaced in various threads but their underlying GL object should 
 /// might get releaced in various threads but their underlying GL object should 
 /// get deleted in the server thread (where the context is). This deleter will
 /// get deleted in the server thread (where the context is). This deleter will
-/// fire a server job with the deletion if the handle gets realeased thread 
+/// fire a server command with the deletion if the handle gets realeased thread 
 /// other than the server thread.
 /// other than the server thread.
-template<typename T, typename TAlloc, typename TDeleteJob>
+template<typename T, typename TAlloc, typename TDeleteCommand>
 class GlHandleDeferredDeleter
 class GlHandleDeferredDeleter
 {
 {
 public:
 public:
-	void operator()(T* obj, TAlloc alloc, GlManager* manager)
+	void operator()(T* obj, TAlloc alloc, GlDevice* manager)
 	{
 	{
 		ANKI_ASSERT(obj);
 		ANKI_ASSERT(obj);
 		ANKI_ASSERT(manager);
 		ANKI_ASSERT(manager);
 		
 		
-		/// If not the server thread then create a job for the server thread
-		if(!manager->_getJobManager().isServerThread())
+		/// If not the server thread then create a command for the server thread
+		if(!manager->_getQueue().isServerThread())
 		{
 		{
-			GlJobChainHandle jobs(manager);
+			GlCommandBufferHandle commands(manager);
 			
 			
-			jobs.template _pushBackNewJob<TDeleteJob>(obj, alloc);
-			jobs.flush();
+			commands.template _pushBackNewCommand<TDeleteCommand>(obj, alloc);
+			commands.flush();
 		}
 		}
 		else
 		else
 		{
 		{

+ 0 - 169
include/anki/gl/GlJobChain.h

@@ -1,169 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#ifndef ANKI_GL_GL_JOB_CHAIN_H
-#define ANKI_GL_GL_JOB_CHAIN_H
-
-#include "anki/gl/GlCommon.h"
-#include "anki/util/Assert.h"
-#include "anki/util/Allocator.h"
-
-namespace anki {
-
-// Forward 
-class GlJobManager;
-class GlJobChain;
-
-/// @addtogroup opengl_private
-/// @{
-
-/// The base of all GL jobs
-class GlJob
-{
-public:
-	GlJob* nextJob = nullptr;
-
-	virtual ~GlJob()
-	{}
-
-	/// Execute job
-	virtual void operator()(GlJobChain*) = 0;
-};
-
-/// A common job that deletes an object
-template<typename T, typename TAlloc>
-class GlDeleteObjectJob: public GlJob
-{
-public:
-	T* m_ptr;
-	TAlloc m_alloc;
-
-	GlDeleteObjectJob(T* ptr, TAlloc alloc)
-		: m_ptr(ptr), m_alloc(alloc)
-	{
-		ANKI_ASSERT(m_ptr);
-	}
-
-	void operator()(GlJobChain*)
-	{
-		m_alloc.deleteInstance(m_ptr);
-	}
-};
-
-/// Job chain initialization hints. They are used to optimize the allocators
-/// of a job chain
-class GlJobChainInitHints
-{
-	friend class GlJobChain;
-
-private:
-	static const PtrSize m_maxChunkSize = 4 * 1024 * 1024; // 1MB
-
-	PtrSize m_chunkSize = 1024;
-};
-
-/// A number of GL jobs organized in a chain
-class GlJobChain: public NonCopyable
-{
-public:
-	/// Default constructor
-	/// @param server The job chains server
-	/// @param hints Hints to optimize the job's allocator
-	GlJobChain(GlJobManager* server, const GlJobChainInitHints& hints);
-
-	/// Move
-	GlJobChain(GlJobChain&& b)
-	{
-		*this = std::move(b);
-	}
-
-	~GlJobChain()
-	{
-		destroy();
-	}
-
-	/// Move
-	GlJobChain& operator=(GlJobChain&& b);
-
-	/// Get he allocator
-	GlJobChainAllocator<U8> getAllocator() const
-	{
-		return m_alloc;
-	}
-
-	GlGlobalHeapAllocator<U8> getGlobalAllocator() const;
-
-	GlJobManager& getJobManager()
-	{
-		return *m_server;
-	}
-
-	const GlJobManager& getJobManager() const
-	{
-		return *m_server;
-	}
-
-	/// Compute initialization hints
-	GlJobChainInitHints computeInitHints() const;
-
-	/// Create a new job and add it to the chain
-	template<typename TJob, typename... TArgs>
-	void pushBackNewJob(TArgs&&... args)
-	{
-		ANKI_ASSERT(m_immutable == false);
-		TJob* newJob = 
-			m_alloc.template newInstance<TJob>(std::forward<TArgs>(args)...);
-
-		if(m_firstJob != nullptr)
-		{
-			ANKI_ASSERT(m_lastJob != nullptr);
-			ANKI_ASSERT(m_lastJob->nextJob == nullptr);
-			m_lastJob->nextJob = newJob;
-			m_lastJob = newJob;
-		}
-		else
-		{
-			m_firstJob = newJob;
-			m_lastJob = newJob;
-		}
-	}
-
-	/// Execute all jobs
-	void executeAllJobs();
-
-	/// Fake that it's been executed
-	void makeExecuted()
-	{
-#if ANKI_DEBUG
-		m_executed = true;
-#endif
-	}
-
-	/// Make immutable
-	void makeImmutable()
-	{
-		m_immutable = true;
-	}
-
-private:
-	GlJobManager* m_server;
-	GlJob* m_firstJob = nullptr;
-	GlJob* m_lastJob = nullptr;
-	GlJobChainAllocator<U8> m_alloc;
-	Bool8 m_immutable = false;
-
-#if ANKI_DEBUG
-	Bool8 m_executed = false;
-#endif
-
-	void destroy();
-};
-
-/// @}
-
-} // end namespace anki
-
-#endif
-

+ 6 - 6
include/anki/gl/GlOperations.h

@@ -18,7 +18,7 @@ namespace anki {
 /// A GL drawcall for elements
 /// A GL drawcall for elements
 class GlDrawcallElements
 class GlDrawcallElements
 {
 {
-	friend class GlDrawElementsJob;
+	friend class GlDrawElementsCommand;
 
 
 public:
 public:
 	/// Indirect structure
 	/// Indirect structure
@@ -94,7 +94,7 @@ public:
 	}
 	}
 
 
 	/// Execute the drawcall
 	/// Execute the drawcall
-	void draw(GlJobChainHandle& jobs);
+	void draw(GlCommandBufferHandle& commands);
 
 
 private:
 private:
 	class IndirectView
 	class IndirectView
@@ -128,14 +128,14 @@ private:
 		IndirectView m_indirect;
 		IndirectView m_indirect;
 	};
 	};
 
 
-	/// Execute the job. Called by the server
+	/// Execute the command. Called by the server
 	void exec();
 	void exec();
 };
 };
 
 
 /// A GL drawcall for arrays
 /// A GL drawcall for arrays
 class GlDrawcallArrays
 class GlDrawcallArrays
 {
 {
-	friend class GlDrawArraysJob;
+	friend class GlDrawArraysCommand;
 
 
 public:
 public:
 	/// Indirect structure
 	/// Indirect structure
@@ -197,7 +197,7 @@ public:
 	}
 	}
 
 
 	/// Execute the drawcall
 	/// Execute the drawcall
-	void draw(GlJobChainHandle& jobs);
+	void draw(GlCommandBufferHandle& commands);
 
 
 private:
 private:
 	/// The GL primitive type (eg GL_POINTS). Need to set it
 	/// The GL primitive type (eg GL_POINTS). Need to set it
@@ -221,7 +221,7 @@ private:
 	/// Indirect buffer stride
 	/// Indirect buffer stride
 	U32 m_stride;
 	U32 m_stride;
 
 
-	/// Execute the job. Called by the server
+	/// Execute the command. Called by the server
 	void exec();
 	void exec();
 };
 };
 
 

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

@@ -33,7 +33,7 @@ public:
 	GlProgramHandle();
 	GlProgramHandle();
 
 
 	/// Create program
 	/// Create program
-	explicit GlProgramHandle(GlJobChainHandle& jobs, 
+	explicit GlProgramHandle(GlCommandBufferHandle& commands, 
 		GLenum shaderType, const GlClientBufferHandle& source);
 		GLenum shaderType, const GlClientBufferHandle& source);
 
 
 	~GlProgramHandle();
 	~GlProgramHandle();

+ 6 - 6
include/anki/gl/GlProgramPipelineHandle.h

@@ -11,7 +11,7 @@
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class GlJobChainHandle;
+class GlCommandBufferHandle;
 class GlProgramPipeline;
 class GlProgramPipeline;
 class GlProgramHandle;
 class GlProgramHandle;
 
 
@@ -30,28 +30,28 @@ public:
 
 
 	/// Create a pipeline
 	/// Create a pipeline
 	explicit GlProgramPipelineHandle(
 	explicit GlProgramPipelineHandle(
-		GlJobChainHandle& jobs,
+		GlCommandBufferHandle& commands,
 		const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
 		const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
 	{
 	{
-		commonConstructor(jobs, progsBegin, progsEnd);
+		commonConstructor(commands, progsBegin, progsEnd);
 	}
 	}
 
 
 	/// Create using initializer list
 	/// Create using initializer list
 	explicit GlProgramPipelineHandle(
 	explicit GlProgramPipelineHandle(
-		GlJobChainHandle& jobs,
+		GlCommandBufferHandle& commands,
 		std::initializer_list<GlProgramHandle> progs);
 		std::initializer_list<GlProgramHandle> progs);
 
 
 	~GlProgramPipelineHandle();
 	~GlProgramPipelineHandle();
 	/// @}
 	/// @}
 
 
 	/// Bind it to the state
 	/// Bind it to the state
-	void bind(GlJobChainHandle& jobs);
+	void bind(GlCommandBufferHandle& commands);
 
 
 	/// Get an attached program. It may serialize
 	/// Get an attached program. It may serialize
 	GlProgramHandle getAttachedProgram(GLenum type) const;
 	GlProgramHandle getAttachedProgram(GLenum type) const;
 
 
 public:
 public:
-	void commonConstructor(GlJobChainHandle& jobs,
+	void commonConstructor(GlCommandBufferHandle& commands,
 		const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd);
 		const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd);
 };
 };
 
 

+ 21 - 21
include/anki/gl/GlJobManager.h → include/anki/gl/GlQueue.h

@@ -3,10 +3,10 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#ifndef ANKI_GL_GL_JOB_MANAGER_H
-#define ANKI_GL_GL_JOB_MANAGER_H
+#ifndef ANKI_GL_GL_QUEUE_H
+#define ANKI_GL_GL_QUEUE_H
 
 
-#include "anki/gl/GlJobChainHandle.h"
+#include "anki/gl/GlCommandBufferHandle.h"
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlState.h"
 #include "anki/gl/GlState.h"
 #include "anki/util/Thread.h"
 #include "anki/util/Thread.h"
@@ -14,33 +14,33 @@
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class GlManager;
+class GlDevice;
 
 
 /// @addtogroup opengl_private
 /// @addtogroup opengl_private
 /// @{
 /// @{
 
 
-/// Job manager. It's essentialy a queue of job chains waiting for execution 
-/// and a server
-class GlJobManager
+/// Command queue. It's essentialy a queue of command buffers waiting for 
+/// execution and a server
+class GlQueue
 {
 {
 public:
 public:
 	/// @name Contructors/Destructor
 	/// @name Contructors/Destructor
 	/// @{
 	/// @{
-	GlJobManager(GlManager* manager, 
+	GlQueue(GlDevice* manager, 
 		AllocAlignedCallback alloc, void* allocUserData);
 		AllocAlignedCallback alloc, void* allocUserData);
 
 
-	~GlJobManager();
+	~GlQueue();
 	/// @}
 	/// @}
 
 
 	/// @name Accessors
 	/// @name Accessors
 	/// @{
 	/// @{
-	GlManager& getManager()
+	GlDevice& getManager()
 	{
 	{
 		ANKI_ASSERT(m_manager);
 		ANKI_ASSERT(m_manager);
 		return *m_manager;
 		return *m_manager;
 	}
 	}
 
 
-	const GlManager& getManager() const
+	const GlDevice& getManager() const
 	{
 	{
 		ANKI_ASSERT(m_manager);
 		ANKI_ASSERT(m_manager);
 		return *m_manager;
 		return *m_manager;
@@ -77,11 +77,11 @@ public:
 	/// Stop the working thread
 	/// Stop the working thread
 	void stop();
 	void stop();
 
 
-	/// Push a job chain to the queue for deferred execution
-	void flushJobChain(GlJobChainHandle& jobs);
+	/// Push a command buffer to the queue for deferred execution
+	void flushCommandChain(GlCommandBufferHandle& commands);
 
 
-	/// Push a job chain to the queue and wait for it
-	void finishJobChain(GlJobChainHandle& jobs);
+	/// Push a command buffer to the queue and wait for it
+	void finishCommandChain(GlCommandBufferHandle& commands);
 
 
 	/// Sync the client and server
 	/// Sync the client and server
 	void syncClientServer();
 	void syncClientServer();
@@ -96,11 +96,11 @@ public:
 	void swapBuffers();
 	void swapBuffers();
 
 
 private:
 private:
-	GlManager* m_manager = nullptr;
+	GlDevice* m_manager = nullptr;
 	AllocAlignedCallback m_allocCb;
 	AllocAlignedCallback m_allocCb;
 	void* m_allocCbUserData;
 	void* m_allocCbUserData;
 
 
-	Array<GlJobChainHandle, 32> m_queue; ///< Job queue
+	Array<GlCommandBufferHandle, 32> m_queue; ///< Command queue
 	U64 m_tail; ///< Tail of queue
 	U64 m_tail; ///< Tail of queue
 	U64 m_head; ///< Head of queue. Points to the end
 	U64 m_head; ///< Head of queue. Points to the end
 	U8 m_renderingThreadSignal; ///< Signal to the thread
 	U8 m_renderingThreadSignal; ///< Signal to the thread
@@ -111,7 +111,7 @@ private:
 	void* m_ctx = nullptr; ///< Pointer to the system GL context
 	void* m_ctx = nullptr; ///< Pointer to the system GL context
 	GlCallback m_makeCurrent; ///< Making a context current
 	GlCallback m_makeCurrent; ///< Making a context current
 
 
-	GlJobChainHandle m_swapBuffersJobs;
+	GlCommandBufferHandle m_swapBuffersCommands;
 	GlCallback m_swapBuffersCallback;
 	GlCallback m_swapBuffersCallback;
 	void* m_swapBuffersCbData;
 	void* m_swapBuffersCbData;
 	std::condition_variable m_frameCondVar;
 	std::condition_variable m_frameCondVar;
@@ -123,9 +123,9 @@ private:
 	GlState m_state;
 	GlState m_state;
 	GLuint m_defaultVao;
 	GLuint m_defaultVao;
 
 
-	/// A special jobchain that is called every time we want to wait for the
-	/// server
-	GlJobChainHandle m_syncJobs;
+	/// A special command buffer that is called every time we want to wait for 
+	/// the server
+	GlCommandBufferHandle m_syncCommands;
 	GlClientSyncHandle m_sync;
 	GlClientSyncHandle m_sync;
 
 
 	String m_error;
 	String m_error;

+ 4 - 4
include/anki/gl/GlSyncHandles.h

@@ -12,7 +12,7 @@ namespace anki {
 
 
 // Forward
 // Forward
 class GlClientSync;
 class GlClientSync;
-class GlJobChainHandle;
+class GlCommandBufferHandle;
 
 
 /// @addtogroup opengl_other
 /// @addtogroup opengl_other
 /// @{
 /// @{
@@ -25,13 +25,13 @@ public:
 
 
 	GlClientSyncHandle();
 	GlClientSyncHandle();
 
 
-	GlClientSyncHandle(GlJobChainHandle& jobs);
+	GlClientSyncHandle(GlCommandBufferHandle& commands);
 
 
 	~GlClientSyncHandle();
 	~GlClientSyncHandle();
 
 
-	/// Fire a job that adds a waits for the client. The client should call 
+	/// Fire a command that adds a waits for the client. The client should call 
 	/// wait some time after this call or the server will keep waiting forever
 	/// wait some time after this call or the server will keep waiting forever
-	void sync(GlJobChainHandle& jobs);
+	void sync(GlCommandBufferHandle& commands);
 
 
 	/// Wait for the server. You need to call sync first or the client will
 	/// Wait for the server. You need to call sync first or the client will
 	/// keep waiting forever
 	/// keep waiting forever

+ 12 - 10
include/anki/gl/GlTextureHandle.h

@@ -41,22 +41,24 @@ public:
 	GlTextureHandle();
 	GlTextureHandle();
 
 
 	/// Create the texture
 	/// Create the texture
-	explicit GlTextureHandle(GlJobChainHandle& jobs, const Initializer& init);
+	explicit GlTextureHandle(GlCommandBufferHandle& commands, 
+		const Initializer& init);
 
 
 	~GlTextureHandle();
 	~GlTextureHandle();
 	/// @}
 	/// @}
 
 
 	/// Bind to a unit
 	/// Bind to a unit
-	void bind(GlJobChainHandle& jobs, U32 unit);
+	void bind(GlCommandBufferHandle& commands, U32 unit);
 
 
 	/// Change filtering type
 	/// Change filtering type
-	void setFilter(GlJobChainHandle& jobs, Filter filter);
+	void setFilter(GlCommandBufferHandle& commands, Filter filter);
 
 
 	/// Generate mips
 	/// Generate mips
-	void generateMipmaps(GlJobChainHandle& jobs);
+	void generateMipmaps(GlCommandBufferHandle& commands);
 
 
 	/// Set a texture parameter
 	/// Set a texture parameter
-	void setParameter(GlJobChainHandle& jobs, GLenum param, GLint value);
+	void setParameter(
+		GlCommandBufferHandle& commands, GLenum param, GLint value);
 
 
 	/// Get depth
 	/// Get depth
 	U32 getDepth() const;
 	U32 getDepth() const;
@@ -83,22 +85,22 @@ public:
 	GlSamplerHandle();
 	GlSamplerHandle();
 
 
 	/// Create the sampler
 	/// Create the sampler
-	explicit GlSamplerHandle(GlJobChainHandle& jobs);
+	explicit GlSamplerHandle(GlCommandBufferHandle& commands);
 
 
 	~GlSamplerHandle();
 	~GlSamplerHandle();
 	/// @}
 	/// @}
 
 
 	/// Bind to a unit
 	/// Bind to a unit
-	void bind(GlJobChainHandle& jobs, U32 unit);
+	void bind(GlCommandBufferHandle& commands, U32 unit);
 
 
 	/// Change filtering type
 	/// Change filtering type
-	void setFilter(GlJobChainHandle& jobs, Filter filter);
+	void setFilter(GlCommandBufferHandle& commands, Filter filter);
 
 
 	/// Set a texture parameter
 	/// Set a texture parameter
-	void setParameter(GlJobChainHandle& jobs, GLenum param, GLint value);
+	void setParameter(GlCommandBufferHandle& commands, GLenum param, GLint value);
 
 
 	/// Bind default sampler
 	/// Bind default sampler
-	static void bindDefault(GlJobChainHandle& jobs, U32 unit);
+	static void bindDefault(GlCommandBufferHandle& commands, U32 unit);
 };
 };
 
 
 /// @}
 /// @}

+ 22 - 18
include/anki/input/Input.h

@@ -15,7 +15,7 @@
 
 
 namespace anki {
 namespace anki {
 
 
-struct InputImpl;
+class InputImpl;
 class NativeWindow;
 class NativeWindow;
 
 
 /// Handle the input and other events
 /// Handle the input and other events
@@ -24,22 +24,27 @@ class NativeWindow;
 class Input
 class Input
 {
 {
 public:
 public:
-	enum Event
+	enum class Event: U8
 	{
 	{
 		WINDOW_FOCUS_LOST_EVENT,
 		WINDOW_FOCUS_LOST_EVENT,
 		WINDOW_FOCUS_GAINED_EVENT,
 		WINDOW_FOCUS_GAINED_EVENT,
 		WINDOW_CLOSED_EVENT,
 		WINDOW_CLOSED_EVENT,
-		EVENTS_COUNT
+		COUNT
 	};
 	};
 
 
-	Input()
+	Input(NativeWindow* nativeWindow)
 	{
 	{
 		reset();
 		reset();
+		init(nativeWindow);
+	}
+
+	~Input()
+	{
+		destroy();
+		ANKI_ASSERT(m_impl == nullptr);
+		ANKI_ASSERT(m_nativeWindow == nullptr);
 	}
 	}
-	~Input();
 
 
-	/// @name Acessors
-	/// @{
 	U getKey(KeyCode i) const
 	U getKey(KeyCode i) const
 	{
 	{
 		return m_keys[static_cast<U>(i)];
 		return m_keys[static_cast<U>(i)];
@@ -58,12 +63,8 @@ public:
 	/// Get the times an event was triggered and resets the counter
 	/// Get the times an event was triggered and resets the counter
 	U getEvent(Event eventId) const
 	U getEvent(Event eventId) const
 	{
 	{
-		return m_events[eventId];
+		return m_events[static_cast<U>(eventId)];
 	}
 	}
-	/// @}
-
-	/// Initialize the platform's input system
-	void init(NativeWindow* nativeWindow);
 
 
 	/// Reset the keys and mouse buttons
 	/// Reset the keys and mouse buttons
 	void reset();
 	void reset();
@@ -88,10 +89,11 @@ public:
 	/// Add a new event
 	/// Add a new event
 	void addEvent(Event eventId)
 	void addEvent(Event eventId)
 	{
 	{
-		++m_events[eventId];
+		++m_events[static_cast<U>(eventId)];
 	}
 	}
 
 
 private:
 private:
+	InputImpl* m_impl = nullptr;
 	NativeWindow* m_nativeWindow = nullptr;
 	NativeWindow* m_nativeWindow = nullptr;
 
 
 	/// @name Keys and btns
 	/// @name Keys and btns
@@ -101,7 +103,7 @@ private:
 	/// - 0 times: unpressed
 	/// - 0 times: unpressed
 	/// - 1 times: pressed once
 	/// - 1 times: pressed once
 	/// - >1 times: Kept pressed 'n' times continuously
 	/// - >1 times: Kept pressed 'n' times continuously
-	Array<U32, U(KeyCode::COUNT)> m_keys;
+	Array<U32, static_cast<U>(KeyCode::COUNT)> m_keys;
 
 
 	/// Mouse btns. Supporting 3 btns & wheel. @see keys
 	/// Mouse btns. Supporting 3 btns & wheel. @see keys
 	Array<U32, 8> m_mouseBtns;
 	Array<U32, 8> m_mouseBtns;
@@ -111,12 +113,14 @@ private:
 
 
 	Array<U8, EVENTS_COUNT> m_events;
 	Array<U8, EVENTS_COUNT> m_events;
 
 
-	std::shared_ptr<InputImpl> m_impl;
-
 	Bool8 m_lockCurs = false;
 	Bool8 m_lockCurs = false;
-};
 
 
-typedef Singleton<Input> InputSingleton;
+	/// Initialize the platform's input system
+	void init(NativeWindow* nativeWindow);
+
+	/// Destroy the platform specific input system
+	void destroy();
+};
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 2 - 2
include/anki/math/Functions.h

@@ -133,14 +133,14 @@ inline T mod(const T x, const T y)
 template<typename T>
 template<typename T>
 inline T abs(const T f)
 inline T abs(const T f)
 { 
 { 
-	return ::fabs(f);
+	return std::fabs(f);
 }
 }
 
 
 #define ANKI_SPECIALIZE_ABS_INT(type_) \
 #define ANKI_SPECIALIZE_ABS_INT(type_) \
 	template<> \
 	template<> \
 	inline type_ abs(const type_ f) \
 	inline type_ abs(const type_ f) \
 	{ \
 	{ \
-		return ::abs(f); \
+		return std::abs(f); \
 	}
 	}
 
 
 ANKI_SPECIALIZE_ABS_INT(I8)
 ANKI_SPECIALIZE_ABS_INT(I8)

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

@@ -28,7 +28,7 @@ private:
 	~Bs();
 	~Bs();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 };
 };
 
 
 /// @}
 /// @}

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

@@ -62,7 +62,7 @@ private:
 	~Dbg();
 	~Dbg();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 };
 };
 
 
 /// @}
 /// @}

+ 3 - 3
include/anki/renderer/DebugDrawer.h

@@ -31,14 +31,14 @@ public:
 	void drawCube(F32 size = 1.0);
 	void drawCube(F32 size = 1.0);
 	void drawLine(const Vec3& from, const Vec3& to, const Vec4& color);
 	void drawLine(const Vec3& from, const Vec3& to, const Vec4& color);
 
 
-	void prepareDraw(GlJobChainHandle& jobs)
+	void prepareDraw(GlCommandBufferHandle& jobs)
 	{
 	{
 		m_jobs = jobs;
 		m_jobs = jobs;
 	}
 	}
 
 
 	void finishDraw()
 	void finishDraw()
 	{
 	{
-		m_jobs = GlJobChainHandle(); // Release job chain
+		m_jobs = GlCommandBufferHandle(); // Release job chain
 	}
 	}
 
 
 	/// @name Render functions. Imitate the GL 1.1 immediate mode
 	/// @name Render functions. Imitate the GL 1.1 immediate mode
@@ -74,7 +74,7 @@ private:
 	ProgramResourcePointer m_frag;
 	ProgramResourcePointer m_frag;
 	ProgramResourcePointer m_vert;
 	ProgramResourcePointer m_vert;
 	GlProgramPipelineHandle m_ppline;
 	GlProgramPipelineHandle m_ppline;
-	GlJobChainHandle m_jobs;
+	GlCommandBufferHandle m_jobs;
 
 
 	static const U MAX_POINTS_PER_DRAW = 256;
 	static const U MAX_POINTS_PER_DRAW = 256;
 	Mat4 m_mMat;
 	Mat4 m_mMat;

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

@@ -38,7 +38,7 @@ public:
 	/// The one and only constructor
 	/// The one and only constructor
 	RenderableDrawer(Renderer* r);
 	RenderableDrawer(Renderer* r);
 
 
-	void prepareDraw(RenderingStage stage, Pass pass, GlJobChainHandle& jobs);
+	void prepareDraw(RenderingStage stage, Pass pass, GlCommandBufferHandle& jobs);
 
 
 	void render(
 	void render(
 		SceneNode& frsn,
 		SceneNode& frsn,
@@ -52,7 +52,7 @@ private:
 
 
 	/// @name State
 	/// @name State
 	/// @{
 	/// @{
-	GlJobChainHandle m_jobs;
+	GlCommandBufferHandle m_jobs;
 	U8* m_uniformPtr;
 	U8* m_uniformPtr;
 
 
 	/// Used to calc if the uni buffer is big enough. Zero it per swap buffers
 	/// 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 init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 };
 };
 
 
 /// @}
 /// @}

+ 2 - 2
include/anki/renderer/Hdr.h

@@ -88,12 +88,12 @@ private:
 	~Hdr();
 	~Hdr();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 
 
 	void initFb(GlFramebufferHandle& fb, GlTextureHandle& rt);
 	void initFb(GlFramebufferHandle& fb, GlTextureHandle& rt);
 	void initInternal(const ConfigSet& initializer);
 	void initInternal(const ConfigSet& initializer);
 
 
-	void updateDefaultBlock(GlJobChainHandle& jobs);
+	void updateDefaultBlock(GlCommandBufferHandle& jobs);
 };
 };
 
 
 /// @}
 /// @}

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

@@ -114,16 +114,16 @@ private:
 	~Is();
 	~Is();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 
 
 	/// Called by init
 	/// Called by init
 	void initInternal(const ConfigSet& initializer);
 	void initInternal(const ConfigSet& initializer);
 
 
 	/// Do the actual pass
 	/// Do the actual pass
-	void lightPass(GlJobChainHandle& jobs);
+	void lightPass(GlCommandBufferHandle& jobs);
 
 
 	/// Prepare GL for rendering
 	/// Prepare GL for rendering
-	void setState(GlJobChainHandle& jobs);
+	void setState(GlCommandBufferHandle& jobs);
 
 
 	/// Calculate the size of the lights UBO
 	/// Calculate the size of the lights UBO
 	PtrSize calcLightsBufferSize() const;
 	PtrSize calcLightsBufferSize() const;
@@ -131,7 +131,7 @@ private:
 	/// Calculate the size of the tile
 	/// Calculate the size of the tile
 	PtrSize calcTileSize() const;
 	PtrSize calcTileSize() const;
 
 
-	void updateCommonBlock(GlJobChainHandle& jobs);
+	void updateCommonBlock(GlCommandBufferHandle& jobs);
 };
 };
 
 
 /// @}
 /// @}

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

@@ -64,7 +64,7 @@ private:
 	~Lf();
 	~Lf();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 	
 	
 	void initInternal(const ConfigSet& initializer);
 	void initInternal(const ConfigSet& initializer);
 };
 };

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

@@ -8,10 +8,12 @@
 
 
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Deformer.h"
 #include "anki/renderer/Deformer.h"
-#include "anki/util/Singleton.h"
 
 
 namespace anki {
 namespace anki {
 
 
+// Forward
+class App;
+
 /// @addtogroup renderer
 /// @addtogroup renderer
 /// @{
 /// @{
 
 
@@ -19,7 +21,7 @@ namespace anki {
 class MainRenderer: public Renderer
 class MainRenderer: public Renderer
 {
 {
 public:
 public:
-	MainRenderer(const ConfigSet& initializer);
+	MainRenderer(App* app, const ConfigSet& initializer);
 
 
 	~MainRenderer();
 	~MainRenderer();
 
 
@@ -36,7 +38,7 @@ private:
 	GlProgramPipelineHandle m_blitPpline;
 	GlProgramPipelineHandle m_blitPpline;
 
 
 	/// Optimize job chain
 	/// Optimize job chain
-	Array<GlJobChainInitHints, JOB_CHAINS_COUNT> m_jobsInitHints; 
+	Array<GlCommandBufferInitHints, JOB_CHAINS_COUNT> m_jobsInitHints; 
 
 
 	/// The same as Renderer::init but with additional initialization.
 	/// The same as Renderer::init but with additional initialization.
 	/// @see Renderer::init
 	/// @see Renderer::init
@@ -46,8 +48,6 @@ private:
 	void initGl();
 	void initGl();
 };
 };
 
 
-typedef SingletonInit<MainRenderer> MainRendererSingleton;
-
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

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

@@ -76,7 +76,7 @@ private:
 	~Ms();
 	~Ms();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 
 
 	/// Create a G buffer FBO
 	/// Create a G buffer FBO
 	void createRt(U32 index, U32 samples);
 	void createRt(U32 index, U32 samples);

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

@@ -109,7 +109,7 @@ private:
 	~Pps();
 	~Pps();
 
 
 	void init(const ConfigSet& initializer);
 	void init(const ConfigSet& initializer);
-	void run(GlJobChainHandle& jobs);
+	void run(GlCommandBufferHandle& jobs);
 
 
 	void initInternal(const ConfigSet& initializer);
 	void initInternal(const ConfigSet& initializer);
 };
 };

+ 12 - 5
include/anki/renderer/Renderer.h

@@ -37,7 +37,7 @@ public:
 	/// GL with a huge job chain
 	/// GL with a huge job chain
 	static const U32 JOB_CHAINS_COUNT = 2;
 	static const U32 JOB_CHAINS_COUNT = 2;
 		
 		
-	Renderer();
+	Renderer(Threadpool* threadpool);
 
 
 	~Renderer();
 	~Renderer();
 
 
@@ -187,6 +187,11 @@ public:
 	{
 	{
 		return m_defaultFb;
 		return m_defaultFb;
 	}
 	}
+
+	Threadpool& _getThreadpool() 
+	{
+		return *m_threadpool;
+	}
 	/// @}
 	/// @}
 
 
 	/// Init the renderer given an initialization class
 	/// Init the renderer given an initialization class
@@ -195,7 +200,7 @@ public:
 
 
 	/// This function does all the rendering stages and produces a final FAI
 	/// This function does all the rendering stages and produces a final FAI
 	void render(SceneGraph& scene, 
 	void render(SceneGraph& scene, 
-		Array<GlJobChainHandle, JOB_CHAINS_COUNT>& jobs);
+		Array<GlCommandBufferHandle, JOB_CHAINS_COUNT>& jobs);
 
 
 	/// My version of gluUnproject
 	/// My version of gluUnproject
 	/// @param windowCoords Window screen coords
 	/// @param windowCoords Window screen coords
@@ -209,9 +214,9 @@ public:
 
 
 	/// Draws a quad. Actually it draws 2 triangles because OpenGL will no
 	/// Draws a quad. Actually it draws 2 triangles because OpenGL will no
 	/// longer support quads
 	/// longer support quads
-	void drawQuad(GlJobChainHandle& jobs);
+	void drawQuad(GlCommandBufferHandle& jobs);
 
 
-	void drawQuadInstanced(GlJobChainHandle& jobs, U32 primitiveCount);
+	void drawQuadInstanced(GlCommandBufferHandle& jobs, U32 primitiveCount);
 
 
 	/// Get the LOD given the distance of an object from the camera
 	/// Get the LOD given the distance of an object from the camera
 	F32 calculateLod(F32 distance) const
 	F32 calculateLod(F32 distance) const
@@ -274,10 +279,12 @@ private:
 	U m_framesNum; ///< Frame number
 	U m_framesNum; ///< Frame number
 
 
 	/// String to pass to the material shaders
 	/// String to pass to the material shaders
-	std::string m_shaderPostProcessorString;
+	String m_shaderPostProcessorString;
 
 
 	GlFramebufferHandle m_defaultFb;
 	GlFramebufferHandle m_defaultFb;
 
 
+	Threadpool* m_threadpool;
+
 	void computeProjectionParams(const Mat4& projMat);
 	void computeProjectionParams(const Mat4& projMat);
 };
 };
 
 

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

@@ -97,7 +97,7 @@ protected:
 	void initBlurring(Renderer& r, U width, U height, U samples, 
 	void initBlurring(Renderer& r, U width, U height, U samples, 
 		F32 blurringDistance);
 		F32 blurringDistance);
 
 
-	void runBlurring(Renderer& r, GlJobChainHandle& jobs);
+	void runBlurring(Renderer& r, GlCommandBufferHandle& jobs);
 };
 };
 
 
 /// @}
 /// @}

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

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

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

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

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

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

+ 36 - 30
include/anki/resource/Animation.h

@@ -7,13 +7,14 @@
 #define ANKI_RESOURCE_ANIMATION_H
 #define ANKI_RESOURCE_ANIMATION_H
 
 
 #include "anki/Math.h"
 #include "anki/Math.h"
-#include "anki/util/Vector.h"
+#include "anki/resource/Common.h"
+#include "anki/util/String.h"
 
 
 namespace anki {
 namespace anki {
 
 
 class XmlElement;
 class XmlElement;
 
 
-/// @addtogroup Resources
+/// @addtogroup resource
 /// @{
 /// @{
 
 
 /// A keyframe 
 /// A keyframe 
@@ -25,77 +26,82 @@ class Key
 public:
 public:
 	F32 getTime() const
 	F32 getTime() const
 	{
 	{
-		return time;
+		return m_time;
 	}
 	}
 
 
 	const T& getValue() const
 	const T& getValue() const
 	{
 	{
-		return value;
+		return m_value;
 	}
 	}
 
 
 private:
 private:
-	F32 time;
-	T value;
+	F32 m_time;
+	T m_value;
 };
 };
 
 
 /// Animation channel
 /// Animation channel
-struct AnimationChannel
+class AnimationChannel
 {
 {
-	std::string name;
-
-	I32 boneIndex = -1; ///< For skeletal animations
-
-	Vector<Key<Vec3>> positions;
-	Vector<Key<Quat>> rotations;
-	Vector<Key<F32>> scales;
-	Vector<Key<F32>> cameraFovs;
+public:
+	BasicString<char, ResourceAllocator<char>> m_name;
+
+	I32 m_boneIndex = -1; ///< For skeletal animations
+
+	ResourceVector<Key<Vec3>> m_positions;
+	ResourceVector<Key<Quat>> m_rotations;
+	ResourceVector<Key<F32>> m_scales;
+	ResourceVector<Key<F32>> m_cameraFovs;
+
+	AnimationChannel(ResourceAllocator<U8>& alloc)
+	:	m_name(alloc),
+		m_positions(alloc),
+		m_rotations(alloc),
+		m_scales(alloc),
+		m_cameraFovs(alloc)
+	{}
 };
 };
 
 
 /// Animation consists of keyframe data
 /// Animation consists of keyframe data
 class Animation
 class Animation
 {
 {
 public:
 public:
-	void load(const char* filename);
-
-	/// @name Accessors
-	/// @{
+	void load(const char* filename, ResourceAllocator<U8>& alloc);
 
 
 	/// Get a vector of all animation channels
 	/// Get a vector of all animation channels
-	const Vector<AnimationChannel>& getChannels() const
+	const ResourceVector<AnimationChannel>& getChannels() const
 	{
 	{
-		return channels;
+		return m_channels;
 	}
 	}
 
 
 	/// Get the duration of the animation in seconds
 	/// Get the duration of the animation in seconds
 	F32 getDuration() const
 	F32 getDuration() const
 	{
 	{
-		return duration;
+		return m_duration;
 	}
 	}
 
 
 	/// Get the time (in seconds) the animation should start
 	/// Get the time (in seconds) the animation should start
 	F32 getStartingTime() const
 	F32 getStartingTime() const
 	{
 	{
-		return startTime;
+		return m_startTime;
 	}
 	}
 
 
 	/// The animation repeats
 	/// The animation repeats
 	Bool getRepeat() const
 	Bool getRepeat() const
 	{
 	{
-		return repeat;
+		return m_repeat;
 	}
 	}
-	/// @}
 
 
 	/// Get the interpolated data
 	/// Get the interpolated data
 	void interpolate(U channelIndex, F32 time, 
 	void interpolate(U channelIndex, F32 time, 
 		Vec3& position, Quat& rotation, F32& scale) const;
 		Vec3& position, Quat& rotation, F32& scale) const;
 
 
 private:
 private:
-	Vector<AnimationChannel> channels;
-	F32 duration;
-	F32 startTime;
-	Bool8 repeat;
+	ResourceVector<AnimationChannel> m_channels;
+	F32 m_duration;
+	F32 m_startTime;
+	Bool8 m_repeat;
 
 
-	void loadInternal(const XmlElement& el);
+	void loadInternal(const XmlElement& el, ResourceAllocator<U8>& alloc);
 };
 };
 /// @}
 /// @}
 
 

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

@@ -0,0 +1,28 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#ifndef ANKI_RESOURCE_COMMON_H
+#define ANKI_RESOURCE_COMMON_H
+
+#include "anki/util/Allocator.h"
+#include "anki/util/Vector.h"
+
+namespace anki {
+
+template<typename T>
+using ResourceAllocator = HeapAllocator<T>;
+
+template<typename T>
+using ResourceVector = Vector<T, ResourceAllocator<T>>;
+
+template<typename T>
+using TempResourceAllocator = StackAllocator<T>;
+
+template<typename T>
+using TempResourceVector = Vector<T, TempResourceAllocator<T>>;
+
+} // end namespace anki
+
+#endif

+ 48 - 42
include/anki/resource/Image.h

@@ -6,11 +6,10 @@
 #ifndef ANKI_RESOURCE_IMAGE_H
 #ifndef ANKI_RESOURCE_IMAGE_H
 #define ANKI_RESOURCE_IMAGE_H
 #define ANKI_RESOURCE_IMAGE_H
 
 
+#include "anki/resource/Common.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
-#include <iosfwd>
-#include <cstdint>
-#include <limits>
+#include "anki/util/Enum.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -20,43 +19,51 @@ class Image
 {
 {
 public:
 public:
 	/// Texture type
 	/// Texture type
-	enum TextureType
+	enum class TextureType: U32
 	{
 	{
-		TT_NONE,
-		TT_2D,
-		TT_CUBE,
-		TT_3D,
-		TT_2D_ARRAY
+		NONE,
+		_2D,
+		CUBE,
+		_3D,
+		_2D_ARRAY
 	};
 	};
 
 
 	/// The acceptable color types of AnKi
 	/// The acceptable color types of AnKi
-	enum ColorFormat
+	enum class ColorFormat: U32
 	{
 	{
-		CF_NONE,
-		CF_RGB8, ///< RGB
-		CF_RGBA8 ///< RGB plus alpha
+		NONE,
+		RGB8, ///< RGB
+		RGBA8 ///< RGB plus alpha
 	};
 	};
 
 
 	/// The data compression
 	/// The data compression
-	enum DataCompression
+	enum class DataCompression: U32
 	{
 	{
-		DC_NONE,
-		DC_RAW = 1 << 0,
-		DC_S3TC = 1 << 1,
-		DC_ETC = 1 << 2
+		NONE,
+		RAW = 1 << 0,
+		S3TC = 1 << 1,
+		ETC = 1 << 2
 	};
 	};
 
 
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(DataCompression, friend)
+
 	/// An image surface
 	/// An image surface
-	struct Surface
+	class Surface
 	{
 	{
-		U32 width;
-		U32 height;
-		U32 mipLevel;
-		Vector<U8> data;
+	public:
+		Surface(ResourceAllocator<U8>& alloc)
+		:	m_data(alloc)
+		{}
+
+		U32 m_width;
+		U32 m_height;
+		U32 m_mipLevel;
+		ResourceVector<U8> m_data;
 	};
 	};
 
 
 	/// Do nothing
 	/// Do nothing
-	Image()
+	Image(ResourceAllocator<U8>& alloc)
+	:	m_surfaces(alloc)
 	{}
 	{}
 
 
 	/// Do nothing
 	/// Do nothing
@@ -67,32 +74,32 @@ public:
 	/// @{
 	/// @{
 	ColorFormat getColorFormat() const
 	ColorFormat getColorFormat() const
 	{
 	{
-		ANKI_ASSERT(colorFormat != CF_NONE);
-		return colorFormat;
+		ANKI_ASSERT(m_colorFormat != ColorFormat::NONE);
+		return m_colorFormat;
 	}
 	}
 
 
 	DataCompression getCompression() const
 	DataCompression getCompression() const
 	{
 	{
-		ANKI_ASSERT(compression != DC_NONE);
-		return compression;
+		ANKI_ASSERT(m_compression != DataCompression::NONE);
+		return m_compression;
 	}
 	}
 
 
 	U getMipLevelsCount() const
 	U getMipLevelsCount() const
 	{
 	{
-		ANKI_ASSERT(mipLevels != 0);
-		return mipLevels;
+		ANKI_ASSERT(m_mipLevels != 0);
+		return m_mipLevels;
 	}
 	}
 
 
 	U getDepth() const
 	U getDepth() const
 	{
 	{
-		ANKI_ASSERT(depth != 0);
-		return depth;
+		ANKI_ASSERT(m_depth != 0);
+		return m_depth;
 	}
 	}
 
 
 	TextureType getTextureType() const
 	TextureType getTextureType() const
 	{
 	{
-		ANKI_ASSERT(textureType != TT_NONE);
-		return textureType;
+		ANKI_ASSERT(m_textureType != TextureType::NONE);
+		return m_textureType;
 	}
 	}
 
 
 	const Surface& getSurface(U mipLevel, U layer) const;
 	const Surface& getSurface(U mipLevel, U layer) const;
@@ -102,8 +109,7 @@ public:
 	/// @param[in] filename The file to load
 	/// @param[in] filename The file to load
 	/// @param[in] maxTextureSize Only load mipmaps less or equal to that. Used
 	/// @param[in] maxTextureSize Only load mipmaps less or equal to that. Used
 	///                           with AnKi textures
 	///                           with AnKi textures
-	void load(const char* filename, 
-		U32 maxTextureSize = std::numeric_limits<U32>::max());
+	void load(const char* filename, U32 maxTextureSize = MAX_U32);
 
 
 	/// Load an image file
 	/// Load an image file
 	/// @param[in] filenames The 6 files to load
 	/// @param[in] filenames The 6 files to load
@@ -111,12 +117,12 @@ public:
 
 
 private:
 private:
 	/// [mip][depthFace]
 	/// [mip][depthFace]
-	Vector<Surface> surfaces;
-	U8 mipLevels = 0;
-	U8 depth = 0;
-	DataCompression compression = DC_NONE;
-	ColorFormat colorFormat = CF_NONE;
-	TextureType textureType = TT_NONE;
+	ResourceVector<Surface> m_surfaces;
+	U8 m_mipLevels = 0;
+	U8 m_depth = 0;
+	DataCompression m_compression = DataCompression::NONE;
+	ColorFormat m_colorFormat = ColorFormat::NONE;
+	TextureType m_textureType = TextureType::NONE;
 };
 };
 
 
 } // end namespace anki
 } // end namespace anki

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

@@ -120,7 +120,7 @@ public:
 	MaterialVariableTemplate(
 	MaterialVariableTemplate(
 		const GlProgramVariable* glvar, Bool instanced, 
 		const GlProgramVariable* glvar, Bool instanced, 
 		const TData* x, U32 size)
 		const TData* x, U32 size)
-		: MaterialVariable(glvar, instanced)
+	:	MaterialVariable(glvar, instanced)
 	{
 	{
 		setupVisitable(this);
 		setupVisitable(this);
 
 

+ 24 - 10
include/anki/resource/MaterialProgramCreator.h

@@ -8,9 +8,11 @@
 
 
 #include "anki/util/StringList.h"
 #include "anki/util/StringList.h"
 #include "anki/Gl.h"
 #include "anki/Gl.h"
+#include "anki/resource/Common.h"
 
 
 namespace anki {
 namespace anki {
 
 
+// Forward
 class XmlElement;
 class XmlElement;
 
 
 /// Creator of shader programs. This class parses between
 /// Creator of shader programs. This class parses between
@@ -23,34 +25,45 @@ class XmlElement;
 class MaterialProgramCreator
 class MaterialProgramCreator
 {
 {
 public:
 public:
+	using MPString = BasicString<char, TempResourceAllocator<char>>; 
+	using MPStringList = BasicStringList<char, TempResourceAllocator<char>>; 
+
 	class Input
 	class Input
 	{
 	{
 	public:
 	public:
-		std::string m_name;
-		std::string m_type;
-		StringList m_value;
+		Input(TempResourceAllocator<char>& alloc)
+		:	m_name(alloc),
+			m_type(alloc),
+			m_value(alloc),
+			m_line(alloc)
+		{}
+
+		MPString m_name;
+		MPString m_type;
+		MPStringList m_value;
 		Bool8 m_constant;
 		Bool8 m_constant;
 		U16 m_arraySize;
 		U16 m_arraySize;
 		Bool8 m_instanced = false;
 		Bool8 m_instanced = false;
 
 
-		std::string m_line;
+		MPStringList m_line;
 		GLbitfield m_shaderDefinedMask = 0; ///< Defined in
 		GLbitfield m_shaderDefinedMask = 0; ///< Defined in
 		GLbitfield m_shaderReferencedMask = 0; ///< Referenced by
 		GLbitfield m_shaderReferencedMask = 0; ///< Referenced by
 		Bool8 m_inBlock = true;
 		Bool8 m_inBlock = true;
 	};
 	};
 
 
-	explicit MaterialProgramCreator(const XmlElement& pt);
+	explicit MaterialProgramCreator(const XmlElement& pt, 
+		TempResourceAllocator<U8>& alloc);
 
 
 	~MaterialProgramCreator();
 	~MaterialProgramCreator();
 
 
 	/// Get the shader program source code
 	/// Get the shader program source code
-	std::string getProgramSource(U shaderType) const
+	MPString getProgramSource(U shaderType) const
 	{
 	{
 		ANKI_ASSERT(m_source[shaderType].size() > 0);
 		ANKI_ASSERT(m_source[shaderType].size() > 0);
 		return m_source[shaderType].join("\n");
 		return m_source[shaderType].join("\n");
 	}
 	}
 
 
-	const Vector<Input>& getInputVariables() const
+	const TempResourceVector<Input>& getInputVariables() const
 	{
 	{
 		return m_inputs;
 		return m_inputs;
 	}
 	}
@@ -61,9 +74,10 @@ public:
 	}
 	}
 
 
 private:
 private:
-	Array<StringList, 5> m_source; ///< Shader program final source
-	Vector<Input> m_inputs;
-	StringList m_uniformBlock;
+	TempResourceAllocator<char> m_alloc; 
+	Array<MPStringList, 5> m_source; ///< Shader program final source
+	TempResourceVector<Input> m_inputs;
+	MPStringList m_uniformBlock;
 	GLbitfield m_uniformBlockReferencedMask = 0;
 	GLbitfield m_uniformBlockReferencedMask = 0;
 	Bool8 m_instanced = false;
 	Bool8 m_instanced = false;
 	U32 m_texBinding = 0;
 	U32 m_texBinding = 0;

+ 3 - 3
include/anki/resource/Model.h

@@ -66,7 +66,7 @@ public:
 	/// offsets and counts
 	/// offsets and counts
 	void getRenderingDataSub(
 	void getRenderingDataSub(
 		const RenderingKey& key, 
 		const RenderingKey& key, 
-		GlJobChainHandle& vertJobs,
+		GlCommandBufferHandle& vertJobs,
 		GlProgramPipelineHandle& ppline,
 		GlProgramPipelineHandle& ppline,
 		const U8* subMeshIndicesArray, 
 		const U8* subMeshIndicesArray, 
 		U32 subMeshIndicesCount,
 		U32 subMeshIndicesCount,
@@ -76,7 +76,7 @@ public:
 
 
 protected:
 protected:
 	/// Array [lod][pass]
 	/// Array [lod][pass]
-	Vector<GlJobChainHandle> m_vertJobs;
+	Vector<GlCommandBufferHandle> m_vertJobs;
 	Material* m_mtl = nullptr;
 	Material* m_mtl = nullptr;
 	Vector<Mesh*> m_meshes; ///< One for each LOD
 	Vector<Mesh*> m_meshes; ///< One for each LOD
 
 
@@ -89,7 +89,7 @@ private:
 	static void createVertexDesc(
 	static void createVertexDesc(
 		const GlProgramHandle& prog,
 		const GlProgramHandle& prog,
 		const Mesh& mesh,
 		const Mesh& mesh,
-		GlJobChainHandle& vertexJobs);
+		GlCommandBufferHandle& vertexJobs);
 
 
 	/// Return the maximum number of LODs
 	/// Return the maximum number of LODs
 	U getLodsCount() const;
 	U getLodsCount() const;

+ 4 - 9
include/anki/resource/Resource.h

@@ -12,13 +12,11 @@
 
 
 namespace anki {
 namespace anki {
 
 
-#define ANKI_RESOURCE_TYPEDEFS(rsrc, name) \
-	class rsrc; \
-	typedef TypeResourceManager<rsrc> rsrc ## ResourceManager; \
-	typedef Singleton<rsrc ## ResourceManager> \
-		rsrc ## ResourceManagerSingleton; \
-	typedef ResourcePointer<rsrc, rsrc ## ResourceManagerSingleton> name;
+#define ANKI_RESOURCE_TYPEDEFS(rsrc_, name_) \
+	class rsrc_; \
+	using name_ = ResourcePointer<rsrc_, ResourceManager>;
 
 
+ANKI_RESOURCE_TYPEDEFS(Animation, AnimationResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(TextureResource, TextureResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(TextureResource, TextureResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(ProgramResource, ProgramResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(ProgramResource, ProgramResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Material, MaterialResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Material, MaterialResourcePointer)
@@ -26,13 +24,10 @@ ANKI_RESOURCE_TYPEDEFS(Mesh, MeshResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(BucketMesh, BucketMeshResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(BucketMesh, BucketMeshResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Skeleton, SkeletonResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Skeleton, SkeletonResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(SkelAnim, SkelAnimResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(SkelAnim, SkelAnimResourcePointer)
-ANKI_RESOURCE_TYPEDEFS(Animation, AnimationResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(LightRsrc, LightRsrcResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(LightRsrc, LightRsrcResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(ParticleEmitterResource, ParticleEmitterResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(ParticleEmitterResource, ParticleEmitterResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Script, ScriptResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Script, ScriptResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Model, ModelResourcePointer)
 ANKI_RESOURCE_TYPEDEFS(Model, ModelResourcePointer)
-ANKI_RESOURCE_TYPEDEFS(Skin, SkinResourcePointer)
-ANKI_RESOURCE_TYPEDEFS(DummyRsrc, DummyRsrcResourcePointer)
 
 
 #undef ANKI_RESOURCE_TYPEDEFS
 #undef ANKI_RESOURCE_TYPEDEFS
 
 

+ 117 - 63
include/anki/resource/ResourceManager.h

@@ -7,40 +7,115 @@
 #define ANKI_RESOURCE_RESOURCE_MANAGER_H
 #define ANKI_RESOURCE_RESOURCE_MANAGER_H
 
 
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
-#include "anki/util/StdTypes.h"
-#include "anki/util/Singleton.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"
 #include "anki/util/String.h"
 #include "anki/util/String.h"
+#include "anki/resource/ResourcePointer.h"
 
 
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
 class ConfigSet;
 class ConfigSet;
 
 
+class Animation;
+class Material;
+class Mesh;
+class Model;
+class BucketMesh;
+class ProgramResource;
+class ParticleEmitterResource;
+class TextureResource;
+
 /// @addtogroup resource
 /// @addtogroup resource
 /// @{
 /// @{
 
 
-/// Holds information about a resource
-template<typename Type>
-struct ResourceHook
+/// Manage resources of a certain type
+template<typename Type, typename TResourceManager>
+class TypeResourceManager
 {
 {
-	String uuid; ///< Unique identifier
-	U32 referenceCounter = 0;
-	Type* resource = nullptr;
+public:
+	using ResourcePointerType = ResourcePointer<Type, TResourceManager>;
+	using Container = 
+		Vector<ResourcePointerType, HeapAllocator<ResourcePointerType>>;
 
 
-	~ResourceHook()
+	TypeResourceManager()
 	{}
 	{}
 
 
-	Bool operator==(const ResourceHook& b) const
+	~TypeResourceManager()
 	{
 	{
-		return uuid == b.uuid 
-			&& referenceCounter == b.referenceCounter 
-			&& resource == b.resource;
+		ANKI_ASSERT(m_ptrs.size() == 0 
+			&& "Forgot to delete some resource ptrs");
+	}
+
+	/// @privatesection
+	/// @{
+	void init(HeapAllocator<U8>& alloc)
+	{
+		HeapAllocator<ResourcePointerType> alloc2 = alloc;
+		Container ptrs(alloc2);
+		m_ptrs = std::move(ptrs);
+	}
+
+	Bool _findLoadedResource(const char* filename, ResourcePointerType& ptr)
+	{
+		auto it = find(filename);
+		
+		if(it != m_ptrs.end())
+		{
+			ptr = *it;
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	void _registerResource(ResourcePointerType& ptr)
+	{
+		ANKI_ASSERT(ptr.getReferenceCount() == 1);
+		ANKI_ASSERT(find(ptr.getResourceName()) == m_ptrs.end());
+	
+		m_ptrs.push_back(ptr);
+	}
+
+	void _unregisterResource(ResourcePointerType& ptr)
+	{
+		auto it = find(ptr.getResourceName());
+		ANKI_ASSERT(it != m_ptrs.end());
+	
+		m_ptrs.erase(it);
+	}
+	/// @}
+
+private:
+	Container m_ptrs;
+
+	typename Container::iterator find(const char* filename)
+	{
+		typename Container::iterator it;
+		
+		for(it = m_ptrs.begin(); it != m_ptrs.end(); ++it)
+		{
+			if(std::strcmp(it->getResourceName(), filename) == 0)
+			{
+				break;
+			}
+		}
+
+		return it;
 	}
 	}
 };
 };
 
 
 /// Resource manager. It holds a few global variables
 /// Resource manager. It holds a few global variables
-class ResourceManager
+class ResourceManager: 
+	public TypeResourceManager<Animation, ResourceManager>,
+	public TypeResourceManager<Material, ResourceManager>,
+	public TypeResourceManager<Mesh, ResourceManager>,
+	public TypeResourceManager<Model, ResourceManager>,
+	public TypeResourceManager<BucketMesh, ResourceManager>,
+	public TypeResourceManager<ProgramResource, ResourceManager>,
+	public TypeResourceManager<ParticleEmitterResource, ResourceManager>,
+	public TypeResourceManager<TextureResource, ResourceManager>
 {
 {
 public:
 public:
 	ResourceManager(const ConfigSet& config);
 	ResourceManager(const ConfigSet& config);
@@ -60,66 +135,45 @@ public:
 		return m_textureAnisotropy;
 		return m_textureAnisotropy;
 	}
 	}
 
 
-	String fixResourcePath(const char* filename) const;
-
-private:
-	String m_dataPath;
-	U32 m_maxTextureSize;
-	U32 m_textureAnisotropy;
-};
-
-/// The singleton of resource manager
-typedef SingletonInit<ResourceManager> ResourceManagerSingleton;
-
-/// Convenience macro to sanitize resources path
-#define ANKI_R(x_) \
-	ResourceManagerSingleton::get().fixResourcePath(x_).c_str()
-
-/// Manage resources of a certain type
-template<typename Type>
-class TypeResourceManager
-{
-public:
-	typedef TypeResourceManager<Type> Self;
-	typedef ResourceHook<Type> Hook;
-	typedef Vector<Hook*> Container;
-	typedef typename Container::iterator Iterator;
-	typedef typename Container::const_iterator ConstIterator;
-
-	virtual ~TypeResourceManager()
+	HeapAllocator<U8>& _getAllocator()
 	{
 	{
-		for(auto it : hooks)
-		{
-			propperDelete(it);
-		}
+		return m_alloc;
 	}
 	}
 
 
-	Hook& load(const char* filename);
-
-	void unload(const Hook& hook);
+	String fixResourcePath(const char* filename) const;
 
 
-protected:
-	Container hooks;
+	/// @privatesection
+	/// @{
+	template<typename T>
+	Bool _findLoadedResource(const char* filename, 
+		ResourcePointer<T, ResourceManager>& ptr)
+	{
+		return TypeResourceManager<T, ResourceManager>::_findLoadedResource(
+			filename, ptr);
+	}
 
 
-	Iterator find(const char* filename);
+	template<typename T>
+	void _registerResource(ResourcePointer<T, ResourceManager>& ptr)
+	{
+		TypeResourceManager<T, ResourceManager>::_registerResource(ptr);
+	}
 
 
-	/// Allocate and load a resource.
-	/// This method allocates memory for a resource and loads it (calls the
-	/// load method). Its been used by the load method. Its a separate
-	/// method because we want to specialize it for async loaded resources
-	virtual void allocAndLoadRsrc(const char* filename, Type*& ptr);
+	template<typename T>
+	void _unregisterResource(ResourcePointer<T, ResourceManager>& ptr)
+	{
+		TypeResourceManager<T, ResourceManager>::_unregisterResource(ptr);
+	}
+	/// @}
 
 
-	/// Dealocate the resource. Its separate for two reasons:
-	/// - Because we want to specialize it for the async loaded resources
-	/// - Because we cannot have the operator delete in a template body.
-	///   Apparently the compiler is to dump to decide
-	virtual void deallocRsrc(Type* rsrc);
+private:
+	HeapAllocator<U8> m_alloc;
+	String m_dataPath;
+	U32 m_maxTextureSize;
+	U32 m_textureAnisotropy;
 };
 };
 
 
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki
 
 
-#include "anki/resource/ResourceManager.inl.h"
-
 #endif
 #endif

+ 66 - 61
include/anki/resource/ResourcePointer.h

@@ -7,33 +7,39 @@
 #define ANKI_RESOURCE_RESOURCE_POINTER_H
 #define ANKI_RESOURCE_RESOURCE_POINTER_H
 
 
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
+#include <atomic>
+#include <cstring>
 
 
 namespace anki {
 namespace anki {
 
 
+// Forward
+class ResourceManager;
+
+/// @addtogroup resource
+/// @{
+
 /// Special smart pointer that points to resource classes.
 /// Special smart pointer that points to resource classes.
 ///
 ///
 /// It looks like auto_ptr but the main difference is that when its out of scope
 /// It looks like auto_ptr but the main difference is that when its out of scope
 /// it tries to unload the resource.
 /// it tries to unload the resource.
-template<typename Type, typename TResourceManagerSingleton>
+template<typename Type, typename TResourceManager>
 class ResourcePointer
 class ResourcePointer
 {
 {
 public:
 public:
-	typedef Type Value; ///< Resource type
-	typedef ResourcePointer<Value, TResourceManagerSingleton> Self;
-	typedef typename TResourceManagerSingleton::Value::Hook Hook;
+	using Value = Type; ///< Resource type
 
 
 	/// Default constructor
 	/// Default constructor
 	ResourcePointer()
 	ResourcePointer()
 	{}
 	{}
 
 
 	/// Copy constructor
 	/// Copy constructor
-	ResourcePointer(const Self& b)
+	ResourcePointer(const ResourcePointer& b)
 	{
 	{
 		copy(b);
 		copy(b);
 	}
 	}
 
 
 	/// Move contructor
 	/// Move contructor
-	ResourcePointer(Self&& b)
+	ResourcePointer(ResourcePointer&& b)
 	{
 	{
 		*this = std::move(b);
 		*this = std::move(b);
 	}
 	}
@@ -46,112 +52,111 @@ public:
 
 
 	~ResourcePointer()
 	~ResourcePointer()
 	{
 	{
-		unload();
+		reset();
 	}
 	}
 
 
-	/// @name Accessors
-	/// @{
 	const Value& operator*() const
 	const Value& operator*() const
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return *hook->resource;
+		ANKI_ASSERT(m_cb != nullptr);
+		return m_cb->m_resource;
 	}
 	}
+
 	Value& operator*()
 	Value& operator*()
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return *hook->resource;
+		ANKI_ASSERT(m_cb != nullptr);
+		return m_cb->m_resource;
 	}
 	}
 
 
 	const Value* operator->() const
 	const Value* operator->() const
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return hook->resource;
+		ANKI_ASSERT(m_cb != nullptr);
+		return &m_cb->m_resource;
 	}
 	}
+
 	Value* operator->()
 	Value* operator->()
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return hook->resource;
+		ANKI_ASSERT(m_cb != nullptr);
+		return &m_cb->m_resource;
 	}
 	}
 
 
 	const Value* get() const
 	const Value* get() const
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return hook->resource;
+		ANKI_ASSERT(m_cb != nullptr);
+		return &m_cb->m_resource;
 	}
 	}
+
 	Value* get()
 	Value* get()
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return hook->resource;
+		ANKI_ASSERT(m_cb != nullptr);
+		return &m_cb->m_resource;
 	}
 	}
 
 
-	const std::string& getResourceName() const
+	const char* getResourceName() const
 	{
 	{
-		ANKI_ASSERT(hook != nullptr);
-		return hook->uuid;
+		ANKI_ASSERT(m_cb != nullptr);
+		return &m_cb->m_uuid[0];
 	}
 	}
-	/// @}
 
 
+	U32 getReferenceCount() const
+	{
+		ANKI_ASSERT(m_cb != nullptr);
+		return &m_cb->m_refcount.load();
+	}
+	
 	/// Copy
 	/// Copy
-	Self& operator=(const Self& b)
+	ResourcePointer& operator=(const ResourcePointer& b)
 	{
 	{
 		copy(b);
 		copy(b);
 		return *this;
 		return *this;
 	}
 	}
 
 
 	/// Move
 	/// Move
-	Self& operator=(Self&& b)
+	ResourcePointer& operator=(ResourcePointer&& b)
 	{
 	{
-		hook = b.hook;
-		b.hook = nullptr;
+		m_cb = b.m_cb;
+		b.m_cb = nullptr;
 		return *this;
 		return *this;
 	}
 	}
 
 
-	/// Load the resource using the resource manager
-	void load(const char* filename)
+	Bool operator==(const ResourcePointer& b) const
 	{
 	{
-		ANKI_ASSERT(hook == nullptr);
-		ANKI_ASSERT(filename != nullptr);
-		hook = &TResourceManagerSingleton::get().load(filename);
+		ANKI_ASSERT(m_cb != nullptr);
+		ANKI_ASSERT(b.m_cb != nullptr);
+		return std::strcmp(&m_cb->m_uuid[0], &b.m_cb->m_uuid[0]) == 0; 
 	}
 	}
 
 
+	/// Load the resource using the resource manager
+	void load(const char* filename, TResourceManager* resources);
+
 	Bool isLoaded() const
 	Bool isLoaded() const
 	{
 	{
-		return hook != nullptr;
+		return m_cb != nullptr;
 	}
 	}
 
 
 private:
 private:
-	/// Points to an element located in a container in the resource manager
-	Hook* hook = nullptr;
-
-	/// Unloads the resource @see loadRsrc
-	void unload()
+	/// Control block
+	class ControlBlock
 	{
 	{
-		if(hook != nullptr)
-		{
-			TResourceManagerSingleton::get().unload(*hook);
-			hook = nullptr;
-		}
-	}
+	public:
+		Type m_resource;
+		std::atomic<U32> m_refcount = {1};
+		TResourceManager* m_resources = nullptr;
+		char m_uuid[1]; ///< This is part of the UUID
+	};
+
+	ControlBlock* m_cb = nullptr;
+
+	void reset();
 
 
 	/// If this empty and @a b empty then unload. If @a b has something then
 	/// If this empty and @a b empty then unload. If @a b has something then
 	/// unload this and load exactly what @b has. In everything else do nothing
 	/// unload this and load exactly what @b has. In everything else do nothing
-	void copy(const Self& b)
-	{
-		if(b.hook == nullptr)
-		{
-			if(hook != nullptr)
-			{
-				unload();
-			}
-		}
-		else
-		{
-			unload();
-			load(b.hook->uuid.c_str());
-		}
-	}
+	void copy(const ResourcePointer& b);
 };
 };
 
 
+/// @}
+
 } // end namespace anki
 } // end namespace anki
 
 
+#include "anki/resource/ResourcePointer.inl.h"
+
 #endif
 #endif

+ 90 - 0
include/anki/resource/ResourcePointer.inl.h

@@ -0,0 +1,90 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include "anki/resource/ResourcePointer.h"
+
+namespace anki {
+
+//==============================================================================
+template<typename T, typename TResourceManager>
+void ResourcePointer<T, TResourceManager>::load(
+	const char* filename, TResourceManager* resources)
+{
+	ANKI_ASSERT(m_cb == nullptr);
+	ANKI_ASSERT(filename != nullptr);
+	ANKI_ASSERT(resources != nullptr);
+
+	ResourcePointer other;
+	Bool found = resources->_findLoadedResource(filename, other);
+
+	if(!found)
+	{
+		// Allocate m_cb
+		U len = std::strlen(filename);
+		PtrSize alignment = alignof(ControlBlock);
+		m_cb = resources->_getAllocator().allocate(
+			sizeof(ControlBlock) + len, &alignment);
+		resources->_getAllocator().construct(m_cb);
+
+		// Populate the m_cb
+		try
+		{
+			m_cb->m_resource.load(filename);
+		}
+		catch(const std::exception& e)
+		{
+			m_cb->m_resources->_getAllocator().deleteInstance(m_cb);	
+		}
+
+		m_cb->m_resources = resources;
+		std::memcpy(&m_cb->m_uuid[0], filename, len + 1);
+
+		// Register resource
+		resources->_registerResource(*this);
+	}
+	else
+	{
+		*this = other;
+	}
+}
+
+//==============================================================================
+template<typename T, typename TResourceManager>
+void ResourcePointer<T, TResourceManager>::reset()
+{
+	if(m_cb != nullptr)
+	{
+		auto count = m_cb->m_refcount.fetch_sub(1);
+		if(count == 2)
+		{
+			m_cb->m_resources->_unregisterResource(*this);
+		}
+		else if(count == 1)
+		{
+			m_cb->m_resources->_getAllocator().deleteInstance(m_cb);
+		}
+
+		m_cb = nullptr;
+	}
+}
+
+//==============================================================================
+template<typename T, typename TResourceManager>
+void ResourcePointer<T, TResourceManager>::copy(const ResourcePointer& b)
+{
+	reset();
+	
+	if(b.m_cb == nullptr)
+	{
+		auto count = b.m_cb->m_refcount.fetch_add(1);
+		ANKI_ASSERT(count > 0);
+		(void)count;
+
+		m_cb = b.m_cb;
+	}
+}
+
+} // end namespace anki
+

+ 1 - 1
include/anki/scene/RenderComponent.h

@@ -219,7 +219,7 @@ public:
 	RenderingKey m_key;
 	RenderingKey m_key;
 	const U8* m_subMeshIndicesArray; ///< @note indices != drawing indices
 	const U8* m_subMeshIndicesArray; ///< @note indices != drawing indices
 	U32 m_subMeshIndicesCount;
 	U32 m_subMeshIndicesCount;
-	GlJobChainHandle m_jobs; ///< A job chain 
+	GlCommandBufferHandle m_jobs; ///< A job chain 
 };
 };
 
 
 /// RenderComponent interface. Implemented by renderable scene nodes
 /// RenderComponent interface. Implemented by renderable scene nodes

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

@@ -13,6 +13,7 @@
 #include "anki/Math.h"
 #include "anki/Math.h"
 #include "anki/util/Singleton.h"
 #include "anki/util/Singleton.h"
 #include "anki/util/HighRezTimer.h"
 #include "anki/util/HighRezTimer.h"
+#include "anki/core/App.h"
 
 
 #include "anki/scene/Sector.h"
 #include "anki/scene/Sector.h"
 #include "anki/physics/PhysicsWorld.h"
 #include "anki/physics/PhysicsWorld.h"
@@ -35,16 +36,14 @@ class SceneGraph
 public:
 public:
 	/// @name Constructors/Destructor
 	/// @name Constructors/Destructor
 	/// @{
 	/// @{
-	SceneGraph(AllocAlignedCallback allocCb, void* allocCbUserData);
+	SceneGraph(AllocAlignedCallback allocCb, void* allocCbData, 
+		Threadpool* threadpool);
 
 
 	~SceneGraph();
 	~SceneGraph();
 	/// @}
 	/// @}
 
 
 	void load(const char* filename);
 	void load(const char* filename);
 
 
-	/// @name Accessors
-	/// @{
-
 	/// @note Return a copy
 	/// @note Return a copy
 	SceneAllocator<U8> getAllocator() const
 	SceneAllocator<U8> getAllocator() const
 	{
 	{
@@ -121,7 +120,11 @@ public:
 	{
 	{
 		return m_sectorGroup;
 		return m_sectorGroup;
 	}
 	}
-	/// @}
+
+	Threadpool& _getThreadpool()
+	{
+		return *m_threadpool;
+	}
 
 
 	void update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer);
 	void update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer);
 
 
@@ -197,6 +200,8 @@ private:
 
 
 	std::atomic<U32> m_objectsMarkedForDeletionCount;
 	std::atomic<U32> m_objectsMarkedForDeletionCount;
 
 
+	Threadpool* m_threadpool;
+
 	/// Put a node in the appropriate containers
 	/// Put a node in the appropriate containers
 	void registerNode(SceneNode* node);
 	void registerNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);
@@ -205,7 +210,6 @@ private:
 	void deleteNodesMarkedForDeletion();
 	void deleteNodesMarkedForDeletion();
 };
 };
 
 
-typedef SingletonInit<SceneGraph> SceneGraphSingleton;
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 4 - 5
include/anki/scene/Visibility.h

@@ -11,7 +11,6 @@
 #include "anki/scene/SceneNode.h"
 #include "anki/scene/SceneNode.h"
 #include "anki/scene/SpatialComponent.h"
 #include "anki/scene/SpatialComponent.h"
 #include "anki/scene/RenderComponent.h"
 #include "anki/scene/RenderComponent.h"
-#include "anki/core/Threadpool.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/util/NonCopyable.h"
 
 
 namespace anki {
 namespace anki {
@@ -131,14 +130,14 @@ public:
 };
 };
 
 
 /// Thread job to short scene nodes by distance
 /// Thread job to short scene nodes by distance
-class DistanceSortJob: public ThreadpoolTask					
+class DistanceSortJob: public Threadpool::Task					
 {
 {
 public:
 public:
 	U32 m_nodesCount;
 	U32 m_nodesCount;
 	VisibilityTestResults::Container::iterator m_nodes;
 	VisibilityTestResults::Container::iterator m_nodes;
 	Vec4 m_origin;
 	Vec4 m_origin;
 
 
-	void operator()(ThreadId /*threadId*/, U /*threadsCount*/)
+	void operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
 	{
 	{
 		DistanceSortFunctor comp;
 		DistanceSortFunctor comp;
 		comp.m_origin = m_origin;
 		comp.m_origin = m_origin;
@@ -147,13 +146,13 @@ public:
 };
 };
 
 
 /// Thread job to short renderable scene nodes by material
 /// Thread job to short renderable scene nodes by material
-class MaterialSortJob: public ThreadpoolTask
+class MaterialSortJob: public Threadpool::Task
 {
 {
 public:
 public:
 	U32 m_nodesCount;
 	U32 m_nodesCount;
 	VisibilityTestResults::Container::iterator m_nodes;
 	VisibilityTestResults::Container::iterator m_nodes;
 
 
-	void operator()(ThreadId /*threadId*/, U /*threadsCount*/)
+	void operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
 	{
 	{
 		std::sort(m_nodes, m_nodes + m_nodesCount, MaterialSortFunctor());
 		std::sort(m_nodes, m_nodes + m_nodesCount, MaterialSortFunctor());
 	}
 	}

+ 12 - 9
include/anki/util/Allocator.h

@@ -122,21 +122,24 @@ public:
 	}
 	}
 
 
 	/// Allocate memory
 	/// Allocate memory
-	pointer allocate(size_type n, const void* hint = 0)
+	/// @param n The bytes to allocate
+	/// @param hint It's been used to override the alignment. The type should
+	///             be PtrSize
+	pointer allocate(size_type n, const void* hint = nullptr)
 	{
 	{
 		(void)hint;
 		(void)hint;
 
 
 		size_type size = n * sizeof(value_type);
 		size_type size = n * sizeof(value_type);
-		
+
 		// Operator new doesn't respect alignment (in GCC at least) so use 
 		// Operator new doesn't respect alignment (in GCC at least) so use 
-		// the allocation
-		void* out = m_pool.allocate(size, alignof(value_type));
+		// the types alignment. If hint override the alignment
+		PtrSize alignment = (hint != nullptr) 
+			? *reinterpret_cast<const PtrSize*>(hint) 
+			: alignof(value_type);
 
 
-		if(out != nullptr)
-		{
-			// Everything ok
-		}
-		else
+		void* out = m_pool.allocate(size, alignment);
+
+		if(out == nullptr)
 		{
 		{
 			throw ANKI_EXCEPTION("Allocation failed. There is not enough room");
 			throw ANKI_EXCEPTION("Allocation failed. There is not enough room");
 		}
 		}

+ 27 - 0
include/anki/util/Enum.h

@@ -0,0 +1,27 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#ifndef ANKI_UTIL_ENUM_H
+#define ANKI_UTIL_ENUM_H
+
+#include "anki/util/StdTypes.h"
+
+#define ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(enum_, qualifier_) \
+	qualifier_ enum_ operator|(enum_ a, enum_ b) \
+	{ \
+		return static_cast<enum_>(static_cast<U64>(a) | static_cast<U64>(b)); \
+	} \
+	qualifier_ void operator|=(enum_& a, enum_ b) \
+	{ \
+		a = static_cast<enum_>(static_cast<U64>(a) | static_cast<U64>(b)); \
+	} \
+	qualifier_ enum_ operator&(enum_ a, enum_ b) \
+	{ \
+		return static_cast<enum_>(static_cast<U64>(a) & static_cast<U64>(b)); \
+	}
+
+#endif
+
+

+ 18 - 17
include/anki/util/Memory.h

@@ -15,10 +15,10 @@ namespace anki {
 /// @{
 /// @{
 
 
 /// Allocate aligned memory
 /// Allocate aligned memory
-void* mallocAligned(PtrSize size, PtrSize alignmentBytes) throw();
+void* mallocAligned(PtrSize size, PtrSize alignmentBytes) noexcept;
 
 
 /// Free aligned memory
 /// Free aligned memory
-void freeAligned(void* ptr) throw();
+void freeAligned(void* ptr) noexcept;
 
 
 /// The function signature of a memory allocation/deallocation. 
 /// The function signature of a memory allocation/deallocation. 
 /// See allocAligned function for the explanation of arguments
 /// See allocAligned function for the explanation of arguments
@@ -36,7 +36,7 @@ using AllocAlignedCallback = void* (*)(void*, void*, PtrSize, PtrSize);
 /// @return On allocation mode it will return the newelly allocated block or
 /// @return On allocation mode it will return the newelly allocated block or
 ///         nullptr on error. On deallocation mode returns nullptr
 ///         nullptr on error. On deallocation mode returns nullptr
 void* allocAligned(
 void* allocAligned(
-	void* userData, void* ptr, PtrSize size, PtrSize alignment) throw();
+	void* userData, void* ptr, PtrSize size, PtrSize alignment) noexcept;
 
 
 /// A dummy interface to match the StackMemoryPool and ChainMemoryPool 
 /// A dummy interface to match the StackMemoryPool and ChainMemoryPool 
 /// interfaces in order to be used by the same allocator template
 /// interfaces in order to be used by the same allocator template
@@ -50,12 +50,12 @@ public:
 	///       that pool will call that constructor and that happens a lot.
 	///       that pool will call that constructor and that happens a lot.
 	///       If that constructor does some actual job then we have a problem.
 	///       If that constructor does some actual job then we have a problem.
 	HeapMemoryPool()
 	HeapMemoryPool()
-		: m_impl(nullptr)
+	:	m_impl(nullptr)
 	{}
 	{}
 
 
 	/// Copy constructor. It's not copying any data
 	/// Copy constructor. It's not copying any data
 	HeapMemoryPool(const HeapMemoryPool& other)
 	HeapMemoryPool(const HeapMemoryPool& other)
-		: m_impl(nullptr)
+	:	m_impl(nullptr)
 	{
 	{
 		*this = other;
 		*this = other;
 	}
 	}
@@ -76,10 +76,10 @@ public:
 	HeapMemoryPool& operator=(const HeapMemoryPool& other);
 	HeapMemoryPool& operator=(const HeapMemoryPool& other);
 
 
 	/// Allocate memory
 	/// Allocate memory
-	void* allocate(PtrSize size, PtrSize alignment) throw();
+	void* allocate(PtrSize size, PtrSize alignment) noexcept;
 
 
 	/// Free memory
 	/// Free memory
-	Bool free(void* ptr) throw();
+	Bool free(void* ptr) noexcept;
 
 
 	/// Return number of allocations
 	/// Return number of allocations
 	U32 getAllocationsCount() const;
 	U32 getAllocationsCount() const;
@@ -109,12 +109,12 @@ public:
 
 
 	/// Default constructor
 	/// Default constructor
 	StackMemoryPool()
 	StackMemoryPool()
-		: m_impl(nullptr)
+	:	m_impl(nullptr)
 	{}
 	{}
 
 
 	/// Copy constructor. It's not copying any data
 	/// Copy constructor. It's not copying any data
 	StackMemoryPool(const StackMemoryPool& other)
 	StackMemoryPool(const StackMemoryPool& other)
-		: m_impl(nullptr)
+	:	m_impl(nullptr)
 	{
 	{
 		*this = other;
 		*this = other;
 	}
 	}
@@ -143,14 +143,14 @@ public:
 	/// @param size The size to allocate
 	/// @param size The size to allocate
 	/// @param alignmentBytes The alignment of the returned address
 	/// @param alignmentBytes The alignment of the returned address
 	/// @return The allocated memory or nullptr on failure
 	/// @return The allocated memory or nullptr on failure
-	void* allocate(PtrSize size, PtrSize alignmentBytes) throw();
+	void* allocate(PtrSize size, PtrSize alignmentBytes) noexcept;
 
 
 	/// Free memory in StackMemoryPool. If the ptr is not the last allocation
 	/// Free memory in StackMemoryPool. If the ptr is not the last allocation
 	/// then nothing happens and the method returns false. The operation is
 	/// then nothing happens and the method returns false. The operation is
 	/// threadsafe
 	/// threadsafe
 	/// @param[in, out] ptr Memory block to deallocate
 	/// @param[in, out] ptr Memory block to deallocate
 	/// @return True if the deallocation actually happened and false otherwise
 	/// @return True if the deallocation actually happened and false otherwise
-	Bool free(void* ptr) throw();
+	Bool free(void* ptr) noexcept;
 
 
 	/// Reinit the pool. All existing allocated memory will be lost
 	/// Reinit the pool. All existing allocated memory will be lost
 	void reset();
 	void reset();
@@ -194,7 +194,7 @@ public:
 	/// Chunk allocation method. Defines the size a newely created chunk should
 	/// Chunk allocation method. Defines the size a newely created chunk should
 	/// have compared to the last created. Used to grow chunks over the time of
 	/// have compared to the last created. Used to grow chunks over the time of
 	/// allocations
 	/// allocations
-	enum ChunkAllocationStepMethod
+	enum class ChunkGrowMethod: U8
 	{
 	{
 		FIXED, ///< All chunks have the same size
 		FIXED, ///< All chunks have the same size
 		MULTIPLY, ///< Next chuck's size will be old_chuck_size * a_value
 		MULTIPLY, ///< Next chuck's size will be old_chuck_size * a_value
@@ -203,12 +203,12 @@ public:
 
 
 	/// Default constructor
 	/// Default constructor
 	ChainMemoryPool()
 	ChainMemoryPool()
-		: m_impl(nullptr)
+	:	m_impl(nullptr)
 	{}
 	{}
 
 
 	/// Copy constructor. It's not copying any data
 	/// Copy constructor. It's not copying any data
 	ChainMemoryPool(const ChainMemoryPool& other)
 	ChainMemoryPool(const ChainMemoryPool& other)
-		: m_impl(nullptr)
+	:	m_impl(nullptr)
 	{
 	{
 		*this = other;
 		*this = other;
 	}
 	}
@@ -227,7 +227,8 @@ public:
 		AllocAlignedCallback alloc, void* allocUserData,
 		AllocAlignedCallback alloc, void* allocUserData,
 		PtrSize initialChunkSize,
 		PtrSize initialChunkSize,
 		PtrSize maxChunkSize,
 		PtrSize maxChunkSize,
-		ChunkAllocationStepMethod chunkAllocStepMethod = MULTIPLY, 
+		ChunkGrowMethod chunkAllocStepMethod = 
+			ChunkGrowMethod::MULTIPLY, 
 		PtrSize chunkAllocStep = 2, 
 		PtrSize chunkAllocStep = 2, 
 		PtrSize alignmentBytes = ANKI_SAFE_ALIGNMENT);
 		PtrSize alignmentBytes = ANKI_SAFE_ALIGNMENT);
 
 
@@ -245,13 +246,13 @@ public:
 	/// @param size The size to allocate
 	/// @param size The size to allocate
 	/// @param alignmentBytes The alignment of the returned address
 	/// @param alignmentBytes The alignment of the returned address
 	/// @return The allocated memory or nullptr on failure
 	/// @return The allocated memory or nullptr on failure
-	void* allocate(PtrSize size, PtrSize alignmentBytes) throw();
+	void* allocate(PtrSize size, PtrSize alignmentBytes) noexcept;
 
 
 	/// Free memory. If the ptr is not the last allocation of the chunk
 	/// Free memory. If the ptr is not the last allocation of the chunk
 	/// then nothing happens and the method returns false
 	/// then nothing happens and the method returns false
 	/// @param[in, out] ptr Memory block to deallocate
 	/// @param[in, out] ptr Memory block to deallocate
 	/// @return True if the deallocation actually happened and false otherwise
 	/// @return True if the deallocation actually happened and false otherwise
-	Bool free(void* ptr) throw();
+	Bool free(void* ptr) noexcept;
 
 
 	/// Get the number of users for this pool
 	/// Get the number of users for this pool
 	U32 getUsersCount() const;
 	U32 getUsersCount() const;

+ 152 - 156
include/anki/util/Thread.h

@@ -9,10 +9,10 @@
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/util/NonCopyable.h"
-#include <thread>
-#include <condition_variable>
-#include <mutex>
 #include <atomic>
 #include <atomic>
+#include <mutex> // XXX
+#include <thread> // XXX
+#include <condition_variable>
 
 
 #define ANKI_DISABLE_THREADPOOL_THREADING 0
 #define ANKI_DISABLE_THREADPOOL_THREADING 0
 
 
@@ -24,228 +24,224 @@ class Threadpool;
 /// @addtogroup util_thread
 /// @addtogroup util_thread
 /// @{
 /// @{
 
 
-typedef U32 ThreadId;
-
-/// Set the name of the current thead
-void setCurrentThreadName(const char* name);
-
-/// Spin lock. Good if the critical section will be executed in a short period
-/// of time
-class SpinLock
+/// Thread implementation
+class Thread: public NonCopyable
 {
 {
 public:
 public:
-	/// Lock 
-	void lock()
+	/// It holds some information to be passed to the thread's callback
+	class Info
 	{
 	{
-		while(m_lock.test_and_set(std::memory_order_acquire))
-		{}
-	}
+	public:
+		void* m_userData;
+		const char* m_threadName;
+	};
 
 
-	/// Unlock
-	void unlock()
-	{
-		m_lock.clear(std::memory_order_release);
-	}
+	/// The type of the tread callback
+	using Callback = I(*)(Info&);
+
+	/// Create a thread with or without a name
+	/// @param[in] name The name of the new thread. Can be nullptr
+	Thread(const char* name);
+
+	~Thread();
+
+	/// Start the thread
+	/// @param userData The user data of the thread callback
+	/// @param callback The thread callback that will be executed
+	void start(void* userData, Callback callback);
+
+	/// Wait for the thread to finish
+	/// @return The error code of the thread's callback
+	I join();
+
+	/// Identify the current thread
+	static U64 getCurrentThreadId();
 
 
 private:
 private:
-	std::atomic_flag m_lock = ATOMIC_FLAG_INIT;	
+	static constexpr U ALIGNMENT = 8;
+	alignas(ALIGNMENT) Array<PtrSize, 1> m_impl; ///< The system native type
+	Array<char, 32> m_name; ///< The name of the thread
+	Callback m_callback = nullptr; ///< The callback
+	void* m_userData = nullptr; ///< The user date to pass to the callback
+
+	/// Pthreads specific function
+	static void* pthreadCallback(void* ud);
+
+	Bool initialized() const
+	{
+		return m_impl[0] != 0;
+	}
 };
 };
 
 
-/// A barrier for thread synchronization. It works just like boost::barrier
-class Barrier: public NonCopyable
+/// Mutex
+class Mutex: public NonCopyable
 {
 {
+	friend class ConditionVariable;
+
 public:
 public:
-	Barrier(U32 count)
-		: m_threshold(count), m_count(count), m_generation(0)
-	{
-		ANKI_ASSERT(count != 0);
-	}
+	Mutex();
 
 
-	Bool wait()
-	{
-		std::unique_lock<std::mutex> lock(m_mtx);
-		U32 gen = m_generation;
+	~Mutex();
 
 
-		if(--m_count == 0)
-		{
-			m_generation++;
-			m_count = m_threshold;
-			m_cond.notify_all();
-			return true;
-		}
+	/// Lock
+	void lock();
 
 
-		while(gen == m_generation)
-		{
-			m_cond.wait(lock);
-		}
-		return false;
-	}
+	/// Try lock
+	/// @return True if it was locked successfully
+	Bool tryLock();
+
+	/// Unlock
+	void unlock();
 
 
 private:
 private:
-	std::mutex m_mtx;
-	std::condition_variable m_cond;
-	U32 m_threshold;
-	U32 m_count;
-	U32 m_generation;
+	static constexpr U ALIGNMENT = 8;
+	alignas(ALIGNMENT) Array<PtrSize, 10> m_impl; ///< The system native type
 };
 };
 
 
-/// A task assignment to threads
-class ThreadTask
+/// Condition variable
+class ConditionVariable: public NonCopyable
 {
 {
 public:
 public:
-	virtual ~ThreadTask()
-	{}
+	ConditionVariable();
 
 
-	virtual void operator()(ThreadId threadId) = 0;
-};
+	~ConditionVariable();
 
 
-/// This is a thread with 2 sync points
-class DualSyncThread
-{
-public:
-	DualSyncThread(ThreadId threadId)
-		:	m_id(threadId),
-			m_barriers{{{2}, {2}}},
-			m_task(nullptr)
-	{}
-
-	/// The thread does not own the task
-	/// @note This operation is not thread safe. Call it between syncs
-	/// @note This class will not own the task
-	void setTask(ThreadTask* task)
-	{
-		m_task = task;
-	}
+	/// Signal one thread
+	void notifyOne();
 
 
-	/// Start the thread
-	void start()
-	{
-		m_thread = std::thread(&DualSyncThread::workingFunc, this);
-	}
+	/// Signal all threads
+	void notifyAll();
 
 
-	/// Sync with one of the 2 sync points
-	void sync(U syncPoint)
-	{
-		m_barriers[syncPoint].wait();
-	}
+	/// Bock until signaled
+	void wait(Mutex& mtx);
 
 
 private:
 private:
-	ThreadId m_id;
-	std::thread m_thread; ///< Runs the workingFunc
-	Array<Barrier, 2> m_barriers;
-	ThreadTask* m_task; ///< Its nullptr if there are no pending task
-
-	/// Thread loop
-	void workingFunc();
+	static constexpr U ALIGNMENT = 16;
+	alignas(ALIGNMENT) Array<PtrSize, 12> m_impl; ///< The system native type
 };
 };
 
 
-/// A task assignment for a ThreadpoolThread
-class ThreadpoolTask
+/// Spin lock. Good if the critical section will be executed in a short period
+/// of time
+class SpinLock: public NonCopyable
 {
 {
 public:
 public:
-	virtual ~ThreadpoolTask()
-	{}
-
-	virtual void operator()(ThreadId threadId, U threadsCount) = 0;
+	/// Lock 
+	void lock()
+	{
+		while(m_lock.test_and_set(std::memory_order_acquire))
+		{}
+	}
 
 
-	/// Chose a starting and end index
-	void choseStartEnd(ThreadId threadId, PtrSize threadsCount, 
-		PtrSize elementsCount, PtrSize& start, PtrSize& end)
+	/// Unlock
+	void unlock()
 	{
 	{
-		start = threadId * (elementsCount / threadsCount);
-		end = (threadId == threadsCount - 1)
-			? elementsCount
-			: start + elementsCount / threadsCount;
+		m_lock.clear(std::memory_order_release);
 	}
 	}
+
+private:
+	std::atomic_flag m_lock = ATOMIC_FLAG_INIT;	
 };
 };
 
 
-/// A dummy thread pool task
-class DummyThreadpoolTask: public ThreadpoolTask
+/// A barrier for thread synchronization. It works just like boost::barrier
+class Barrier: public NonCopyable
 {
 {
 public:
 public:
-	void operator()(ThreadId threadId, U threadsCount)
+	Barrier(U32 count)
+	:	m_threshold(count), 
+		m_count(count), 
+		m_generation(0)
 	{
 	{
-		(void)threadId;
-		(void)threadsCount;
+		ANKI_ASSERT(count != 0);
 	}
 	}
-};
 
 
-/// The thread that executes a ThreadpoolTask
-class ThreadpoolThread
-{
-public:
-	/// Constructor
-	ThreadpoolThread(ThreadId id, Barrier* barrier, Threadpool* threadpool);
+	~Barrier() = default;
 
 
-	/// Assign new task to the thread
-	/// @note 
-	void assignNewTask(ThreadpoolTask* task);
+	/// TODO
+	Bool wait();
 
 
 private:
 private:
-	ThreadId m_id; ///< An ID
-	std::thread m_thread; ///< Runs the workingFunc
-	std::mutex m_mutex; ///< Protect the task
-	std::condition_variable m_condVar; ///< To wake up the thread
-	Barrier* m_barrier; ///< For synchronization
-	ThreadpoolTask* m_task; ///< Its NULL if there are no pending task
-	Threadpool* m_threadpool;
-
-	/// Start thread
-	void start()
-	{
-		m_thread = std::thread(&ThreadpoolThread::workingFunc, this);
-	}
-
-	/// Thread loop
-	void workingFunc();
+	Mutex m_mtx;
+	ConditionVariable m_cond;
+	U32 m_threshold;
+	U32 m_count;
+	U32 m_generation;
 };
 };
 
 
-/// Parallel task dispatcher.You feed it with tasks and sends them for
+// Forward
+namespace detail {
+class ThreadpoolThread;
+}
+
+/// Parallel task dispatcher. You feed it with tasks and sends them for
 /// execution in parallel and then waits for all to finish
 /// execution in parallel and then waits for all to finish
 class Threadpool: public NonCopyable
 class Threadpool: public NonCopyable
 {
 {
+	friend class detail::ThreadpoolThread;
+
 public:
 public:
 	static constexpr U MAX_THREADS = 32; ///< An absolute limit
 	static constexpr U MAX_THREADS = 32; ///< An absolute limit
 
 
-	/// Default constructor
-	Threadpool()
-	{}
-
-	/// Constructor #2
-	Threadpool(U threadsNum)
+	/// A task assignment for a Threadpool
+	class Task
 	{
 	{
-		init(threadsNum);
-	}
+	public:
+		virtual ~Task()
+		{}
 
 
-	~Threadpool();
+		virtual void operator()(U32 taskId, PtrSize threadsCount) = 0;
 
 
-	/// Init the manager
-	void init(U threadsNum);
+		/// Chose a starting and end index
+		static void choseStartEnd(U32 taskId, PtrSize threadsCount, 
+			PtrSize elementsCount, PtrSize& start, PtrSize& end)
+		{
+			start = taskId * (elementsCount / threadsCount);
+			end = (taskId == threadsCount - 1)
+				? elementsCount
+				: start + elementsCount / threadsCount;
+		}
+	};
+
+	/// Constructor 
+	Threadpool(U32 threadsCount);
+
+	~Threadpool();
 
 
 	/// Assign a task to a working thread
 	/// Assign a task to a working thread
-	void assignNewTask(U taskId, ThreadpoolTask* task)
-	{
-		ANKI_ASSERT(taskId < getThreadsCount());
-		m_threads[taskId]->assignNewTask(task);
-	}
+	/// @param slot The slot of the task
+	/// @param task The task. If it's nullptr then a dummy task will be assigned
+	void assignNewTask(U32 slot, Task* task);
 
 
 	/// Wait for all tasks to finish
 	/// Wait for all tasks to finish
 	void waitForAllThreadsToFinish()
 	void waitForAllThreadsToFinish()
 	{
 	{
 #if !ANKI_DISABLE_THREADPOOL_THREADING
 #if !ANKI_DISABLE_THREADPOOL_THREADING
-		m_barrier->wait();
+		m_barrier.wait();
 #endif
 #endif
 	}
 	}
 
 
-	U getThreadsCount() const
+	PtrSize getThreadsCount() const
 	{
 	{
 		return m_threadsCount;
 		return m_threadsCount;
 	}
 	}
 
 
 private:
 private:
-	ThreadpoolThread** m_threads = nullptr; ///< Worker threads array
+	/// A dummy task for a Threadpool
+	class DummyTask: public Task
+	{
+	public:
+		void operator()(U32 taskId, PtrSize threadsCount)
+		{
+			(void)taskId;
+			(void)threadsCount;
+		}
+	};
+
+#if !ANKI_DISABLE_THREADPOOL_THREADING
+	Barrier m_barrier; ///< Synchronization barrier
+	detail::ThreadpoolThread** m_threads = nullptr; ///< Threads array
+#endif
 	U8 m_threadsCount = 0;
 	U8 m_threadsCount = 0;
-	std::unique_ptr<Barrier> m_barrier; ///< Synchronization barrier
+	static DummyTask m_dummyTask;
 };
 };
 
 
 /// @}
 /// @}

+ 39 - 20
src/core/App.cpp

@@ -24,6 +24,8 @@
 #	include <android_native_app_glue.h>
 #	include <android_native_app_glue.h>
 #endif
 #endif
 
 
+// Sybsystems
+
 namespace anki {
 namespace anki {
 
 
 #if ANKI_OS == ANKI_OS_ANDROID
 #if ANKI_OS == ANKI_OS_ANDROID
@@ -32,34 +34,49 @@ android_app* gAndroidApp = nullptr;
 #endif
 #endif
 
 
 //==============================================================================
 //==============================================================================
-/// Bad things signal handler
-/*static void handler(int sig)
+App::App(AllocAlignedCallback allocCb, void* allocCbUserData)
+:	m_allocCb(allocCb),
+	m_allocCbData(allocCbUserData),
+	m_heapAlloc(HeapMemoryPool(allocCbUserData, allocCb))
 {
 {
-	void *array[10];
-	size_t size;
-
-	// get void*'s for all entries on the stack
-	size = backtrace(array, 10);
-
-	// print out all the frames to stderr
-	fprintf(stderr, "Error: signal %d:\n", sig);
-	backtrace_symbols_fd(array, size, 2);
-	exit(1);
-}*/
+	init(config);
+}
 
 
 //==============================================================================
 //==============================================================================
-void App::init()
+void App::init(const Config& config)
 {
 {
-	setCurrentThreadName("anki_main");
-	// Install signal handlers
-	/*signal(SIGSEGV, handler);
-	signal(SIGBUS, handler);
-	signal(SIGFPE, handler);*/
-
 	printAppInfo();
 	printAppInfo();
 	initDirs();
 	initDirs();
 
 
 	timerTick = 1.0 / 60.0; // in sec. 1.0 / period
 	timerTick = 1.0 / 60.0; // in sec. 1.0 / period
+
+	// Logger
+	LoggerSingleton::init(
+		Logger::InitFlags::WITH_SYSTEM_MESSAGE_HANDLER, m_heapAlloc);
+
+	// Window
+	NativeWindow::Initializer nwinit;
+	nwinit.m_width = config.get("width");
+	nwinit.m_height = config.get("height");
+	nwinit.m_majorVersion = config.get("glmajor");
+	nwinit.m_minorVersion = config.get("glminor");
+	nwinit.m_depthBits = 0;
+	nwinit.m_stencilBits = 0;
+	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_window->contextMakeCurrent(nullptr);
+
+	// Input
+	m_input = m_heapAlloc.newInstance<Input>(m_window);
+
+	// Threadpool
+	m_threadpool = m_heapAlloc.newInstance<Threadpool>(getCpuCoresCount());
+
+	// Scene
+	m_scene = m_heapAlloc.newInstance<SceneGraph>(
+		m_allocCb, m_allocCbData, m_threadpool);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -142,6 +159,7 @@ void App::printAppInfo()
 //==============================================================================
 //==============================================================================
 void App::mainLoop()
 void App::mainLoop()
 {
 {
+#if 0
 	ANKI_LOGI("Entering main loop");
 	ANKI_LOGI("Entering main loop");
 
 
 	HighRezTimer::Scalar prevUpdateTime = HighRezTimer::getCurrentTime();
 	HighRezTimer::Scalar prevUpdateTime = HighRezTimer::getCurrentTime();
@@ -184,6 +202,7 @@ void App::mainLoop()
 	// Counters end
 	// Counters end
 	ANKI_COUNTER_STOP_TIMER_INC(FPS);
 	ANKI_COUNTER_STOP_TIMER_INC(FPS);
 	ANKI_COUNTERS_FLUSH();
 	ANKI_COUNTERS_FLUSH();
+#endif
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 1 - 1
src/core/Counters.cpp

@@ -45,7 +45,7 @@ static const Array<CounterInfo, (U)Counter::COUNT> cinfo = {{
 	{"GL_SERVER_WAIT_TIME", CF_PER_FRAME | CF_PER_RUN | CF_F64},
 	{"GL_SERVER_WAIT_TIME", CF_PER_FRAME | CF_PER_RUN | CF_F64},
 	{"GL_DRAWCALLS_COUNT", CF_PER_RUN | CF_U64},
 	{"GL_DRAWCALLS_COUNT", CF_PER_RUN | CF_U64},
 	{"GL_VERTICES_COUNT", CF_PER_FRAME | CF_PER_RUN | CF_U64},
 	{"GL_VERTICES_COUNT", CF_PER_FRAME | CF_PER_RUN | CF_U64},
-	{"GL_JOB_CHAINS_SIZE", CF_PER_FRAME | CF_PER_RUN | CF_U64},
+	{"GL_QUEUES_SIZE", CF_PER_FRAME | CF_PER_RUN | CF_U64},
 	{"GL_CLIENT_BUFFERS_SIZE", CF_PER_FRAME | CF_PER_RUN | CF_U64}
 	{"GL_CLIENT_BUFFERS_SIZE", CF_PER_FRAME | CF_PER_RUN | CF_U64}
 }};
 }};
 
 

+ 5 - 8
src/core/NativeWindowSdl.cpp

@@ -12,13 +12,10 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-NativeWindow::~NativeWindow()
-{}
-
-//==============================================================================
-void NativeWindow::create(NativeWindowInitializer& init)
+void NativeWindow::create(Initializer& init, HeapAllocator<U8>& alloc)
 {
 {
-	m_impl.reset(new NativeWindowImpl);
+	m_alloc = alloc;
+	m_impl = m_alloc.newInstance<NativeWindowImpl>();
 
 
 	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS 
 	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS 
 		| SDL_INIT_GAMECONTROLLER) != 0)
 		| SDL_INIT_GAMECONTROLLER) != 0)
@@ -113,7 +110,7 @@ void NativeWindow::create(NativeWindowInitializer& init)
 //==============================================================================
 //==============================================================================
 void NativeWindow::destroy()
 void NativeWindow::destroy()
 {
 {
-	if(m_impl.get())
+	if(m_impl != nullptr)
 	{
 	{
 		if(m_impl->m_context)
 		if(m_impl->m_context)
 		{
 		{
@@ -126,7 +123,7 @@ void NativeWindow::destroy()
 		}
 		}
 	}
 	}
 
 
-	m_impl.reset();
+	m_alloc.deleteInstance(m_impl);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 29 - 15
src/core/StdinListener.cpp

@@ -11,39 +11,53 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-void StdinListener::workingFunc()
+StdinListener::StdinListener()
+:	m_thrd("anki_stdin")
 {
 {
-	setCurrentThreadName("anki_stdin");
+	m_thrd.start(this, workingFunc);	
+}
+
+//==============================================================================
+StdinListener::~StdinListener()
+{
+	m_quit = true;
+	// TODO write(0, );
+	m_thrd.join();
+}
+
+//==============================================================================
+I StdinListener::workingFunc(Thread::Info& info)
+{
+	StdinListener& self = *reinterpret_cast<StdinListener*>(info.m_userData);
 	Array<char, 512> buff;
 	Array<char, 512> buff;
 
 
-	while(1)
+	while(!self.m_quit)
 	{
 	{
-		int m = read(0, &buff[0], sizeof(buff));
+		I m = read(0, &buff[0], sizeof(buff));
 		buff[m] = '\0';
 		buff[m] = '\0';
-		{
-			std::lock_guard<std::mutex> lock(m_mtx);
-			m_q.push(String(&buff[0]));
-		}
+		self.m_mtx.lock();
+		self.m_q.push(String(&buff[0]));
+		self.m_mtx.unlock();
 	}
 	}
+
+	return 1;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 String StdinListener::getLine()
 String StdinListener::getLine()
 {
 {
 	String ret;
 	String ret;
-	std::lock_guard<std::mutex> lock(m_mtx);
+	m_mtx.lock();
+	
 	if(!m_q.empty())
 	if(!m_q.empty())
 	{
 	{
 		ret = m_q.front();
 		ret = m_q.front();
 		m_q.pop();
 		m_q.pop();
 	}
 	}
-	return ret;
-}
 
 
-//==============================================================================
-void StdinListener::start()
-{
-	m_thrd = std::thread(&StdinListener::workingFunc, this);
+	m_mtx.unlock();
+
+	return ret;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 68 - 52
src/gl/GlBufferHandle.cpp

@@ -7,13 +7,13 @@
 #include "anki/gl/GlHandleDeferredDeleter.h"
 #include "anki/gl/GlHandleDeferredDeleter.h"
 #include "anki/gl/GlClientBufferHandle.h"
 #include "anki/gl/GlClientBufferHandle.h"
 #include "anki/gl/GlBuffer.h"
 #include "anki/gl/GlBuffer.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlDevice.h"
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-/// Create buffer job
-class GlBufferCreateJob: public GlJob
+/// Create buffer command
+class GlBufferCreateCommand: public GlCommand
 {
 {
 public:
 public:
 	GlBufferHandle m_buff;
 	GlBufferHandle m_buff;
@@ -23,20 +23,26 @@ public:
 	GLbitfield m_flags;
 	GLbitfield m_flags;
 	Bool8 m_empty;
 	Bool8 m_empty;
 
 
-	GlBufferCreateJob(
+	GlBufferCreateCommand(
 		GlBufferHandle buff, GLenum target, GlClientBufferHandle data, 
 		GlBufferHandle buff, GLenum target, GlClientBufferHandle data, 
 		GLenum flags)
 		GLenum flags)
-		:	m_buff(buff), m_target(target), m_data(data), m_flags(flags), 
-			m_empty(false)
+	:	m_buff(buff), 
+		m_target(target), 
+		m_data(data), 
+		m_flags(flags), 
+		m_empty(false)
 	{}
 	{}
 
 
-	GlBufferCreateJob(
+	GlBufferCreateCommand(
 		GlBufferHandle buff, GLenum target, PtrSize size, GLenum flags)
 		GlBufferHandle buff, GLenum target, PtrSize size, GLenum flags)
-		:	m_buff(buff), m_target(target), m_size(size), m_flags(flags), 
-			m_empty(true)
+	:	m_buff(buff), 
+		m_target(target), 
+		m_size(size), 
+		m_flags(flags), 
+		m_empty(true)
 	{}
 	{}
 
 
-	void operator()(GlJobChain*)
+	void operator()(GlCommandBuffer*)
 	{
 	{
 		if(!m_empty)
 		if(!m_empty)
 		{
 		{
@@ -61,47 +67,51 @@ GlBufferHandle::GlBufferHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-GlBufferHandle::GlBufferHandle(GlJobChainHandle& jobs,
+GlBufferHandle::GlBufferHandle(GlCommandBufferHandle& commands,
 	GLenum target, GlClientBufferHandle& data, GLenum flags)
 	GLenum target, GlClientBufferHandle& data, GLenum flags)
 {
 {
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(!isCreated());
 
 
-	typedef GlGlobalHeapAllocator<GlBuffer> Alloc;
+	using Alloc = GlGlobalHeapAllocator<GlBuffer>;
 
 
-	typedef GlDeleteObjectJob<GlBuffer, GlGlobalHeapAllocator<U8>> DeleteJob;
+	using DeleteCommand = 
+		GlDeleteObjectCommand<GlBuffer, GlGlobalHeapAllocator<U8>>;
 
 
-	typedef GlHandleDeferredDeleter<GlBuffer, Alloc, DeleteJob> Deleter;
+	using Deleter = GlHandleDeferredDeleter<GlBuffer, Alloc, DeleteCommand>;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._getJobManager().getManager(),
-		jobs._getJobManager().getManager()._getAllocator(), 
+		&commands._getQueue().getManager(),
+		commands._getQueue().getManager()._getAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
-	// Fire the job
-	jobs._pushBackNewJob<GlBufferCreateJob>(*this, target, data, flags);
+	// Fire the command
+	commands._pushBackNewCommand<GlBufferCreateCommand>(
+		*this, target, data, flags);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-GlBufferHandle::GlBufferHandle(GlJobChainHandle& jobs,
+GlBufferHandle::GlBufferHandle(GlCommandBufferHandle& commands,
 	GLenum target, PtrSize size, GLenum flags)
 	GLenum target, PtrSize size, GLenum flags)
 {
 {
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(!isCreated());
 
 
-	typedef GlGlobalHeapAllocator<GlBuffer> Alloc;
+	using Alloc = GlGlobalHeapAllocator<GlBuffer>;
 
 
-	typedef GlDeleteObjectJob<GlBuffer, GlGlobalHeapAllocator<U8>> DeleteJob;
+	using DeleteCommand = 
+		GlDeleteObjectCommand<GlBuffer, GlGlobalHeapAllocator<U8>>;
 
 
-	typedef GlHandleDeferredDeleter<GlBuffer, Alloc, DeleteJob>	Deleter;
+	using Deleter = GlHandleDeferredDeleter<GlBuffer, Alloc, DeleteCommand>;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._getJobManager().getManager(),
-		jobs._getJobManager().getManager()._getAllocator(), 
+		&commands._getQueue().getManager(),
+		commands._getQueue().getManager()._getAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
-	// Fire the job
-	jobs._pushBackNewJob<GlBufferCreateJob>(*this, target, size, flags);
+	// Fire the command
+	commands._pushBackNewCommand<GlBufferCreateCommand>(
+		*this, target, size, flags);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -109,10 +119,11 @@ GlBufferHandle::~GlBufferHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlBufferHandle::write(GlJobChainHandle& chain, GlClientBufferHandle& data, 
-	PtrSize readOffset, PtrSize writeOffset, PtrSize size)
+void GlBufferHandle::write(GlCommandBufferHandle& commands, 
+	GlClientBufferHandle& data, PtrSize readOffset, PtrSize writeOffset, 
+	PtrSize size)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlBufferHandle m_buff;
 		GlBufferHandle m_buff;
@@ -121,13 +132,13 @@ void GlBufferHandle::write(GlJobChainHandle& chain, GlClientBufferHandle& data,
 		PtrSize m_writeOffset;
 		PtrSize m_writeOffset;
 		PtrSize m_size;
 		PtrSize m_size;
 
 
-		Job(GlBufferHandle& buff, GlClientBufferHandle& data, 
+		Command(GlBufferHandle& buff, GlClientBufferHandle& data, 
 			PtrSize readOffset, PtrSize writeOffset, PtrSize size)
 			PtrSize readOffset, PtrSize writeOffset, PtrSize size)
 			:	m_buff(buff), m_data(data), m_readOffset(readOffset), 
 			:	m_buff(buff), m_data(data), m_readOffset(readOffset), 
 				m_writeOffset(writeOffset), m_size(size)
 				m_writeOffset(writeOffset), m_size(size)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			ANKI_ASSERT(m_readOffset + m_size <= m_data.getSize());
 			ANKI_ASSERT(m_readOffset + m_size <= m_data.getSize());
 
 
@@ -139,14 +150,15 @@ void GlBufferHandle::write(GlJobChainHandle& chain, GlClientBufferHandle& data,
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	chain._pushBackNewJob<Job>(*this, data, readOffset, writeOffset, size);
+	commands._pushBackNewCommand<Command>(
+		*this, data, readOffset, writeOffset, size);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlBufferHandle::bindShaderBufferInternal(GlJobChainHandle& jobs,
+void GlBufferHandle::bindShaderBufferInternal(GlCommandBufferHandle& commands,
 	I32 offset, I32 size, U32 bindingPoint)
 	I32 offset, I32 size, U32 bindingPoint)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlBufferHandle m_buff;
 		GlBufferHandle m_buff;
@@ -154,11 +166,11 @@ void GlBufferHandle::bindShaderBufferInternal(GlJobChainHandle& jobs,
 		I32 m_size;
 		I32 m_size;
 		U8 m_binding;
 		U8 m_binding;
 
 
-		Job(GlBufferHandle& buff, I32 offset, I32 size, U8 binding)
+		Command(GlBufferHandle& buff, I32 offset, I32 size, U8 binding)
 			: m_buff(buff), m_offset(offset), m_size(size), m_binding(binding)
 			: m_buff(buff), m_offset(offset), m_size(size), m_binding(binding)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			U32 offset = (m_offset != -1) ? m_offset : 0;
 			U32 offset = (m_offset != -1) ? m_offset : 0;
 			U32 size = (m_size != -1) ? m_size : m_buff._get().getSize();
 			U32 size = (m_size != -1) ? m_size : m_buff._get().getSize();
@@ -168,12 +180,12 @@ void GlBufferHandle::bindShaderBufferInternal(GlJobChainHandle& jobs,
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, offset, size, bindingPoint);
+	commands._pushBackNewCommand<Command>(*this, offset, size, bindingPoint);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 void GlBufferHandle::bindVertexBuffer(
 void GlBufferHandle::bindVertexBuffer(
-	GlJobChainHandle& jobs, 
+	GlCommandBufferHandle& commands, 
 	U32 elementSize,
 	U32 elementSize,
 	GLenum type,
 	GLenum type,
 	Bool normalized,
 	Bool normalized,
@@ -181,7 +193,7 @@ void GlBufferHandle::bindVertexBuffer(
 	PtrSize offset,
 	PtrSize offset,
 	U32 attribLocation)
 	U32 attribLocation)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlBufferHandle m_buff;
 		GlBufferHandle m_buff;
@@ -192,14 +204,18 @@ void GlBufferHandle::bindVertexBuffer(
 		U32 m_offset;
 		U32 m_offset;
 		U32 m_attribLocation;
 		U32 m_attribLocation;
 
 
-		Job(GlBufferHandle& buff, U32 elementSize, GLenum type, 
+		Command(GlBufferHandle& buff, U32 elementSize, GLenum type, 
 			Bool8 normalized, U32 stride, U32 offset, U32 attribLocation)
 			Bool8 normalized, U32 stride, U32 offset, U32 attribLocation)
-			:	m_buff(buff), m_elementSize(elementSize), m_type(type), 
-				m_normalized(normalized), m_stride(stride),	m_offset(offset),
-				m_attribLocation(attribLocation)
+		:	m_buff(buff), 
+			m_elementSize(elementSize), 
+			m_type(type), 
+			m_normalized(normalized), 
+			m_stride(stride),
+			m_offset(offset),
+			m_attribLocation(attribLocation)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			GlBuffer& buff = m_buff._get();
 			GlBuffer& buff = m_buff._get();
 			ANKI_ASSERT(m_offset < m_buff.getSize());
 			ANKI_ASSERT(m_offset < m_buff.getSize());
@@ -219,23 +235,23 @@ void GlBufferHandle::bindVertexBuffer(
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, elementSize, type, normalized, stride,
-		offset, attribLocation);
+	commands._pushBackNewCommand<Command>(*this, elementSize, type, 
+		normalized, stride, offset, attribLocation);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlBufferHandle::bindIndexBuffer(GlJobChainHandle& jobs)
+void GlBufferHandle::bindIndexBuffer(GlCommandBufferHandle& commands)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlBufferHandle m_buff;
 		GlBufferHandle m_buff;
 
 
-		Job(GlBufferHandle& buff)
-			: m_buff(buff)
+		Command(GlBufferHandle& buff)
+		:	m_buff(buff)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			GlBuffer& buff = m_buff._get();
 			GlBuffer& buff = m_buff._get();
 			buff.setTarget(GL_ELEMENT_ARRAY_BUFFER);
 			buff.setTarget(GL_ELEMENT_ARRAY_BUFFER);
@@ -244,7 +260,7 @@ void GlBufferHandle::bindIndexBuffer(GlJobChainHandle& jobs)
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this);
+	commands._pushBackNewCommand<Command>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 5 - 5
src/gl/GlClientBufferHandle.cpp

@@ -5,8 +5,8 @@
 
 
 #include "anki/gl/GlClientBufferHandle.h"
 #include "anki/gl/GlClientBufferHandle.h"
 #include "anki/gl/GlClientBuffer.h"
 #include "anki/gl/GlClientBuffer.h"
-#include "anki/gl/GlJobChainHandle.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlCommandBufferHandle.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"
 
 
 namespace anki {
 namespace anki {
@@ -17,14 +17,14 @@ GlClientBufferHandle::GlClientBufferHandle()
 
 
 //==============================================================================
 //==============================================================================
 GlClientBufferHandle::GlClientBufferHandle(
 GlClientBufferHandle::GlClientBufferHandle(
-	GlJobChainHandle& jobs, PtrSize size, void* preallocatedMem)
+	GlCommandBufferHandle& commands, PtrSize size, void* preallocatedMem)
 {
 {
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(!isCreated());
 
 
-	auto alloc = jobs._getAllocator();
+	auto alloc = commands._getAllocator();
 
 
 	typedef GlHandleDefaultDeleter<
 	typedef GlHandleDefaultDeleter<
-		GlClientBuffer, GlJobChainAllocator<GlClientBuffer>> Deleter;
+		GlClientBuffer, GlCommandBufferAllocator<GlClientBuffer>> Deleter;
 
 
 	if(preallocatedMem != nullptr)
 	if(preallocatedMem != nullptr)
 	{
 	{

+ 117 - 0
src/gl/GlCommandBuffer.cpp

@@ -0,0 +1,117 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include "anki/gl/GlCommandBuffer.h"
+#include "anki/gl/GlQueue.h"
+#include "anki/gl/GlDevice.h"
+#include "anki/gl/GlError.h"
+#include "anki/core/Logger.h"
+#include "anki/core/Counters.h"
+#include <cstring>
+
+namespace anki {
+
+//==============================================================================
+GlCommandBuffer::GlCommandBuffer(GlQueue* server, 
+	const GlCommandBufferInitHints& hints)
+:	m_server(server),
+	m_alloc(GlCommandBufferAllocator<GlCommand*>(ChainMemoryPool(
+		m_server->getAllocationCallback(),
+		m_server->getAllocationCallbackUserData(),
+		hints.m_chunkSize, 
+		hints.m_maxChunkSize, 
+		ChainMemoryPool::ChunkGrowMethod::ADD,
+		hints.m_chunkSize)))
+{
+	//std::cout << hints.m_chunkSize << std::endl;
+	ANKI_ASSERT(m_server);
+}
+
+//==============================================================================
+GlCommandBuffer& GlCommandBuffer::operator=(GlCommandBuffer&& b)
+{
+	destroy();
+	m_server = b.m_server; 
+	b.m_server = nullptr;
+	
+	m_firstCommand = b.m_firstCommand;
+	b.m_firstCommand = nullptr;
+	
+	m_lastCommand = b.m_lastCommand;
+	b.m_lastCommand = nullptr;
+
+	m_alloc = b.m_alloc;
+	b.m_alloc = GlCommandBufferAllocator<U8>();
+
+	m_immutable = b.m_immutable;
+	b.m_immutable = false;
+
+	return *this;
+}
+
+//==============================================================================
+void GlCommandBuffer::destroy()
+{
+#if ANKI_DEBUG
+	if(!m_executed && m_firstCommand)
+	{
+		ANKI_LOGW("Chain contains commands but never executed. "
+			"This should only happen on exceptions");
+	}
+#endif
+
+	GlCommand* command = m_firstCommand;
+	while(command != nullptr)
+	{
+		GlCommand* next = command->m_nextCommand; // Get next before deleting
+		m_alloc.deleteInstance(command);
+		command = next;
+	}
+
+	ANKI_ASSERT(m_alloc.getMemoryPool().getUsersCount() == 1 
+		&& "Someone is holding a reference to the command buffer's allocator");
+
+	m_alloc = GlCommandBufferAllocator<U8>();
+}
+
+//==============================================================================
+GlGlobalHeapAllocator<U8> GlCommandBuffer::getGlobalAllocator() const
+{
+	return m_server->getManager()._getAllocator();
+}
+
+//==============================================================================
+void GlCommandBuffer::executeAllCommands()
+{
+	ANKI_ASSERT(m_firstCommand != nullptr && "Empty command buffer");
+	ANKI_ASSERT(m_lastCommand != nullptr && "Empty command buffer");
+#if ANKI_DEBUG
+	m_executed = true;
+#endif
+	
+	GlCommand* command = m_firstCommand;
+
+	while(command != nullptr)
+	{
+		(*command)(this);
+		ANKI_CHECK_GL_ERROR();
+
+		command = command->m_nextCommand;
+	}
+}
+
+//==============================================================================
+GlCommandBufferInitHints GlCommandBuffer::computeInitHints() const
+{
+	GlCommandBufferInitHints out;
+	out.m_chunkSize = m_alloc.getMemoryPool().getAllocatedSize() + 16;
+
+	ANKI_COUNTER_INC(GL_QUEUES_SIZE, 
+		U64(m_alloc.getMemoryPool().getAllocatedSize()));
+
+	return out;
+}
+
+} // end namespace anki

+ 118 - 116
src/gl/GlJobChainHandle.cpp → src/gl/GlCommandBufferHandle.cpp

@@ -3,8 +3,8 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#include "anki/gl/GlJobChainHandle.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlCommandBufferHandle.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlFramebuffer.h"
 #include "anki/gl/GlFramebuffer.h"
 #include "anki/gl/GlTextureHandle.h"
 #include "anki/gl/GlTextureHandle.h"
@@ -16,90 +16,90 @@ namespace anki {
 
 
 //==============================================================================
 //==============================================================================
 // Macros because we are bored to type
 // Macros because we are bored to type
-#define ANKI_STATE_JOB_0(type_, glfunc_) \
-	class Job: public GlJob \
+#define ANKI_STATE_CMD_0(type_, glfunc_) \
+	class Command: public GlCommand \
 	{ \
 	{ \
 	public: \
 	public: \
-		Job() = default \
-		void operator()(GlJobChain*) \
+		Command() = default \
+		void operator()(GlCommandBuffer*) \
 		{ \
 		{ \
 			glfunc_(); \
 			glfunc_(); \
 		} \
 		} \
 	}; \
 	}; \
-	_pushBackNewJob<Job>(value_)
+	_pushBackNewCommand<Command>(value_)
 
 
-#define ANKI_STATE_JOB_1(type_, glfunc_, value_) \
-	class Job: public GlJob \
+#define ANKI_STATE_CMD_1(type_, glfunc_, value_) \
+	class Command: public GlCommand \
 	{ \
 	{ \
 	public: \
 	public: \
 		type_ m_value; \
 		type_ m_value; \
-		Job(type_ v) \
+		Command(type_ v) \
 			: m_value(v) \
 			: m_value(v) \
 		{} \
 		{} \
-		void operator()(GlJobChain*) \
+		void operator()(GlCommandBuffer*) \
 		{ \
 		{ \
 			glfunc_(m_value); \
 			glfunc_(m_value); \
 		} \
 		} \
 	}; \
 	}; \
-	_pushBackNewJob<Job>(value_)
+	_pushBackNewCommand<Command>(value_)
 
 
-#define ANKI_STATE_JOB_2(type_, glfunc_, a_, b_) \
-	class Job: public GlJob \
+#define ANKI_STATE_CMD_2(type_, glfunc_, a_, b_) \
+	class Command: public GlCommand \
 	{ \
 	{ \
 	public: \
 	public: \
 		Array<type_, 2> m_value; \
 		Array<type_, 2> m_value; \
-		Job(type_ a, type_ b) \
+		Command(type_ a, type_ b) \
 		{ \
 		{ \
 			m_value = {{a, b}}; \
 			m_value = {{a, b}}; \
 		} \
 		} \
-		void operator()(GlJobChain*) \
+		void operator()(GlCommandBuffer*) \
 		{ \
 		{ \
 			glfunc_(m_value[0], m_value[1]); \
 			glfunc_(m_value[0], m_value[1]); \
 		} \
 		} \
 	}; \
 	}; \
-	_pushBackNewJob<Job>(a_, b_)
+	_pushBackNewCommand<Command>(a_, b_)
 
 
-#define ANKI_STATE_JOB_3(type_, glfunc_, a_, b_, c_) \
-	class Job: public GlJob \
+#define ANKI_STATE_CMD_3(type_, glfunc_, a_, b_, c_) \
+	class Command: public GlCommand \
 	{ \
 	{ \
 	public: \
 	public: \
 		Array<type_, 3> m_value; \
 		Array<type_, 3> m_value; \
-		Job(type_ a, type_ b, type_ c) \
+		Command(type_ a, type_ b, type_ c) \
 		{ \
 		{ \
 			m_value = {{a, b, c}}; \
 			m_value = {{a, b, c}}; \
 		} \
 		} \
-		void operator()(GlJobChain*) \
+		void operator()(GlCommandBuffer*) \
 		{ \
 		{ \
 			glfunc_(m_value[0], m_value[1], m_value[2]); \
 			glfunc_(m_value[0], m_value[1], m_value[2]); \
 		} \
 		} \
 	}; \
 	}; \
-	_pushBackNewJob<Job>(a_, b_, c_)
+	_pushBackNewCommand<Command>(a_, b_, c_)
 
 
-#define ANKI_STATE_JOB_4(type_, glfunc_, a_, b_, c_, d_) \
-	class Job: public GlJob \
+#define ANKI_STATE_CMD_4(type_, glfunc_, a_, b_, c_, d_) \
+	class Command: public GlCommand \
 	{ \
 	{ \
 	public: \
 	public: \
 		Array<type_, 4> m_value; \
 		Array<type_, 4> m_value; \
-		Job(type_ a, type_ b, type_ c, type_ d) \
+		Command(type_ a, type_ b, type_ c, type_ d) \
 		{ \
 		{ \
 			m_value = {{a, b, c, d}}; \
 			m_value = {{a, b, c, d}}; \
 		} \
 		} \
-		void operator()(GlJobChain*) \
+		void operator()(GlCommandBuffer*) \
 		{ \
 		{ \
 			glfunc_(m_value[0], m_value[1], m_value[2], m_value[3]); \
 			glfunc_(m_value[0], m_value[1], m_value[2], m_value[3]); \
 		} \
 		} \
 	}; \
 	}; \
-	_pushBackNewJob<Job>(a_, b_, c_, d_)
+	_pushBackNewCommand<Command>(a_, b_, c_, d_)
 
 
-#define ANKI_STATE_JOB_ENABLE(enum_, enable_) \
-	class Job: public GlJob \
+#define ANKI_STATE_CMD_ENABLE(enum_, enable_) \
+	class Command: public GlCommand \
 	{ \
 	{ \
 	public: \
 	public: \
 		Bool8 m_enable; \
 		Bool8 m_enable; \
-		Job(Bool enable) \
+		Command(Bool enable) \
 			: m_enable(enable) \
 			: m_enable(enable) \
 		{} \
 		{} \
-		void operator()(GlJobChain*) \
+		void operator()(GlCommandBuffer*) \
 		{ \
 		{ \
 			if(m_enable) \
 			if(m_enable) \
 			{ \
 			{ \
@@ -111,131 +111,133 @@ namespace anki {
 			} \
 			} \
 		} \
 		} \
 	}; \
 	}; \
-	_pushBackNewJob<Job>(enable_)
+	_pushBackNewCommand<Command>(enable_)
 
 
 //==============================================================================
 //==============================================================================
-GlJobChainHandle::GlJobChainHandle()
+GlCommandBufferHandle::GlCommandBufferHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-GlJobChainHandle::GlJobChainHandle(GlManager* gl, GlJobChainInitHints hints)
+GlCommandBufferHandle::GlCommandBufferHandle(GlDevice* gl, 
+	GlCommandBufferInitHints hints)
 {
 {
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(!isCreated());
 	ANKI_ASSERT(gl);
 	ANKI_ASSERT(gl);
 
 
-	typedef GlGlobalHeapAllocator<GlJobChain> Alloc;
+	typedef GlGlobalHeapAllocator<GlCommandBuffer> Alloc;
 	Alloc alloc = gl->_getAllocator();
 	Alloc alloc = gl->_getAllocator();
 
 
 	*static_cast<Base*>(this) = Base(
 	*static_cast<Base*>(this) = Base(
 		gl,
 		gl,
 		alloc, 
 		alloc, 
-		GlHandleDefaultDeleter<GlJobChain, Alloc>(), 
-		&gl->_getJobManager(), 
+		GlHandleDefaultDeleter<GlCommandBuffer, Alloc>(), 
+		&gl->_getQueue(), 
 		hints);
 		hints);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-GlJobChainHandle::~GlJobChainHandle()
+GlCommandBufferHandle::~GlCommandBufferHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::pushBackUserJob(UserCallback callback, void* data)
+void GlCommandBufferHandle::pushBackUserCommand(UserCallback callback, void* data)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		UserCallback m_callback;
 		UserCallback m_callback;
 		void* m_userData;
 		void* m_userData;
 
 
-		Job(UserCallback callback, void* userData)
+		Command(UserCallback callback, void* userData)
 			: m_callback(callback), m_userData(userData)
 			: m_callback(callback), m_userData(userData)
 		{
 		{
 			ANKI_ASSERT(m_callback);
 			ANKI_ASSERT(m_callback);
 		}
 		}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
 			(*m_callback)(m_userData);
 			(*m_callback)(m_userData);
 		}
 		}
 	};
 	};
 
 
-	_pushBackNewJob<Job>(callback, data);
+	_pushBackNewCommand<Command>(callback, data);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::pushBackOtherJobChain(GlJobChainHandle& jobs)
+void GlCommandBufferHandle::pushBackOtherCommandBuffer(
+	GlCommandBufferHandle& commands)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
-		GlJobChainHandle m_jobs;
+		GlCommandBufferHandle m_commands;
 
 
-		Job(GlJobChainHandle& jobs)
-			: m_jobs(jobs)
+		Command(GlCommandBufferHandle& commands)
+			: m_commands(commands)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
-			m_jobs._executeAllJobs();
+			m_commands._executeAllCommands();
 		}
 		}
 	};
 	};
 
 
-	jobs._get().makeImmutable();
-	_pushBackNewJob<Job>(jobs);
+	commands._get().makeImmutable();
+	_pushBackNewCommand<Command>(commands);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::flush()
+void GlCommandBufferHandle::flush()
 {
 {
-	_get().getJobManager().flushJobChain(*this);
+	_get().getQueue().flushCommandChain(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::finish()
+void GlCommandBufferHandle::finish()
 {
 {
-	_get().getJobManager().finishJobChain(*this);
+	_get().getQueue().finishCommandChain(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setClearColor(F32 r, F32 g, F32 b, F32 a)
+void GlCommandBufferHandle::setClearColor(F32 r, F32 g, F32 b, F32 a)
 {
 {
-	ANKI_STATE_JOB_4(F32, glClearColor, r, g, b, a);
+	ANKI_STATE_CMD_4(F32, glClearColor, r, g, b, a);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setClearDepth(F32 value)
+void GlCommandBufferHandle::setClearDepth(F32 value)
 {
 {
-	ANKI_STATE_JOB_1(F32, glClearDepth, value);
+	ANKI_STATE_CMD_1(F32, glClearDepth, value);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setClearStencil(U32 value)
+void GlCommandBufferHandle::setClearStencil(U32 value)
 {
 {
-	ANKI_STATE_JOB_1(U32, glClearStencil, value);
+	ANKI_STATE_CMD_1(U32, glClearStencil, value);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::clearBuffers(U32 mask)
+void GlCommandBufferHandle::clearBuffers(U32 mask)
 {
 {
-	ANKI_STATE_JOB_1(U32, glClear, mask);
+	ANKI_STATE_CMD_1(U32, glClear, mask);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
+void GlCommandBufferHandle::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		Array<U16, 4> m_value;
 		Array<U16, 4> m_value;
 		
 		
-		Job(U16 a, U16 b, U16 c, U16 d)
+		Command(U16 a, U16 b, U16 c, U16 d)
 		{
 		{
 			m_value = {{a, b, c, d}};
 			m_value = {{a, b, c, d}};
 		}
 		}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
-			GlState& state = jobs->getJobManager().getState();
+			GlState& state = commands->getQueue().getState();
 
 
 			if(state.m_viewport[0] != m_value[0] 
 			if(state.m_viewport[0] != m_value[0] 
 				|| state.m_viewport[1] != m_value[1]
 				|| state.m_viewport[1] != m_value[1]
@@ -249,88 +251,88 @@ void GlJobChainHandle::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 		}
 		}
 	};
 	};
 
 
-	_pushBackNewJob<Job>(minx, miny, maxx, maxy);
+	_pushBackNewCommand<Command>(minx, miny, maxx, maxy);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setColorWriteMask(
+void GlCommandBufferHandle::setColorWriteMask(
 	Bool red, Bool green, Bool blue, Bool alpha)
 	Bool red, Bool green, Bool blue, Bool alpha)
 {
 {
-	ANKI_STATE_JOB_4(Bool8, glColorMask, red, green, blue, alpha);
+	ANKI_STATE_CMD_4(Bool8, glColorMask, red, green, blue, alpha);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::enableDepthTest(Bool enable)
+void GlCommandBufferHandle::enableDepthTest(Bool enable)
 {
 {
-	ANKI_STATE_JOB_ENABLE(GL_DEPTH_TEST, enable);
+	ANKI_STATE_CMD_ENABLE(GL_DEPTH_TEST, enable);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setDepthFunction(GLenum func)
+void GlCommandBufferHandle::setDepthFunction(GLenum func)
 {
 {
-	ANKI_STATE_JOB_1(GLenum, glDepthFunc, func);
+	ANKI_STATE_CMD_1(GLenum, glDepthFunc, func);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setDepthWriteMask(Bool write)
+void GlCommandBufferHandle::setDepthWriteMask(Bool write)
 {
 {
-	ANKI_STATE_JOB_1(Bool8, glDepthMask, write);
+	ANKI_STATE_CMD_1(Bool8, glDepthMask, write);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::enableStencilTest(Bool enable)
+void GlCommandBufferHandle::enableStencilTest(Bool enable)
 {
 {
-	ANKI_STATE_JOB_ENABLE(GL_STENCIL_TEST, enable);
+	ANKI_STATE_CMD_ENABLE(GL_STENCIL_TEST, enable);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setStencilFunction(
+void GlCommandBufferHandle::setStencilFunction(
 	GLenum function, U32 reference, U32 mask)
 	GLenum function, U32 reference, U32 mask)
 {
 {
-	ANKI_STATE_JOB_3(U32, glStencilFunc, function, reference, mask);
+	ANKI_STATE_CMD_3(U32, glStencilFunc, function, reference, mask);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setStencilPlaneMask(U32 mask)
+void GlCommandBufferHandle::setStencilPlaneMask(U32 mask)
 {
 {
-	ANKI_STATE_JOB_1(U32, glStencilMask, mask);
+	ANKI_STATE_CMD_1(U32, glStencilMask, mask);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setStencilOperations(GLenum stencFail, GLenum depthFail, 
+void GlCommandBufferHandle::setStencilOperations(GLenum stencFail, GLenum depthFail, 
 	GLenum depthPass)
 	GLenum depthPass)
 {
 {
-	ANKI_STATE_JOB_3(GLenum, glStencilOp, stencFail, depthFail, depthPass);
+	ANKI_STATE_CMD_3(GLenum, glStencilOp, stencFail, depthFail, depthPass);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::enableBlend(Bool enable)
+void GlCommandBufferHandle::enableBlend(Bool enable)
 {
 {
-	ANKI_STATE_JOB_ENABLE(GL_BLEND, enable);
+	ANKI_STATE_CMD_ENABLE(GL_BLEND, enable);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setBlendEquation(GLenum equation)
+void GlCommandBufferHandle::setBlendEquation(GLenum equation)
 {
 {
-	ANKI_STATE_JOB_1(GLenum, glBlendEquation, equation);
+	ANKI_STATE_CMD_1(GLenum, glBlendEquation, equation);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setBlendFunctions(GLenum sfactor, GLenum dfactor)
+void GlCommandBufferHandle::setBlendFunctions(GLenum sfactor, GLenum dfactor)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GLenum m_sfactor;
 		GLenum m_sfactor;
 		GLenum m_dfactor;
 		GLenum m_dfactor;
 
 
-		Job(GLenum sfactor, GLenum dfactor)
+		Command(GLenum sfactor, GLenum dfactor)
 			: m_sfactor(sfactor), m_dfactor(dfactor)
 			: m_sfactor(sfactor), m_dfactor(dfactor)
 		{}
 		{}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
-			GlState& state = jobs->getJobManager().getState();
+			GlState& state = commands->getQueue().getState();
 
 
 			if(state.m_blendSfunc != m_sfactor 
 			if(state.m_blendSfunc != m_sfactor 
 				|| state.m_blendDfunc != m_dfactor)
 				|| state.m_blendDfunc != m_dfactor)
@@ -343,70 +345,70 @@ void GlJobChainHandle::setBlendFunctions(GLenum sfactor, GLenum dfactor)
 		}
 		}
 	};
 	};
 
 
-	_pushBackNewJob<Job>(sfactor, dfactor);
+	_pushBackNewCommand<Command>(sfactor, dfactor);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setBlendColor(F32 r, F32 g, F32 b, F32 a)
+void GlCommandBufferHandle::setBlendColor(F32 r, F32 g, F32 b, F32 a)
 {
 {
-	ANKI_STATE_JOB_4(F32, glBlendColor, r, g, b, a);
+	ANKI_STATE_CMD_4(F32, glBlendColor, r, g, b, a);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::enablePrimitiveRestart(Bool enable)
+void GlCommandBufferHandle::enablePrimitiveRestart(Bool enable)
 {
 {
-	ANKI_STATE_JOB_ENABLE(GL_PRIMITIVE_RESTART, enable);
+	ANKI_STATE_CMD_ENABLE(GL_PRIMITIVE_RESTART, enable);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setPatchVertexCount(U32 count)
+void GlCommandBufferHandle::setPatchVertexCount(U32 count)
 {
 {
-	ANKI_STATE_JOB_2(GLint, glPatchParameteri, GL_PATCH_VERTICES, count);
+	ANKI_STATE_CMD_2(GLint, glPatchParameteri, GL_PATCH_VERTICES, count);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::enableCulling(Bool enable)
+void GlCommandBufferHandle::enableCulling(Bool enable)
 {
 {
-	ANKI_STATE_JOB_ENABLE(GL_CULL_FACE, enable);
+	ANKI_STATE_CMD_ENABLE(GL_CULL_FACE, enable);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setCullFace(GLenum mode)
+void GlCommandBufferHandle::setCullFace(GLenum mode)
 {
 {
-	ANKI_STATE_JOB_1(GLenum, glCullFace, mode);
+	ANKI_STATE_CMD_1(GLenum, glCullFace, mode);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::setPolygonOffset(F32 factor, F32 units)
+void GlCommandBufferHandle::setPolygonOffset(F32 factor, F32 units)
 {
 {
-	ANKI_STATE_JOB_2(F32, glPolygonOffset, factor, units);
+	ANKI_STATE_CMD_2(F32, glPolygonOffset, factor, units);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::enablePolygonOffset(Bool enable)
+void GlCommandBufferHandle::enablePolygonOffset(Bool enable)
 {
 {
-	ANKI_STATE_JOB_ENABLE(GL_POLYGON_OFFSET_FILL, enable);
+	ANKI_STATE_CMD_ENABLE(GL_POLYGON_OFFSET_FILL, enable);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobChainHandle::bindTextures(U32 first, 
+void GlCommandBufferHandle::bindTextures(U32 first, 
 	const std::initializer_list<GlTextureHandle>& textures)
 	const std::initializer_list<GlTextureHandle>& textures)
 {
 {
-	using Vec = Vector<GlTextureHandle, GlJobChainAllocator<GlTextureHandle>>;
+	using Vec = Vector<GlTextureHandle, GlCommandBufferAllocator<GlTextureHandle>>;
 		
 		
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		Vec m_texes;
 		Vec m_texes;
 		U32 m_first;
 		U32 m_first;
 
 
-		Job(Vec& texes, U32 first)
+		Command(Vec& texes, U32 first)
 			: m_first(first)
 			: m_first(first)
 		{
 		{
 			m_texes = std::move(texes);
 			m_texes = std::move(texes);
 		}
 		}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
 			Array<GLuint, 16> names;
 			Array<GLuint, 16> names;
 
 
@@ -429,7 +431,7 @@ void GlJobChainHandle::bindTextures(U32 first,
 		texes.push_back(t);
 		texes.push_back(t);
 	}
 	}
 
 
-	_pushBackNewJob<Job>(texes, first);
+	_pushBackNewCommand<Command>(texes, first);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 14 - 14
src/gl/GlManager.cpp → src/gl/GlDevice.cpp

@@ -3,13 +3,13 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/core/Timestamp.h"
 #include "anki/core/Timestamp.h"
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-GlManager::GlManager(
+GlDevice::GlDevice(
 	GlCallback makeCurrentCallback, void* context,
 	GlCallback makeCurrentCallback, void* context,
 	GlCallback swapBuffersCallback, void* swapBuffersCbData,
 	GlCallback swapBuffersCallback, void* swapBuffersCbData,
 	Bool registerDebugMessages,
 	Bool registerDebugMessages,
@@ -18,10 +18,10 @@ GlManager::GlManager(
 	m_alloc = HeapAllocator<U8>(HeapMemoryPool(alloc, allocUserData));
 	m_alloc = HeapAllocator<U8>(HeapMemoryPool(alloc, allocUserData));
 
 
 	// Start the server
 	// Start the server
-	m_jobManager = m_alloc.newInstance<GlJobManager>(
+	m_queue = m_alloc.newInstance<GlQueue>(
 		this, alloc, allocUserData);
 		this, alloc, allocUserData);
 
 
-	m_jobManager->start(makeCurrentCallback, context, 
+	m_queue->start(makeCurrentCallback, context, 
 		swapBuffersCallback, swapBuffersCbData, 
 		swapBuffersCallback, swapBuffersCbData, 
 		registerDebugMessages);
 		registerDebugMessages);
 
 
@@ -29,31 +29,31 @@ GlManager::GlManager(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlManager::destroy()
+void GlDevice::destroy()
 {
 {
-	if(m_jobManager)
+	if(m_queue)
 	{
 	{
-		m_jobManager->stop();
-		m_alloc.deleteInstance(m_jobManager);
+		m_queue->stop();
+		m_alloc.deleteInstance(m_queue);
 	}
 	}
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlManager::syncClientServer()
+void GlDevice::syncClientServer()
 {
 {
-	m_jobManager->syncClientServer();
+	m_queue->syncClientServer();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlManager::swapBuffers()
+void GlDevice::swapBuffers()
 {
 {
-	m_jobManager->swapBuffers();
+	m_queue->swapBuffers();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-PtrSize GlManager::getBufferOffsetAlignment(GLenum target)
+PtrSize GlDevice::getBufferOffsetAlignment(GLenum target)
 {
 {
-	const GlState& state = m_jobManager->getState();
+	const GlState& state = m_queue->getState();
 
 
 	if(target == GL_UNIFORM_BUFFER)
 	if(target == GL_UNIFORM_BUFFER)
 	{
 	{

+ 35 - 27
src/gl/GlFramebufferHandle.cpp

@@ -14,24 +14,27 @@ GlFramebufferHandle::GlFramebufferHandle()
 
 
 //==============================================================================
 //==============================================================================
 GlFramebufferHandle::GlFramebufferHandle(
 GlFramebufferHandle::GlFramebufferHandle(
-	GlJobChainHandle& jobs,
+	GlCommandBufferHandle& commands,
 	const std::initializer_list<Attachment>& attachments)
 	const std::initializer_list<Attachment>& attachments)
 {
 {
 	using Attachments = 
 	using Attachments = 
 		Array<Attachment, GlFramebuffer::MAX_COLOR_ATTACHMENTS + 1>;
 		Array<Attachment, GlFramebuffer::MAX_COLOR_ATTACHMENTS + 1>;
 
 
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		Attachments m_attachments;
 		Attachments m_attachments;
 		U8 m_size;
 		U8 m_size;
 		GlFramebufferHandle m_fb;
 		GlFramebufferHandle m_fb;
 
 
-		Job(GlFramebufferHandle& handle, const Attachments& attachments, U size)
-			: m_attachments(attachments), m_size(size), m_fb(handle)
+		Command(GlFramebufferHandle& handle, const Attachments& attachments, 
+			U size)
+		:	m_attachments(attachments), 
+			m_size(size), 
+			m_fb(handle)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			Attachment* begin;
 			Attachment* begin;
 			Attachment* end;
 			Attachment* end;
@@ -54,13 +57,14 @@ GlFramebufferHandle::GlFramebufferHandle(
 		}
 		}
 	};
 	};
 
 
-	typedef GlGlobalHeapAllocator<GlFramebuffer> Alloc;
-	typedef GlDeleteObjectJob<GlFramebuffer, Alloc> DeleteJob;
-	typedef GlHandleDeferredDeleter<GlFramebuffer, Alloc, DeleteJob> Deleter;
+	using Alloc = GlGlobalHeapAllocator<GlFramebuffer>;
+	using DeleteCommand = GlDeleteObjectCommand<GlFramebuffer, Alloc>;
+	using Deleter = 
+		GlHandleDeferredDeleter<GlFramebuffer, Alloc, DeleteCommand>;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._get().getJobManager().getManager(),
-		jobs._get().getGlobalAllocator(), 
+		&commands._get().getQueue().getManager(),
+		commands._get().getGlobalAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
@@ -71,7 +75,7 @@ GlFramebufferHandle::GlFramebufferHandle(
 		att[i++] = a;
 		att[i++] = a;
 	}
 	}
 
 
-	jobs._pushBackNewJob<Job>(*this, att, attachments.size());
+	commands._pushBackNewCommand<Command>(*this, att, attachments.size());
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -79,36 +83,37 @@ GlFramebufferHandle::~GlFramebufferHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlFramebufferHandle::bind(GlJobChainHandle& jobs, Bool invalidate)
+void GlFramebufferHandle::bind(GlCommandBufferHandle& commands, Bool invalidate)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlFramebufferHandle m_fb;
 		GlFramebufferHandle m_fb;
 		Bool8 m_invalidate;
 		Bool8 m_invalidate;
 
 
-		Job(GlFramebufferHandle& fb, Bool invalidate)
-			: m_fb(fb), m_invalidate(invalidate)
+		Command(GlFramebufferHandle& fb, Bool invalidate)
+		:	m_fb(fb), 
+			m_invalidate(invalidate)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_fb._get().bind(m_invalidate);
 			m_fb._get().bind(m_invalidate);
 		}
 		}
 	};
 	};
 
 
-	jobs._pushBackNewJob<Job>(*this, invalidate);
+	commands._pushBackNewCommand<Command>(*this, invalidate);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlFramebufferHandle::blit(GlJobChainHandle& jobs,
+void GlFramebufferHandle::blit(GlCommandBufferHandle& commands,
 	const GlFramebufferHandle& b, 
 	const GlFramebufferHandle& b, 
 	const Array<U32, 4>& sourceRect,
 	const Array<U32, 4>& sourceRect,
 	const Array<U32, 4>& destRect, 
 	const Array<U32, 4>& destRect, 
 	GLbitfield attachmentMask,
 	GLbitfield attachmentMask,
 	Bool linear)
 	Bool linear)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlFramebufferHandle m_fbDest;
 		GlFramebufferHandle m_fbDest;
@@ -116,26 +121,29 @@ void GlFramebufferHandle::blit(GlJobChainHandle& jobs,
 		Array<U32, 4> m_sourceRect;
 		Array<U32, 4> m_sourceRect;
 		Array<U32, 4> m_destRect;
 		Array<U32, 4> m_destRect;
 		GLbitfield m_attachmentMask;
 		GLbitfield m_attachmentMask;
-		Bool m_linear;
+		Bool8 m_linear;
 
 
-		Job(GlFramebufferHandle& fbDest, const GlFramebufferHandle& fbSrc,
+		Command(GlFramebufferHandle& fbDest, const GlFramebufferHandle& fbSrc,
 			const Array<U32, 4>& sourceRect,
 			const Array<U32, 4>& sourceRect,
 			const Array<U32, 4>& destRect,
 			const Array<U32, 4>& destRect,
 			GLbitfield attachmentMask,
 			GLbitfield attachmentMask,
-			Bool linear)
-			:	m_fbDest(fbDest), m_fbSrc(fbSrc), m_sourceRect(sourceRect),
-				m_destRect(destRect), m_attachmentMask(attachmentMask), 
-				m_linear(linear)
+			Bool8 linear)
+		:	m_fbDest(fbDest), 
+			m_fbSrc(fbSrc), 
+			m_sourceRect(sourceRect),
+			m_destRect(destRect), 
+			m_attachmentMask(attachmentMask), 
+			m_linear(linear)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_fbDest._get().blit(m_fbSrc._get(), m_sourceRect, m_destRect, 
 			m_fbDest._get().blit(m_fbSrc._get(), m_sourceRect, m_destRect, 
 				m_attachmentMask, m_linear);
 				m_attachmentMask, m_linear);
 		}
 		}
 	};
 	};
 
 
-	jobs._pushBackNewJob<Job>(
+	commands._pushBackNewCommand<Command>(
 		*this, b, sourceRect, destRect, attachmentMask, linear);
 		*this, b, sourceRect, destRect, attachmentMask, linear);
 }
 }
 
 

+ 0 - 116
src/gl/GlJobChain.cpp

@@ -1,116 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/gl/GlJobChain.h"
-#include "anki/gl/GlJobManager.h"
-#include "anki/gl/GlManager.h"
-#include "anki/gl/GlError.h"
-#include "anki/core/Logger.h"
-#include "anki/core/Counters.h"
-#include <cstring>
-
-namespace anki {
-
-//==============================================================================
-GlJobChain::GlJobChain(GlJobManager* server, const GlJobChainInitHints& hints)
-	:	m_server(server),
-		m_alloc(GlJobChainAllocator<GlJob*>(ChainMemoryPool(
-			m_server->getAllocationCallback(),
-			m_server->getAllocationCallbackUserData(),
-			hints.m_chunkSize, 
-			hints.m_maxChunkSize, 
-			ChainMemoryPool::ADD,
-			hints.m_chunkSize)))
-{
-	//std::cout << hints.m_chunkSize << std::endl;
-	ANKI_ASSERT(m_server);
-}
-
-//==============================================================================
-GlJobChain& GlJobChain::operator=(GlJobChain&& b)
-{
-	destroy();
-	m_server = b.m_server; 
-	b.m_server = nullptr;
-	
-	m_firstJob = b.m_firstJob;
-	b.m_firstJob = nullptr;
-	
-	m_lastJob = b.m_lastJob;
-	b.m_lastJob = nullptr;
-
-	m_alloc = b.m_alloc;
-	b.m_alloc = GlJobChainAllocator<U8>();
-
-	m_immutable = b.m_immutable;
-	b.m_immutable = false;
-
-	return *this;
-}
-
-//==============================================================================
-void GlJobChain::destroy()
-{
-#if ANKI_DEBUG
-	if(!m_executed && m_firstJob)
-	{
-		ANKI_LOGW("Chain contains jobs but never executed. "
-			"This should only happen on exceptions");
-	}
-#endif
-
-	GlJob* job = m_firstJob;
-	while(job != nullptr)
-	{
-		GlJob* next = job->nextJob; // Get next before deleting
-		m_alloc.deleteInstance(job);
-		job = next;
-	}
-
-	ANKI_ASSERT(m_alloc.getMemoryPool().getUsersCount() == 1 
-		&& "Someone is holding a reference to the chain's allocator");
-
-	m_alloc = GlJobChainAllocator<U8>();
-}
-
-//==============================================================================
-GlGlobalHeapAllocator<U8> GlJobChain::getGlobalAllocator() const
-{
-	return m_server->getManager()._getAllocator();
-}
-
-//==============================================================================
-void GlJobChain::executeAllJobs()
-{
-	ANKI_ASSERT(m_firstJob != nullptr && "Empty job chain");
-	ANKI_ASSERT(m_lastJob != nullptr && "Empty job chain");
-#if ANKI_DEBUG
-	m_executed = true;
-#endif
-	
-	GlJob* job = m_firstJob;
-
-	while(job != nullptr)
-	{
-		(*job)(this);
-		ANKI_CHECK_GL_ERROR();
-
-		job = job->nextJob;
-	}
-}
-
-//==============================================================================
-GlJobChainInitHints GlJobChain::computeInitHints() const
-{
-	GlJobChainInitHints out;
-	out.m_chunkSize = m_alloc.getMemoryPool().getAllocatedSize() + 16;
-
-	ANKI_COUNTER_INC(GL_JOB_CHAINS_SIZE, 
-		U64(m_alloc.getMemoryPool().getAllocatedSize()));
-
-	return out;
-}
-
-} // end namespace anki

+ 10 - 10
src/gl/GlOperations.cpp

@@ -14,25 +14,25 @@ namespace anki {
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
-class GlDrawElementsJob: public GlJob
+class GlDrawElementsCommand: public GlCommand
 {
 {
 public:
 public:
 	GlDrawcallElements m_dc;
 	GlDrawcallElements m_dc;
 
 
-	GlDrawElementsJob(const GlDrawcallElements& dc)
+	GlDrawElementsCommand(const GlDrawcallElements& dc)
 		: m_dc(dc)
 		: m_dc(dc)
 	{}
 	{}
 
 
-	void operator()(GlJobChain*)
+	void operator()(GlCommandBuffer*)
 	{
 	{
 		m_dc.exec();
 		m_dc.exec();
 	}
 	}
 };
 };
 
 
 //==============================================================================
 //==============================================================================
-void GlDrawcallElements::draw(GlJobChainHandle& jobs)
+void GlDrawcallElements::draw(GlCommandBufferHandle& commands)
 {
 {
-	jobs._pushBackNewJob<GlDrawElementsJob>(*this);
+	commands._pushBackNewCommand<GlDrawElementsCommand>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -110,25 +110,25 @@ void GlDrawcallElements::exec()
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
-class GlDrawArraysJob: public GlJob
+class GlDrawArraysCommand: public GlCommand
 {
 {
 public:
 public:
 	GlDrawcallArrays m_dc;
 	GlDrawcallArrays m_dc;
 
 
-	GlDrawArraysJob(const GlDrawcallArrays& dc)
+	GlDrawArraysCommand(const GlDrawcallArrays& dc)
 		: m_dc(dc)
 		: m_dc(dc)
 	{}
 	{}
 
 
-	void operator()(GlJobChain*)
+	void operator()(GlCommandBuffer*)
 	{
 	{
 		m_dc.exec();
 		m_dc.exec();
 	}
 	}
 };
 };
 
 
 //==============================================================================
 //==============================================================================
-void GlDrawcallArrays::draw(GlJobChainHandle& jobs)
+void GlDrawcallArrays::draw(GlCommandBufferHandle& commands)
 {
 {
-	jobs._pushBackNewJob<GlDrawArraysJob>(*this);
+	commands._pushBackNewCommand<GlDrawArraysCommand>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 12 - 12
src/gl/GlProgramHandle.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/gl/GlProgramHandle.h"
 #include "anki/gl/GlProgramHandle.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/gl/GlClientBufferHandle.h"
 #include "anki/gl/GlClientBufferHandle.h"
 #include "anki/gl/GlHandleDeferredDeleter.h"
 #include "anki/gl/GlHandleDeferredDeleter.h"
 #include "anki/gl/GlProgram.h"
 #include "anki/gl/GlProgram.h"
@@ -12,23 +12,23 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-/// Create program job
-class GlProgramCreateJob: public GlJob
+/// Create program command
+class GlProgramCreateCommand: public GlCommand
 {
 {
 public:
 public:
 	GlProgramHandle m_prog;
 	GlProgramHandle m_prog;
 	GLenum m_type;
 	GLenum m_type;
 	GlClientBufferHandle m_source;
 	GlClientBufferHandle m_source;
 
 
-	GlProgramCreateJob(GlProgramHandle prog, 
+	GlProgramCreateCommand(GlProgramHandle prog, 
 		GLenum type, GlClientBufferHandle source)
 		GLenum type, GlClientBufferHandle source)
 		: m_prog(prog), m_type(type), m_source(source)
 		: m_prog(prog), m_type(type), m_source(source)
 	{}
 	{}
 
 
-	void operator()(GlJobChain* jobs)
+	void operator()(GlCommandBuffer* commands)
 	{
 	{
 		GlProgram p(m_type, (const char*)m_source.getBaseAddress(), 
 		GlProgram p(m_type, (const char*)m_source.getBaseAddress(), 
-			jobs->getJobManager().getManager()._getAllocator());
+			commands->getQueue().getManager()._getAllocator());
 		m_prog._get() = std::move(p);
 		m_prog._get() = std::move(p);
 
 
 		GlHandleState oldState = m_prog._setState(GlHandleState::CREATED);
 		GlHandleState oldState = m_prog._setState(GlHandleState::CREATED);
@@ -42,20 +42,20 @@ GlProgramHandle::GlProgramHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-GlProgramHandle::GlProgramHandle(GlJobChainHandle& jobs, 
+GlProgramHandle::GlProgramHandle(GlCommandBufferHandle& commands, 
 	GLenum type, const GlClientBufferHandle& source)
 	GLenum type, const GlClientBufferHandle& source)
 {
 {
 	typedef GlGlobalHeapAllocator<GlProgram> Alloc;
 	typedef GlGlobalHeapAllocator<GlProgram> Alloc;
-	typedef GlDeleteObjectJob<GlProgram, Alloc> DeleteJob;
-	typedef GlHandleDeferredDeleter<GlProgram, Alloc, DeleteJob> Deleter;
+	typedef GlDeleteObjectCommand<GlProgram, Alloc> DeleteCommand;
+	typedef GlHandleDeferredDeleter<GlProgram, Alloc, DeleteCommand> Deleter;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._get().getJobManager().getManager(),
-		jobs._get().getGlobalAllocator(), 
+		&commands._get().getQueue().getManager(),
+		commands._get().getGlobalAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
-	jobs._pushBackNewJob<GlProgramCreateJob>(*this, type, source);
+	commands._pushBackNewCommand<GlProgramCreateCommand>(*this, type, source);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 17 - 17
src/gl/GlProgramPipelineHandle.cpp

@@ -15,7 +15,7 @@ GlProgramPipelineHandle::GlProgramPipelineHandle()
 
 
 //==============================================================================
 //==============================================================================
 GlProgramPipelineHandle::GlProgramPipelineHandle(
 GlProgramPipelineHandle::GlProgramPipelineHandle(
-	GlJobChainHandle& jobs,
+	GlCommandBufferHandle& commands,
 	std::initializer_list<GlProgramHandle> iprogs)
 	std::initializer_list<GlProgramHandle> iprogs)
 {
 {
 	Array<GlProgramHandle, 6> progs;
 	Array<GlProgramHandle, 6> progs;
@@ -26,7 +26,7 @@ GlProgramPipelineHandle::GlProgramPipelineHandle(
 		progs[count++] = prog;
 		progs[count++] = prog;
 	}
 	}
 
 
-	commonConstructor(jobs, &progs[0], &progs[0] + count);
+	commonConstructor(commands, &progs[0], &progs[0] + count);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -35,17 +35,17 @@ GlProgramPipelineHandle::~GlProgramPipelineHandle()
 
 
 //==============================================================================
 //==============================================================================
 void GlProgramPipelineHandle::commonConstructor(
 void GlProgramPipelineHandle::commonConstructor(
-	GlJobChainHandle& jobs,
+	GlCommandBufferHandle& commands,
 	const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
 	const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlProgramPipelineHandle m_ppline;
 		GlProgramPipelineHandle m_ppline;
 		Array<GlProgramHandle, 6> m_progs;
 		Array<GlProgramHandle, 6> m_progs;
 		U8 m_progsCount;
 		U8 m_progsCount;
 
 
-		Job(GlProgramPipelineHandle& ppline, 
+		Command(GlProgramPipelineHandle& ppline, 
 			const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
 			const GlProgramHandle* progsBegin, const GlProgramHandle* progsEnd)
 			: m_ppline(ppline)
 			: m_ppline(ppline)
 		{
 		{
@@ -57,7 +57,7 @@ void GlProgramPipelineHandle::commonConstructor(
 			} while(++prog != progsEnd);
 			} while(++prog != progsEnd);
 		}
 		}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			GlProgramPipeline ppline(&m_progs[0], &m_progs[0] + m_progsCount);
 			GlProgramPipeline ppline(&m_progs[0], &m_progs[0] + m_progsCount);
 			m_ppline._get() = std::move(ppline);
 			m_ppline._get() = std::move(ppline);
@@ -68,36 +68,36 @@ void GlProgramPipelineHandle::commonConstructor(
 	};
 	};
 
 
 	typedef GlGlobalHeapAllocator<GlProgramPipeline> Alloc;
 	typedef GlGlobalHeapAllocator<GlProgramPipeline> Alloc;
-	typedef GlDeleteObjectJob<GlProgramPipeline, Alloc> DeleteJob;
-	typedef GlHandleDeferredDeleter<GlProgramPipeline, Alloc, DeleteJob> 
+	typedef GlDeleteObjectCommand<GlProgramPipeline, Alloc> DeleteCommand;
+	typedef GlHandleDeferredDeleter<GlProgramPipeline, Alloc, DeleteCommand> 
 		Deleter;
 		Deleter;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._get().getJobManager().getManager(),
-		jobs._get().getGlobalAllocator(), 
+		&commands._get().getQueue().getManager(),
+		commands._get().getGlobalAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
-	jobs._pushBackNewJob<Job>(*this, progsBegin, progsEnd);
+	commands._pushBackNewCommand<Command>(*this, progsBegin, progsEnd);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlProgramPipelineHandle::bind(GlJobChainHandle& jobs)
+void GlProgramPipelineHandle::bind(GlCommandBufferHandle& commands)
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 
 
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlProgramPipelineHandle m_ppline;
 		GlProgramPipelineHandle m_ppline;
 
 
-		Job(GlProgramPipelineHandle& ppline)
+		Command(GlProgramPipelineHandle& ppline)
 			: m_ppline(ppline)
 			: m_ppline(ppline)
 		{}
 		{}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
-			GlState& state = jobs->getJobManager().getState();
+			GlState& state = commands->getQueue().getState();
 
 
 			if(state.m_crntPpline != m_ppline._get().getGlName())
 			if(state.m_crntPpline != m_ppline._get().getGlName())
 			{
 			{
@@ -108,7 +108,7 @@ void GlProgramPipelineHandle::bind(GlJobChainHandle& jobs)
 		}
 		}
 	};
 	};
 
 
-	jobs._pushBackNewJob<Job>(*this);
+	commands._pushBackNewCommand<Command>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 45 - 45
src/gl/GlJobManager.cpp → src/gl/GlQueue.cpp

@@ -3,16 +3,16 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#include "anki/gl/GlJobManager.h"
-#include "anki/gl/GlJobChain.h"
+#include "anki/gl/GlQueue.h"
+#include "anki/gl/GlCommandBuffer.h"
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlSyncHandles.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/core/Logger.h"
 #include "anki/core/Logger.h"
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-GlJobManager::GlJobManager(GlManager* manager, 
+GlQueue::GlQueue(GlDevice* manager, 
 	AllocAlignedCallback allocCb, void* allocCbUserData)
 	AllocAlignedCallback allocCb, void* allocCbUserData)
 	:	m_manager(manager), 
 	:	m_manager(manager), 
 		m_allocCb(allocCb),
 		m_allocCb(allocCb),
@@ -25,15 +25,15 @@ GlJobManager::GlJobManager(GlManager* manager,
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-GlJobManager::~GlJobManager()
+GlQueue::~GlQueue()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::flushJobChain(GlJobChainHandle& jobs)
+void GlQueue::flushCommandChain(GlCommandBufferHandle& commands)
 {
 {
-	jobs._get().makeImmutable();
+	commands._get().makeImmutable();
 
 
-#if !ANKI_JOB_MANAGER_DISABLE_ASYNC
+#if !ANKI_QUEUE_DISABLE_ASYNC
 	{
 	{
 		std::unique_lock<std::mutex> lock(m_mtx);
 		std::unique_lock<std::mutex> lock(m_mtx);
 
 
@@ -43,14 +43,14 @@ void GlJobManager::flushJobChain(GlJobChainHandle& jobs)
 				&m_error[0]);
 				&m_error[0]);
 		}
 		}
 
 
-		// Set jobc
+		// Set commandc
 		U64 diff = m_tail - m_head;
 		U64 diff = m_tail - m_head;
 
 
 		if(diff < m_queue.size())
 		if(diff < m_queue.size())
 		{
 		{
 			U64 idx = m_tail % m_queue.size();
 			U64 idx = m_tail % m_queue.size();
 
 
-			m_queue[idx] = jobs;
+			m_queue[idx] = commands;
 			++m_tail;
 			++m_tail;
 		}
 		}
 		else
 		else
@@ -61,25 +61,25 @@ void GlJobManager::flushJobChain(GlJobChainHandle& jobs)
 
 
 	m_condVar.notify_one(); // Wake the thread
 	m_condVar.notify_one(); // Wake the thread
 #else
 #else
-	jobs._executeAllJobs();
+	commands._executeAllCommands();
 #endif
 #endif
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::finishJobChain(GlJobChainHandle& jobs)
+void GlQueue::finishCommandChain(GlCommandBufferHandle& commands)
 {
 {
-#if !ANKI_JOB_MANAGER_DISABLE_ASYNC
-	flushJobChain(jobs);
+#if !ANKI_QUEUE_DISABLE_ASYNC
+	flushCommandChain(commands);
 
 
-	flushJobChain(m_syncJobs);
+	flushCommandChain(m_syncCommands);
 	m_sync.wait();
 	m_sync.wait();
 #else
 #else
-	flushJobChain(jobs);
+	flushCommandChain(commands);
 #endif
 #endif
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::start(
+void GlQueue::start(
 	GlCallback makeCurrentCallback, void* context, 
 	GlCallback makeCurrentCallback, void* context, 
 	GlCallback swapBuffersCallback, void* swapBuffersCbData,
 	GlCallback swapBuffersCallback, void* swapBuffersCbData,
 	Bool registerMessages)
 	Bool registerMessages)
@@ -96,26 +96,26 @@ void GlJobManager::start(
 	ANKI_ASSERT(swapBuffersCallback != nullptr);
 	ANKI_ASSERT(swapBuffersCallback != nullptr);
 	m_swapBuffersCallback = swapBuffersCallback;
 	m_swapBuffersCallback = swapBuffersCallback;
 	m_swapBuffersCbData = swapBuffersCbData;
 	m_swapBuffersCbData = swapBuffersCbData;
-	m_swapBuffersJobs = GlJobChainHandle(m_manager);
-	m_swapBuffersJobs.pushBackUserJob(swapBuffersInternal, this);
+	m_swapBuffersCommands = GlCommandBufferHandle(m_manager);
+	m_swapBuffersCommands.pushBackUserCommand(swapBuffersInternal, this);
 
 
-#if !ANKI_JOB_MANAGER_DISABLE_ASYNC
+#if !ANKI_QUEUE_DISABLE_ASYNC
 	// Start thread
 	// Start thread
-	m_thread = std::thread(&GlJobManager::threadLoop, this);
+	m_thread = std::thread(&GlQueue::threadLoop, this);
 
 
-	// Create sync job chain
-	m_syncJobs = GlJobChainHandle(m_manager);
-	m_sync = GlClientSyncHandle(m_syncJobs);
-	m_sync.sync(m_syncJobs);
+	// Create sync command buffer
+	m_syncCommands = GlCommandBufferHandle(m_manager);
+	m_sync = GlClientSyncHandle(m_syncCommands);
+	m_sync.sync(m_syncCommands);
 #else
 #else
 	prepare();
 	prepare();
 #endif
 #endif
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::stop()
+void GlQueue::stop()
 {
 {
-#if !ANKI_JOB_MANAGER_DISABLE_ASYNC
+#if !ANKI_QUEUE_DISABLE_ASYNC
 	{
 	{
 		std::unique_lock<std::mutex> lock(m_mtx);
 		std::unique_lock<std::mutex> lock(m_mtx);
 		m_renderingThreadSignal = 1;
 		m_renderingThreadSignal = 1;
@@ -131,7 +131,7 @@ void GlJobManager::stop()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::prepare()
+void GlQueue::prepare()
 {
 {
 	ANKI_ASSERT(m_makeCurrent && m_ctx);
 	ANKI_ASSERT(m_makeCurrent && m_ctx);
 	(*m_makeCurrent)(m_ctx);
 	(*m_makeCurrent)(m_ctx);
@@ -156,7 +156,7 @@ void GlJobManager::prepare()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::finish()
+void GlQueue::finish()
 {
 {
 	// Iterate the queue and release the refcounts
 	// Iterate the queue and release the refcounts
 	for(U i = 0; i < m_queue.size(); i++)
 	for(U i = 0; i < m_queue.size(); i++)
@@ -167,7 +167,7 @@ void GlJobManager::finish()
 			m_queue[i]._get().makeExecuted();
 			m_queue[i]._get().makeExecuted();
 
 
 			// Release
 			// Release
-			m_queue[i] = GlJobChainHandle();
+			m_queue[i] = GlCommandBufferHandle();
 		}
 		}
 	}
 	}
 
 
@@ -180,15 +180,15 @@ void GlJobManager::finish()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::threadLoop()
+void GlQueue::threadLoop()
 {
 {
-	setCurrentThreadName("anki_gl");
+	//setCurrentThreadName("anki_gl");
 
 
 	prepare();
 	prepare();
 
 
 	while(1)
 	while(1)
 	{
 	{
-		GlJobChainHandle jobc;
+		GlCommandBufferHandle commandc;
 
 
 		// Wait for something
 		// Wait for something
 		{
 		{
@@ -206,17 +206,17 @@ void GlJobManager::threadLoop()
 			}
 			}
 
 
 			U64 idx = m_head % m_queue.size();
 			U64 idx = m_head % m_queue.size();
-			// Pop a job
-			jobc = m_queue[idx];
-			m_queue[idx] = GlJobChainHandle(); // Insert empty jobchain
+			// Pop a command
+			commandc = m_queue[idx];
+			m_queue[idx] = GlCommandBufferHandle(); // Insert empty cmd buffer
 
 
 			++m_head;
 			++m_head;
 		}
 		}
 
 
 		try
 		try
 		{
 		{
-			// Exec jobs of chain
-			jobc._executeAllJobs();
+			// Exec commands of chain
+			commandc._executeAllCommands();
 		}
 		}
 		catch(const std::exception& e)
 		catch(const std::exception& e)
 		{
 		{
@@ -229,19 +229,19 @@ void GlJobManager::threadLoop()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::syncClientServer()
+void GlQueue::syncClientServer()
 {
 {
-#if !ANKI_JOB_MANAGER_DISABLE_ASYNC
-	flushJobChain(m_syncJobs);
+#if !ANKI_QUEUE_DISABLE_ASYNC
+	flushCommandChain(m_syncCommands);
 	m_sync.wait();
 	m_sync.wait();
 #endif
 #endif
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::swapBuffersInternal(void* ptr)
+void GlQueue::swapBuffersInternal(void* ptr)
 {
 {
 	ANKI_ASSERT(ptr);
 	ANKI_ASSERT(ptr);
-	GlJobManager& self = *reinterpret_cast<GlJobManager*>(ptr);
+	GlQueue& self = *reinterpret_cast<GlQueue*>(ptr);
 
 
 	self.m_swapBuffersCallback(self.m_swapBuffersCbData);
 	self.m_swapBuffersCallback(self.m_swapBuffersCbData);
 
 
@@ -255,7 +255,7 @@ void GlJobManager::swapBuffersInternal(void* ptr)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlJobManager::swapBuffers()
+void GlQueue::swapBuffers()
 {
 {
 	// Wait for the rendering thread to finish swap buffers...
 	// Wait for the rendering thread to finish swap buffers...
 	{
 	{
@@ -269,7 +269,7 @@ void GlJobManager::swapBuffers()
 	}
 	}
 
 
 	// ...and then flush a new swap buffers
 	// ...and then flush a new swap buffers
-	flushJobChain(m_swapBuffersJobs);
+	flushCommandChain(m_swapBuffersCommands);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 11 - 11
src/gl/GlSyncHandles.cpp

@@ -5,25 +5,25 @@
 
 
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlSyncHandles.h"
 #include "anki/gl/GlSync.h"
 #include "anki/gl/GlSync.h"
-#include "anki/gl/GlJobChainHandle.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlCommandBufferHandle.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"
 
 
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-/// Wait job
-class GlClientSyncWaitJob: public GlJob
+/// Wait command
+class GlClientSyncWaitCommand: public GlCommand
 {
 {
 public:
 public:
 	GlClientSyncHandle m_sync;	
 	GlClientSyncHandle m_sync;	
 
 
-	GlClientSyncWaitJob(const GlClientSyncHandle& s)
+	GlClientSyncWaitCommand(const GlClientSyncHandle& s)
 		: m_sync(s)
 		: m_sync(s)
 	{}
 	{}
 
 
-	void operator()(GlJobChain*)
+	void operator()(GlCommandBuffer*)
 	{
 	{
 		ANKI_COUNTER_START_TIMER(GL_SERVER_WAIT_TIME);
 		ANKI_COUNTER_START_TIMER(GL_SERVER_WAIT_TIME);
 		m_sync._get().wait();
 		m_sync._get().wait();
@@ -36,15 +36,15 @@ GlClientSyncHandle::GlClientSyncHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-GlClientSyncHandle::GlClientSyncHandle(GlJobChainHandle& jobs)
+GlClientSyncHandle::GlClientSyncHandle(GlCommandBufferHandle& commands)
 {
 {
-	auto alloc = jobs._getGlobalAllocator();
+	auto alloc = commands._getGlobalAllocator();
 
 
 	typedef GlHandleDefaultDeleter<GlClientSync, GlGlobalHeapAllocator<U8>>
 	typedef GlHandleDefaultDeleter<GlClientSync, GlGlobalHeapAllocator<U8>>
 		Deleter;
 		Deleter;
 
 
 	*static_cast<Base*>(this) = Base(
 	*static_cast<Base*>(this) = Base(
-		&jobs._getJobManager().getManager(), alloc, Deleter());
+		&commands._getQueue().getManager(), alloc, Deleter());
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -52,9 +52,9 @@ GlClientSyncHandle::~GlClientSyncHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlClientSyncHandle::sync(GlJobChainHandle& jobs)
+void GlClientSyncHandle::sync(GlCommandBufferHandle& commands)
 {
 {
-	jobs._pushBackNewJob<GlClientSyncWaitJob>(*this);
+	commands._pushBackNewCommand<GlClientSyncWaitCommand>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 70 - 68
src/gl/GlTextureHandle.cpp

@@ -5,7 +5,7 @@
 
 
 #include "anki/gl/GlTextureHandle.h"
 #include "anki/gl/GlTextureHandle.h"
 #include "anki/gl/GlTexture.h"
 #include "anki/gl/GlTexture.h"
-#include "anki/gl/GlManager.h"
+#include "anki/gl/GlDevice.h"
 #include "anki/gl/GlHandleDeferredDeleter.h"	
 #include "anki/gl/GlHandleDeferredDeleter.h"	
 
 
 namespace anki {
 namespace anki {
@@ -20,23 +20,24 @@ GlTextureHandle::GlTextureHandle()
 
 
 //==============================================================================
 //==============================================================================
 GlTextureHandle::GlTextureHandle(
 GlTextureHandle::GlTextureHandle(
-	GlJobChainHandle& jobs, const Initializer& init)
+	GlCommandBufferHandle& commands, const Initializer& init)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlTextureHandle m_tex;
 		GlTextureHandle m_tex;
 		GlTextureHandle::Initializer m_init;
 		GlTextureHandle::Initializer m_init;
 
 
-		Job(
+		Command(
 			GlTextureHandle tex, 
 			GlTextureHandle tex, 
 			const GlTextureHandle::Initializer& init)
 			const GlTextureHandle::Initializer& init)
-			: m_tex(tex), m_init(init)
+		:	m_tex(tex), 
+			m_init(init)
 		{}
 		{}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
-			ANKI_ASSERT(jobs);
+			ANKI_ASSERT(commands);
 			GlTexture::Initializer init;
 			GlTexture::Initializer init;
 
 
 			static_cast<GlTextureInitializerBase&>(init) = m_init;
 			static_cast<GlTextureInitializerBase&>(init) = m_init;
@@ -79,7 +80,7 @@ GlTextureHandle::GlTextureHandle(
 				}
 				}
 			}
 			}
 
 
-			auto alloc = jobs->getGlobalAllocator();
+			auto alloc = commands->getGlobalAllocator();
 			GlTexture newTex(init, alloc);
 			GlTexture newTex(init, alloc);
 
 
 			m_tex._get() = std::move(newTex);
 			m_tex._get() = std::move(newTex);
@@ -94,21 +95,21 @@ GlTextureHandle::GlTextureHandle(
 
 
 	typedef GlGlobalHeapAllocator<GlTexture> Alloc;
 	typedef GlGlobalHeapAllocator<GlTexture> Alloc;
 
 
-	typedef GlDeleteObjectJob<
+	typedef GlDeleteObjectCommand<
 		GlTexture, 
 		GlTexture, 
-		Alloc> DeleteJob;
+		Alloc> DeleteCommand;
 
 
-	typedef GlHandleDeferredDeleter<GlTexture, Alloc, DeleteJob>
+	typedef GlHandleDeferredDeleter<GlTexture, Alloc, DeleteCommand>
 		Deleter;
 		Deleter;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._getJobManager().getManager(),
-		jobs._getJobManager().getManager()._getAllocator(), 
+		&commands._getQueue().getManager(),
+		commands._getQueue().getManager()._getAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
-	// Fire the job
-	jobs._pushBackNewJob<Job>(*this, init);
+	// Fire the command
+	commands._pushBackNewCommand<Command>(*this, init);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -116,98 +117,98 @@ GlTextureHandle::~GlTextureHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlTextureHandle::bind(GlJobChainHandle& jobs, U32 unit)
+void GlTextureHandle::bind(GlCommandBufferHandle& commands, U32 unit)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlTextureHandle m_tex;
 		GlTextureHandle m_tex;
 		U32 m_unit;
 		U32 m_unit;
 
 
-		Job(GlTextureHandle& tex, U32 unit)
+		Command(GlTextureHandle& tex, U32 unit)
 			: m_tex(tex), m_unit(unit)
 			: m_tex(tex), m_unit(unit)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_tex._get().bind(m_unit);
 			m_tex._get().bind(m_unit);
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, unit);
+	commands._pushBackNewCommand<Command>(*this, unit);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlTextureHandle::setFilter(GlJobChainHandle& jobs, Filter filter)
+void GlTextureHandle::setFilter(GlCommandBufferHandle& commands, Filter filter)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlTextureHandle m_tex;
 		GlTextureHandle m_tex;
 		GlTexture::Filter m_filter;
 		GlTexture::Filter m_filter;
 
 
-		Job(GlTextureHandle tex, GlTexture::Filter filter)
+		Command(GlTextureHandle tex, GlTexture::Filter filter)
 			: m_tex(tex), m_filter(filter)
 			: m_tex(tex), m_filter(filter)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_tex._get().setFilter(m_filter);
 			m_tex._get().setFilter(m_filter);
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, filter);
+	commands._pushBackNewCommand<Command>(*this, filter);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlTextureHandle::generateMipmaps(GlJobChainHandle& jobs)
+void GlTextureHandle::generateMipmaps(GlCommandBufferHandle& commands)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlTextureHandle m_tex;
 		GlTextureHandle m_tex;
 
 
-		Job(GlTextureHandle tex)
+		Command(GlTextureHandle tex)
 			: m_tex(tex)
 			: m_tex(tex)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_tex._get().generateMipmaps();
 			m_tex._get().generateMipmaps();
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this);
+	commands._pushBackNewCommand<Command>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlTextureHandle::setParameter(GlJobChainHandle& jobs, GLenum param, 
-	GLint value)
+void GlTextureHandle::setParameter(GlCommandBufferHandle& commands, 
+	GLenum param, GLint value)
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
 
 
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlTextureHandle m_tex;
 		GlTextureHandle m_tex;
 		GLenum m_param;
 		GLenum m_param;
 		GLint m_value;
 		GLint m_value;
 
 
-		Job(GlTextureHandle& tex, GLenum param, GLint value)
+		Command(GlTextureHandle& tex, GLenum param, GLint value)
 			: m_tex(tex), m_param(param), m_value(value)
 			: m_tex(tex), m_param(param), m_value(value)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_tex._get().setParameter(m_param, m_value);
 			m_tex._get().setParameter(m_param, m_value);
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, param, value);
+	commands._pushBackNewCommand<Command>(*this, param, value);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -240,25 +241,26 @@ GlSamplerHandle::GlSamplerHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-GlSamplerHandle::GlSamplerHandle(GlJobChainHandle& jobs)
+GlSamplerHandle::GlSamplerHandle(GlCommandBufferHandle& commands)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlSamplerHandle m_sampler;
 		GlSamplerHandle m_sampler;
 
 
-		Job(const GlSamplerHandle& sampler)
+		Command(const GlSamplerHandle& sampler)
 			: m_sampler(sampler)
 			: m_sampler(sampler)
 		{}
 		{}
 
 
-		void operator()(GlJobChain* jobs)
+		void operator()(GlCommandBuffer* commands)
 		{
 		{
-			ANKI_ASSERT(jobs);
+			ANKI_ASSERT(commands);
 
 
 			GlSampler newSampler;
 			GlSampler newSampler;
 			m_sampler._get() = std::move(newSampler);
 			m_sampler._get() = std::move(newSampler);
 
 
-			GlHandleState oldState = m_sampler._setState(GlHandleState::CREATED);
+			GlHandleState oldState = 
+				m_sampler._setState(GlHandleState::CREATED);
 			ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
 			ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
 			(void)oldState;
 			(void)oldState;
 		}
 		}
@@ -266,20 +268,20 @@ GlSamplerHandle::GlSamplerHandle(GlJobChainHandle& jobs)
 
 
 	typedef GlGlobalHeapAllocator<GlSampler> Alloc;
 	typedef GlGlobalHeapAllocator<GlSampler> Alloc;
 
 
-	typedef GlDeleteObjectJob<
+	typedef GlDeleteObjectCommand<
 		GlSampler, 
 		GlSampler, 
-		Alloc> DeleteJob;
+		Alloc> DeleteCommand;
 
 
-	typedef GlHandleDeferredDeleter<GlSampler, Alloc, DeleteJob>
+	typedef GlHandleDeferredDeleter<GlSampler, Alloc, DeleteCommand>
 		Deleter;
 		Deleter;
 
 
 	*static_cast<Base::Base*>(this) = Base::Base(
 	*static_cast<Base::Base*>(this) = Base::Base(
-		&jobs._getJobManager().getManager(),
-		jobs._getJobManager().getManager()._getAllocator(), 
+		&commands._getQueue().getManager(),
+		commands._getQueue().getManager()._getAllocator(), 
 		Deleter());
 		Deleter());
 	_setState(GlHandleState::TO_BE_CREATED);
 	_setState(GlHandleState::TO_BE_CREATED);
 
 
-	jobs._pushBackNewJob<Job>(*this);
+	commands._pushBackNewCommand<Command>(*this);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -287,95 +289,95 @@ GlSamplerHandle::~GlSamplerHandle()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-void GlSamplerHandle::bind(GlJobChainHandle& jobs, U32 unit)
+void GlSamplerHandle::bind(GlCommandBufferHandle& commands, U32 unit)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlSamplerHandle m_sampler;
 		GlSamplerHandle m_sampler;
 		U32 m_unit;
 		U32 m_unit;
 
 
-		Job(GlSamplerHandle& sampler, U32 unit)
+		Command(GlSamplerHandle& sampler, U32 unit)
 			: m_sampler(sampler), m_unit(unit)
 			: m_sampler(sampler), m_unit(unit)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_sampler._get().bind(m_unit);
 			m_sampler._get().bind(m_unit);
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, unit);
+	commands._pushBackNewCommand<Command>(*this, unit);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlSamplerHandle::setFilter(GlJobChainHandle& jobs, Filter filter)
+void GlSamplerHandle::setFilter(GlCommandBufferHandle& commands, Filter filter)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlSamplerHandle m_sampler;
 		GlSamplerHandle m_sampler;
 		GlSamplerHandle::Filter m_filter;
 		GlSamplerHandle::Filter m_filter;
 
 
-		Job(const GlSamplerHandle& sampler, GlSamplerHandle::Filter filter)
+		Command(const GlSamplerHandle& sampler, GlSamplerHandle::Filter filter)
 			: m_sampler(sampler), m_filter(filter)
 			: m_sampler(sampler), m_filter(filter)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_sampler._get().setFilter(m_filter);
 			m_sampler._get().setFilter(m_filter);
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, filter);
+	commands._pushBackNewCommand<Command>(*this, filter);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 void GlSamplerHandle::setParameter(
 void GlSamplerHandle::setParameter(
-	GlJobChainHandle& jobs, GLenum param, GLint value)
+	GlCommandBufferHandle& commands, GLenum param, GLint value)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		GlSamplerHandle m_sampler;
 		GlSamplerHandle m_sampler;
 		GLenum m_param;
 		GLenum m_param;
 		GLint m_value;
 		GLint m_value;
 
 
-		Job(GlSamplerHandle& sampler, GLenum param, GLint value)
+		Command(GlSamplerHandle& sampler, GLenum param, GLint value)
 			: m_sampler(sampler), m_param(param), m_value(value)
 			: m_sampler(sampler), m_param(param), m_value(value)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			m_sampler._get().setParameter(m_param, m_value);
 			m_sampler._get().setParameter(m_param, m_value);
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	jobs._pushBackNewJob<Job>(*this, param, value);
+	commands._pushBackNewCommand<Command>(*this, param, value);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void GlSamplerHandle::bindDefault(GlJobChainHandle& jobs, U32 unit)
+void GlSamplerHandle::bindDefault(GlCommandBufferHandle& commands, U32 unit)
 {
 {
-	class Job: public GlJob
+	class Command: public GlCommand
 	{
 	{
 	public:
 	public:
 		U32 m_unit;
 		U32 m_unit;
 
 
-		Job(U32 unit)
+		Command(U32 unit)
 			: m_unit(unit)
 			: m_unit(unit)
 		{}
 		{}
 
 
-		void operator()(GlJobChain*)
+		void operator()(GlCommandBuffer*)
 		{
 		{
 			GlSampler::unbind(m_unit);
 			GlSampler::unbind(m_unit);
 		}
 		}
 	};
 	};
 
 
-	jobs._pushBackNewJob<Job>(unit);
+	commands._pushBackNewCommand<Command>(unit);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 4 - 4
src/input/Input.cpp

@@ -9,12 +9,12 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-void Input::reset(void)
+void Input::reset()
 {
 {
-	memset(&m_keys[0], 0, m_keys.getSize() * sizeof(U32));
-	memset(&m_mouseBtns[0], 0, m_mouseBtns.getSize() * sizeof(U32));
+	std::memset(&m_keys[0], 0, sizeof(m_keys));
+	std::memset(&m_mouseBtns[0], 0, sizeof(m_mouseBtns));
 	m_mousePosNdc = Vec2(0.0);
 	m_mousePosNdc = Vec2(0.0);
-	memset(&m_events[0], 0, sizeof(m_events));
+	std::memset(&m_events[0], 0, sizeof(m_events));
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 10 - 5
src/input/InputSdl.cpp

@@ -11,10 +11,6 @@
 
 
 namespace anki {
 namespace anki {
 
 
-//==============================================================================
-Input::~Input()
-{}
-
 //==============================================================================
 //==============================================================================
 void Input::init(NativeWindow* nativeWindow)
 void Input::init(NativeWindow* nativeWindow)
 {
 {
@@ -22,7 +18,7 @@ void Input::init(NativeWindow* nativeWindow)
 	m_nativeWindow = nativeWindow;
 	m_nativeWindow = nativeWindow;
 
 
 	// Init native
 	// Init native
-	m_impl.reset(new InputImpl);
+	m_impl = m_nativeWindow->_getAllocator().newInstance<InputImpl>();
 
 
 	//impl
 	//impl
 	m_impl->m_sdlToAnki[SDLK_RETURN] = KeyCode::RETURN;
 	m_impl->m_sdlToAnki[SDLK_RETURN] = KeyCode::RETURN;
@@ -265,6 +261,15 @@ void Input::init(NativeWindow* nativeWindow)
 	handleEvents();
 	handleEvents();
 }
 }
 
 
+//==============================================================================
+void Input::destroy()
+{
+	if(m_impl != nullptr)
+	{
+		m_nativeWindow->_getAllocator().deleteInstance(m_impl);
+	}
+}
+
 //==============================================================================
 //==============================================================================
 void Input::handleEvents()
 void Input::handleEvents()
 {
 {

+ 1 - 1
src/renderer/Bs.cpp

@@ -21,7 +21,7 @@ void Bs::init(const ConfigSet&)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Bs::run(GlJobChainHandle& jobs)
+void Bs::run(GlCommandBufferHandle& jobs)
 {
 {
 	jobs.enableDepthTest(true);
 	jobs.enableDepthTest(true);
 	jobs.setDepthWriteMask(false);
 	jobs.setDepthWriteMask(false);

+ 3 - 3
src/renderer/Dbg.cpp

@@ -25,8 +25,8 @@ void Dbg::init(const ConfigSet& initializer)
 
 
 	try
 	try
 	{
 	{
-		GlManager& gl = GlManagerSingleton::get();
-		GlJobChainHandle jobs(&gl);
+		GlDevice& gl = GlDeviceSingleton::get();
+		GlCommandBufferHandle jobs(&gl);
 
 
 		// Chose the correct color FAI
 		// Chose the correct color FAI
 		if(m_r->getPps().getEnabled())
 		if(m_r->getPps().getEnabled())
@@ -54,7 +54,7 @@ void Dbg::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Dbg::run(GlJobChainHandle& jobs)
+void Dbg::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 

+ 2 - 2
src/renderer/DebugDrawer.cpp

@@ -20,12 +20,12 @@ namespace anki {
 //==============================================================================
 //==============================================================================
 DebugDrawer::DebugDrawer()
 DebugDrawer::DebugDrawer()
 {
 {
-	GlManager& gl = GlManagerSingleton::get();
+	GlDevice& gl = GlDeviceSingleton::get();
 
 
 	m_vert.load("shaders/Dbg.vert.glsl");
 	m_vert.load("shaders/Dbg.vert.glsl");
 	m_frag.load("shaders/Dbg.frag.glsl");
 	m_frag.load("shaders/Dbg.frag.glsl");
 
 
-	GlJobChainHandle jobs(&gl);
+	GlCommandBufferHandle jobs(&gl);
 
 
 	m_ppline = GlProgramPipelineHandle(jobs, 
 	m_ppline = GlProgramPipelineHandle(jobs, 
 		{m_vert->getGlProgram(), m_frag->getGlProgram()});
 		{m_vert->getGlProgram(), m_frag->getGlProgram()});

+ 6 - 6
src/renderer/Drawer.cpp

@@ -30,7 +30,7 @@ public:
 	Ptr<const FrustumComponent> m_fr;
 	Ptr<const FrustumComponent> m_fr;
 	Ptr<RenderableDrawer> m_drawer;
 	Ptr<RenderableDrawer> m_drawer;
 	U8 m_instanceCount;
 	U8 m_instanceCount;
-	GlJobChainHandle m_jobs;
+	GlCommandBufferHandle m_jobs;
 
 
 	F32 m_flod;
 	F32 m_flod;
 
 
@@ -229,8 +229,8 @@ RenderableDrawer::RenderableDrawer(Renderer* r)
 	: m_r(r)
 	: m_r(r)
 {
 {
 	// Create the uniform buffer
 	// Create the uniform buffer
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 	m_uniformBuff = GlBufferHandle(jobs, GL_UNIFORM_BUFFER, 
 	m_uniformBuff = GlBufferHandle(jobs, GL_UNIFORM_BUFFER, 
 		MAX_UNIFORM_BUFFER_SIZE,
 		MAX_UNIFORM_BUFFER_SIZE,
 		GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
 		GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
@@ -260,7 +260,7 @@ void RenderableDrawer::setupUniforms(
 	// Find a place to write the uniforms
 	// Find a place to write the uniforms
 	//
 	//
 	U8* prevUniformPtr = m_uniformPtr;
 	U8* prevUniformPtr = m_uniformPtr;
-	alignRoundUp(GlManagerSingleton::get().getBufferOffsetAlignment(
+	alignRoundUp(GlDeviceSingleton::get().getBufferOffsetAlignment(
 		m_uniformBuff.getTarget()), m_uniformPtr);
 		m_uniformBuff.getTarget()), m_uniformPtr);
 	U diff = m_uniformPtr - prevUniformPtr;
 	U diff = m_uniformPtr - prevUniformPtr;
 
 
@@ -368,7 +368,7 @@ void RenderableDrawer::render(SceneNode& frsn, VisibleNode& visibleNode)
 
 
 //==============================================================================
 //==============================================================================
 void RenderableDrawer::prepareDraw(RenderingStage stage, Pass pass,
 void RenderableDrawer::prepareDraw(RenderingStage stage, Pass pass,
-	GlJobChainHandle& jobs)
+	GlCommandBufferHandle& jobs)
 {
 {
 	// Set some numbers
 	// Set some numbers
 	m_stage = stage;
 	m_stage = stage;
@@ -387,7 +387,7 @@ void RenderableDrawer::prepareDraw(RenderingStage stage, Pass pass,
 void RenderableDrawer::finishDraw()
 void RenderableDrawer::finishDraw()
 {
 {
 	// Release the job chain
 	// Release the job chain
-	m_jobs = GlJobChainHandle();
+	m_jobs = GlCommandBufferHandle();
 
 
 	if(m_uniformsUsedSize > MAX_UNIFORM_BUFFER_SIZE / 3)
 	if(m_uniformsUsedSize > MAX_UNIFORM_BUFFER_SIZE / 3)
 	{
 	{

+ 1 - 1
src/renderer/Ez.cpp

@@ -19,7 +19,7 @@ void Ez::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Ez::run(GlJobChainHandle& jobs)
+void Ez::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 

+ 6 - 6
src/renderer/Hdr.cpp

@@ -16,13 +16,13 @@ Hdr::~Hdr()
 //==============================================================================
 //==============================================================================
 void Hdr::initFb(GlFramebufferHandle& fb, GlTextureHandle& rt)
 void Hdr::initFb(GlFramebufferHandle& fb, GlTextureHandle& rt)
 {
 {
-	GlManager& gl = GlManagerSingleton::get();
+	GlDevice& gl = GlDeviceSingleton::get();
 
 
 	m_r->createRenderTarget(m_width, m_height, GL_RGB8, GL_RGB, 
 	m_r->createRenderTarget(m_width, m_height, GL_RGB8, GL_RGB, 
 		GL_UNSIGNED_BYTE, 1, rt);
 		GL_UNSIGNED_BYTE, 1, rt);
 
 
 	// Set to bilinear because the blurring techniques take advantage of that
 	// Set to bilinear because the blurring techniques take advantage of that
-	GlJobChainHandle jobs(&gl);
+	GlCommandBufferHandle jobs(&gl);
 	rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
 	rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
 
 
 	// Create FB
 	// Create FB
@@ -56,8 +56,8 @@ void Hdr::initInternal(const ConfigSet& initializer)
 	initFb(m_vblurFb, m_vblurRt);
 	initFb(m_vblurFb, m_vblurRt);
 
 
 	// init shaders
 	// init shaders
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	m_commonBuff = GlBufferHandle(jobs, GL_SHADER_STORAGE_BUFFER, 
 	m_commonBuff = GlBufferHandle(jobs, GL_SHADER_STORAGE_BUFFER, 
 		sizeof(Vec4), GL_DYNAMIC_STORAGE_BIT);
 		sizeof(Vec4), GL_DYNAMIC_STORAGE_BIT);
@@ -119,7 +119,7 @@ void Hdr::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Hdr::run(GlJobChainHandle& jobs)
+void Hdr::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 
@@ -166,7 +166,7 @@ void Hdr::run(GlJobChainHandle& jobs)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Hdr::updateDefaultBlock(GlJobChainHandle& jobs)
+void Hdr::updateDefaultBlock(GlCommandBufferHandle& jobs)
 {
 {
 	GlClientBufferHandle tempBuff(jobs, sizeof(Vec4), nullptr);
 	GlClientBufferHandle tempBuff(jobs, sizeof(Vec4), nullptr);
 	
 	

+ 11 - 12
src/renderer/Is.cpp

@@ -8,7 +8,6 @@
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Light.h"
 #include "anki/scene/Light.h"
-#include "anki/core/Threadpool.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Logger.h"
 #include "anki/core/Logger.h"
 #include <sstream>
 #include <sstream>
@@ -71,7 +70,7 @@ public:
 
 
 //==============================================================================
 //==============================================================================
 /// Write the lights to a client buffer
 /// Write the lights to a client buffer
-class WriteLightsJob: public ThreadpoolTask
+class WriteLightsJob: public Threadpool::Task
 {
 {
 public:
 public:
 	shader::PointLight* m_pointLights = nullptr;
 	shader::PointLight* m_pointLights = nullptr;
@@ -100,7 +99,7 @@ public:
 	/// Bin lights on CPU path
 	/// Bin lights on CPU path
 	Bool m_binLights = true;
 	Bool m_binLights = true;
 
 
-	void operator()(ThreadId threadId, U threadsCount)
+	void operator()(U32 threadId, PtrSize threadsCount)
 	{
 	{
 		U ligthsCount = m_lightsEnd - m_lightsBegin;
 		U ligthsCount = m_lightsEnd - m_lightsBegin;
 
 
@@ -455,8 +454,8 @@ void Is::initInternal(const ConfigSet& initializer)
 	}
 	}
 
 
 	// point light
 	// point light
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl); // Job for initialization
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl); // Job for initialization
 
 
 	m_lightVert.load(ProgramResource::createSrcCodeToCache(
 	m_lightVert.load(ProgramResource::createSrcCodeToCache(
 		"shaders/IsLp.vert.glsl", pps.str().c_str(), "r_").c_str());
 		"shaders/IsLp.vert.glsl", pps.str().c_str(), "r_").c_str());
@@ -507,9 +506,9 @@ void Is::initInternal(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Is::lightPass(GlJobChainHandle& jobs)
+void Is::lightPass(GlCommandBufferHandle& jobs)
 {
 {
-	Threadpool& threadPool = ThreadpoolSingleton::get();
+	Threadpool& threadPool = m_r->_getThreadpool();
 	m_cam = &m_r->getSceneGraph().getActiveCamera();
 	m_cam = &m_r->getSceneGraph().getActiveCamera();
 	VisibilityTestResults& vi = m_cam->getVisibilityTestResults();
 	VisibilityTestResults& vi = m_cam->getVisibilityTestResults();
 
 
@@ -567,7 +566,7 @@ void Is::lightPass(GlJobChainHandle& jobs)
 	//
 	//
 	// Write the lights and tiles UBOs
 	// Write the lights and tiles UBOs
 	//
 	//
-	GlManager& gl = GlManagerSingleton::get();
+	GlDevice& gl = GlDeviceSingleton::get();
 	U32 blockAlignment = gl.getBufferOffsetAlignment(m_lightsBuff.getTarget());
 	U32 blockAlignment = gl.getBufferOffsetAlignment(m_lightsBuff.getTarget());
 
 
 	// Get the offsets and sizes of each uniform block
 	// Get the offsets and sizes of each uniform block
@@ -756,7 +755,7 @@ void Is::lightPass(GlJobChainHandle& jobs)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Is::setState(GlJobChainHandle& jobs)
+void Is::setState(GlCommandBufferHandle& jobs)
 {
 {
 	Bool drawToDefaultFbo = !m_r->getPps().getEnabled() 
 	Bool drawToDefaultFbo = !m_r->getPps().getEnabled() 
 		&& !m_r->getDbg().getEnabled() 
 		&& !m_r->getDbg().getEnabled() 
@@ -777,14 +776,14 @@ void Is::setState(GlJobChainHandle& jobs)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Is::run(GlJobChainHandle& jobs)
+void Is::run(GlCommandBufferHandle& jobs)
 {
 {
 	// Do the light pass including the shadow passes
 	// Do the light pass including the shadow passes
 	lightPass(jobs);
 	lightPass(jobs);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Is::updateCommonBlock(GlJobChainHandle& jobs)
+void Is::updateCommonBlock(GlCommandBufferHandle& jobs)
 {
 {
 	SceneGraph& scene = m_r->getSceneGraph();
 	SceneGraph& scene = m_r->getSceneGraph();
 
 
@@ -810,7 +809,7 @@ void Is::updateCommonBlock(GlJobChainHandle& jobs)
 //==============================================================================
 //==============================================================================
 PtrSize Is::calcLightsBufferSize() const
 PtrSize Is::calcLightsBufferSize() const
 {
 {
-	U32 buffAlignment = GlManagerSingleton::get().getBufferOffsetAlignment(
+	U32 buffAlignment = GlDeviceSingleton::get().getBufferOffsetAlignment(
 		GL_SHADER_STORAGE_BUFFER);
 		GL_SHADER_STORAGE_BUFFER);
 	PtrSize size;
 	PtrSize size;
 
 

+ 3 - 3
src/renderer/Lf.cpp

@@ -77,8 +77,8 @@ void Lf::initInternal(const ConfigSet& initializer)
 		return;
 		return;
 	}
 	}
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	m_maxFlaresPerLight = initializer.get("pps.lf.maxFlaresPerLight");
 	m_maxFlaresPerLight = initializer.get("pps.lf.maxFlaresPerLight");
 	m_maxLightsWithFlares = initializer.get("pps.lf.maxLightsWithFlares");
 	m_maxLightsWithFlares = initializer.get("pps.lf.maxLightsWithFlares");
@@ -142,7 +142,7 @@ void Lf::initInternal(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Lf::run(GlJobChainHandle& jobs)
+void Lf::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 

+ 9 - 7
src/renderer/MainRenderer.cpp

@@ -8,13 +8,15 @@
 #include "anki/renderer/Deformer.h"
 #include "anki/renderer/Deformer.h"
 #include "anki/util/File.h"
 #include "anki/util/File.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"
+#include "anki/core/App.h"
 #include <cstdlib>
 #include <cstdlib>
 #include <cstdio>
 #include <cstdio>
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-MainRenderer::MainRenderer(const ConfigSet& initializer)
+MainRenderer::MainRenderer(App* app, const ConfigSet& initializer)
+:	Renderer(&app->getThreadpool())
 {
 {
 	init(initializer);
 	init(initializer);
 }
 }
@@ -53,13 +55,13 @@ void MainRenderer::render(SceneGraph& scene)
 {
 {
 	ANKI_COUNTER_START_TIMER(MAIN_RENDERER_TIME);
 	ANKI_COUNTER_START_TIMER(MAIN_RENDERER_TIME);
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	Array<GlJobChainHandle, JOB_CHAINS_COUNT> jobs;
-	GlJobChainHandle& lastJobs = jobs[JOB_CHAINS_COUNT - 1];
+	GlDevice& gl = GlDeviceSingleton::get();
+	Array<GlCommandBufferHandle, JOB_CHAINS_COUNT> jobs;
+	GlCommandBufferHandle& lastJobs = jobs[JOB_CHAINS_COUNT - 1];
 
 
 	for(U i = 0; i < JOB_CHAINS_COUNT; i++)
 	for(U i = 0; i < JOB_CHAINS_COUNT; i++)
 	{
 	{
-		jobs[i] = GlJobChainHandle(&gl, m_jobsInitHints[i]);
+		jobs[i] = GlCommandBufferHandle(&gl, m_jobsInitHints[i]);
 	}
 	}
 
 
 	Renderer::render(scene, jobs);
 	Renderer::render(scene, jobs);
@@ -111,8 +113,8 @@ void MainRenderer::render(SceneGraph& scene)
 void MainRenderer::initGl()
 void MainRenderer::initGl()
 {
 {
 	// get max texture units
 	// get max texture units
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	jobs.enableCulling(true);
 	jobs.enableCulling(true);
 	jobs.setCullFace(GL_BACK);
 	jobs.setCullFace(GL_BACK);

+ 5 - 5
src/renderer/Ms.cpp

@@ -32,8 +32,8 @@ void Ms::createRt(U32 index, U32 samples)
 	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGBA8,
 	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGBA8,
 		GL_RGBA, GL_UNSIGNED_BYTE, samples, plane.m_rt1);
 		GL_RGBA, GL_UNSIGNED_BYTE, samples, plane.m_rt1);
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	plane.m_fb = GlFramebufferHandle(
 	plane.m_fb = GlFramebufferHandle(
 		jobs,
 		jobs,
@@ -63,8 +63,8 @@ void Ms::init(const ConfigSet& initializer)
 				GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT,
 				GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT,
 				GL_UNSIGNED_INT, 1, m_smallDepthRt);
 				GL_UNSIGNED_INT, 1, m_smallDepthRt);
 
 
-			GlManager& gl = GlManagerSingleton::get();
-			GlJobChainHandle jobs(&gl);
+			GlDevice& gl = GlDeviceSingleton::get();
+			GlCommandBufferHandle jobs(&gl);
 
 
 			m_smallDepthRt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
 			m_smallDepthRt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
 
 
@@ -84,7 +84,7 @@ void Ms::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Ms::run(GlJobChainHandle& jobs)
+void Ms::run(GlCommandBufferHandle& jobs)
 {
 {
 	// Chose the multisampled or the singlesampled framebuffer
 	// Chose the multisampled or the singlesampled framebuffer
 	if(m_r->getSamples() > 1)
 	if(m_r->getSamples() > 1)

+ 3 - 3
src/renderer/Pps.cpp

@@ -42,8 +42,8 @@ void Pps::initInternal(const ConfigSet& initializer)
 	m_sslr.init(initializer);
 	m_sslr.init(initializer);
 
 
 	// FBO
 	// FBO
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGB8, GL_RGB,
 	m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), GL_RGB8, GL_RGB,
 		GL_UNSIGNED_BYTE, 1, m_rt);
 		GL_UNSIGNED_BYTE, 1, m_rt);
@@ -84,7 +84,7 @@ void Pps::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Pps::run(GlJobChainHandle& jobs)
+void Pps::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 

+ 17 - 16
src/renderer/Renderer.cpp

@@ -13,13 +13,14 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-Renderer::Renderer()
-	:	m_ms(this), 
-		m_is(this),
-		m_pps(this),
-		m_bs(this),
-		m_dbg(this), 
-		m_sceneDrawer(this)
+Renderer::Renderer(Threadpool* threadpool)
+:	m_ms(this), 
+	m_is(this),
+	m_pps(this),
+	m_bs(this),
+	m_dbg(this), 
+	m_sceneDrawer(this),
+	m_threadpool(threadpool)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
@@ -58,8 +59,8 @@ void Renderer::init(const ConfigSet& initializer)
 	static const F32 quadVertCoords[][2] = {{1.0, 1.0}, {-1.0, 1.0}, 
 	static const F32 quadVertCoords[][2] = {{1.0, 1.0}, {-1.0, 1.0}, 
 		{1.0, -1.0}, {-1.0, -1.0}};
 		{1.0, -1.0}, {-1.0, -1.0}};
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	GlClientBufferHandle tmpBuff = GlClientBufferHandle(jobs, 
 	GlClientBufferHandle tmpBuff = GlClientBufferHandle(jobs, 
 		sizeof(quadVertCoords), (void*)&quadVertCoords[0][0]);
 		sizeof(quadVertCoords), (void*)&quadVertCoords[0][0]);
@@ -93,7 +94,7 @@ void Renderer::init(const ConfigSet& initializer)
 
 
 //==============================================================================
 //==============================================================================
 void Renderer::render(SceneGraph& scene, 
 void Renderer::render(SceneGraph& scene, 
-	Array<GlJobChainHandle, JOB_CHAINS_COUNT>& jobs)
+	Array<GlCommandBufferHandle, JOB_CHAINS_COUNT>& jobs)
 {
 {
 	m_scene = &scene;
 	m_scene = &scene;
 	Camera& cam = m_scene->getActiveCamera();
 	Camera& cam = m_scene->getActiveCamera();
@@ -141,13 +142,13 @@ void Renderer::render(SceneGraph& scene,
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Renderer::drawQuad(GlJobChainHandle& jobs)
+void Renderer::drawQuad(GlCommandBufferHandle& jobs)
 {
 {
 	drawQuadInstanced(jobs, 1);
 	drawQuadInstanced(jobs, 1);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Renderer::drawQuadInstanced(GlJobChainHandle& jobs, U32 primitiveCount)
+void Renderer::drawQuadInstanced(GlCommandBufferHandle& jobs, U32 primitiveCount)
 {
 {
 	m_quadPositionsBuff.bindVertexBuffer(jobs, 2, GL_FLOAT, false, 0, 0, 0);
 	m_quadPositionsBuff.bindVertexBuffer(jobs, 2, GL_FLOAT, false, 0, 0, 0);
 
 
@@ -226,8 +227,8 @@ void Renderer::createRenderTarget(U32 w, U32 h, GLenum internalFormat,
 	init.m_genMipmaps = false;
 	init.m_genMipmaps = false;
 	init.m_samples = samples;
 	init.m_samples = samples;
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 	rt = GlTextureHandle(jobs, init);
 	rt = GlTextureHandle(jobs, init);
 	jobs.finish();
 	jobs.finish();
 }
 }
@@ -236,8 +237,8 @@ void Renderer::createRenderTarget(U32 w, U32 h, GLenum internalFormat,
 GlProgramPipelineHandle Renderer::createDrawQuadProgramPipeline(
 GlProgramPipelineHandle Renderer::createDrawQuadProgramPipeline(
 	GlProgramHandle frag)
 	GlProgramHandle frag)
 {
 {
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	Array<GlProgramHandle, 2> progs = {{m_drawQuadVert->getGlProgram(), frag}};
 	Array<GlProgramHandle, 2> progs = {{m_drawQuadVert->getGlProgram(), frag}};
 
 

+ 3 - 3
src/renderer/RenderingPass.cpp

@@ -13,8 +13,8 @@ namespace anki {
 void BlurringRenderingPass::initBlurring(
 void BlurringRenderingPass::initBlurring(
 	Renderer& r, U width, U height, U samples, F32 blurringDistance)
 	Renderer& r, U width, U height, U samples, F32 blurringDistance)
 {
 {
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	Array<std::stringstream, 2> pps;
 	Array<std::stringstream, 2> pps;
 
 
@@ -57,7 +57,7 @@ void BlurringRenderingPass::initBlurring(
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void BlurringRenderingPass::runBlurring(Renderer& r, GlJobChainHandle& jobs)
+void BlurringRenderingPass::runBlurring(Renderer& r, GlCommandBufferHandle& jobs)
 {
 {
 	m_dirs[(U)DirectionEnum::VERTICAL].m_rt.bind(jobs, 1); // H pass input
 	m_dirs[(U)DirectionEnum::VERTICAL].m_rt.bind(jobs, 1); // H pass input
 	m_dirs[(U)DirectionEnum::HORIZONTAL].m_rt.bind(jobs, 0); // V pass input
 	m_dirs[(U)DirectionEnum::HORIZONTAL].m_rt.bind(jobs, 0); // V pass input

+ 6 - 6
src/renderer/Sm.cpp

@@ -54,8 +54,8 @@ void Sm::init(const ConfigSet& initializer)
 		sminit.m_filterType = GlTextureHandle::Filter::NEAREST;
 		sminit.m_filterType = GlTextureHandle::Filter::NEAREST;
 	}
 	}
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	m_sm2DArrayTex = GlTextureHandle(jobs, sminit);
 	m_sm2DArrayTex = GlTextureHandle(jobs, sminit);
 
 
@@ -79,7 +79,7 @@ void Sm::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Sm::prepareDraw(GlJobChainHandle& jobs)
+void Sm::prepareDraw(GlCommandBufferHandle& jobs)
 {
 {
 	// disable color & blend & enable depth test
 	// disable color & blend & enable depth test
 
 
@@ -95,7 +95,7 @@ void Sm::prepareDraw(GlJobChainHandle& jobs)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Sm::finishDraw(GlJobChainHandle& jobs)
+void Sm::finishDraw(GlCommandBufferHandle& jobs)
 {
 {
 	m_r->getSceneDrawer().finishDraw();
 	m_r->getSceneDrawer().finishDraw();
 
 
@@ -106,7 +106,7 @@ void Sm::finishDraw(GlJobChainHandle& jobs)
 
 
 //==============================================================================
 //==============================================================================
 void Sm::run(Light* shadowCasters[], U32 shadowCastersCount, 
 void Sm::run(Light* shadowCasters[], U32 shadowCastersCount, 
-	GlJobChainHandle& jobs)
+	GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 
@@ -162,7 +162,7 @@ Sm::Shadowmap& Sm::bestCandidate(Light& light)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-Sm::Shadowmap* Sm::doLight(Light& light, GlJobChainHandle& jobs)
+Sm::Shadowmap* Sm::doLight(Light& light, GlCommandBufferHandle& jobs)
 {
 {
 	Shadowmap& sm = bestCandidate(light);
 	Shadowmap& sm = bestCandidate(light);
 
 

+ 5 - 5
src/renderer/Ssao.cpp

@@ -69,13 +69,13 @@ public:
 //==============================================================================
 //==============================================================================
 void Ssao::createFb(GlFramebufferHandle & fb, GlTextureHandle& rt)
 void Ssao::createFb(GlFramebufferHandle & fb, GlTextureHandle& rt)
 {
 {
-	GlManager& gl = GlManagerSingleton::get();
+	GlDevice& gl = GlDeviceSingleton::get();
 
 
 	m_r->createRenderTarget(m_width, m_height, GL_RED, GL_RED, 
 	m_r->createRenderTarget(m_width, m_height, GL_RED, GL_RED, 
 		GL_UNSIGNED_BYTE, 1, rt);
 		GL_UNSIGNED_BYTE, 1, rt);
 
 
 	// Set to bilinear because the blurring techniques take advantage of that
 	// Set to bilinear because the blurring techniques take advantage of that
-	GlJobChainHandle jobs(&gl);
+	GlCommandBufferHandle jobs(&gl);
 	rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
 	rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
 
 
 	// create FB
 	// create FB
@@ -116,8 +116,8 @@ void Ssao::initInternal(const ConfigSet& initializer)
 	//
 	//
 	// noise texture
 	// noise texture
 	//
 	//
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	GlClientBufferHandle noise(
 	GlClientBufferHandle noise(
 		jobs, sizeof(Vec3) * NOISE_TEX_SIZE * NOISE_TEX_SIZE, nullptr);
 		jobs, sizeof(Vec3) * NOISE_TEX_SIZE * NOISE_TEX_SIZE, nullptr);
@@ -229,7 +229,7 @@ void Ssao::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Ssao::run(GlJobChainHandle& jobs)
+void Ssao::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 

+ 3 - 3
src/renderer/Sslr.cpp

@@ -43,8 +43,8 @@ void Sslr::init(const ConfigSet& initializer)
 		m_reflectionFrag->getGlProgram());
 		m_reflectionFrag->getGlProgram());
 
 
 	// Sampler
 	// Sampler
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 	m_depthMapSampler = GlSamplerHandle(jobs);
 	m_depthMapSampler = GlSamplerHandle(jobs);
 	m_depthMapSampler.setFilter(jobs, GlSamplerHandle::Filter::NEAREST);
 	m_depthMapSampler.setFilter(jobs, GlSamplerHandle::Filter::NEAREST);
 
 
@@ -78,7 +78,7 @@ void Sslr::init(const ConfigSet& initializer)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Sslr::run(GlJobChainHandle& jobs)
+void Sslr::run(GlCommandBufferHandle& jobs)
 {
 {
 	ANKI_ASSERT(m_enabled);
 	ANKI_ASSERT(m_enabled);
 
 

+ 5 - 6
src/renderer/Tiler.cpp

@@ -6,7 +6,6 @@
 #include "anki/renderer/Tiler.h"
 #include "anki/renderer/Tiler.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/resource/ProgramResource.h"
 #include "anki/resource/ProgramResource.h"
-#include "anki/core/Threadpool.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Camera.h"
 #include <sstream>
 #include <sstream>
 
 
@@ -24,7 +23,7 @@ namespace anki {
 	ANKI_ASSERT(U(p_ - &m_tiler->m_allPlanes[0]) < m_tiler->m_allPlanes.size());
 	ANKI_ASSERT(U(p_ - &m_tiler->m_allPlanes[0]) < m_tiler->m_allPlanes.size());
 
 
 /// Job that updates the left, right, top and buttom tile planes
 /// Job that updates the left, right, top and buttom tile planes
-struct UpdatePlanesPerspectiveCameraJob: ThreadpoolTask
+struct UpdatePlanesPerspectiveCameraJob: Threadpool::Task
 {
 {
 	Tiler* m_tiler = nullptr;
 	Tiler* m_tiler = nullptr;
 	PerspectiveCamera* m_cam = nullptr;
 	PerspectiveCamera* m_cam = nullptr;
@@ -33,7 +32,7 @@ struct UpdatePlanesPerspectiveCameraJob: ThreadpoolTask
 	const PixelArray* m_pixels = nullptr;
 	const PixelArray* m_pixels = nullptr;
 #endif
 #endif
 
 
-	void operator()(ThreadId threadId, U threadsCount)
+	void operator()(U32 threadId, PtrSize threadsCount)
 	{
 	{
 #if ANKI_TILER_ENABLE_GPU
 #if ANKI_TILER_ENABLE_GPU
 		ANKI_ASSERT(tiler && cam && pixels);
 		ANKI_ASSERT(tiler && cam && pixels);
@@ -243,8 +242,8 @@ void Tiler::initInternal(Renderer* r)
 	m_r->createRenderTarget(m_r->getTilesCount().x(), m_r->getTilesCount().y(),
 	m_r->createRenderTarget(m_r->getTilesCount().x(), m_r->getTilesCount().y(),
 		GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, 1, m_rt);
 		GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, 1, m_rt);
 
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
+	GlDevice& gl = GlDeviceSingleton::get();
+	GlCommandBufferHandle jobs(&gl);
 
 
 	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}});
 	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}});
 
 
@@ -327,7 +326,7 @@ void Tiler::updateTiles(Camera& cam)
 	Bool frustumChanged =
 	Bool frustumChanged =
 		camTimestamp >= m_planes4UpdateTimestamp || m_prevCam != &cam;
 		camTimestamp >= m_planes4UpdateTimestamp || m_prevCam != &cam;
 
 
-	Threadpool& threadPool = ThreadpoolSingleton::get();
+	Threadpool& threadPool = m_r->_getThreadpool();
 
 
 	switch(cam.getCameraType())
 	switch(cam.getCameraType())
 	{
 	{

+ 52 - 51
src/resource/Animation.cpp

@@ -10,13 +10,13 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-void Animation::load(const char* filename)
+void Animation::load(const char* filename, ResourceAllocator<U8>& alloc)
 {
 {
 	try
 	try
 	{
 	{
 		XmlDocument doc;
 		XmlDocument doc;
 		doc.loadFile(filename);
 		doc.loadFile(filename);
-		loadInternal(doc.getChildElement("animation"));
+		loadInternal(doc.getChildElement("animation"), alloc);
 	}
 	}
 	catch(const std::exception& e)
 	catch(const std::exception& e)
 	{
 	{
@@ -25,9 +25,10 @@ void Animation::load(const char* filename)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void Animation::loadInternal(const XmlElement& el)
+void Animation::loadInternal(
+	const XmlElement& el, ResourceAllocator<U8>& alloc)
 {
 {
-	startTime = MAX_F32;
+	m_startTime = MAX_F32;
 	F32 maxTime = MIN_F32;
 	F32 maxTime = MIN_F32;
 
 
 	// Count the number of identity keys. If all of the keys are identities
 	// Count the number of identity keys. If all of the keys are identities
@@ -40,11 +41,11 @@ void Animation::loadInternal(const XmlElement& el)
 	XmlElement repel = el.getChildElementOptional("repeat");
 	XmlElement repel = el.getChildElementOptional("repeat");
 	if(repel)
 	if(repel)
 	{
 	{
-		repeat = repel.getInt();
+		m_repeat = repel.getInt();
 	}
 	}
 	else
 	else
 	{
 	{
-		repeat = false;
+		m_repeat = false;
 	}
 	}
 
 
 	// <channels>
 	// <channels>
@@ -54,11 +55,11 @@ void Animation::loadInternal(const XmlElement& el)
 	// For all channels
 	// For all channels
 	do
 	do
 	{
 	{
-		channels.push_back(AnimationChannel());	
-		AnimationChannel& ch = channels.back();
+		m_channels.push_back(AnimationChannel(alloc));	
+		AnimationChannel& ch = m_channels.back();
 
 
 		// <name>
 		// <name>
-		ch.name = chEl.getChildElement("name").getText();
+		ch.m_name = chEl.getChildElement("name").getText();
 
 
 		XmlElement keysEl, keyEl;
 		XmlElement keysEl, keyEl;
 
 
@@ -72,18 +73,18 @@ void Animation::loadInternal(const XmlElement& el)
 				Key<Vec3> key;
 				Key<Vec3> key;
 
 
 				// <time>
 				// <time>
-				key.time = keyEl.getChildElement("time").getFloat();
-				startTime = std::min(startTime, key.time);
-				maxTime = std::max(maxTime, key.time);
+				key.m_time = keyEl.getChildElement("time").getFloat();
+				m_startTime = std::min(m_startTime, key.m_time);
+				maxTime = std::max(maxTime, key.m_time);
 
 
 				// <value>
 				// <value>
-				key.value = keyEl.getChildElement("value").getVec3();
+				key.m_value = keyEl.getChildElement("value").getVec3();
 
 
 				// push_back
 				// push_back
-				ch.positions.push_back(key);
+				ch.m_positions.push_back(key);
 
 
 				// Check ident
 				// Check ident
-				if(key.value == Vec3(0.0))
+				if(key.m_value == Vec3(0.0))
 				{
 				{
 					++identPosCount;
 					++identPosCount;
 				}
 				}
@@ -103,18 +104,18 @@ void Animation::loadInternal(const XmlElement& el)
 				Key<Quat> key;
 				Key<Quat> key;
 
 
 				// <time>
 				// <time>
-				key.time = keyEl.getChildElement("time").getFloat();
-				startTime = std::min(startTime, key.time);
-				maxTime = std::max(maxTime, key.time);
+				key.m_time = keyEl.getChildElement("time").getFloat();
+				m_startTime = std::min(m_startTime, key.m_time);
+				maxTime = std::max(maxTime, key.m_time);
 
 
 				// <value>
 				// <value>
-				key.value = Quat(keyEl.getChildElement("value").getVec4());
+				key.m_value = Quat(keyEl.getChildElement("value").getVec4());
 
 
 				// push_back
 				// push_back
-				ch.rotations.push_back(key);
+				ch.m_rotations.push_back(key);
 
 
 				// Check ident
 				// Check ident
-				if(key.value == Quat::getIdentity())
+				if(key.m_value == Quat::getIdentity())
 				{
 				{
 					++identRotCount;
 					++identRotCount;
 				}
 				}
@@ -134,18 +135,18 @@ void Animation::loadInternal(const XmlElement& el)
 				Key<F32> key;
 				Key<F32> key;
 
 
 				// <time>
 				// <time>
-				key.time = keyEl.getChildElement("time").getFloat();
-				startTime = std::min(startTime, key.time);
-				maxTime = std::max(maxTime, key.time);
+				key.m_time = keyEl.getChildElement("time").getFloat();
+				m_startTime = std::min(m_startTime, key.m_time);
+				maxTime = std::max(maxTime, key.m_time);
 
 
 				// <value>
 				// <value>
-				key.value = keyEl.getChildElement("value").getFloat();
+				key.m_value = keyEl.getChildElement("value").getFloat();
 
 
 				// push_back
 				// push_back
-				ch.scales.push_back(key);
+				ch.m_scales.push_back(key);
 
 
 				// Check ident
 				// Check ident
-				if(isZero(key.value - 1.0))
+				if(isZero(key.m_value - 1.0))
 				{
 				{
 					++identScaleCount;
 					++identScaleCount;
 				}
 				}
@@ -156,24 +157,24 @@ void Animation::loadInternal(const XmlElement& el)
 		}
 		}
 
 
 		// Remove identity vectors
 		// Remove identity vectors
-		if(identPosCount == ch.positions.size())
+		if(identPosCount == ch.m_positions.size())
 		{
 		{
-			ch.positions.clear();
+			ch.m_positions.clear();
 		}
 		}
-		if(identRotCount == ch.rotations.size())
+		if(identRotCount == ch.m_rotations.size())
 		{
 		{
-			ch.rotations.clear();
+			ch.m_rotations.clear();
 		}
 		}
-		if(identScaleCount == ch.scales.size())
+		if(identScaleCount == ch.m_scales.size())
 		{
 		{
-			ch.scales.clear();
+			ch.m_scales.clear();
 		}
 		}
 
 
 		// Move to next channel
 		// Move to next channel
 		chEl = chEl.getNextSiblingElement("channel");
 		chEl = chEl.getNextSiblingElement("channel");
 	} while(chEl);
 	} while(chEl);
 
 
-	duration = maxTime - startTime;
+	m_duration = maxTime - m_startTime;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -181,50 +182,50 @@ void Animation::interpolate(U channelIndex, F32 time,
 	Vec3& pos, Quat& rot, F32& scale) const
 	Vec3& pos, Quat& rot, F32& scale) const
 {
 {
 	// Audjust time
 	// Audjust time
-	if(repeat && time > startTime + duration)
+	if(m_repeat && time > m_startTime + m_duration)
 	{
 	{
-		time = mod(time - startTime, duration) + startTime;
+		time = mod(time - m_startTime, m_duration) + m_startTime;
 	}
 	}
 
 
-	ANKI_ASSERT(time >= startTime && time <= startTime + duration);
-	ANKI_ASSERT(channelIndex < channels.size());
+	ANKI_ASSERT(time >= m_startTime && time <= m_startTime + m_duration);
+	ANKI_ASSERT(channelIndex < m_channels.size());
 
 
-	const AnimationChannel& channel = channels[channelIndex];
+	const AnimationChannel& channel = m_channels[channelIndex];
 
 
 	// Position
 	// Position
-	if(channel.positions.size() > 1)
+	if(channel.m_positions.size() > 1)
 	{
 	{
-		auto next = channel.positions.begin();
+		auto next = channel.m_positions.begin();
 
 
 		do
 		do
 		{
 		{
-		} while((next->time < time) && (++next != channel.positions.end()));
+		} while((next->m_time < time) && (++next != channel.m_positions.end()));
 
 
-		ANKI_ASSERT(next != channel.positions.end());
+		ANKI_ASSERT(next != channel.m_positions.end());
 		auto prev = next - 1;
 		auto prev = next - 1;
 		/*auto prevprev = 
 		/*auto prevprev = 
 			(prev == channel.positions.begin()) ? prev : prev - 1;
 			(prev == channel.positions.begin()) ? prev : prev - 1;
 		auto nextnext = 
 		auto nextnext = 
 			(next == channel.positions.end() - 1) ? next : next + 1;*/
 			(next == channel.positions.end() - 1) ? next : next + 1;*/
 
 
-		F32 u = (time - prev->time) / (next->time - prev->time);
-		pos = linearInterpolate(prev->value, next->value, u);
+		F32 u = (time - prev->m_time) / (next->m_time - prev->m_time);
+		pos = linearInterpolate(prev->m_value, next->m_value, u);
 	}
 	}
 
 
 	// Rotation
 	// Rotation
-	if(channel.rotations.size() > 1)
+	if(channel.m_rotations.size() > 1)
 	{
 	{
-		auto next = channel.rotations.begin();
+		auto next = channel.m_rotations.begin();
 
 
 		do
 		do
 		{
 		{
-		} while((next->time < time) && (++next != channel.rotations.end()));
+		} while((next->m_time < time) && (++next != channel.m_rotations.end()));
 
 
-		ANKI_ASSERT(next != channel.rotations.end());
+		ANKI_ASSERT(next != channel.m_rotations.end());
 		auto prev = next - 1;
 		auto prev = next - 1;
 
 
-		F32 u = (time - prev->time) / (next->time - prev->time);
-		rot = prev->value.slerp(next->value, u);
+		F32 u = (time - prev->m_time) / (next->m_time - prev->m_time);
+		rot = prev->m_value.slerp(next->m_value, u);
 	}
 	}
 }
 }
 
 

+ 109 - 100
src/resource/Image.cpp

@@ -23,7 +23,7 @@ static U8 tgaHeaderCompressed[12] = {0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 
 //==============================================================================
 //==============================================================================
 static void loadUncompressedTga(
 static void loadUncompressedTga(
-	File& fs, U32& width, U32& height, U32& bpp, Vector<U8>& data)
+	File& fs, U32& width, U32& height, U32& bpp, ResourceVector<U8>& data)
 {
 {
 	// read the info from header
 	// read the info from header
 	U8 header6[6];
 	U8 header6[6];
@@ -56,7 +56,7 @@ static void loadUncompressedTga(
 
 
 //==============================================================================
 //==============================================================================
 static void loadCompressedTga(
 static void loadCompressedTga(
-	File& fs, U32& width, U32& height, U32& bpp, Vector<U8>& data)
+	File& fs, U32& width, U32& height, U32& bpp, ResourceVector<U8>& data)
 {
 {
 	U8 header6[6];
 	U8 header6[6];
 	fs.read((char*)&header6[0], sizeof(header6));
 	fs.read((char*)&header6[0], sizeof(header6));
@@ -140,18 +140,19 @@ static void loadCompressedTga(
 
 
 //==============================================================================
 //==============================================================================
 static void loadTga(const char* filename, 
 static void loadTga(const char* filename, 
-	U32& width, U32& height, U32& bpp, Vector<U8>& data)
+	U32& width, U32& height, U32& bpp, ResourceVector<U8>& data)
 {
 {
 	File fs(filename, File::OpenFlag::READ | File::OpenFlag::BINARY);
 	File fs(filename, File::OpenFlag::READ | File::OpenFlag::BINARY);
 	char myTgaHeader[12];
 	char myTgaHeader[12];
 
 
 	fs.read(&myTgaHeader[0], sizeof(myTgaHeader));
 	fs.read(&myTgaHeader[0], sizeof(myTgaHeader));
 
 
-	if(memcmp(tgaHeaderUncompressed, &myTgaHeader[0], sizeof(myTgaHeader)) == 0)
+	if(std::memcmp(
+		tgaHeaderUncompressed, &myTgaHeader[0], sizeof(myTgaHeader)) == 0)
 	{
 	{
 		loadUncompressedTga(fs, width, height, bpp, data);
 		loadUncompressedTga(fs, width, height, bpp, data);
 	}
 	}
-	else if(memcmp(tgaHeaderCompressed, &myTgaHeader[0],
+	else if(std::memcmp(tgaHeaderCompressed, &myTgaHeader[0],
 		sizeof(myTgaHeader)) == 0)
 		sizeof(myTgaHeader)) == 0)
 	{
 	{
 		loadCompressedTga(fs, width, height, bpp, data);
 		loadCompressedTga(fs, width, height, bpp, data);
@@ -172,18 +173,19 @@ static void loadTga(const char* filename,
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
-struct AnkiTextureHeader
+class AnkiTextureHeader
 {
 {
-	Array<U8, 8> magic;
-	U32 width;
-	U32 height;
-	U32 depth;
-	U32 type;
-	U32 colorFormat;
-	U32 compressionFormats;
-	U32 normal;
-	U32 mipLevels;
-	U8 padding[88];
+public:
+	Array<U8, 8> m_magic;
+	U32 m_width;
+	U32 m_height;
+	U32 m_depth;
+	Image::TextureType m_type;
+	Image::ColorFormat m_colorFormat;
+	Image::DataCompression m_compressionFormats;
+	U32 m_normal;
+	U32 m_mipLevels;
+	U8 m_padding[88];
 };
 };
 
 
 static_assert(sizeof(AnkiTextureHeader) == 128, 
 static_assert(sizeof(AnkiTextureHeader) == 128, 
@@ -200,14 +202,15 @@ static PtrSize calcSurfaceSize(const U width, const U height,
 
 
 	switch(comp)
 	switch(comp)
 	{
 	{
-	case Image::DC_RAW:
-		out = width * height * ((cf == Image::CF_RGB8) ? 3 : 4);
+	case Image::DataCompression::RAW:
+		out = width * height * ((cf == Image::ColorFormat::RGB8) ? 3 : 4);
 		break;
 		break;
-	case Image::DC_S3TC:
+	case Image::DataCompression::S3TC:
 		out = (width / 4) * (height / 4) 
 		out = (width / 4) * (height / 4) 
-			* ((cf == Image::CF_RGB8) ? 8 : 16); // This is the block size
+			* ((cf == Image::ColorFormat::RGB8) ? 8 : 16); // This is the 
+		                                                   // block size
 		break;
 		break;
-	case Image::DC_ETC:
+	case Image::DataCompression::ETC:
 		out = (width / 4) * (height / 4) * 8;
 		out = (width / 4) * (height / 4) * 8;
 		break;
 		break;
 	default:
 	default:
@@ -225,22 +228,22 @@ static PtrSize calcSizeOfSegment(const AnkiTextureHeader& header,
 	Image::DataCompression comp)
 	Image::DataCompression comp)
 {
 {
 	PtrSize out = 0;
 	PtrSize out = 0;
-	U width = header.width;
-	U height = header.height;
-	U mips = header.mipLevels;
+	U width = header.m_width;
+	U height = header.m_height;
+	U mips = header.m_mipLevels;
 	U layers = 0;
 	U layers = 0;
 
 
-	switch(header.type)
+	switch(header.m_type)
 	{
 	{
-	case Image::TT_2D:
+	case Image::TextureType::_2D:
 		layers = 1;
 		layers = 1;
 		break;
 		break;
-	case Image::TT_CUBE:
+	case Image::TextureType::CUBE:
 		layers = 6;
 		layers = 6;
 		break;
 		break;
-	case Image::TT_2D_ARRAY:
-	case Image::TT_3D:
-		layers = header.depth;
+	case Image::TextureType::_2D_ARRAY:
+	case Image::TextureType::_3D:
+		layers = header.m_depth;
 		break;
 		break;
 	default:
 	default:
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
@@ -253,8 +256,7 @@ static PtrSize calcSizeOfSegment(const AnkiTextureHeader& header,
 
 
 		while(l-- != 0)
 		while(l-- != 0)
 		{
 		{
-			out += calcSurfaceSize(width, height, comp, 
-				(Image::ColorFormat)header.colorFormat);
+			out += calcSurfaceSize(width, height, comp, header.m_colorFormat);
 		}
 		}
 
 
 		width /= 2;
 		width /= 2;
@@ -269,7 +271,7 @@ static void loadAnkiTexture(
 	const char* filename, 
 	const char* filename, 
 	U32 maxTextureSize,
 	U32 maxTextureSize,
 	Image::DataCompression& preferredCompression,
 	Image::DataCompression& preferredCompression,
-	Vector<Image::Surface>& surfaces, 
+	ResourceVector<Image::Surface>& surfaces, 
 	U8& depth, 
 	U8& depth, 
 	U8& mipLevels, 
 	U8& mipLevels, 
 	Image::TextureType& textureType,
 	Image::TextureType& textureType,
@@ -285,50 +287,52 @@ static void loadAnkiTexture(
 	AnkiTextureHeader header;
 	AnkiTextureHeader header;
 	file.read(&header, sizeof(AnkiTextureHeader));
 	file.read(&header, sizeof(AnkiTextureHeader));
 
 
-	if(memcmp(&header.magic[0], "ANKITEX1", 8) != 0)
+	if(std::memcmp(&header.m_magic[0], "ANKITEX1", 8) != 0)
 	{
 	{
 		throw ANKI_EXCEPTION("Wrong magic word");
 		throw ANKI_EXCEPTION("Wrong magic word");
 	}
 	}
 
 
-	if(header.width == 0 
-		|| !isPowerOfTwo(header.width) 
-		|| header.width > 4096
-		|| header.height == 0 
-		|| !isPowerOfTwo(header.height) 
-		|| header.height > 4096)
+	if(header.m_width == 0 
+		|| !isPowerOfTwo(header.m_width) 
+		|| header.m_width > 4096
+		|| header.m_height == 0 
+		|| !isPowerOfTwo(header.m_height) 
+		|| header.m_height > 4096)
 	{
 	{
 		throw ANKI_EXCEPTION("Incorrect width/height value");
 		throw ANKI_EXCEPTION("Incorrect width/height value");
 	}
 	}
 
 
-	if(header.depth < 1 || header.depth > 16)
+	if(header.m_depth < 1 || header.m_depth > 16)
 	{
 	{
 		throw ANKI_EXCEPTION("Zero or too big depth");
 		throw ANKI_EXCEPTION("Zero or too big depth");
 	}
 	}
 
 
-	if(header.type < Image::TT_2D || header.type > Image::TT_2D_ARRAY)
+	if(header.m_type < Image::TextureType::_2D 
+		|| header.m_type > Image::TextureType::_2D_ARRAY)
 	{
 	{
 		throw ANKI_EXCEPTION("Incorrect header: texture type");
 		throw ANKI_EXCEPTION("Incorrect header: texture type");
 	}
 	}
 
 
-	if(header.colorFormat < Image::CF_RGB8 
-		|| header.colorFormat > Image::CF_RGBA8)
+	if(header.m_colorFormat < Image::ColorFormat::RGB8 
+		|| header.m_colorFormat > Image::ColorFormat::RGBA8)
 	{
 	{
 		throw ANKI_EXCEPTION("Incorrect header: color format");
 		throw ANKI_EXCEPTION("Incorrect header: color format");
 	}
 	}
 
 
-	if((header.compressionFormats & preferredCompression) == 0)
+	if((header.m_compressionFormats & preferredCompression) 
+		== Image::DataCompression::NONE)
 	{
 	{
 		throw ANKI_EXCEPTION("File does not contain the wanted compression");
 		throw ANKI_EXCEPTION("File does not contain the wanted compression");
 	}
 	}
 
 
-	if(header.normal != 0 && header.normal != 1)
+	if(header.m_normal != 0 && header.m_normal != 1)
 	{
 	{
 		throw ANKI_EXCEPTION("Incorrect header: normal");
 		throw ANKI_EXCEPTION("Incorrect header: normal");
 	}
 	}
 
 
 	// Check mip levels
 	// Check mip levels
-	U size = std::min(header.width, header.height);
-	U maxsize = std::max(header.width, header.height);
+	U size = std::min(header.m_width, header.m_height);
+	U maxsize = std::max(header.m_width, header.m_height);
 	mipLevels = 0;
 	mipLevels = 0;
 	U tmpMipLevels = 0;
 	U tmpMipLevels = 0;
 	while(size >= 4) // The minimum size is 4x4
 	while(size >= 4) // The minimum size is 4x4
@@ -344,64 +348,67 @@ static void loadAnkiTexture(
 		maxsize /= 2;
 		maxsize /= 2;
 	}
 	}
 
 
-	if(tmpMipLevels != header.mipLevels)
+	if(tmpMipLevels != header.m_mipLevels)
 	{
 	{
 		throw ANKI_EXCEPTION("Incorrect number of mip levels");
 		throw ANKI_EXCEPTION("Incorrect number of mip levels");
 	}
 	}
 
 
-	colorFormat = (Image::ColorFormat)header.colorFormat;
+	colorFormat = header.m_colorFormat;
 
 
-	switch(header.type)
+	switch(header.m_type)
 	{
 	{
-		case Image::TT_2D:
+		case Image::TextureType::_2D:
 			depth = 1;
 			depth = 1;
 			break;
 			break;
-		case Image::TT_CUBE:
+		case Image::TextureType::CUBE:
 			depth = 6;
 			depth = 6;
 			break;
 			break;
-		case Image::TT_3D:
-		case Image::TT_2D_ARRAY:
-			depth = header.depth;
+		case Image::TextureType::_3D:
+		case Image::TextureType::_2D_ARRAY:
+			depth = header.m_depth;
 			break;
 			break;
 		default:
 		default:
 			ANKI_ASSERT(0);
 			ANKI_ASSERT(0);
 	}
 	}
 
 
-	textureType = (Image::TextureType)header.type;
+	textureType = header.m_type;
 
 
 	//
 	//
 	// Move file pointer
 	// Move file pointer
 	//
 	//
 
 
-	if(preferredCompression == Image::DC_RAW)
+	if(preferredCompression == Image::DataCompression::RAW)
 	{
 	{
 		// Do nothing
 		// Do nothing
 	}
 	}
-	else if(preferredCompression == Image::DC_S3TC)
+	else if(preferredCompression == Image::DataCompression::S3TC)
 	{
 	{
-		if(header.compressionFormats & Image::DC_RAW)
+		if((header.m_compressionFormats & Image::DataCompression::RAW)
+			!= Image::DataCompression::NONE)
 		{
 		{
 			// If raw compression is present then skip it
 			// If raw compression is present then skip it
 			file.seek(
 			file.seek(
-				calcSizeOfSegment(header, Image::DC_RAW), 
+				calcSizeOfSegment(header, Image::DataCompression::RAW), 
 				File::SeekOrigin::CURRENT);
 				File::SeekOrigin::CURRENT);
 		}
 		}
 	}
 	}
-	else if(preferredCompression == Image::DC_ETC)
+	else if(preferredCompression == Image::DataCompression::ETC)
 	{
 	{
-		if(header.compressionFormats & Image::DC_RAW)
+		if((header.m_compressionFormats & Image::DataCompression::RAW)
+			!= Image::DataCompression::NONE)
 		{
 		{
 			// If raw compression is present then skip it
 			// If raw compression is present then skip it
 			file.seek(
 			file.seek(
-				calcSizeOfSegment(header, Image::DC_RAW), 
+				calcSizeOfSegment(header, Image::DataCompression::RAW), 
 				File::SeekOrigin::CURRENT);
 				File::SeekOrigin::CURRENT);
 		}
 		}
 
 
-		if(header.compressionFormats & Image::DC_S3TC)
+		if((header.m_compressionFormats & Image::DataCompression::S3TC)
+			!= Image::DataCompression::NONE)
 		{
 		{
 			// If s3tc compression is present then skip it
 			// If s3tc compression is present then skip it
 			file.seek(
 			file.seek(
-				calcSizeOfSegment(header, Image::DC_S3TC), 
+				calcSizeOfSegment(header, Image::DataCompression::S3TC), 
 				File::SeekOrigin::CURRENT);
 				File::SeekOrigin::CURRENT);
 		}
 		}
 	}
 	}
@@ -411,18 +418,19 @@ static void loadAnkiTexture(
 	//
 	//
 
 
 	// Allocate the surfaces
 	// Allocate the surfaces
-	surfaces.resize(mipLevels * depth);
+	ResourceAllocator<U8> alloc = surfaces.get_allocator(); 
+	surfaces.resize(mipLevels * depth, Image::Surface(alloc));
 
 
 	// Read all surfaces
 	// Read all surfaces
-	U mipWidth = header.width;
-	U mipHeight = header.height;
-	for(U mip = 0; mip < header.mipLevels; mip++)
+	U mipWidth = header.m_width;
+	U mipHeight = header.m_height;
+	for(U mip = 0; mip < header.m_mipLevels; mip++)
 	{
 	{
 		for(U d = 0; d < depth; d++)
 		for(U d = 0; d < depth; d++)
 		{
 		{
 			U dataSize = calcSurfaceSize(
 			U dataSize = calcSurfaceSize(
 				mipWidth, mipHeight, preferredCompression, 
 				mipWidth, mipHeight, preferredCompression, 
-				(Image::ColorFormat)header.colorFormat);
+				header.m_colorFormat);
 
 
 			// Check if this mipmap can be skipped because of size
 			// Check if this mipmap can be skipped because of size
 			if(std::max(mipWidth, mipHeight) <= maxTextureSize)
 			if(std::max(mipWidth, mipHeight) <= maxTextureSize)
@@ -430,11 +438,11 @@ static void loadAnkiTexture(
 				U index = (mip - tmpMipLevels + mipLevels) * depth + d;
 				U index = (mip - tmpMipLevels + mipLevels) * depth + d;
 				ANKI_ASSERT(index < surfaces.size());
 				ANKI_ASSERT(index < surfaces.size());
 				Image::Surface& surf = surfaces[index];
 				Image::Surface& surf = surfaces[index];
-				surf.width = mipWidth;
-				surf.height = mipHeight;
+				surf.m_width = mipWidth;
+				surf.m_height = mipHeight;
 
 
-				surf.data.resize(dataSize);
-				file.read(&surf.data[0], dataSize);
+				surf.m_data.resize(dataSize);
+				file.read(&surf.m_data[0], dataSize);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -466,43 +474,44 @@ void Image::load(const char* filename, U32 maxTextureSize)
 	try
 	try
 	{
 	{
 		U32 bpp;
 		U32 bpp;
-		textureType = TT_2D;
-		compression = DC_RAW;
+		m_textureType = TextureType::_2D;
+		m_compression = DataCompression::RAW;
 
 
-		if(strcmp(ext, "tga") == 0)
+		if(std::strcmp(ext, "tga") == 0)
 		{
 		{
-			surfaces.resize(1);
-			mipLevels = 1;
-			depth = 1;
-			loadTga(filename, surfaces[0].width, surfaces[0].height, bpp, 
-				surfaces[0].data);
+			ResourceAllocator<U8> alloc = m_surfaces.get_allocator(); 
+			m_surfaces.resize(1, Surface(alloc));
+			m_mipLevels = 1;
+			m_depth = 1;
+			loadTga(filename, m_surfaces[0].m_width, m_surfaces[0].m_height, 
+				bpp, m_surfaces[0].m_data);
 
 
 			if(bpp == 32)
 			if(bpp == 32)
 			{
 			{
-				colorFormat = CF_RGBA8;
+				m_colorFormat = ColorFormat::RGBA8;
 			}
 			}
 			else if(bpp == 24)
 			else if(bpp == 24)
 			{
 			{
-				colorFormat = CF_RGB8;
+				m_colorFormat = ColorFormat::RGB8;
 			}
 			}
 			else
 			else
 			{
 			{
 				ANKI_ASSERT(0);
 				ANKI_ASSERT(0);
 			}
 			}
 		}
 		}
-		else if(strcmp(ext, "ankitex") == 0)
+		else if(std::strcmp(ext, "ankitex") == 0)
 		{
 		{
 #if 0
 #if 0
-			compression = Image::DC_RAW;
+			compression = Image::DataCompression::RAW;
 #elif ANKI_GL == ANKI_GL_DESKTOP
 #elif ANKI_GL == ANKI_GL_DESKTOP
-			compression = Image::DC_S3TC;
+			m_compression = Image::DataCompression::S3TC;
 #else
 #else
-			compression = Image::DC_ETC;
+			m_compression = Image::DataCompression::ETC;
 #endif
 #endif
 
 
 			loadAnkiTexture(filename, maxTextureSize, 
 			loadAnkiTexture(filename, maxTextureSize, 
-				compression, surfaces, depth, 
-				mipLevels, textureType, colorFormat);
+				m_compression, m_surfaces, m_depth, 
+				m_mipLevels, m_textureType, m_colorFormat);
 
 
 		}
 		}
 		else
 		else
@@ -519,21 +528,21 @@ void Image::load(const char* filename, U32 maxTextureSize)
 //==============================================================================
 //==============================================================================
 const Image::Surface& Image::getSurface(U mipLevel, U layer) const
 const Image::Surface& Image::getSurface(U mipLevel, U layer) const
 {
 {
-	ANKI_ASSERT(mipLevel < mipLevels);
+	ANKI_ASSERT(mipLevel < m_mipLevels);
 
 
 	U layers = 0;
 	U layers = 0;
 
 
-	switch(textureType)
+	switch(m_textureType)
 	{
 	{
-	case TT_2D:
+	case TextureType::_2D:
 		layers = 1;
 		layers = 1;
 		break;
 		break;
-	case TT_CUBE:
+	case TextureType::CUBE:
 		layers = 6;
 		layers = 6;
 		break;
 		break;
-	case TT_3D:
-	case TT_2D_ARRAY:
-		layers = depth;
+	case TextureType::_3D:
+	case TextureType::_2D_ARRAY:
+		layers = m_depth;
 		break;
 		break;
 	default:
 	default:
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
@@ -543,9 +552,9 @@ const Image::Surface& Image::getSurface(U mipLevel, U layer) const
 	// [mip][depthFace]
 	// [mip][depthFace]
 	U index = mipLevel * layers + layer;
 	U index = mipLevel * layers + layer;
 	
 	
-	ANKI_ASSERT(index < surfaces.size());
+	ANKI_ASSERT(index < m_surfaces.size());
 
 
-	return surfaces[index];
+	return m_surfaces[index];
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 5 - 2
src/resource/Material.cpp

@@ -240,8 +240,8 @@ GlProgramPipelineHandle Material::getProgramPipeline(
 
 
 		progs[progCount++] = getProgram(key, 4)->getGlProgram();
 		progs[progCount++] = getProgram(key, 4)->getGlProgram();
 
 
-		GlManager& gl = GlManagerSingleton::get();
-		GlJobChainHandle jobs(&gl);
+		GlDevice& gl = GlDeviceSingleton::get();
+		GlCommandBufferHandle jobs(&gl);
 
 
 		ppline = GlProgramPipelineHandle(
 		ppline = GlProgramPipelineHandle(
 			jobs, &progs[0], &progs[0] + progCount);
 			jobs, &progs[0], &progs[0] + progCount);
@@ -378,9 +378,12 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 					src << "#define PASS " << pid << "\n";
 					src << "#define PASS " << pid << "\n";
 					src << "#define TESSELLATION " << tess << "\n";
 					src << "#define TESSELLATION " << tess << "\n";
 
 
+#if 0
 					src << MainRendererSingleton::get().
 					src << MainRendererSingleton::get().
 						getShaderPostProcessorString() << "\n"
 						getShaderPostProcessorString() << "\n"
 						<< mspc.getProgramSource(shader) << std::endl;
 						<< mspc.getProgramSource(shader) << std::endl;
+#endif
+					ANKI_ASSERT(0 && "TODO");
 
 
 					std::string filename =
 					std::string filename =
 						createProgramSourceToChache(src.str().c_str());
 						createProgramSourceToChache(src.str().c_str());

Some files were not shown because too many files changed in this diff