Parcourir la source

GL refactoring

Panagiotis Christopoulos Charitos il y a 10 ans
Parent
commit
7d38765db0

+ 0 - 15
include/anki/gr/CommandBufferHandle.h

@@ -155,21 +155,6 @@ public:
 	/// @{
 	void copyTextureToBuffer(TextureHandle& from, BufferHandle& To);
 	/// @}
-
-	/// @privatesection
-	/// @{
-
-	// XXX
-#if 0
-	/// Add a new command to the list
-	template<typename TCommand, typename... TArgs>
-	void pushBackNewCommand(TArgs&&... args)
-	{
-		get().template pushBackNewCommand<TCommand>(
-			std::forward<TArgs>(args)...);
-	}
-#endif
-	/// @}
 };
 /// @}
 

+ 2 - 38
include/anki/gr/Common.h

@@ -50,6 +50,8 @@ class CommandBufferImpl;
 class CommandBufferHandle;
 class GrManager;
 class GrManagerImpl;
+struct FramebufferInitializer;
+struct TextureInitializer;
 
 /// @addtogroup graphics_private
 /// @{
@@ -90,44 +92,6 @@ private:
 
 	PtrSize m_chunkSize = 1024;
 };
-
-struct SurfaceData
-{
-	void* m_ptr = nullptr;
-	PtrSize m_size = 0;
-};
-
-/// Texture initializer.
-struct TextureInitializer
-{
-	U32 m_width = 0;
-	U32 m_height = 0;
-	U32 m_depth = 0; ///< Relevant only for 3D and 2DArray textures
-	GLenum m_target = GL_TEXTURE_2D;
-	GLenum m_internalFormat = GL_NONE;
-	U32 m_mipmapsCount = 0;
-	TextureFilter m_filterType = TextureFilter::NEAREST;
-	Bool8 m_repeat = false;
-	I32 m_anisotropyLevel = 0;
-	U32 m_samples = 1;
-
-	/// [level][slice]
-	Array2d<SurfaceData, MAX_MIPMAPS, MAX_TEXTURE_LAYERS> m_data;
-};
-
-struct Attachment
-{
-	TextureHandle* m_texture = nullptr;
-	GLenum m_point;
-	U32 m_layer = 0;
-	U32 m_mipmap = 0;
-};
-
-/// Framebuffer initializer.
-struct FramebufferInitializer
-{
-	SArray<Attachment> m_attachments;
-};
 /// @}
 
 /// @addtogroup opengl_containers

+ 36 - 0
include/anki/gr/FramebufferCommon.h

@@ -0,0 +1,36 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#ifndef ANKI_GR_FRAMEBUFFER_COMMON_H
+#define ANKI_GR_FRAMEBUFFER_COMMON_H
+
+#include "anki/gr/Common.h"
+#include "anki/gr/TextureHandle.h"
+
+namespace anki {
+
+/// @addtogroup graphics
+/// @{
+
+struct Attachment
+{
+	TextureHandle m_texture;
+	U32 m_layer = 0;
+	U32 m_mipmap = 0;
+};
+
+/// Framebuffer initializer.
+struct FramebufferInitializer
+{
+	Array<Attachment, MAX_COLOR_ATTACHMENTS> m_colorAttachments;
+	U32 m_colorAttachmentsCount = 0;
+	Attachment m_depthStencilAttachment;
+};
+/// @}
+
+} // end namespace anki
+
+#endif
+

+ 10 - 29
include/anki/gr/FramebufferHandle.h

@@ -3,50 +3,31 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#ifndef ANKI_GL_GL_FRAMEBUFFER_HANDLE_H
-#define ANKI_GL_GL_FRAMEBUFFER_HANDLE_H
+#ifndef ANKI_GR_FRAMEBUFFER_HANDLE_H
+#define ANKI_GR_FRAMEBUFFER_HANDLE_H
 
-#include "anki/gr/GlContainerHandle.h"
-#include "anki/gr/gl/FramebufferImpl.h" // XXX
+#include "anki/gr/GrHandle.h"
+#include "anki/gr/FramebufferCommon.h"
 
 namespace anki {
 
-/// @addtogroup opengl_other
+/// @addtogroup graphics
 /// @{
 
-/// Attachment.
-struct GlAttachment
-{
-	TextureHandle m_texture;
-	U32 m_layer = 0;
-	GlAttachmentLoadOperation m_loadOp;
-	GlAttachmentStoreOperation m_storeOp;
-};
-
-/// GlFramebuffer initializer. XXX
-struct GlFramebufferInitializer
-{
-	GlAttachment* m_colorAttachments = nullptr;
-	U32 m_colorAttachmentsCount = 0;
-	GlAttachment* m_depthStencilAttachment = nullptr;
-};
-
 /// Framebuffer handle
-class FramebufferHandle: public GlContainerHandle<FramebufferImpl>
+class FramebufferHandle: public GrHandle<FramebufferImpl>
 {
 public:
-	using Base = GlContainerHandle<FramebufferImpl>;
-	using Attachment = FramebufferImpl::Attachment;
-	using Initializer = GlFramebufferInitializer;
+	using Base = GrHandle<FramebufferImpl>;
+	using Initializer = FramebufferInitializer;
 
 	FramebufferHandle();
 
 	~FramebufferHandle();
 
 	/// Create a framebuffer
-	ANKI_USE_RESULT Error create(
-		CommandBufferHandle& commands,
-		const std::initializer_list<Attachment>& attachments);
+	ANKI_USE_RESULT Error create(CommandBufferHandle& commands,
+		Initializer& attachments);
 
 	/// Bind it to the state
 	/// @param commands The command buffer

+ 7 - 6
include/anki/gr/OcclusionQueryHandle.h

@@ -6,26 +6,27 @@
 #ifndef ANKI_GR_OCCLUSION_QUERY_HANDLE_H
 #define ANKI_GR_OCCLUSION_QUERY_HANDLE_H
 
-#include "anki/gr/GlContainerHandle.h"
+#include "anki/gr/GrHandle.h"
 
 namespace anki {
 
-/// @addtogroup opengl_other
+/// @addtogroup graphics
 /// @{
 
 /// Occlusion query handle.
-class OcclusionQueryHandle: public GlContainerHandle<OcclusionQueryImpl>
+class OcclusionQueryHandle: public GrHandle<OcclusionQueryImpl>
 {
 public:
-	using Base = GlContainerHandle<OcclusionQueryImpl>;
-	using ResultBit = GlOcclusionQueryResultBit;
+	using Base = GrHandle<OcclusionQueryImpl>;
+	using ResultBit = OcclusionQueryResultBit;
 
 	OcclusionQueryHandle();
 
 	~OcclusionQueryHandle();
 
 	/// Create a query.
-	ANKI_USE_RESULT Error create(GlDevice* dev, ResultBit condRenderingBit);
+	ANKI_USE_RESULT Error create(
+		GrManager* manager, ResultBit condRenderingBit);
 
 	/// Begin query.
 	void begin(CommandBufferHandle& commands);

+ 5 - 6
include/anki/gr/PipelineHandle.h

@@ -6,18 +6,18 @@
 #ifndef ANKI_GR_PIPELINE_HANDLE_H
 #define ANKI_GR_PIPELINE_HANDLE_H
 
-#include "anki/gr/GlContainerHandle.h"
+#include "anki/gr/GrHandle.h"
 
 namespace anki {
 
-/// @addtogroup opengl_other
+/// @addtogroup graphics
 /// @{
 
-/// Program pipeline handle
-class PipelineHandle: public GlContainerHandle<PipelineImpl>
+/// Program pipeline handle.
+class PipelineHandle: public GrHandle<PipelineImpl>
 {
 public:
-	using Base = GlContainerHandle<PipelineImpl>;
+	using Base = GrHandle<PipelineImpl>;
 
 	PipelineHandle();
 
@@ -46,7 +46,6 @@ public:
 	ANKI_USE_RESULT Error commonConstructor(CommandBufferHandle& commands,
 		const ShaderHandle* progsBegin, const ShaderHandle* progsEnd);
 };
-
 /// @}
 
 } // end namespace anki

+ 1 - 1
include/anki/gr/ShaderHandle.h

@@ -25,7 +25,7 @@ public:
 
 	/// Create shader program.
 	ANKI_USE_RESULT Error create(CommandBufferHandle& commands, 
-		GLenum shaderType, const void* source);
+		GLenum shaderType, const void* source, PtrSize sourceSize);
 
 	/// @name Accessors
 	/// They will sync client with server.

+ 45 - 0
include/anki/gr/TextureCommon.h

@@ -0,0 +1,45 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#ifndef ANKI_GR_TEXTURE_COMMON_H
+#define ANKI_GR_TEXTURE_COMMON_H
+
+#include "anki/gr/Common.h"
+
+namespace anki {
+
+/// @addtogroup graphics
+/// @{
+
+struct SurfaceData
+{
+	void* m_ptr = nullptr;
+	PtrSize m_size = 0;
+};
+
+/// Texture initializer.
+struct TextureInitializer
+{
+	U32 m_width = 0;
+	U32 m_height = 0;
+	U32 m_depth = 0; ///< Relevant only for 3D and 2DArray textures
+	GLenum m_target = GL_TEXTURE_2D;
+	GLenum m_internalFormat = GL_NONE;
+	U32 m_mipmapsCount = 0;
+	TextureFilter m_filterType = TextureFilter::NEAREST;
+	Bool8 m_repeat = false;
+	I32 m_anisotropyLevel = 0;
+	U32 m_samples = 1;
+
+	/// [level][slice]
+	Array2d<SurfaceData, MAX_MIPMAPS, MAX_TEXTURE_LAYERS> m_data;
+};
+/// @}
+
+} // end namespace anki
+
+#endif
+
+

+ 1 - 0
include/anki/gr/TextureHandle.h

@@ -7,6 +7,7 @@
 #define ANKI_GR_TEXTURE_HANDLE_H
 
 #include "anki/gr/GrHandle.h"
+#include "anki/gr/TextureCommon.h"
 
 namespace anki {
 

+ 2 - 2
include/anki/gr/gl/CommandBufferImpl.h

@@ -50,8 +50,8 @@ public:
 	/// @param hints Hints to optimize the command's allocator
 	ANKI_USE_RESULT Error create(const InitHints& hints);
 
-	/// Get he allocator
-	CommandBufferAllocator<U8> getAllocator() const
+	/// Get the internal allocator.
+	CommandBufferAllocator<U8> getInternalAllocator() const
 	{
 		return m_alloc;
 	}

+ 5 - 2
include/anki/gr/gl/GrManagerImpl.h

@@ -10,6 +10,9 @@
 
 namespace anki {
 
+// Forward
+class RenderingThread;
+
 /// @addtogroup opengl
 /// @{
 
@@ -23,9 +26,9 @@ public:
 		ANKI_ASSERT(manager);
 	}
 
-	ANKI_USE_RESULT Error create(GrManagerInitializer& init);
+	~GrManager();
 
-	GrAllocator<U8> getAllocator() const;
+	ANKI_USE_RESULT Error create(GrManagerInitializer& init);
 
 	const RenderingThread& getRenderingThread() const
 	{

+ 3 - 1
include/anki/gr/gl/OcclusionQueryImpl.h

@@ -21,7 +21,9 @@ public:
 	using ResultBit = OcclusionQueryResultBit;
 	using Result = OcclusionQueryResult;
 
-	OcclusionQueryImpl() = default;
+	OcclusionQueryImpl(GrManager* manager)
+	:	Base(manager)
+	{}
 
 	~OcclusionQueryImpl()
 	{

+ 2 - 30
include/anki/gr/gl/RenderingThread.h

@@ -12,9 +12,6 @@
 
 namespace anki {
 
-// Forward
-class GlDevice;
-
 /// @addtogroup opengl_private
 /// @{
 
@@ -25,33 +22,10 @@ class RenderingThread
 	friend class SyncCommand;
 
 public:
-	RenderingThread(GlDevice* device, 
-		AllocAlignedCallback alloc, void* allocUserData);
+	RenderingThread(GlDevice* device);
 
 	~RenderingThread();
 
-	GlDevice& getDevice()
-	{
-		ANKI_ASSERT(m_device);
-		return *m_device;
-	}
-
-	const GlDevice& getDevice() const
-	{
-		ANKI_ASSERT(m_device);
-		return *m_device;
-	}
-
-	AllocAlignedCallback getAllocationCallback() const
-	{
-		return m_allocCb;
-	}
-
-	void* getAllocationCallbackUserData() const
-	{
-		return m_allocCbUserData;
-	}
-
 	State& getState()
 	{
 		return m_state;
@@ -96,9 +70,7 @@ public:
 	void swapBuffers();
 
 private:
-	GlDevice* m_device = nullptr;
-	AllocAlignedCallback m_allocCb;
-	void* m_allocCbUserData;
+	GrManager* m_manager = nullptr;
 
 	Array<CommandBufferHandle, 128> m_queue; ///< Command queue
 	U64 m_tail; ///< Tail of queue

+ 1 - 1
src/gr/Common.cpp

@@ -3,7 +3,7 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include "anki/gr/GlCommon.h"
+#include "anki/gr/Common.h"
 
 namespace anki {
 

+ 0 - 102
src/gr/GrManager.cpp

@@ -1,102 +0,0 @@
-// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/gr/GlDevice.h"
-#include "anki/core/Timestamp.h"
-#include <cstring>
-
-namespace anki {
-
-//==============================================================================
-Error GlDevice::create(
-	AllocAlignedCallback alloc, void* allocUserData,
-	const CString& cacheDir)
-{
-	m_alloc = HeapAllocator<U8>(alloc, allocUserData);
-
-	// Allocate cache dir
-	auto len = cacheDir.getLength();
-	m_cacheDir = reinterpret_cast<char*>(m_alloc.allocate(len + 1));
-	std::memcpy(m_cacheDir, &cacheDir[0], len + 1);
-
-	// Create queue
-	m_queue = m_alloc.newInstance<RenderingThread>(
-		this, alloc, allocUserData);
-
-#if ANKI_QUEUE_DISABLE_ASYNC
-	ANKI_LOGW("GL queue works in synchronous mode");
-#endif
-
-	return ErrorCode::NONE;
-}
-
-//==============================================================================
-void GlDevice::destroy()
-{
-	if(m_queue)
-	{
-		if(m_queueStarted)
-		{
-			m_queue->stop();
-		}
-
-		m_alloc.deleteInstance(m_queue);
-	}
-
-	if(m_cacheDir)
-	{
-		m_alloc.deallocate(m_cacheDir, std::strlen(m_cacheDir) + 1);
-	}
-}
-
-//==============================================================================
-Error GlDevice::startServer(
-	GlMakeCurrentCallback makeCurrentCb, void* makeCurrentCbData, void* ctx,
-	GlCallback swapBuffersCallback, void* swapBuffersCbData,
-	Bool registerDebugMessages)
-{
-	Error err = m_queue->start(makeCurrentCb, makeCurrentCbData, ctx, 
-		swapBuffersCallback, swapBuffersCbData, 
-		registerDebugMessages);
-
-	if(!err)
-	{
-		syncClientServer();
-
-		m_queueStarted = true;
-	}
-
-	return err;
-}
-
-//==============================================================================
-void GlDevice::syncClientServer()
-{
-	m_queue->syncClientServer();
-}
-
-//==============================================================================
-void GlDevice::swapBuffers()
-{
-	m_queue->swapBuffers();
-}
-
-//==============================================================================
-PtrSize GlDevice::getBufferOffsetAlignment(GLenum target) const
-{
-	const State& state = m_queue->getState();
-
-	if(target == GL_UNIFORM_BUFFER)
-	{
-		return state.m_uniBuffOffsetAlignment;
-	}
-	else
-	{
-		ANKI_ASSERT(target == GL_SHADER_STORAGE_BUFFER);
-		return state.m_ssBuffOffsetAlignment;
-	}
-}
-
-} // end namespace anki

+ 1 - 1
src/gr/GrObject.cpp

@@ -11,7 +11,7 @@ namespace anki {
 //==============================================================================
 GrAllocator<U8> GrObject::getAllocator() const
 {
-	m_manager->getAllocator();
+	return m_manager->getAllocator();
 }
 
 } // end namespace anki

+ 0 - 116
src/gr/OcclusionQueryHandle.cpp

@@ -1,116 +0,0 @@
-// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/gr/OcclusionQueryHandle.h"
-#include "anki/gr/gl/OcclusionQueryImpl.h"
-#include "anki/gr/GlHandleDeferredDeleter.h"
-
-namespace anki {
-
-//==============================================================================
-OcclusionQueryHandle::OcclusionQueryHandle()
-{}
-
-//==============================================================================
-OcclusionQueryHandle::~OcclusionQueryHandle()
-{}
-
-//==============================================================================
-Error OcclusionQueryHandle::create(GlDevice* dev, ResultBit condRenderingBit)
-{
-	class Command: public GlCommand
-	{
-	public:	
-		OcclusionQueryHandle m_handle;
-		ResultBit m_condRenderingBit;
-
-		Command(OcclusionQueryHandle& handle, ResultBit condRenderingBit)
-		:	m_handle(handle),
-			m_condRenderingBit(condRenderingBit)
-		{}
-
-		Error operator()(CommandBufferImpl*)
-		{
-			Error err = m_handle._get().create(m_condRenderingBit);
-
-			GlHandleState oldState = m_handle._setState(
-				(err) ? GlHandleState::ERROR : GlHandleState::CREATED);
-			ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
-			(void)oldState;
-
-			return err;
-		}
-	};
-
-	using Alloc = GlAllocator<OcclusionQueryImpl>;
-	using DeleteCommand = GlDeleteObjectCommand<OcclusionQueryImpl, Alloc>;
-	using Deleter = 
-		GlHandleDeferredDeleter<OcclusionQueryImpl, Alloc, DeleteCommand>;
-
-	CommandBufferHandle cmd;
-	Error err = cmd.create(dev);
-
-	if(!err)
-	{
-		err = _createAdvanced(dev, dev->_getAllocator(), Deleter());
-	}
-
-	if(!err)
-	{
-		_setState(GlHandleState::TO_BE_CREATED);
-
-		cmd._pushBackNewCommand<Command>(*this, condRenderingBit);
-		cmd.flush();
-	}
-
-	return err;
-}
-
-//==============================================================================
-void OcclusionQueryHandle::begin(CommandBufferHandle& commands)
-{
-	class Command: public GlCommand
-	{
-	public:
-		OcclusionQueryHandle m_handle;
-
-		Command(OcclusionQueryHandle& handle)
-		:	m_handle(handle)
-		{}
-
-		Error operator()(CommandBufferImpl*)
-		{
-			m_handle._get().begin();
-			return ErrorCode::NONE;
-		}
-	};
-
-	commands._pushBackNewCommand<Command>(*this);
-}
-
-//==============================================================================
-void OcclusionQueryHandle::end(CommandBufferHandle& commands)
-{
-	class Command: public GlCommand
-	{
-	public:
-		OcclusionQueryHandle m_handle;
-
-		Command(OcclusionQueryHandle& handle)
-		:	m_handle(handle)
-		{}
-
-		Error operator()(CommandBufferImpl*)
-		{
-			m_handle._get().end();
-			return ErrorCode::NONE;
-		}
-	};
-
-	commands._pushBackNewCommand<Command>(*this);
-}
-
-} // end namespace anki
-

+ 46 - 42
src/gr/gl/CommandBufferHandle.cpp

@@ -4,7 +4,10 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/gr/CommandBufferHandle.h"
-#include "anki/gr/GlDevice.h"
+#include "anki/gr/gl/CommandBufferImpl.h"
+#include "anki/gr/GrManager.h"
+#include "anki/gr/gl/GrManagerImpl.h"
+#include "anki/gr/gl/RenderingThread.h"
 #include "anki/gr/gl/FramebufferImpl.h"
 #include "anki/gr/TextureHandle.h"
 #include "anki/gr/gl/TextureImpl.h"
@@ -20,7 +23,7 @@ namespace anki {
 //==============================================================================
 // Macros because we are bored to type
 #define ANKI_STATE_CMD_0(type_, glfunc_) \
-	class Command: public GlCommand \
+	class Command final: public GlCommand \
 	{ \
 	public: \
 		Command() = default \
@@ -30,7 +33,7 @@ namespace anki {
 			return ErrorCode::NONE; \
 		} \
 	}; \
-	_pushBackNewCommand<Command>(value_)
+	get().pushBackNewCommand<Command>(value_)
 
 #define ANKI_STATE_CMD_1(type_, glfunc_, value_) \
 	class Command: public GlCommand \
@@ -46,7 +49,7 @@ namespace anki {
 			return ErrorCode::NONE; \
 		} \
 	}; \
-	_pushBackNewCommand<Command>(value_)
+	get().pushBackNewCommand<Command>(value_)
 
 #define ANKI_STATE_CMD_2(type_, glfunc_, a_, b_) \
 	class Command: public GlCommand \
@@ -63,7 +66,7 @@ namespace anki {
 			return ErrorCode::NONE; \
 		} \
 	}; \
-	_pushBackNewCommand<Command>(a_, b_)
+	get().pushBackNewCommand<Command>(a_, b_)
 
 #define ANKI_STATE_CMD_3(type_, glfunc_, a_, b_, c_) \
 	class Command: public GlCommand \
@@ -80,7 +83,7 @@ namespace anki {
 			return ErrorCode::NONE; \
 		} \
 	}; \
-	_pushBackNewCommand<Command>(a_, b_, c_)
+	get().pushBackNewCommand<Command>(a_, b_, c_)
 
 #define ANKI_STATE_CMD_4(type_, glfunc_, a_, b_, c_, d_) \
 	class Command: public GlCommand \
@@ -97,7 +100,7 @@ namespace anki {
 			return ErrorCode::NONE; \
 		} \
 	}; \
-	_pushBackNewCommand<Command>(a_, b_, c_, d_)
+	get().pushBackNewCommand<Command>(a_, b_, c_, d_)
 
 #define ANKI_STATE_CMD_ENABLE(enum_, enable_) \
 	class Command: public GlCommand \
@@ -120,7 +123,7 @@ namespace anki {
 			return ErrorCode::NONE; \
 		} \
 	}; \
-	_pushBackNewCommand<Command>(enable_)
+	get().pushBackNewCommand<Command>(enable_)
 
 //==============================================================================
 CommandBufferHandle::CommandBufferHandle()
@@ -131,23 +134,19 @@ CommandBufferHandle::~CommandBufferHandle()
 {}
 
 //==============================================================================
-Error CommandBufferHandle::create(GlDevice* gl, 
-	CommandBufferImplInitHints hints)
+Error CommandBufferHandle::create(GrManager* manager, 
+	CommandBufferInitHints hints)
 {
 	ANKI_ASSERT(!isCreated());
-	ANKI_ASSERT(gl);
-
-	using Alloc = GlAllocator<CommandBufferImpl>;
-	Alloc alloc = gl->_getAllocator();
+	ANKI_ASSERT(manager);
 
-	Error err = _createAdvanced(
-		gl,
-		alloc, 
-		GlHandleDefaultDeleter<CommandBufferImpl, Alloc>());
+	Error err = Base::create(
+		*manager,
+		GrHandleDefaultDeleter<CommandBufferImpl>());
 
 	if(!err)
 	{
-		err = _get().create(&gl->_getRenderingThread(), hints);
+		err = get().create(hints);
 	}
 
 	return err;
@@ -182,7 +181,7 @@ void CommandBufferHandle::pushBackUserCommand(
 		}
 	};
 
-	_pushBackNewCommand<Command>(callback, data);
+	get().pushBackNewCommand<Command>(callback, data);
 }
 
 //==============================================================================
@@ -200,24 +199,26 @@ void CommandBufferHandle::pushBackOtherCommandBuffer(
 
 		Error operator()(CommandBufferImpl*)
 		{
-			return m_commands._executeAllCommands();
+			return m_commands.get().executeAllCommands();
 		}
 	};
 
-	commands._get().makeImmutable();
-	_pushBackNewCommand<Command>(commands);
+	commands.get().makeImmutable();
+	get().pushBackNewCommand<Command>(commands);
 }
 
 //==============================================================================
 void CommandBufferHandle::flush()
 {
-	_get().getRenderingThread().flushCommandBuffer(*this);
+	get().getManager().getImplementation().
+		getRenderingThread().flushCommandBuffer(*this);
 }
 
 //==============================================================================
 void CommandBufferHandle::finish()
 {
-	_get().getRenderingThread().finishCommandBuffer(*this);
+	get().getManager().getImplementation().getRenderingThread().
+		finishCommandBuffer(*this);
 }
 
 //==============================================================================
@@ -259,7 +260,8 @@ void CommandBufferHandle::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 
 		Error operator()(CommandBufferImpl* commands)
 		{
-			State& state = commands->getRenderingThread().getState();
+			State& state = commands->getManager().getImplementation().
+				getRenderingThread().getState();
 
 			if(state.m_viewport[0] != m_value[0] 
 				|| state.m_viewport[1] != m_value[1]
@@ -275,7 +277,7 @@ void CommandBufferHandle::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 		}
 	};
 
-	_pushBackNewCommand<Command>(minx, miny, maxx, maxy);
+	get().pushBackNewCommand<Command>(minx, miny, maxx, maxy);
 }
 
 //==============================================================================
@@ -356,7 +358,8 @@ void CommandBufferHandle::setBlendFunctions(GLenum sfactor, GLenum dfactor)
 
 		Error operator()(CommandBufferImpl* commands)
 		{
-			State& state = commands->getRenderingThread().getState();
+			State& state = commands->getManager().getImplementation().
+				getRenderingThread().getState();
 
 			if(state.m_blendSfunc != m_sfactor 
 				|| state.m_blendDfunc != m_dfactor)
@@ -371,7 +374,7 @@ void CommandBufferHandle::setBlendFunctions(GLenum sfactor, GLenum dfactor)
 		}
 	};
 
-	_pushBackNewCommand<Command>(sfactor, dfactor);
+	get().pushBackNewCommand<Command>(sfactor, dfactor);
 }
 
 //==============================================================================
@@ -459,7 +462,7 @@ public:
 		U i = 0;
 		while(count-- != 0)
 		{
-			names[i++] = m_texes[count]._get().getGlName();
+			names[i++] = m_texes[count].get().getGlName();
 		}
 
 		glBindTextures(m_first, m_texCount, &names[0]);
@@ -473,7 +476,7 @@ void CommandBufferHandle::bindTextures(U32 first,
 {
 	ANKI_ASSERT(count > 0);
 
-	_pushBackNewCommand<BindTexturesCommand>(&textures[0], count, first);
+	get().pushBackNewCommand<BindTexturesCommand>(&textures[0], count, first);
 }
 
 //==============================================================================
@@ -517,7 +520,7 @@ public:
 			break;
 		};
 
-		if(!m_query.isCreated() || !m_query._get().skipDrawcall())
+		if(!m_query.isCreated() || !m_query.get().skipDrawcall())
 		{
 			glDrawElementsInstancedBaseVertexBaseInstance(
 				m_mode,
@@ -542,7 +545,7 @@ void CommandBufferHandle::drawElements(
 	GlDrawElementsIndirectInfo info(count, instanceCount, firstIndex, 
 		baseVertex, baseInstance);
 
-	_pushBackNewCommand<DrawElementsCondCommand>(mode, indexSize, info);
+	get().pushBackNewCommand<DrawElementsCondCommand>(mode, indexSize, info);
 }
 
 //==============================================================================
@@ -564,7 +567,7 @@ public:
 
 	Error operator()(CommandBufferImpl*)
 	{
-		if(!m_query.isCreated() || !m_query._get().skipDrawcall())
+		if(!m_query.isCreated() || !m_query.get().skipDrawcall())
 		{
 			glDrawArraysInstancedBaseInstance(
 				m_mode,
@@ -585,7 +588,7 @@ void CommandBufferHandle::drawArrays(
 {
 	GlDrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
 
-	_pushBackNewCommand<DrawArraysCondCommand>(mode, info);
+	get().pushBackNewCommand<DrawArraysCondCommand>(mode, info);
 }
 
 //==============================================================================
@@ -597,7 +600,7 @@ void CommandBufferHandle::drawElementsConditional(
 	GlDrawElementsIndirectInfo info(count, instanceCount, firstIndex, 
 		baseVertex, baseInstance);
 
-	_pushBackNewCommand<DrawElementsCondCommand>(mode, indexSize, info, query);
+	get().pushBackNewCommand<DrawElementsCondCommand>(mode, indexSize, info, query);
 }
 
 //==============================================================================
@@ -607,7 +610,7 @@ void CommandBufferHandle::drawArraysConditional(
 {
 	GlDrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
 
-	_pushBackNewCommand<DrawArraysCondCommand>(mode, info, query);
+	get().pushBackNewCommand<DrawArraysCondCommand>(mode, info, query);
 }
 
 //==============================================================================
@@ -624,11 +627,12 @@ public:
 
 	Error operator()(CommandBufferImpl* cmd)
 	{
-		TextureImpl& tex = m_tex._get();
-		BufferImpl& buff = m_buff._get();
+		TextureImpl& tex = m_tex.get();
+		BufferImpl& buff = m_buff.get();
 
 		// Bind
-		GLuint copyFbo = cmd->getRenderingThread().getCopyFbo();
+		GLuint copyFbo = cmd->getManager().getImplementation().
+			getRenderingThread().getCopyFbo();
 		glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);
 
 		// Attach texture
@@ -644,7 +648,7 @@ public:
 		buff.bind();
 
 		// Read pixels
-		GLuint format, type;
+		GLuint format = GL_NONE, type = GL_NONE;
 		if(tex.getInternalFormat() == GL_RG32UI)
 		{
 			format = GL_RG_INTEGER;
@@ -674,7 +678,7 @@ public:
 void CommandBufferHandle::copyTextureToBuffer(
 	TextureHandle& from, BufferHandle& to)
 {
-	_pushBackNewCommand<CopyBuffTex>(from, to);
+	get().pushBackNewCommand<CopyBuffTex>(from, to);
 }
 
 } // end namespace anki

+ 100 - 117
src/gr/gl/FramebufferHandle.cpp

@@ -4,10 +4,98 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/gr/FramebufferHandle.h"
-#include "anki/gr/GlHandleDeferredDeleter.h"
+#include "anki/gr/gl/DeferredDeleter.h"
+#include "anki/gr/gl/FramebufferImpl.h"
 
 namespace anki {
 
+//==============================================================================
+// Commands                                                                    =
+//==============================================================================
+
+/// Create framebuffer command.
+class CreateFramebufferCommand: public GlCommand
+{
+public:
+	FramebufferHandle m_fb;
+	FramebufferHandle::Initializer m_init;
+
+	CreateFramebufferCommand(FramebufferHandle& handle, 
+		FramebufferHandle::Initializer& init)
+	:	m_fb(handle), 
+		m_init(init)
+	{}
+
+	Error operator()(CommandBufferImpl*)
+	{
+		Error err = m_fb.get().create(m_init);
+
+		GlObject::State oldState = m_fb.get().setStateAtomically(
+			(err) ? GlObject::State::ERROR : GlObject::State::CREATED);
+		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
+		(void)oldState;
+
+		return err;
+	}
+};
+
+/// Bind framebuffer command.
+class BindFramebufferCommand: public GlCommand
+{
+public:
+	FramebufferHandle m_fb;
+	Bool8 m_invalidate;
+
+	BindFramebufferCommand(FramebufferHandle& fb, Bool invalidate)
+	:	m_fb(fb), 
+		m_invalidate(invalidate)
+	{}
+
+	Error operator()(CommandBufferImpl*)
+	{
+		m_fb.get().bind(m_invalidate);
+		return ErrorCode::NONE;
+	}
+};
+
+/// Blit.
+class BlitFramebufferCommand: public GlCommand
+{
+public:
+	FramebufferHandle m_fbDest;
+	FramebufferHandle m_fbSrc;
+	Array<U32, 4> m_sourceRect;
+	Array<U32, 4> m_destRect;
+	GLbitfield m_attachmentMask;
+	Bool8 m_linear;
+
+	BlitFramebufferCommand(FramebufferHandle& fbDest, 
+		const FramebufferHandle& fbSrc,
+		const Array<U32, 4>& sourceRect,
+		const Array<U32, 4>& destRect,
+		GLbitfield attachmentMask,
+		Bool8 linear)
+	:	m_fbDest(fbDest), 
+		m_fbSrc(fbSrc), 
+		m_sourceRect(sourceRect),
+		m_destRect(destRect), 
+		m_attachmentMask(attachmentMask), 
+		m_linear(linear)
+	{}
+
+	Error operator()(CommandBufferImpl*)
+	{
+		m_fbDest.get().blit(m_fbSrc.get(), m_sourceRect, m_destRect, 
+			m_attachmentMask, m_linear);
+
+		return ErrorCode::NONE;
+	}
+};
+
+//==============================================================================
+// FramebufferHandle                                                           =
+//==============================================================================
+
 //==============================================================================
 FramebufferHandle::FramebufferHandle()
 {}
@@ -17,75 +105,19 @@ FramebufferHandle::~FramebufferHandle()
 {}
 
 //==============================================================================
-Error FramebufferHandle::create(
-	CommandBufferHandle& commands,
-	const std::initializer_list<Attachment>& attachments)
+Error FramebufferHandle::create(CommandBufferHandle& commands, 
+	Initializer& init)
 {
-	using Attachments = 
-		Array<Attachment, FramebufferImpl::MAX_COLOR_ATTACHMENTS + 1>;
-
-	class Command: public GlCommand
-	{
-	public:
-		Attachments m_attachments;
-		U8 m_size;
-		FramebufferHandle m_fb;
-
-		Command(FramebufferHandle& handle, const Attachments& attachments, 
-			U size)
-		:	m_attachments(attachments), 
-			m_size(size), 
-			m_fb(handle)
-		{}
-
-		Error operator()(CommandBufferImpl*)
-		{
-			Attachment* begin;
-			Attachment* end;
-
-			if(m_size > 0)
-			{
-				begin = &m_attachments[0];
-				end = begin + m_size;
-			}
-			else
-			{
-				begin = end = nullptr;
-			}
-
-			Error err = m_fb._get().create(begin, end);
-
-			GlHandleState oldState = m_fb._setState(
-				(err) ? GlHandleState::ERROR : GlHandleState::CREATED);
-			ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
-			(void)oldState;
-
-			return err;
-		}
-	};
-
-	using Alloc = GlAllocator<FramebufferImpl>;
-	using DeleteCommand = GlDeleteObjectCommand<FramebufferImpl, Alloc>;
-	using Deleter = 
-		GlHandleDeferredDeleter<FramebufferImpl, Alloc, DeleteCommand>;
-
-	Error err = _createAdvanced(
-		&commands._get().getRenderingThread().getDevice(),
-		commands._get().getGlobalAllocator(), 
-		Deleter());
+	using DeleteCommand = DeleteObjectCommand<FramebufferImpl>;
+	using Deleter = DeferredDeleter<FramebufferImpl, DeleteCommand>;
 
+	Error err = Base::create(commands.get().getManager(), Deleter());
 	if(!err)
 	{
-		_setState(GlHandleState::TO_BE_CREATED);
+		get().setStateAtomically(GlObject::State::TO_BE_CREATED);
 
-		Attachments att;
-		U i = 0;
-		for(const Attachment& a : attachments)
-		{
-			att[i++] = a;
-		}
-
-		commands._pushBackNewCommand<Command>(*this, att, attachments.size());
+		commands.get().pushBackNewCommand<CreateFramebufferCommand>(
+			*this, init);
 	}
 
 	return err;
@@ -94,25 +126,8 @@ Error FramebufferHandle::create(
 //==============================================================================
 void FramebufferHandle::bind(CommandBufferHandle& commands, Bool invalidate)
 {
-	class Command: public GlCommand
-	{
-	public:
-		FramebufferHandle m_fb;
-		Bool8 m_invalidate;
-
-		Command(FramebufferHandle& fb, Bool invalidate)
-		:	m_fb(fb), 
-			m_invalidate(invalidate)
-		{}
-
-		Error operator()(CommandBufferImpl*)
-		{
-			m_fb._get().bind(m_invalidate);
-			return ErrorCode::NONE;
-		}
-	};
-
-	commands._pushBackNewCommand<Command>(*this, invalidate);
+	commands.get().pushBackNewCommand<BindFramebufferCommand>(
+		*this, invalidate);
 }
 
 //==============================================================================
@@ -123,39 +138,7 @@ void FramebufferHandle::blit(CommandBufferHandle& commands,
 	GLbitfield attachmentMask,
 	Bool linear)
 {
-	class Command: public GlCommand
-	{
-	public:
-		FramebufferHandle m_fbDest;
-		FramebufferHandle m_fbSrc;
-		Array<U32, 4> m_sourceRect;
-		Array<U32, 4> m_destRect;
-		GLbitfield m_attachmentMask;
-		Bool8 m_linear;
-
-		Command(FramebufferHandle& fbDest, const FramebufferHandle& fbSrc,
-			const Array<U32, 4>& sourceRect,
-			const Array<U32, 4>& destRect,
-			GLbitfield attachmentMask,
-			Bool8 linear)
-		:	m_fbDest(fbDest), 
-			m_fbSrc(fbSrc), 
-			m_sourceRect(sourceRect),
-			m_destRect(destRect), 
-			m_attachmentMask(attachmentMask), 
-			m_linear(linear)
-		{}
-
-		Error operator()(CommandBufferImpl*)
-		{
-			m_fbDest._get().blit(m_fbSrc._get(), m_sourceRect, m_destRect, 
-				m_attachmentMask, m_linear);
-
-			return ErrorCode::NONE;
-		}
-	};
-
-	commands._pushBackNewCommand<Command>(
+	commands.get().pushBackNewCommand<BlitFramebufferCommand>(
 		*this, b, sourceRect, destRect, attachmentMask, linear);
 }
 

+ 20 - 22
src/gr/gl/FramebufferImpl.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/gr/gl/FramebufferImpl.h"
+#include "anki/gr/FramebufferCommon.h"
 #include "anki/gr/gl/TextureImpl.h"
 #include "anki/util/Logger.h"
 
@@ -12,7 +13,8 @@ namespace anki {
 //==============================================================================
 Error FramebufferImpl::create(Initializer& init)
 {
-	if(init.m_attachments.getSize() == 0)
+	if(init.m_colorAttachmentsCount == 0 
+		&& !init.m_depthStencilAttachment.m_texture.isCreated())
 	{
 		m_bindDefault = true;
 		return ErrorCode::NONE;
@@ -22,30 +24,26 @@ Error FramebufferImpl::create(Initializer& init)
 
 	Array<U, MAX_COLOR_ATTACHMENTS + 1> layers;
 	GLenum depthStencilBindingPoint = GL_NONE;
-	Attachment* attachment = init.m_attachments.getBegin();
-	Attachment* attachmentsEnd = init.m_attachments.getEnd();
-	do
-	{
-		if(attachment->m_point >= GL_COLOR_ATTACHMENT0 
-			&& attachment->m_point < 
-				GL_COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS)
-		{
-			// Color attachment
 
-			U32 i = attachment->m_point - GL_COLOR_ATTACHMENT0;
-			m_attachments[i] = *attachment->m_texture;
-			layers[i] = attachment->m_layer;
-		}
-		else
-		{
-			// Depth & stencil
+	// Do color attachments
+	for(U i = 0; i < init.m_colorAttachmentsCount; ++i)
+	{
+		auto& attachment = init.m_colorAttachments[i];
+		ANKI_ASSERT(attachment.m_texture.isCreated());
+		m_attachments[i] = attachment.m_texture;
+		layers[i] = attachment.m_layer;
+	}
 
-			m_attachments[MAX_COLOR_ATTACHMENTS] = *attachment->m_texture;
-			layers[MAX_COLOR_ATTACHMENTS] = attachment->m_layer;
-			depthStencilBindingPoint = attachment->m_point;
-		}
+	// Do depth stencil
+	if(init.m_depthStencilAttachment.m_texture.isCreated())
+	{
+		m_attachments[MAX_COLOR_ATTACHMENTS] = 
+			init.m_depthStencilAttachment.m_texture;
+		layers[MAX_COLOR_ATTACHMENTS] = 
+			init.m_depthStencilAttachment.m_layer;
 
-	} while(++attachment != attachmentsEnd);
+		depthStencilBindingPoint = GL_DEPTH_STENCIL_ATTACHMENT;
+	}
 
 	// Now create the FBO
 	Error err = createFbo(layers, depthStencilBindingPoint);

+ 72 - 0
src/gr/gl/GrManager.cpp

@@ -0,0 +1,72 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include "anki/gr/GrManager.h"
+#include "anki/core/Timestamp.h"
+#include <cstring>
+
+namespace anki {
+
+//==============================================================================
+Error GlDevice::create(Initializer& init)
+{
+	m_alloc = HeapAllocator<U8>(alloc, allocUserData);
+
+	Error err = m_cacheDir.create(m_alloc, cacheDir);
+
+	if(!err)
+	{
+		m_impl = m_alloc.newInstance<GrManagerImpl>(this);
+	}
+
+	if(m_impl)
+	{
+		err = m_impl->create(init);
+	}
+	else
+	{
+		err = ErrorCode::OUT_OF_MEMORY;
+	}
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+void GlDevice::destroy()
+{
+	if(m_impl)
+	{
+		m_alloc.deleteInstance(m_impl);
+	}
+
+	if(m_cacheDir)
+	{
+		m_alloc.deallocate(m_cacheDir, std::strlen(m_cacheDir) + 1);
+	}
+}
+
+//==============================================================================
+void GlDevice::swapBuffers()
+{
+	m_queue->swapBuffers();
+}
+
+//==============================================================================
+PtrSize GlDevice::getBufferOffsetAlignment(GLenum target) const
+{
+	const State& state = m_queue->getState();
+
+	if(target == GL_UNIFORM_BUFFER)
+	{
+		return state.m_uniBuffOffsetAlignment;
+	}
+	else
+	{
+		ANKI_ASSERT(target == GL_SHADER_STORAGE_BUFFER);
+		return state.m_ssBuffOffsetAlignment;
+	}
+}
+
+} // end namespace anki

+ 19 - 7
src/gr/gl/GrManagerImpl.cpp

@@ -8,13 +8,31 @@
 
 namespace anki {
 
+//==============================================================================
+GrManager::~GrManager()
+{
+	if(m_thread)
+	{
+		m_thread->stop();
+		m_manager->getAllocator().deleteInstance(m_thread);
+		m_thread = nullptr;
+	}
+
+	m_manager = nullptr;
+}
+
 //==============================================================================
 Error GlManagerImpl::create(GrManagerInitializer& init)
 {
 	Error err = ErrorCode::NONE;
 
+#if ANKI_QUEUE_DISABLE_ASYNC
+	ANKI_LOGW("GL queue works in synchronous mode");
+#endif
+
 	// Create thread
-	m_thread = getAllocator().newInstance<RenderingThread>(m_manager);
+	m_thread = 
+		m_manager->getAllocator().newInstance<RenderingThread>(m_manager);
 	if(!thread)
 	{
 		err = ErrorCode::OUT_OF_MEMORY;
@@ -36,11 +54,5 @@ Error GlManagerImpl::create(GrManagerInitializer& init)
 	return err;
 }
 
-//==============================================================================
-GrAllocator<U8> GlManagerImpl::getAllocator() const
-{
-	return m_manager->getAllocator();
-}
-
 } // end namespace anki
 

+ 129 - 0
src/gr/gl/OcclusionQueryHandle.cpp

@@ -0,0 +1,129 @@
+// Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include "anki/gr/OcclusionQueryHandle.h"
+#include "anki/gr/gl/OcclusionQueryImpl.h"
+#include "anki/gr/gl/DeferredDeleter.h"
+
+namespace anki {
+
+//==============================================================================
+// Commands                                                                    =
+//==============================================================================
+
+/// Create command.
+class OqCreateCommand final: public GlCommand
+{
+public:	
+	OcclusionQueryHandle m_handle;
+	OcclusionQueryResultBit m_condRenderingBit;
+
+	OqCreateCommand(OcclusionQueryHandle& handle, 
+		OcclusionQueryResultBit condRenderingBit)
+	:	m_handle(handle),
+		m_condRenderingBit(condRenderingBit)
+	{}
+
+	Error operator()(CommandBufferImpl*)
+	{
+		Error err = m_handle.get().create(m_condRenderingBit);
+
+		GlObject::State oldState = m_handle.get().setStateAtomically(
+			(err) ? GlObject::State::ERROR : GlObject::State::CREATED);
+		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
+		(void)oldState;
+
+		return err;
+	}
+};
+
+/// Begin query.
+class OqBeginCommand final: public GlCommand
+{
+public:
+	OcclusionQueryHandle m_handle;
+
+	OqBeginCommand(OcclusionQueryHandle& handle)
+	:	m_handle(handle)
+	{}
+
+	Error operator()(CommandBufferImpl*)
+	{
+		m_handle.get().begin();
+		return ErrorCode::NONE;
+	}
+};
+
+/// End query.
+class OqEndCommand final: public GlCommand
+{
+public:
+	OcclusionQueryHandle m_handle;
+
+	OqEndCommand(OcclusionQueryHandle& handle)
+	:	m_handle(handle)
+	{}
+
+	Error operator()(CommandBufferImpl*)
+	{
+		m_handle.get().end();
+		return ErrorCode::NONE;
+	}
+};
+
+//==============================================================================
+// OcclusionQueryHandle                                                        =
+//==============================================================================
+
+//==============================================================================
+OcclusionQueryHandle::OcclusionQueryHandle()
+{}
+
+//==============================================================================
+OcclusionQueryHandle::~OcclusionQueryHandle()
+{}
+
+//==============================================================================
+Error OcclusionQueryHandle::create(
+	GrManager* manager, ResultBit condRenderingBit)
+{
+	using DeleteCommand = DeleteObjectCommand<OcclusionQueryImpl>;
+	using Deleter = DeferredDeleter<OcclusionQueryImpl, DeleteCommand>;
+
+	CommandBufferHandle cmd;
+	Error err = cmd.create(manager);
+
+	if(!err)
+	{
+		err = Base::create(*manager, Deleter());
+	}
+
+	if(!err)
+	{
+		get().setStateAtomically(GlObject::State::TO_BE_CREATED);
+
+		cmd.get().pushBackNewCommand<OqCreateCommand>(*this, condRenderingBit);
+		cmd.flush();
+	}
+
+	return err;
+}
+
+//==============================================================================
+void OcclusionQueryHandle::begin(CommandBufferHandle& commands)
+{
+	ANKI_ASSERT(isCreated());
+	commands.get().pushBackNewCommand<OqBeginCommand>(*this);
+}
+
+//==============================================================================
+void OcclusionQueryHandle::end(CommandBufferHandle& commands)
+{
+	ANKI_ASSERT(isCreated());
+	commands.get().pushBackNewCommand<OqEndCommand>(*this);
+}
+
+} // end namespace anki
+

+ 76 - 74
src/gr/gl/PipelineHandle.cpp

@@ -5,10 +5,76 @@
 
 #include "anki/gr/PipelineHandle.h"
 #include "anki/gr/gl/PipelineImpl.h"
-#include "anki/gr/GlHandleDeferredDeleter.h"
+#include "anki/gr/gl/DeferredDeleter.h"
 
 namespace anki {
 
+//==============================================================================
+// Commands                                                                    =
+//==============================================================================
+
+class CreatePipelineCommand final: public GlCommand
+{
+public:
+	PipelineHandle m_ppline;
+	Array<ShaderHandle, 6> m_progs;
+	U8 m_progsCount;
+
+	CreatePipelineCommand(PipelineHandle& ppline, 
+		const ShaderHandle* progsBegin, const ShaderHandle* progsEnd)
+	:	m_ppline(ppline)
+	{
+		m_progsCount = 0;
+		const ShaderHandle* prog = progsBegin;
+		do
+		{
+			m_progs[m_progsCount++] = *prog;
+		} while(++prog != progsEnd);
+	}
+
+	Error operator()(CommandBufferImpl* cmdb)
+	{
+		Error err = m_ppline.get().create(
+			&m_progs[0], &m_progs[0] + m_progsCount);
+
+		GlObject::State oldState = m_ppline.get().setStateAtomically(
+			err ? GlObject::State::ERROR : GlObject::State::CREATED);
+		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
+		(void)oldState;
+
+		return err;
+	}
+};
+
+class BindPipelineCommand final: public GlCommand
+{
+public:
+	PipelineHandle m_ppline;
+
+	BindPipelineCommand(PipelineHandle& ppline)
+	:	m_ppline(ppline)
+	{}
+
+	Error operator()(CommandBufferImpl* commands)
+	{
+		State& state = commands->getManager().getImplementation().
+			getRenderingThread().getState();
+
+		auto name = m_ppline.get().getGlName();
+		if(state.m_crntPpline != name)
+		{
+			m_ppline.get().bind();
+			state.m_crntPpline = name;
+		}
+
+		return ErrorCode::NONE;
+	}
+};
+
+//==============================================================================
+// PipelineHandle                                                              =
+//==============================================================================
+
 //==============================================================================
 PipelineHandle::PipelineHandle()
 {}
@@ -38,55 +104,16 @@ Error PipelineHandle::commonConstructor(
 	CommandBufferHandle& commands,
 	const ShaderHandle* progsBegin, const ShaderHandle* progsEnd)
 {
-	class Command: public GlCommand
-	{
-	public:
-		PipelineHandle m_ppline;
-		Array<ShaderHandle, 6> m_progs;
-		U8 m_progsCount;
-
-		Command(PipelineHandle& ppline, 
-			const ShaderHandle* progsBegin, const ShaderHandle* progsEnd)
-		:	m_ppline(ppline)
-		{
-			m_progsCount = 0;
-			const ShaderHandle* prog = progsBegin;
-			do
-			{
-				m_progs[m_progsCount++] = *prog;
-			} while(++prog != progsEnd);
-		}
-
-		Error operator()(CommandBufferImpl* cmdb)
-		{
-			Error err = m_ppline._get().create(
-				&m_progs[0], &m_progs[0] + m_progsCount,
-				cmdb->getGlobalAllocator());
-
-			GlHandleState oldState = m_ppline._setState(
-				err ? GlHandleState::ERROR : GlHandleState::CREATED);
-			ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
-			(void)oldState;
-
-			return err;
-		}
-	};
-
-	using Alloc = GlAllocator<PipelineImpl>;
-	using DeleteCommand = GlDeleteObjectCommand<PipelineImpl, Alloc>;
-	using Deleter = 
-		GlHandleDeferredDeleter<PipelineImpl, Alloc, DeleteCommand>;
-
-	Error err = _createAdvanced(
-		&commands._get().getRenderingThread().getDevice(),
-		commands._get().getGlobalAllocator(), 
-		Deleter());
+	using DeleteCommand = DeleteObjectCommand<PipelineImpl>;
+	using Deleter = DeferredDeleter<PipelineImpl, DeleteCommand>;
 
+	Error err = Base::create(commands.get().getManager(), Deleter());
 	if(!err)
 	{
-		_setState(GlHandleState::TO_BE_CREATED);
+		get().setStateAtomically(GlObject::State::TO_BE_CREATED);
 
-		commands._pushBackNewCommand<Command>(*this, progsBegin, progsEnd);
+		commands.get().pushBackNewCommand<CreatePipelineCommand>(
+			*this, progsBegin, progsEnd);
 	}
 
 	return err;
@@ -96,42 +123,17 @@ Error PipelineHandle::commonConstructor(
 void PipelineHandle::bind(CommandBufferHandle& commands)
 {
 	ANKI_ASSERT(isCreated());
-
-	class Command: public GlCommand
-	{
-	public:
-		PipelineHandle m_ppline;
-
-		Command(PipelineHandle& ppline)
-		:	m_ppline(ppline)
-		{}
-
-		Error operator()(CommandBufferImpl* commands)
-		{
-			State& state = commands->getRenderingThread().getState();
-
-			if(state.m_crntPpline != m_ppline._get().getGlName())
-			{
-				m_ppline._get().bind();
-
-				state.m_crntPpline = m_ppline._get().getGlName();
-			}
-
-			return ErrorCode::NONE;
-		}
-	};
-
-	commands._pushBackNewCommand<Command>(*this);
+	commands.get().pushBackNewCommand<BindPipelineCommand>(*this);
 }
 
 //==============================================================================
 ShaderHandle PipelineHandle::getAttachedProgram(GLenum type) const
 {
 	ANKI_ASSERT(isCreated());
-	Error err = serializeOnGetter();
+	Error err = get().serializeOnGetter();
 	if(!err)
 	{
-		return _get().getAttachedProgram(type);
+		return get().getAttachedProgram(type);
 	}
 	else
 	{

+ 7 - 10
src/gr/gl/RenderingThread.cpp

@@ -5,7 +5,7 @@
 
 #include "anki/gr/gl/RenderingThread.h"
 #include "anki/gr/gl/CommandBufferImpl.h"
-#include "anki/gr/GlDevice.h"
+#include "anki/gr/GrManager.h"
 #include "anki/util/Logger.h"
 #include "anki/core/Counters.h"
 
@@ -16,7 +16,7 @@ namespace anki {
 //==============================================================================
 
 //==============================================================================
-class SyncCommand: public GlCommand
+class SyncCommand final: public GlCommand
 {
 	ANKI_USE_RESULT Error operator()(CommandBufferImpl* cmd)
 	{
@@ -30,17 +30,14 @@ class SyncCommand: public GlCommand
 //==============================================================================
 
 //==============================================================================
-RenderingThread::RenderingThread(GlDevice* device, 
-	AllocAlignedCallback allocCb, void* allocCbUserData)
-:	m_device(device), 
-	m_allocCb(allocCb),
-	m_allocCbUserData(allocCbUserData),
+RenderingThread::RenderingThread(GrManager* manager)
+:	m_manager(manager), 
 	m_tail(0), 
 	m_head(0),
 	m_renderingThreadSignal(0),
 	m_thread("anki_gl")
 {
-	ANKI_ASSERT(m_device);
+	ANKI_ASSERT(m_manager);
 }
 
 //==============================================================================
@@ -116,7 +113,7 @@ Error RenderingThread::start(
 	ANKI_ASSERT(swapBuffersCallback != nullptr);
 	m_swapBuffersCallback = swapBuffersCallback;
 	m_swapBuffersCbData = swapBuffersCbData;
-	err = m_swapBuffersCommands.create(m_device);
+	err = m_swapBuffersCommands.create(m_manager);
 	if(!err)
 	{
 		m_swapBuffersCommands.pushBackUserCommand(swapBuffersInternal, this);
@@ -131,7 +128,7 @@ Error RenderingThread::start(
 		threadStarted = true;
 
 		// Create sync command buffer
-		err = m_syncCommands.create(m_device);
+		err = m_syncCommands.create(m_manager);
 	}
 
 	if(!err)

+ 32 - 27
src/gr/gl/ShaderHandle.cpp

@@ -4,24 +4,26 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/gr/ShaderHandle.h"
-#include "anki/gr/GlDevice.h"
-#include "anki/gr/ClientBufferHandle.h"
-#include "anki/gr/GlHandleDeferredDeleter.h"
+#include "anki/gr/GrManager.h"
+#include "anki/gr/gl/DeferredDeleter.h"
 #include "anki/gr/gl/ShaderImpl.h"
 
 namespace anki {
 
 //==============================================================================
+// Commands                                                                    =
+//==============================================================================
+
 /// Create program command
-class ShaderCreateCommand: public GlCommand
+class ShaderCreateCommand final: public GlCommand
 {
 public:
 	ShaderHandle m_shader;
 	GLenum m_type;
-	ClientBufferHandle m_source;
+	const char* m_source;
 
 	ShaderCreateCommand(ShaderHandle shader, 
-		GLenum type, ClientBufferHandle source)
+		GLenum type, const char* source)
 	:	m_shader(shader), 
 		m_type(type), 
 		m_source(source)
@@ -29,20 +31,22 @@ public:
 
 	Error operator()(CommandBufferImpl* commands)
 	{
-		Error err = m_shader._get().create(m_type, 
-			reinterpret_cast<const char*>(m_source.getBaseAddress()),
-			commands->getRenderingThread().getDevice()._getAllocator(),
-			commands->getRenderingThread().getDevice()._getCacheDirectory());
-
-		GlHandleState oldState = m_shader._setState(
-			(err) ? GlHandleState::ERROR : GlHandleState::CREATED);
-		ANKI_ASSERT(oldState == GlHandleState::TO_BE_CREATED);
+		Error err = m_shader.get().create(m_type, 
+			static_cast<const char*>(m_source));
+
+		GlObject::State oldState = m_shader.get().setStateAtomically(
+			(err) ? GlObject::State::ERROR : GlObject::State::CREATED);
+		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
 		(void)oldState;
 
 		return err;
 	}
 };
 
+//==============================================================================
+// ShaderHandle                                                                =
+//==============================================================================
+
 //==============================================================================
 ShaderHandle::ShaderHandle()
 {}
@@ -53,23 +57,24 @@ ShaderHandle::~ShaderHandle()
 
 //==============================================================================
 Error ShaderHandle::create(CommandBufferHandle& commands, 
-	GLenum type, const ClientBufferHandle& source)
+	GLenum type, const void* source, PtrSize sourceSize)
 {
-	using Alloc = GlAllocator<ShaderImpl>;
-	using DeleteCommand = GlDeleteObjectCommand<ShaderImpl, Alloc>;
-	using Deleter = GlHandleDeferredDeleter<ShaderImpl, Alloc, DeleteCommand>;
-
-	Error err = _createAdvanced(
-		&commands._get().getRenderingThread().getDevice(),
-		commands._get().getGlobalAllocator(), 
-		Deleter());
+	ANKI_ASSERT(strlen(source) == sourceSize + 1);
+	using DeleteCommand = DeleteObjectCommand<ShaderImpl>;
+	using Deleter = DeferredDeleter<ShaderImpl, DeleteCommand>;
 
+	Error err = Base::create(commands.get().getManager(), Deleter());
 	if(!err)
 	{
-		_setState(GlHandleState::TO_BE_CREATED);
+		get().setStateAtomically(GlObject::State::TO_BE_CREATED);
+
+		// Copy source to the command buffer
+		void* src = commands.get().getInternalAllocator().newArray<char>(
+			sourceSize);
+		memcpy(src, source, sourceSize);
 
-		commands._pushBackNewCommand<ShaderCreateCommand>(
-			*this, type, source);
+		commands.get().pushBackNewCommand<ShaderCreateCommand>(
+			*this, type, static_cast<char*>(src));
 	}
 
 	return err;
@@ -78,7 +83,7 @@ Error ShaderHandle::create(CommandBufferHandle& commands,
 //==============================================================================
 GLenum ShaderHandle::getType() const
 {
-	return (serializeOnGetter()) ? GL_NONE : _get().getType();
+	return (get().serializeOnGetter()) ? GL_NONE : get().getType();
 }
 
 } // end namespace anki

+ 1 - 0
src/gr/gl/TextureImpl.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include "anki/gr/gl/TextureImpl.h"
+#include "anki/gr/TextureCommon.h"
 #include "anki/gr/gl/Error.h"
 #include "anki/util/Functions.h"
 #include "anki/util/DArray.h"