Browse Source

[REFACTOR] Remove PIMPL from the GL backend

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
f3038efce2
51 changed files with 868 additions and 787 deletions
  1. 24 0
      src/anki/gr/Buffer.h
  2. 2 1
      src/anki/gr/Enums.h
  3. 7 0
      src/anki/gr/Shader.h
  4. 56 3
      src/anki/gr/Texture.h
  5. 42 69
      src/anki/gr/gl/Buffer.cpp
  6. 41 12
      src/anki/gr/gl/BufferImpl.h
  7. 205 157
      src/anki/gr/gl/CommandBuffer.cpp
  8. 12 7
      src/anki/gr/gl/CommandBufferImpl.cpp
  9. 2 11
      src/anki/gr/gl/CommandBufferImpl.h
  10. 3 0
      src/anki/gr/gl/Common.h
  11. 18 24
      src/anki/gr/gl/Fence.cpp
  12. 5 5
      src/anki/gr/gl/FenceImpl.cpp
  13. 3 2
      src/anki/gr/gl/FenceImpl.h
  14. 7 15
      src/anki/gr/gl/Framebuffer.cpp
  15. 16 16
      src/anki/gr/gl/FramebufferImpl.cpp
  16. 5 5
      src/anki/gr/gl/FramebufferImpl.h
  17. 25 32
      src/anki/gr/gl/GlObject.cpp
  18. 3 17
      src/anki/gr/gl/GlObject.h
  19. 100 20
      src/anki/gr/gl/GrManager.cpp
  20. 8 10
      src/anki/gr/gl/GrManagerImpl.cpp
  21. 4 8
      src/anki/gr/gl/GrManagerImpl.h
  22. 7 15
      src/anki/gr/gl/OcclusionQuery.cpp
  23. 4 3
      src/anki/gr/gl/OcclusionQueryImpl.h
  24. 22 22
      src/anki/gr/gl/RenderingThread.cpp
  25. 2 2
      src/anki/gr/gl/RenderingThread.h
  26. 7 16
      src/anki/gr/gl/Sampler.cpp
  27. 4 3
      src/anki/gr/gl/SamplerImpl.h
  28. 33 45
      src/anki/gr/gl/Shader.cpp
  29. 4 4
      src/anki/gr/gl/ShaderImpl.cpp
  30. 2 2
      src/anki/gr/gl/ShaderImpl.h
  31. 30 75
      src/anki/gr/gl/ShaderProgram.cpp
  32. 8 13
      src/anki/gr/gl/ShaderProgramImpl.cpp
  33. 6 2
      src/anki/gr/gl/ShaderProgramImpl.h
  34. 19 12
      src/anki/gr/gl/StateTracker.h
  35. 28 38
      src/anki/gr/gl/Texture.cpp
  36. 36 32
      src/anki/gr/gl/TextureImpl.cpp
  37. 9 15
      src/anki/gr/gl/TextureImpl.h
  38. 0 3
      src/anki/gr/vulkan/BufferImpl.h
  39. 19 19
      src/anki/gr/vulkan/CommandBufferImpl.cpp
  40. 2 2
      src/anki/gr/vulkan/CommandBufferImpl.inl.h
  41. 5 5
      src/anki/gr/vulkan/FramebufferImpl.cpp
  42. 4 6
      src/anki/gr/vulkan/TextureImpl.cpp
  43. 2 11
      src/anki/gr/vulkan/TextureImpl.h
  44. 3 3
      src/anki/gr/vulkan/TextureImpl.inl.h
  45. 0 2
      src/anki/renderer/Indirect.cpp
  46. 0 1
      src/anki/renderer/Renderer.cpp
  47. 0 1
      src/anki/resource/TextureResource.cpp
  48. 0 1
      src/anki/ui/Font.cpp
  49. 2 3
      tests/framework/Framework.cpp
  50. 21 16
      tests/gr/Gr.cpp
  51. 1 1
      tests/ui/Ui.cpp

+ 24 - 0
src/anki/gr/Buffer.h

@@ -45,6 +45,26 @@ class Buffer : public GrObject
 public:
 public:
 	static const GrObjectType CLASS_TYPE = GrObjectType::BUFFER;
 	static const GrObjectType CLASS_TYPE = GrObjectType::BUFFER;
 
 
+	/// Return the size of the buffer.
+	PtrSize getSize() const
+	{
+		ANKI_ASSERT(m_size > 0);
+		return m_size;
+	}
+
+	/// Return the BufferUsageBit of the Buffer.
+	BufferUsageBit getBufferUsage() const
+	{
+		ANKI_ASSERT(!!m_usage);
+		return m_usage;
+	}
+
+	/// Return the BufferMapAccessBit of the Buffer.
+	BufferMapAccessBit getMapAccess() const
+	{
+		return m_access;
+	}
+
 	/// Map the buffer.
 	/// Map the buffer.
 	void* map(PtrSize offset, PtrSize range, BufferMapAccessBit access);
 	void* map(PtrSize offset, PtrSize range, BufferMapAccessBit access);
 
 
@@ -52,6 +72,10 @@ public:
 	void unmap();
 	void unmap();
 
 
 protected:
 protected:
+	PtrSize m_size = 0;
+	BufferUsageBit m_usage = BufferUsageBit::NONE;
+	BufferMapAccessBit m_access = BufferMapAccessBit::NONE;
+
 	/// Construct.
 	/// Construct.
 	Buffer(GrManager* manager)
 	Buffer(GrManager* manager)
 		: GrObject(manager, CLASS_TYPE)
 		: GrObject(manager, CLASS_TYPE)

+ 2 - 1
src/anki/gr/Enums.h

@@ -179,7 +179,8 @@ enum class TextureType : U8
 	_3D,
 	_3D,
 	_2D_ARRAY,
 	_2D_ARRAY,
 	CUBE,
 	CUBE,
-	CUBE_ARRAY
+	CUBE_ARRAY,
+	COUNT
 };
 };
 
 
 /// Texture usage hints. They are very important.
 /// Texture usage hints. They are very important.

+ 7 - 0
src/anki/gr/Shader.h

@@ -80,6 +80,13 @@ public:
 		: GrBaseInitInfo(name)
 		: GrBaseInitInfo(name)
 	{
 	{
 	}
 	}
+
+	ShaderInitInfo(ShaderType type, CString source, CString name = {})
+		: GrBaseInitInfo(name)
+		, m_shaderType(type)
+		, m_source(source)
+	{
+	}
 };
 };
 
 
 /// GPU shader.
 /// GPU shader.

+ 56 - 3
src/anki/gr/Texture.h

@@ -53,9 +53,6 @@ public:
 	TextureUsageBit m_usage = TextureUsageBit::NONE; ///< How the texture will be used.
 	TextureUsageBit m_usage = TextureUsageBit::NONE; ///< How the texture will be used.
 	TextureUsageBit m_initialUsage = TextureUsageBit::NONE; ///< It's initial usage.
 	TextureUsageBit m_initialUsage = TextureUsageBit::NONE; ///< It's initial usage.
 
 
-	/// It's usual usage. That way you won't need to call CommandBuffer::informTextureXXXCurrentUsage() all the time.
-	TextureUsageBit m_usageWhenEncountered = TextureUsageBit::NONE;
-
 	TextureType m_type = TextureType::_2D;
 	TextureType m_type = TextureType::_2D;
 
 
 	U8 m_mipmapsCount = 1;
 	U8 m_mipmapsCount = 1;
@@ -91,7 +88,63 @@ class Texture : public GrObject
 public:
 public:
 	static const GrObjectType CLASS_TYPE = GrObjectType::TEXTURE;
 	static const GrObjectType CLASS_TYPE = GrObjectType::TEXTURE;
 
 
+	U32 getWidth() const
+	{
+		ANKI_ASSERT(m_width);
+		return m_width;
+	}
+
+	U32 getHeight() const
+	{
+		ANKI_ASSERT(m_height);
+		return m_height;
+	}
+
+	U32 getDepth() const
+	{
+		ANKI_ASSERT(m_depth);
+		return m_depth;
+	}
+
+	U32 getLayercount() const
+	{
+		ANKI_ASSERT(m_layerCount);
+		return m_layerCount;
+	}
+
+	U32 getMipmapCount() const
+	{
+		ANKI_ASSERT(m_mipCount);
+		return m_mipCount;
+	}
+
+	TextureType getTextureType() const
+	{
+		ANKI_ASSERT(m_texType != TextureType::COUNT);
+		return m_texType;
+	}
+
+	TextureUsageBit getTextureUsage() const
+	{
+		ANKI_ASSERT(!!m_usage);
+		return m_usage;
+	}
+
+	const PixelFormat& getPixelFormat() const
+	{
+		return m_format;
+	}
+
 protected:
 protected:
+	U32 m_width = 0;
+	U32 m_height = 0;
+	U32 m_depth = 0;
+	U32 m_layerCount = 0;
+	U32 m_mipCount = 0;
+	TextureType m_texType = TextureType::COUNT;
+	TextureUsageBit m_usage = TextureUsageBit::NONE;
+	PixelFormat m_format;
+
 	/// Construct.
 	/// Construct.
 	Texture(GrManager* manager)
 	Texture(GrManager* manager)
 		: GrObject(manager, CLASS_TYPE)
 		: GrObject(manager, CLASS_TYPE)

+ 42 - 69
src/anki/gr/gl/Buffer.cpp

@@ -11,85 +11,58 @@
 namespace anki
 namespace anki
 {
 {
 
 
-Buffer::Buffer(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
+Buffer* Buffer::newInstance(GrManager* manager, const BufferInitInfo& inf)
 {
 {
-}
-
-Buffer::~Buffer()
-{
-}
-
-class BufferCreateCommand final : public GlCommand
-{
-public:
-	BufferPtr m_buff;
-	PtrSize m_size;
-	BufferUsageBit m_usage;
-	BufferMapAccessBit m_access;
-
-	BufferCreateCommand(Buffer* buff, PtrSize size, BufferUsageBit usage, BufferMapAccessBit access)
-		: m_buff(buff)
-		, m_size(size)
-		, m_usage(usage)
-		, m_access(access)
-	{
-	}
-
-	Error operator()(GlState&)
+	class BufferCreateCommand final : public GlCommand
 	{
 	{
-		BufferImpl& impl = *m_buff->m_impl;
-
-		impl.init(m_size, m_usage, m_access);
-
-		GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
-
-		(void)oldState;
-		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
-
-		return Error::NONE;
-	}
-};
-
-void Buffer::init(const BufferInitInfo& inf)
-{
-	m_impl.reset(getAllocator().newInstance<BufferImpl>(&getManager()));
-
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
-
-	cmdb->m_impl->pushBackNewCommand<BufferCreateCommand>(this, inf.m_size, inf.m_usage, inf.m_access);
-	cmdb->flush();
+	public:
+		BufferPtr m_buff;
+		PtrSize m_size;
+		BufferUsageBit m_usage;
+		BufferMapAccessBit m_access;
+
+		BufferCreateCommand(Buffer* buff, PtrSize size, BufferUsageBit usage, BufferMapAccessBit access)
+			: m_buff(buff)
+			, m_size(size)
+			, m_usage(usage)
+			, m_access(access)
+		{
+		}
+
+		Error operator()(GlState&)
+		{
+			BufferImpl& impl = static_cast<BufferImpl&>(*m_buff);
+
+			impl.init(m_size, m_usage, m_access);
+
+			GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
+			(void)oldState;
+			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
+
+			return Error::NONE;
+		}
+	};
+
+	BufferImpl* impl = manager->getAllocator().newInstance<BufferImpl>(manager);
+
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<BufferCreateCommand>(
+		impl, inf.m_size, inf.m_usage, inf.m_access);
+	static_cast<CommandBufferImpl&>(*cmdb).flush();
+
+	return impl;
 }
 }
 
 
 void* Buffer::map(PtrSize offset, PtrSize range, BufferMapAccessBit access)
 void* Buffer::map(PtrSize offset, PtrSize range, BufferMapAccessBit access)
 {
 {
-	// Wait for its creation
-	if(m_impl->serializeRenderingThread())
-	{
-		return nullptr;
-	}
-
-	// Sanity checks
-	ANKI_ASSERT(offset + range <= m_impl->m_size);
-	ANKI_ASSERT(m_impl->m_persistentMapping);
-
-	U8* ptr = static_cast<U8*>(m_impl->m_persistentMapping);
-	ptr += offset;
-
-#if ANKI_EXTRA_CHECKS
-	ANKI_ASSERT(!m_impl->m_mapped);
-	m_impl->m_mapped = true;
-#endif
-
-	return static_cast<void*>(ptr);
+	ANKI_GL_SELF(BufferImpl);
+	return self.map(offset, range, access);
 }
 }
 
 
 void Buffer::unmap()
 void Buffer::unmap()
 {
 {
-#if ANKI_EXTRA_CHECKS
-	ANKI_ASSERT(m_impl->m_mapped);
-	m_impl->m_mapped = false;
-#endif
+	ANKI_GL_SELF(BufferImpl);
+	self.unmap();
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 41 - 12
src/anki/gr/gl/BufferImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/Buffer.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/gl/GlObject.h>
 
 
 namespace anki
 namespace anki
@@ -14,26 +15,17 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Buffer implementation
 /// Buffer implementation
-class BufferImpl : public GlObject
+class BufferImpl final : public Buffer, public GlObject
 {
 {
 public:
 public:
-	U32 m_size = 0; ///< The size of the buffer
-	void* m_persistentMapping = nullptr;
-	BufferUsageBit m_usage = BufferUsageBit::NONE;
-	BufferMapAccessBit m_access = BufferMapAccessBit::NONE;
-	GLenum m_target = GL_NONE; ///< A guess
-#if ANKI_EXTRA_CHECKS
-	Bool m_mapped = false;
-#endif
-
 	BufferImpl(GrManager* manager)
 	BufferImpl(GrManager* manager)
-		: GlObject(manager)
+		: Buffer(manager)
 	{
 	{
 	}
 	}
 
 
 	~BufferImpl()
 	~BufferImpl()
 	{
 	{
-		destroyDeferred(glDeleteBuffers);
+		destroyDeferred(getManager(), glDeleteBuffers);
 	}
 	}
 
 
 	void init(PtrSize size, BufferUsageBit usage, BufferMapAccessBit access);
 	void init(PtrSize size, BufferUsageBit usage, BufferMapAccessBit access);
@@ -74,6 +66,43 @@ public:
 
 
 		glClearNamedBufferSubData(m_glName, GL_R32UI, offset, size, GL_RED_INTEGER, GL_UNSIGNED_INT, &value);
 		glClearNamedBufferSubData(m_glName, GL_R32UI, offset, size, GL_RED_INTEGER, GL_UNSIGNED_INT, &value);
 	}
 	}
+
+	void* map(PtrSize offset, PtrSize range, BufferMapAccessBit access)
+	{
+		// Wait for its creation
+		if(serializeRenderingThread(getManager()))
+		{
+			return nullptr;
+		}
+
+		// Sanity checks
+		ANKI_ASSERT(offset + range <= m_size);
+		ANKI_ASSERT(m_persistentMapping);
+
+		U8* ptr = static_cast<U8*>(m_persistentMapping);
+		ptr += offset;
+
+#if ANKI_EXTRA_CHECKS
+		ANKI_ASSERT(!m_mapped);
+		m_mapped = true;
+#endif
+		return static_cast<void*>(ptr);
+	}
+
+	void unmap()
+	{
+#if ANKI_EXTRA_CHECKS
+		ANKI_ASSERT(m_mapped);
+		m_mapped = false;
+#endif
+	}
+
+private:
+	void* m_persistentMapping = nullptr;
+	GLenum m_target = GL_NONE; ///< A guess
+#if ANKI_EXTRA_CHECKS
+	Bool m_mapped = false;
+#endif
 };
 };
 /// @}
 /// @}
 
 

+ 205 - 157
src/anki/gr/gl/CommandBuffer.cpp

@@ -28,55 +28,44 @@
 namespace anki
 namespace anki
 {
 {
 
 
-CommandBuffer::CommandBuffer(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
+CommandBuffer* CommandBuffer::newInstance(GrManager* manager, const CommandBufferInitInfo& inf)
 {
 {
-}
-
-CommandBuffer::~CommandBuffer()
-{
-}
-
-void CommandBuffer::init(CommandBufferInitInfo& inf)
-{
-	m_impl.reset(getAllocator().newInstance<CommandBufferImpl>(&getManager()));
-	m_impl->init(inf);
-
-#if ANKI_EXTRA_CHECKS
-	m_impl->m_state.m_secondLevel = !!(inf.m_flags & CommandBufferFlag::SECOND_LEVEL);
-#endif
-
-	if(!!(inf.m_flags & CommandBufferFlag::SECOND_LEVEL))
-	{
-		m_impl->m_state.m_fb = inf.m_framebuffer->m_impl.get();
-	}
+	CommandBufferImpl* impl = manager->getAllocator().newInstance<CommandBufferImpl>(manager);
+	impl->init(inf);
+	return impl;
 }
 }
 
 
 void CommandBuffer::flush(FencePtr* fence)
 void CommandBuffer::flush(FencePtr* fence)
 {
 {
-	if(!m_impl->isSecondLevel())
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	if(!self.isSecondLevel())
 	{
 	{
-		ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
+		ANKI_ASSERT(!self.m_state.insideRenderPass());
 	}
 	}
 	else
 	else
 	{
 	{
 		ANKI_ASSERT(fence == nullptr);
 		ANKI_ASSERT(fence == nullptr);
 	}
 	}
 
 
-	if(!m_impl->isSecondLevel())
+	if(!self.isSecondLevel())
 	{
 	{
-		getManager().getImplementation().getRenderingThread().flushCommandBuffer(CommandBufferPtr(this), fence);
+		static_cast<GrManagerImpl&>(getManager())
+			.getRenderingThread()
+			.flushCommandBuffer(CommandBufferPtr(this), fence);
 	}
 	}
 }
 }
 
 
 void CommandBuffer::finish()
 void CommandBuffer::finish()
 {
 {
-	if(!m_impl->isSecondLevel())
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	if(!self.isSecondLevel())
 	{
 	{
-		ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
+		ANKI_ASSERT(!self.m_state.insideRenderPass());
 	}
 	}
 
 
-	getManager().getImplementation().getRenderingThread().finishCommandBuffer(CommandBufferPtr(this));
+	static_cast<GrManagerImpl&>(getManager()).getRenderingThread().finishCommandBuffer(CommandBufferPtr(this));
 }
 }
 
 
 void CommandBuffer::bindVertexBuffer(
 void CommandBuffer::bindVertexBuffer(
@@ -102,7 +91,7 @@ void CommandBuffer::bindVertexBuffer(
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			glBindVertexBuffer(m_binding, m_buff->m_impl->getGlName(), m_offset, m_stride);
+			glBindVertexBuffer(m_binding, static_cast<const BufferImpl&>(*m_buff).getGlName(), m_offset, m_stride);
 			glVertexBindingDivisor(m_binding, (m_instanced) ? 1 : 0);
 			glVertexBindingDivisor(m_binding, (m_instanced) ? 1 : 0);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
@@ -110,10 +99,11 @@ void CommandBuffer::bindVertexBuffer(
 
 
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(stride > 0);
 	ANKI_ASSERT(stride > 0);
+	ANKI_GL_SELF(CommandBufferImpl);
 
 
-	if(m_impl->m_state.bindVertexBuffer(binding, buff, offset, stride, stepRate))
+	if(self.m_state.bindVertexBuffer(binding, buff, offset, stride, stepRate))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(binding, buff, offset, stride, stepRate == VertexStepRate::INSTANCE);
+		self.pushBackNewCommand<Cmd>(binding, buff, offset, stride, stepRate == VertexStepRate::INSTANCE);
 	}
 	}
 }
 }
 
 
@@ -147,7 +137,9 @@ void CommandBuffer::setVertexAttribute(U32 location, U32 buffBinding, const Pixe
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setVertexAttribute(location, buffBinding, fmt, relativeOffset))
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	if(self.m_state.setVertexAttribute(location, buffBinding, fmt, relativeOffset))
 	{
 	{
 		U compCount;
 		U compCount;
 		GLenum type;
 		GLenum type;
@@ -155,7 +147,7 @@ void CommandBuffer::setVertexAttribute(U32 location, U32 buffBinding, const Pixe
 
 
 		convertVertexFormat(fmt, compCount, type, normalized);
 		convertVertexFormat(fmt, compCount, type, normalized);
 
 
-		m_impl->pushBackNewCommand<Cmd>(location, buffBinding, compCount, type, normalized, relativeOffset);
+		self.pushBackNewCommand<Cmd>(location, buffBinding, compCount, type, normalized, relativeOffset);
 	}
 	}
 }
 }
 
 
@@ -173,16 +165,17 @@ void CommandBuffer::bindIndexBuffer(BufferPtr buff, PtrSize offset, IndexType ty
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buff->m_impl->getGlName());
+			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, static_cast<const BufferImpl&>(*m_buff).getGlName());
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(buff);
+	ANKI_GL_SELF(CommandBufferImpl);
 
 
-	if(m_impl->m_state.bindIndexBuffer(buff, offset, type))
+	if(self.m_state.bindIndexBuffer(buff, offset, type))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(buff);
+		self.pushBackNewCommand<Cmd>(buff);
 	}
 	}
 }
 }
 
 
@@ -213,9 +206,10 @@ void CommandBuffer::setPrimitiveRestart(Bool enable)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setPrimitiveRestart(enable))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setPrimitiveRestart(enable))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(enable);
+		self.pushBackNewCommand<Cmd>(enable);
 	}
 	}
 }
 }
 
 
@@ -238,9 +232,10 @@ void CommandBuffer::setViewport(U32 minx, U32 miny, U32 width, U32 height)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setViewport(minx, miny, width, height))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setViewport(minx, miny, width, height))
 	{
 	{
-		m_impl->pushBackNewCommand<ViewportCommand>(minx, miny, width, height);
+		self.pushBackNewCommand<ViewportCommand>(minx, miny, width, height);
 	}
 	}
 }
 }
 
 
@@ -277,9 +272,10 @@ void CommandBuffer::setScissor(U32 minx, U32 miny, U32 width, U32 height)
 	const GLsizei iminx = minx;
 	const GLsizei iminx = minx;
 	const GLsizei iminy = miny;
 	const GLsizei iminy = miny;
 
 
-	if(m_impl->m_state.setScissor(iminx, iminy, iwidth, iheight))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setScissor(iminx, iminy, iwidth, iheight))
 	{
 	{
-		m_impl->pushBackNewCommand<ScissorCommand>(iminx, iminy, iwidth, iheight);
+		self.pushBackNewCommand<ScissorCommand>(iminx, iminy, iwidth, iheight);
 	}
 	}
 }
 }
 
 
@@ -302,9 +298,10 @@ void CommandBuffer::setFillMode(FillMode mode)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setFillMode(mode))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setFillMode(mode))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(convertFillMode(mode));
+		self.pushBackNewCommand<Cmd>(convertFillMode(mode));
 	}
 	}
 }
 }
 
 
@@ -327,9 +324,10 @@ void CommandBuffer::setCullMode(FaceSelectionBit mode)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setCullMode(mode))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setCullMode(mode))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(convertFaceMode(mode));
+		self.pushBackNewCommand<Cmd>(convertFaceMode(mode));
 	}
 	}
 }
 }
 
 
@@ -363,9 +361,10 @@ void CommandBuffer::setPolygonOffset(F32 factor, F32 units)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setPolygonOffset(factor, units))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setPolygonOffset(factor, units))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(factor, units);
+		self.pushBackNewCommand<Cmd>(factor, units);
 	}
 	}
 }
 }
 
 
@@ -397,9 +396,10 @@ void CommandBuffer::setStencilOperations(FaceSelectionBit face,
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setStencilOperations(face, stencilFail, stencilPassDepthFail, stencilPassDepthPass))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setStencilOperations(face, stencilFail, stencilPassDepthFail, stencilPassDepthPass))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(convertFaceMode(face),
+		self.pushBackNewCommand<Cmd>(convertFaceMode(face),
 			convertStencilOperation(stencilFail),
 			convertStencilOperation(stencilFail),
 			convertStencilOperation(stencilPassDepthFail),
 			convertStencilOperation(stencilPassDepthFail),
 			convertStencilOperation(stencilPassDepthPass));
 			convertStencilOperation(stencilPassDepthPass));
@@ -408,12 +408,14 @@ void CommandBuffer::setStencilOperations(FaceSelectionBit face,
 
 
 void CommandBuffer::setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
 void CommandBuffer::setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
 {
 {
-	m_impl->m_state.setStencilCompareOperation(face, comp);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.m_state.setStencilCompareOperation(face, comp);
 }
 }
 
 
 void CommandBuffer::setStencilCompareMask(FaceSelectionBit face, U32 mask)
 void CommandBuffer::setStencilCompareMask(FaceSelectionBit face, U32 mask)
 {
 {
-	m_impl->m_state.setStencilCompareMask(face, mask);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.m_state.setStencilCompareMask(face, mask);
 }
 }
 
 
 void CommandBuffer::setStencilWriteMask(FaceSelectionBit face, U32 mask)
 void CommandBuffer::setStencilWriteMask(FaceSelectionBit face, U32 mask)
@@ -452,15 +454,17 @@ void CommandBuffer::setStencilWriteMask(FaceSelectionBit face, U32 mask)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setStencilWriteMask(face, mask))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setStencilWriteMask(face, mask))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(convertFaceMode(face), mask);
+		self.pushBackNewCommand<Cmd>(convertFaceMode(face), mask);
 	}
 	}
 }
 }
 
 
 void CommandBuffer::setStencilReference(FaceSelectionBit face, U32 ref)
 void CommandBuffer::setStencilReference(FaceSelectionBit face, U32 ref)
 {
 {
-	m_impl->m_state.setStencilReference(face, ref);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.m_state.setStencilReference(face, ref);
 }
 }
 
 
 void CommandBuffer::setDepthWrite(Bool enable)
 void CommandBuffer::setDepthWrite(Bool enable)
@@ -483,9 +487,10 @@ void CommandBuffer::setDepthWrite(Bool enable)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setDepthWrite(enable))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setDepthWrite(enable))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(enable);
+		self.pushBackNewCommand<Cmd>(enable);
 	}
 	}
 }
 }
 
 
@@ -508,9 +513,10 @@ void CommandBuffer::setDepthCompareOperation(CompareOperation op)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setDepthCompareOperation(op))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setDepthCompareOperation(op))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(convertCompareOperation(op));
+		self.pushBackNewCommand<Cmd>(convertCompareOperation(op));
 	}
 	}
 }
 }
 
 
@@ -548,9 +554,10 @@ void CommandBuffer::setColorChannelWriteMask(U32 attachment, ColorBit mask)
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setColorChannelWriteMask(attachment, mask))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setColorChannelWriteMask(attachment, mask))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(attachment, mask);
+		self.pushBackNewCommand<Cmd>(attachment, mask);
 	}
 	}
 }
 }
 
 
@@ -582,9 +589,10 @@ void CommandBuffer::setBlendFactors(
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setBlendFactors(attachment, srcRgb, dstRgb, srcA, dstA))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setBlendFactors(attachment, srcRgb, dstRgb, srcA, dstA))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(attachment,
+		self.pushBackNewCommand<Cmd>(attachment,
 			convertBlendFactor(srcRgb),
 			convertBlendFactor(srcRgb),
 			convertBlendFactor(dstRgb),
 			convertBlendFactor(dstRgb),
 			convertBlendFactor(srcA),
 			convertBlendFactor(srcA),
@@ -615,9 +623,10 @@ void CommandBuffer::setBlendOperation(U32 attachment, BlendOperation funcRgb, Bl
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.setBlendOperation(attachment, funcRgb, funcA))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.setBlendOperation(attachment, funcRgb, funcA))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(attachment, convertBlendOperation(funcRgb), convertBlendOperation(funcA));
+		self.pushBackNewCommand<Cmd>(attachment, convertBlendOperation(funcRgb), convertBlendOperation(funcA));
 	}
 	}
 }
 }
 
 
@@ -642,7 +651,7 @@ void CommandBuffer::bindTexture(
 		{
 		{
 			if(m_tex)
 			if(m_tex)
 			{
 			{
-				glBindTextureUnit(m_unit, m_tex->m_impl->getGlName());
+				glBindTextureUnit(m_unit, static_cast<const TextureImpl&>(*m_tex).getGlName());
 			}
 			}
 
 
 			if(m_samplerChanged)
 			if(m_samplerChanged)
@@ -653,11 +662,12 @@ void CommandBuffer::bindTexture(
 		}
 		}
 	};
 	};
 
 
+	ANKI_GL_SELF(CommandBufferImpl);
 	Bool texChanged, samplerChanged;
 	Bool texChanged, samplerChanged;
-	if(m_impl->m_state.bindTexture(set, binding, tex, aspect, texChanged, samplerChanged))
+	if(self.m_state.bindTexture(set, binding, tex, aspect, texChanged, samplerChanged))
 	{
 	{
 		U unit = binding + MAX_TEXTURE_BINDINGS * set;
 		U unit = binding + MAX_TEXTURE_BINDINGS * set;
-		m_impl->pushBackNewCommand<Cmd>(unit, (texChanged) ? tex : TexturePtr(), samplerChanged);
+		self.pushBackNewCommand<Cmd>(unit, (texChanged) ? tex : TexturePtr(), samplerChanged);
 	}
 	}
 }
 }
 
 
@@ -680,16 +690,17 @@ void CommandBuffer::bindTextureAndSampler(
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			glBindTextureUnit(m_unit, m_tex->m_impl->getGlName());
-			glBindSampler(m_unit, m_sampler->m_impl->getGlName());
+			glBindTextureUnit(m_unit, static_cast<const TextureImpl&>(*m_tex).getGlName());
+			glBindSampler(m_unit, static_cast<const SamplerImpl&>(*m_sampler).getGlName());
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.bindTextureAndSampler(set, binding, tex, sampler, aspect))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.bindTextureAndSampler(set, binding, tex, sampler, aspect))
 	{
 	{
 		U unit = binding + MAX_TEXTURE_BINDINGS * set;
 		U unit = binding + MAX_TEXTURE_BINDINGS * set;
-		m_impl->pushBackNewCommand<Cmd>(unit, tex, sampler);
+		self.pushBackNewCommand<Cmd>(unit, tex, sampler);
 	}
 	}
 }
 }
 
 
@@ -713,18 +724,19 @@ void CommandBuffer::bindUniformBuffer(U32 set, U32 binding, BufferPtr buff, PtrS
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_buff->m_impl->bind(GL_UNIFORM_BUFFER, m_binding, m_offset, m_range);
+			static_cast<const BufferImpl&>(*m_buff).bind(GL_UNIFORM_BUFFER, m_binding, m_offset, m_range);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(range > 0);
 	ANKI_ASSERT(range > 0);
+	ANKI_GL_SELF(CommandBufferImpl);
 
 
-	if(m_impl->m_state.bindUniformBuffer(set, binding, buff, offset, range))
+	if(self.m_state.bindUniformBuffer(set, binding, buff, offset, range))
 	{
 	{
 		binding = binding + MAX_UNIFORM_BUFFER_BINDINGS * set;
 		binding = binding + MAX_UNIFORM_BUFFER_BINDINGS * set;
-		m_impl->pushBackNewCommand<Cmd>(binding, buff, offset, range);
+		self.pushBackNewCommand<Cmd>(binding, buff, offset, range);
 	}
 	}
 }
 }
 
 
@@ -748,18 +760,19 @@ void CommandBuffer::bindStorageBuffer(U32 set, U32 binding, BufferPtr buff, PtrS
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_buff->m_impl->bind(GL_SHADER_STORAGE_BUFFER, m_binding, m_offset, m_range);
+			static_cast<const BufferImpl&>(*m_buff).bind(GL_SHADER_STORAGE_BUFFER, m_binding, m_offset, m_range);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(range > 0);
 	ANKI_ASSERT(range > 0);
+	ANKI_GL_SELF(CommandBufferImpl);
 
 
-	if(m_impl->m_state.bindStorageBuffer(set, binding, buff, offset, range))
+	if(self.m_state.bindStorageBuffer(set, binding, buff, offset, range))
 	{
 	{
 		binding = binding + MAX_STORAGE_BUFFER_BINDINGS * set;
 		binding = binding + MAX_STORAGE_BUFFER_BINDINGS * set;
-		m_impl->pushBackNewCommand<Cmd>(binding, buff, offset, range);
+		self.pushBackNewCommand<Cmd>(binding, buff, offset, range);
 	}
 	}
 }
 }
 
 
@@ -782,22 +795,23 @@ void CommandBuffer::bindImage(U32 set, U32 binding, TexturePtr img, U32 level)
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
 			glBindImageTexture(m_unit,
 			glBindImageTexture(m_unit,
-				m_img->m_impl->getGlName(),
+				static_cast<const TextureImpl&>(*m_img).getGlName(),
 				m_level,
 				m_level,
 				GL_TRUE,
 				GL_TRUE,
 				0,
 				0,
 				GL_READ_WRITE,
 				GL_READ_WRITE,
-				m_img->m_impl->m_internalFormat);
+				static_cast<const TextureImpl&>(*m_img).m_internalFormat);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(img);
 	ANKI_ASSERT(img);
+	ANKI_GL_SELF(CommandBufferImpl);
 
 
-	if(m_impl->m_state.bindImage(set, binding, img, level))
+	if(self.m_state.bindImage(set, binding, img, level))
 	{
 	{
 		binding = binding + set * MAX_IMAGE_BINDINGS;
 		binding = binding + set * MAX_IMAGE_BINDINGS;
-		m_impl->pushBackNewCommand<Cmd>(binding, img, level);
+		self.pushBackNewCommand<Cmd>(binding, img, level);
 	}
 	}
 }
 }
 
 
@@ -826,10 +840,10 @@ void CommandBuffer::bindTextureBuffer(
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			ANKI_ASSERT(m_offset + m_range <= m_buff->m_impl->m_size);
+			ANKI_ASSERT(m_offset + m_range <= m_buff->getSize());
 
 
 			const GLuint tex = state.m_texBuffTextures[m_set][m_binding];
 			const GLuint tex = state.m_texBuffTextures[m_set][m_binding];
-			glTextureBufferRange(tex, m_fmt, m_buff->m_impl->getGlName(), m_offset, m_range);
+			glTextureBufferRange(tex, m_fmt, static_cast<const BufferImpl&>(*m_buff).getGlName(), m_offset, m_range);
 
 
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
@@ -846,7 +860,8 @@ void CommandBuffer::bindTextureBuffer(
 	(void)type;
 	(void)type;
 	(void)dsAspect;
 	(void)dsAspect;
 
 
-	m_impl->pushBackNewCommand<Cmd>(set, binding, buff, offset, range, internalFormat);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.pushBackNewCommand<Cmd>(set, binding, buff, offset, range, internalFormat);
 }
 }
 
 
 void CommandBuffer::bindShaderProgram(ShaderProgramPtr prog)
 void CommandBuffer::bindShaderProgram(ShaderProgramPtr prog)
@@ -863,16 +878,17 @@ void CommandBuffer::bindShaderProgram(ShaderProgramPtr prog)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			glUseProgram(m_prog->m_impl->getGlName());
+			glUseProgram(static_cast<const ShaderProgramImpl&>(*m_prog).getGlName());
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
 	ANKI_ASSERT(prog);
 	ANKI_ASSERT(prog);
+	ANKI_GL_SELF(CommandBufferImpl);
 
 
-	if(m_impl->m_state.bindShaderProgram(prog))
+	if(self.m_state.bindShaderProgram(prog))
 	{
 	{
-		m_impl->pushBackNewCommand<Cmd>(prog);
+		self.pushBackNewCommand<Cmd>(prog);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -902,14 +918,16 @@ void CommandBuffer::beginRenderPass(FramebufferPtr fb,
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			m_fb->m_impl->bind(state, m_renderArea[0], m_renderArea[1], m_renderArea[2], m_renderArea[3]);
+			static_cast<const FramebufferImpl&>(*m_fb).bind(
+				state, m_renderArea[0], m_renderArea[1], m_renderArea[2], m_renderArea[3]);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	if(m_impl->m_state.beginRenderPass(fb))
+	ANKI_GL_SELF(CommandBufferImpl);
+	if(self.m_state.beginRenderPass(fb))
 	{
 	{
-		m_impl->pushBackNewCommand<BindFramebufferCommand>(fb, minx, miny, width, height);
+		self.pushBackNewCommand<BindFramebufferCommand>(fb, minx, miny, width, height);
 	}
 	}
 }
 }
 
 
@@ -918,9 +936,9 @@ void CommandBuffer::endRenderPass()
 	class Command final : public GlCommand
 	class Command final : public GlCommand
 	{
 	{
 	public:
 	public:
-		FramebufferImpl* m_fb;
+		const FramebufferImpl* m_fb;
 
 
-		Command(FramebufferImpl* fb)
+		Command(const FramebufferImpl* fb)
 			: m_fb(fb)
 			: m_fb(fb)
 		{
 		{
 			ANKI_ASSERT(fb);
 			ANKI_ASSERT(fb);
@@ -933,8 +951,9 @@ void CommandBuffer::endRenderPass()
 		}
 		}
 	};
 	};
 
 
-	m_impl->pushBackNewCommand<Command>(m_impl->m_state.m_fb);
-	m_impl->m_state.endRenderPass();
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.pushBackNewCommand<Command>(self.m_state.m_fb);
+	self.m_state.endRenderPass();
 }
 }
 
 
 void CommandBuffer::drawElements(
 void CommandBuffer::drawElements(
@@ -970,24 +989,26 @@ void CommandBuffer::drawElements(
 		}
 		}
 	};
 	};
 
 
-	m_impl->m_state.checkIndexedDracall();
-	m_impl->flushDrawcall(*this);
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	self.m_state.checkIndexedDracall();
+	self.flushDrawcall(*this);
 
 
 	U idxBytes;
 	U idxBytes;
-	if(m_impl->m_state.m_idx.m_indexType == GL_UNSIGNED_SHORT)
+	if(self.m_state.m_idx.m_indexType == GL_UNSIGNED_SHORT)
 	{
 	{
 		idxBytes = sizeof(U16);
 		idxBytes = sizeof(U16);
 	}
 	}
 	else
 	else
 	{
 	{
-		ANKI_ASSERT(m_impl->m_state.m_idx.m_indexType == GL_UNSIGNED_INT);
+		ANKI_ASSERT(self.m_state.m_idx.m_indexType == GL_UNSIGNED_INT);
 		idxBytes = sizeof(U32);
 		idxBytes = sizeof(U32);
 	}
 	}
 
 
-	firstIndex = firstIndex * idxBytes + m_impl->m_state.m_idx.m_offset;
+	firstIndex = firstIndex * idxBytes + self.m_state.m_idx.m_offset;
 
 
 	DrawElementsIndirectInfo info(count, instanceCount, firstIndex, baseVertex, baseInstance);
 	DrawElementsIndirectInfo info(count, instanceCount, firstIndex, baseVertex, baseInstance);
-	m_impl->pushBackNewCommand<Cmd>(convertPrimitiveTopology(topology), m_impl->m_state.m_idx.m_indexType, info);
+	self.pushBackNewCommand<Cmd>(convertPrimitiveTopology(topology), self.m_state.m_idx.m_indexType, info);
 }
 }
 
 
 void CommandBuffer::drawArrays(PrimitiveTopology topology, U32 count, U32 instanceCount, U32 first, U32 baseInstance)
 void CommandBuffer::drawArrays(PrimitiveTopology topology, U32 count, U32 instanceCount, U32 first, U32 baseInstance)
@@ -1015,11 +1036,13 @@ void CommandBuffer::drawArrays(PrimitiveTopology topology, U32 count, U32 instan
 		}
 		}
 	};
 	};
 
 
-	m_impl->m_state.checkNonIndexedDrawcall();
-	m_impl->flushDrawcall(*this);
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	self.m_state.checkNonIndexedDrawcall();
+	self.flushDrawcall(*this);
 
 
 	DrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
 	DrawArraysIndirectInfo info(count, instanceCount, first, baseInstance);
-	m_impl->pushBackNewCommand<DrawArraysCommand>(convertPrimitiveTopology(topology), info);
+	self.pushBackNewCommand<DrawArraysCommand>(convertPrimitiveTopology(topology), info);
 }
 }
 
 
 void CommandBuffer::drawElementsIndirect(
 void CommandBuffer::drawElementsIndirect(
@@ -1047,9 +1070,9 @@ void CommandBuffer::drawElementsIndirect(
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			const BufferImpl& buff = *m_buff->m_impl;
+			const BufferImpl& buff = static_cast<const BufferImpl&>(*m_buff);
 
 
-			ANKI_ASSERT(m_offset + sizeof(DrawElementsIndirectInfo) * m_drawCount <= buff.m_size);
+			ANKI_ASSERT(m_offset + sizeof(DrawElementsIndirectInfo) * m_drawCount <= buff.getSize());
 
 
 			glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buff.getGlName());
 			glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buff.getGlName());
 
 
@@ -1061,10 +1084,12 @@ void CommandBuffer::drawElementsIndirect(
 		}
 		}
 	};
 	};
 
 
-	m_impl->m_state.checkIndexedDracall();
-	m_impl->flushDrawcall(*this);
-	m_impl->pushBackNewCommand<DrawElementsIndirectCommand>(
-		convertPrimitiveTopology(topology), m_impl->m_state.m_idx.m_indexType, drawCount, offset, indirectBuff);
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	self.m_state.checkIndexedDracall();
+	self.flushDrawcall(*this);
+	self.pushBackNewCommand<DrawElementsIndirectCommand>(
+		convertPrimitiveTopology(topology), self.m_state.m_idx.m_indexType, drawCount, offset, indirectBuff);
 }
 }
 
 
 void CommandBuffer::drawArraysIndirect(
 void CommandBuffer::drawArraysIndirect(
@@ -1090,9 +1115,9 @@ void CommandBuffer::drawArraysIndirect(
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			const BufferImpl& buff = *m_buff->m_impl;
+			const BufferImpl& buff = static_cast<const BufferImpl&>(*m_buff);
 
 
-			ANKI_ASSERT(m_offset + sizeof(DrawArraysIndirectInfo) * m_drawCount <= buff.m_size);
+			ANKI_ASSERT(m_offset + sizeof(DrawArraysIndirectInfo) * m_drawCount <= buff.getSize());
 
 
 			glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buff.getGlName());
 			glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buff.getGlName());
 
 
@@ -1104,9 +1129,10 @@ void CommandBuffer::drawArraysIndirect(
 		}
 		}
 	};
 	};
 
 
-	m_impl->m_state.checkNonIndexedDrawcall();
-	m_impl->flushDrawcall(*this);
-	m_impl->pushBackNewCommand<DrawArraysIndirectCommand>(
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.m_state.checkNonIndexedDrawcall();
+	self.flushDrawcall(*this);
+	self.pushBackNewCommand<DrawArraysIndirectCommand>(
 		convertPrimitiveTopology(topology), drawCount, offset, indirectBuff);
 		convertPrimitiveTopology(topology), drawCount, offset, indirectBuff);
 }
 }
 
 
@@ -1129,9 +1155,11 @@ void CommandBuffer::dispatchCompute(U32 groupCountX, U32 groupCountY, U32 groupC
 		}
 		}
 	};
 	};
 
 
-	ANKI_ASSERT(!!(m_impl->m_flags & CommandBufferFlag::COMPUTE_WORK));
-	m_impl->m_state.checkDispatch();
-	m_impl->pushBackNewCommand<DispatchCommand>(groupCountX, groupCountY, groupCountZ);
+	ANKI_GL_SELF(CommandBufferImpl);
+
+	ANKI_ASSERT(!!(self.m_flags & CommandBufferFlag::COMPUTE_WORK));
+	self.m_state.checkDispatch();
+	self.pushBackNewCommand<DispatchCommand>(groupCountX, groupCountY, groupCountZ);
 }
 }
 
 
 void CommandBuffer::resetOcclusionQuery(OcclusionQueryPtr query)
 void CommandBuffer::resetOcclusionQuery(OcclusionQueryPtr query)
@@ -1153,12 +1181,13 @@ void CommandBuffer::beginOcclusionQuery(OcclusionQueryPtr query)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_handle->m_impl->begin();
+			static_cast<OcclusionQueryImpl&>(*m_handle).begin();
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	m_impl->pushBackNewCommand<OqBeginCommand>(query);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.pushBackNewCommand<OqBeginCommand>(query);
 }
 }
 
 
 void CommandBuffer::endOcclusionQuery(OcclusionQueryPtr query)
 void CommandBuffer::endOcclusionQuery(OcclusionQueryPtr query)
@@ -1175,12 +1204,13 @@ void CommandBuffer::endOcclusionQuery(OcclusionQueryPtr query)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_handle->m_impl->end();
+			static_cast<OcclusionQueryImpl&>(*m_handle).end();
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	m_impl->pushBackNewCommand<OqEndCommand>(query);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.pushBackNewCommand<OqEndCommand>(query);
 }
 }
 
 
 void CommandBuffer::copyBufferToTextureSurface(
 void CommandBuffer::copyBufferToTextureSurface(
@@ -1207,7 +1237,8 @@ void CommandBuffer::copyBufferToTextureSurface(
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			m_tex->m_impl->writeSurface(m_surf, m_buff->m_impl->getGlName(), m_offset, m_range);
+			static_cast<TextureImpl&>(*m_tex).writeSurface(
+				m_surf, static_cast<const BufferImpl&>(*m_buff).getGlName(), m_offset, m_range);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
@@ -1215,9 +1246,10 @@ void CommandBuffer::copyBufferToTextureSurface(
 	ANKI_ASSERT(tex);
 	ANKI_ASSERT(tex);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(range > 0);
 	ANKI_ASSERT(range > 0);
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
 
 
-	m_impl->pushBackNewCommand<TexSurfUploadCommand>(buff, offset, range, tex, surf);
+	self.pushBackNewCommand<TexSurfUploadCommand>(buff, offset, range, tex, surf);
 }
 }
 
 
 void CommandBuffer::copyBufferToTextureVolume(
 void CommandBuffer::copyBufferToTextureVolume(
@@ -1243,7 +1275,8 @@ void CommandBuffer::copyBufferToTextureVolume(
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			m_tex->m_impl->writeVolume(m_vol, m_buff->m_impl->getGlName(), m_offset, m_range);
+			static_cast<const TextureImpl&>(*m_tex).writeVolume(
+				m_vol, static_cast<const BufferImpl&>(*m_buff).getGlName(), m_offset, m_range);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
@@ -1251,9 +1284,10 @@ void CommandBuffer::copyBufferToTextureVolume(
 	ANKI_ASSERT(tex);
 	ANKI_ASSERT(tex);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(range > 0);
 	ANKI_ASSERT(range > 0);
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
 
 
-	m_impl->pushBackNewCommand<TexVolUploadCommand>(buff, offset, range, tex, vol);
+	self.pushBackNewCommand<TexVolUploadCommand>(buff, offset, range, tex, vol);
 }
 }
 
 
 void CommandBuffer::copyBufferToBuffer(
 void CommandBuffer::copyBufferToBuffer(
@@ -1279,7 +1313,8 @@ void CommandBuffer::copyBufferToBuffer(
 
 
 		Error operator()(GlState& state)
 		Error operator()(GlState& state)
 		{
 		{
-			m_dst->m_impl->write(m_src->m_impl->getGlName(), m_srcOffset, m_dstOffset, m_range);
+			static_cast<BufferImpl&>(*m_dst).write(
+				static_cast<const BufferImpl&>(*m_src).getGlName(), m_srcOffset, m_dstOffset, m_range);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
@@ -1287,9 +1322,10 @@ void CommandBuffer::copyBufferToBuffer(
 	ANKI_ASSERT(src);
 	ANKI_ASSERT(src);
 	ANKI_ASSERT(dst);
 	ANKI_ASSERT(dst);
 	ANKI_ASSERT(range > 0);
 	ANKI_ASSERT(range > 0);
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
 
 
-	m_impl->pushBackNewCommand<Cmd>(src, srcOffset, dst, dstOffset, range);
+	self.pushBackNewCommand<Cmd>(src, srcOffset, dst, dstOffset, range);
 }
 }
 
 
 void CommandBuffer::generateMipmaps2d(TexturePtr tex, U face, U layer)
 void CommandBuffer::generateMipmaps2d(TexturePtr tex, U face, U layer)
@@ -1310,13 +1346,14 @@ void CommandBuffer::generateMipmaps2d(TexturePtr tex, U face, U layer)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_tex->m_impl->generateMipmaps2d(m_face, m_layer);
+			static_cast<TextureImpl&>(*m_tex).generateMipmaps2d(m_face, m_layer);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
-	m_impl->pushBackNewCommand<GenMipsCommand>(tex, face, layer);
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
+	self.pushBackNewCommand<GenMipsCommand>(tex, face, layer);
 }
 }
 
 
 void CommandBuffer::generateMipmaps3d(TexturePtr tex)
 void CommandBuffer::generateMipmaps3d(TexturePtr tex)
@@ -1326,7 +1363,8 @@ void CommandBuffer::generateMipmaps3d(TexturePtr tex)
 
 
 CommandBufferInitHints CommandBuffer::computeInitHints() const
 CommandBufferInitHints CommandBuffer::computeInitHints() const
 {
 {
-	return m_impl->computeInitHints();
+	ANKI_GL_SELF_CONST(CommandBufferImpl);
+	return self.computeInitHints();
 }
 }
 
 
 void CommandBuffer::pushSecondLevelCommandBuffer(CommandBufferPtr cmdb)
 void CommandBuffer::pushSecondLevelCommandBuffer(CommandBufferPtr cmdb)
@@ -1343,20 +1381,20 @@ void CommandBuffer::pushSecondLevelCommandBuffer(CommandBufferPtr cmdb)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			ANKI_TRACE_START_EVENT(GL_2ND_LEVEL_CMD_BUFFER);
-			Error err = m_cmdb->m_impl->executeAllCommands();
-			ANKI_TRACE_STOP_EVENT(GL_2ND_LEVEL_CMD_BUFFER);
-			return err;
+			ANKI_TRACE_SCOPED_EVENT(GL_2ND_LEVEL_CMD_BUFFER);
+			return static_cast<CommandBufferImpl&>(*m_cmdb).executeAllCommands();
 		}
 		}
 	};
 	};
 
 
-	m_impl->m_state.m_lastSecondLevelCmdb = cmdb->m_impl.get();
-	m_impl->pushBackNewCommand<ExecCmdbCommand>(cmdb);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.m_state.m_lastSecondLevelCmdb = static_cast<CommandBufferImpl*>(cmdb.get());
+	self.pushBackNewCommand<ExecCmdbCommand>(cmdb);
 }
 }
 
 
 Bool CommandBuffer::isEmpty() const
 Bool CommandBuffer::isEmpty() const
 {
 {
-	return m_impl->isEmpty();
+	ANKI_GL_SELF_CONST(CommandBufferImpl);
+	return self.isEmpty();
 }
 }
 
 
 void CommandBuffer::copyTextureSurfaceToTextureSurface(
 void CommandBuffer::copyTextureSurfaceToTextureSurface(
@@ -1381,13 +1419,17 @@ void CommandBuffer::copyTextureSurfaceToTextureSurface(
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			TextureImpl::copy(*m_src->m_impl, m_srcSurf, *m_dest->m_impl, m_destSurf);
+			TextureImpl::copy(static_cast<const TextureImpl&>(*m_src),
+				m_srcSurf,
+				static_cast<const TextureImpl&>(*m_dest),
+				m_destSurf);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
-	m_impl->pushBackNewCommand<CopyTexCommand>(src, srcSurf, dest, destSurf);
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
+	self.pushBackNewCommand<CopyTexCommand>(src, srcSurf, dest, destSurf);
 }
 }
 
 
 void CommandBuffer::setBufferBarrier(
 void CommandBuffer::setBufferBarrier(
@@ -1450,7 +1492,8 @@ void CommandBuffer::setBufferBarrier(
 	}
 	}
 
 
 	ANKI_ASSERT(d);
 	ANKI_ASSERT(d);
-	m_impl->pushBackNewCommand<SetBufferMemBarrierCommand>(d);
+	ANKI_GL_SELF(CommandBufferImpl);
+	self.pushBackNewCommand<SetBufferMemBarrierCommand>(d);
 }
 }
 
 
 void CommandBuffer::setTextureSurfaceBarrier(
 void CommandBuffer::setTextureSurfaceBarrier(
@@ -1487,13 +1530,14 @@ void CommandBuffer::clearTextureSurface(
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_tex->m_impl->clear(m_surf, m_val, m_aspect);
+			static_cast<TextureImpl&>(*m_tex).clear(m_surf, m_val, m_aspect);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
-	m_impl->pushBackNewCommand<ClearTextCommand>(tex, surf, clearValue, aspect);
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
+	self.pushBackNewCommand<ClearTextCommand>(tex, surf, clearValue, aspect);
 }
 }
 
 
 void CommandBuffer::fillBuffer(BufferPtr buff, PtrSize offset, PtrSize size, U32 value)
 void CommandBuffer::fillBuffer(BufferPtr buff, PtrSize offset, PtrSize size, U32 value)
@@ -1516,13 +1560,14 @@ void CommandBuffer::fillBuffer(BufferPtr buff, PtrSize offset, PtrSize size, U32
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			m_buff->m_impl->fill(m_offset, m_size, m_value);
+			static_cast<BufferImpl&>(*m_buff).fill(m_offset, m_size, m_value);
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
-	m_impl->pushBackNewCommand<FillBufferCommand>(buff, offset, size, value);
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
+	self.pushBackNewCommand<FillBufferCommand>(buff, offset, size, value);
 }
 }
 
 
 void CommandBuffer::writeOcclusionQueryResultToBuffer(OcclusionQueryPtr query, PtrSize offset, BufferPtr buff)
 void CommandBuffer::writeOcclusionQueryResultToBuffer(OcclusionQueryPtr query, PtrSize offset, BufferPtr buff)
@@ -1544,19 +1589,22 @@ void CommandBuffer::writeOcclusionQueryResultToBuffer(OcclusionQueryPtr query, P
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			const BufferImpl& buff = *m_buff->m_impl;
-			ANKI_ASSERT(m_offset + 4 <= buff.m_size);
+			const BufferImpl& buff = static_cast<const BufferImpl&>(*m_buff);
+			ANKI_ASSERT(m_offset + 4 <= buff.getSize());
 
 
 			glBindBuffer(GL_QUERY_BUFFER, buff.getGlName());
 			glBindBuffer(GL_QUERY_BUFFER, buff.getGlName());
-			glGetQueryObjectuiv(m_query->m_impl->getGlName(), GL_QUERY_RESULT, numberToPtr<GLuint*>(m_offset));
+			glGetQueryObjectuiv(static_cast<const OcclusionQueryImpl&>(*m_query).getGlName(),
+				GL_QUERY_RESULT,
+				numberToPtr<GLuint*>(m_offset));
 			glBindBuffer(GL_QUERY_BUFFER, 0);
 			glBindBuffer(GL_QUERY_BUFFER, 0);
 
 
 			return Error::NONE;
 			return Error::NONE;
 		}
 		}
 	};
 	};
 
 
-	ANKI_ASSERT(!m_impl->m_state.insideRenderPass());
-	m_impl->pushBackNewCommand<WriteOcclResultToBuff>(query, offset, buff);
+	ANKI_GL_SELF(CommandBufferImpl);
+	ANKI_ASSERT(!self.m_state.insideRenderPass());
+	self.pushBackNewCommand<WriteOcclResultToBuff>(query, offset, buff);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 12 - 7
src/anki/gr/gl/CommandBufferImpl.cpp

@@ -23,12 +23,22 @@ namespace anki
 
 
 void CommandBufferImpl::init(const CommandBufferInitInfo& init)
 void CommandBufferImpl::init(const CommandBufferInitInfo& init)
 {
 {
-	auto& pool = m_manager->getAllocator().getMemoryPool();
+	auto& pool = getManager().getAllocator().getMemoryPool();
 
 
 	m_alloc = CommandBufferAllocator<GlCommand*>(
 	m_alloc = CommandBufferAllocator<GlCommand*>(
 		pool.getAllocationCallback(), pool.getAllocationCallbackUserData(), init.m_hints.m_chunkSize, 1.0, 0, false);
 		pool.getAllocationCallback(), pool.getAllocationCallbackUserData(), init.m_hints.m_chunkSize, 1.0, 0, false);
 
 
 	m_flags = init.m_flags;
 	m_flags = init.m_flags;
+
+#if ANKI_EXTRA_CHECKS
+	m_state.m_secondLevel = !!(init.m_flags & CommandBufferFlag::SECOND_LEVEL);
+#endif
+
+	if(!!(init.m_flags & CommandBufferFlag::SECOND_LEVEL))
+	{
+		// TODO Need to hold a ref
+		m_state.m_fb = static_cast<const FramebufferImpl*>(init.m_framebuffer.get());
+	}
 }
 }
 
 
 void CommandBufferImpl::destroy()
 void CommandBufferImpl::destroy()
@@ -67,7 +77,7 @@ Error CommandBufferImpl::executeAllCommands()
 #endif
 #endif
 
 
 	Error err = Error::NONE;
 	Error err = Error::NONE;
-	GlState& state = m_manager->getImplementation().getState();
+	GlState& state = static_cast<GrManagerImpl&>(getManager()).getState();
 
 
 	GlCommand* command = m_firstCommand;
 	GlCommand* command = m_firstCommand;
 
 
@@ -90,11 +100,6 @@ CommandBufferImpl::InitHints CommandBufferImpl::computeInitHints() const
 	return out;
 	return out;
 }
 }
 
 
-GrAllocator<U8> CommandBufferImpl::getAllocator() const
-{
-	return m_manager->getAllocator();
-}
-
 void CommandBufferImpl::flushDrawcall(CommandBuffer& cmdb)
 void CommandBufferImpl::flushDrawcall(CommandBuffer& cmdb)
 {
 {
 	ANKI_ASSERT(!!(m_flags & CommandBufferFlag::GRAPHICS_WORK));
 	ANKI_ASSERT(!!(m_flags & CommandBufferFlag::GRAPHICS_WORK));

+ 2 - 11
src/anki/gr/gl/CommandBufferImpl.h

@@ -37,12 +37,11 @@ public:
 };
 };
 
 
 /// A number of GL commands organized in a chain
 /// A number of GL commands organized in a chain
-class CommandBufferImpl
+class CommandBufferImpl final : public CommandBuffer
 {
 {
 public:
 public:
 	using InitHints = CommandBufferInitHints;
 	using InitHints = CommandBufferInitHints;
 
 
-	GrManager* m_manager = nullptr;
 	GlCommand* m_firstCommand = nullptr;
 	GlCommand* m_firstCommand = nullptr;
 	GlCommand* m_lastCommand = nullptr;
 	GlCommand* m_lastCommand = nullptr;
 	CommandBufferAllocator<U8> m_alloc;
 	CommandBufferAllocator<U8> m_alloc;
@@ -57,7 +56,7 @@ public:
 
 
 	/// Default constructor
 	/// Default constructor
 	CommandBufferImpl(GrManager* manager)
 	CommandBufferImpl(GrManager* manager)
-		: m_manager(manager)
+		: CommandBuffer(manager)
 	{
 	{
 	}
 	}
 
 
@@ -75,9 +74,6 @@ public:
 		return m_alloc;
 		return m_alloc;
 	}
 	}
 
 
-	/// For the UniquePtr destructor.
-	GrAllocator<U8> getAllocator() const;
-
 	/// Compute initialization hints.
 	/// Compute initialization hints.
 	InitHints computeInitHints() const;
 	InitHints computeInitHints() const;
 
 
@@ -102,11 +98,6 @@ public:
 		m_immutable = true;
 		m_immutable = true;
 	}
 	}
 
 
-	GrManager& getManager()
-	{
-		return *m_manager;
-	}
-
 	Bool isEmpty() const
 	Bool isEmpty() const
 	{
 	{
 		return m_firstCommand == nullptr;
 		return m_firstCommand == nullptr;

+ 3 - 0
src/anki/gr/gl/Common.h

@@ -36,6 +36,9 @@ class RenderingThread;
 #define ANKI_GL_LOGW(...) ANKI_LOG("GL  ", WARNING, __VA_ARGS__)
 #define ANKI_GL_LOGW(...) ANKI_LOG("GL  ", WARNING, __VA_ARGS__)
 #define ANKI_GL_LOGF(...) ANKI_LOG("GL  ", FATAL, __VA_ARGS__)
 #define ANKI_GL_LOGF(...) ANKI_LOG("GL  ", FATAL, __VA_ARGS__)
 
 
+#define ANKI_GL_SELF(class_) class_& self = *static_cast<class_*>(this)
+#define ANKI_GL_SELF_CONST(class_) const class_& self = *static_cast<const class_*>(this)
+
 enum class GlExtensions : U16
 enum class GlExtensions : U16
 {
 {
 	NONE = 0,
 	NONE = 0,

+ 18 - 24
src/anki/gr/gl/Fence.cpp

@@ -13,18 +13,9 @@
 namespace anki
 namespace anki
 {
 {
 
 
-Fence::Fence(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
+Bool Fence::clientWait(Second seconds)
 {
 {
-}
-
-Fence::~Fence()
-{
-}
-
-Bool Fence::clientWait(F64 seconds)
-{
-	if(m_impl->m_signaled.load())
+	if(static_cast<FenceImpl&>(*this).m_signaled.load())
 	{
 	{
 		return true;
 		return true;
 	}
 	}
@@ -33,11 +24,11 @@ Bool Fence::clientWait(F64 seconds)
 	{
 	{
 	public:
 	public:
 		FencePtr m_fence;
 		FencePtr m_fence;
-		F64 m_timeout;
-		F64 m_flushTime;
+		Second m_timeout;
+		Second m_flushTime;
 		Barrier* m_barrier;
 		Barrier* m_barrier;
 
 
-		CheckFenceCommand(FencePtr fence, F64 timeout, F64 flushTime, Barrier* barrier)
+		CheckFenceCommand(FencePtr fence, Second timeout, Second flushTime, Barrier* barrier)
 			: m_fence(fence)
 			: m_fence(fence)
 			, m_timeout(timeout)
 			, m_timeout(timeout)
 			, m_flushTime(flushTime)
 			, m_flushTime(flushTime)
@@ -49,7 +40,7 @@ Bool Fence::clientWait(F64 seconds)
 		{
 		{
 			// Since there is a delay between flushing the cmdb and returning this result try to adjust the time we
 			// Since there is a delay between flushing the cmdb and returning this result try to adjust the time we
 			// wait
 			// wait
-			F64 timeToWait;
+			Second timeToWait;
 			if(m_timeout != 0.0)
 			if(m_timeout != 0.0)
 			{
 			{
 				timeToWait = m_timeout - (HighRezTimer::getCurrentTime() - m_flushTime);
 				timeToWait = m_timeout - (HighRezTimer::getCurrentTime() - m_flushTime);
@@ -60,11 +51,12 @@ Bool Fence::clientWait(F64 seconds)
 				timeToWait = 0.0;
 				timeToWait = 0.0;
 			}
 			}
 
 
-			GLenum out = glClientWaitSync(m_fence->m_impl->m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, timeToWait * 1e+9);
+			FenceImpl& impl = static_cast<FenceImpl&>(*m_fence);
+			GLenum out = glClientWaitSync(impl.m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, timeToWait * 1e+9);
 
 
 			if(out == GL_ALREADY_SIGNALED || out == GL_CONDITION_SATISFIED)
 			if(out == GL_ALREADY_SIGNALED || out == GL_CONDITION_SATISFIED)
 			{
 			{
-				m_fence->m_impl->m_signaled.store(true);
+				impl.m_signaled.store(true);
 			}
 			}
 			else if(out == GL_TIMEOUT_EXPIRED)
 			else if(out == GL_TIMEOUT_EXPIRED)
 			{
 			{
@@ -85,14 +77,15 @@ Bool Fence::clientWait(F64 seconds)
 		}
 		}
 	};
 	};
 
 
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
+	CommandBufferPtr cmdb = getManager().newCommandBuffer(CommandBufferInitInfo());
 
 
 	if(seconds == 0.0)
 	if(seconds == 0.0)
 	{
 	{
 		// Send a cmd that will update the fence's status in case someone calls clientWait with seconds==0.0 all the
 		// Send a cmd that will update the fence's status in case someone calls clientWait with seconds==0.0 all the
 		// time
 		// time
-		cmdb->m_impl->pushBackNewCommand<CheckFenceCommand>(FencePtr(this), seconds, 0.0, nullptr);
-		cmdb->flush();
+		static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CheckFenceCommand>(
+			FencePtr(this), seconds, 0.0, nullptr);
+		static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
 		return false;
 		return false;
 	}
 	}
@@ -100,14 +93,15 @@ Bool Fence::clientWait(F64 seconds)
 	{
 	{
 		Barrier barrier(2);
 		Barrier barrier(2);
 
 
-		F64 flushTime = HighRezTimer::getCurrentTime();
+		Second flushTime = HighRezTimer::getCurrentTime();
 
 
-		cmdb->m_impl->pushBackNewCommand<CheckFenceCommand>(FencePtr(this), seconds, flushTime, &barrier);
-		cmdb->flush();
+		static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CheckFenceCommand>(
+			FencePtr(this), seconds, flushTime, &barrier);
+		static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
 		barrier.wait();
 		barrier.wait();
 
 
-		return m_impl->m_signaled.load();
+		return static_cast<FenceImpl&>(*this).m_signaled.load();
 	}
 	}
 }
 }
 
 

+ 5 - 5
src/anki/gr/gl/FenceImpl.cpp

@@ -34,16 +34,16 @@ FenceImpl::~FenceImpl()
 
 
 	if(m_fence)
 	if(m_fence)
 	{
 	{
-		GrManager& manager = getManager();
-		RenderingThread& thread = manager.getImplementation().getRenderingThread();
+		GrManagerImpl& manager = static_cast<GrManagerImpl&>(getManager());
+		RenderingThread& thread = manager.getRenderingThread();
 
 
 		if(!thread.isServerThread())
 		if(!thread.isServerThread())
 		{
 		{
 			CommandBufferPtr commands;
 			CommandBufferPtr commands;
 
 
-			commands = manager.newInstance<CommandBuffer>(CommandBufferInitInfo());
-			commands->m_impl->pushBackNewCommand<DeleteFenceCommand>(m_fence);
-			commands->flush();
+			commands = manager.newCommandBuffer(CommandBufferInitInfo());
+			static_cast<CommandBufferImpl&>(*commands).pushBackNewCommand<DeleteFenceCommand>(m_fence);
+			static_cast<CommandBufferImpl&>(*commands).flush();
 		}
 		}
 		else
 		else
 		{
 		{

+ 3 - 2
src/anki/gr/gl/FenceImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/Fence.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/gl/GlObject.h>
 
 
 namespace anki
 namespace anki
@@ -14,14 +15,14 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Fence implementation.
 /// Fence implementation.
-class FenceImpl : public GlObject
+class FenceImpl final : public Fence, public GlObject
 {
 {
 public:
 public:
 	GLsync m_fence = nullptr;
 	GLsync m_fence = nullptr;
 	Atomic<Bool> m_signaled = {false};
 	Atomic<Bool> m_signaled = {false};
 
 
 	FenceImpl(GrManager* gr)
 	FenceImpl(GrManager* gr)
-		: GlObject(gr)
+		: Fence(gr)
 	{
 	{
 	}
 	}
 
 

+ 7 - 15
src/anki/gr/gl/Framebuffer.cpp

@@ -11,16 +11,7 @@
 namespace anki
 namespace anki
 {
 {
 
 
-Framebuffer::Framebuffer(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
-{
-}
-
-Framebuffer::~Framebuffer()
-{
-}
-
-void Framebuffer::init(const FramebufferInitInfo& init)
+Framebuffer* Framebuffer::newInstance(GrManager* manager, const FramebufferInitInfo& init)
 {
 {
 	class CreateFramebufferCommand final : public GlCommand
 	class CreateFramebufferCommand final : public GlCommand
 	{
 	{
@@ -36,7 +27,7 @@ void Framebuffer::init(const FramebufferInitInfo& init)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			FramebufferImpl& impl = *m_fb->m_impl;
+			FramebufferImpl& impl = static_cast<FramebufferImpl&>(*m_fb);
 			Error err = impl.init(m_init);
 			Error err = impl.init(m_init);
 
 
 			GlObject::State oldState =
 			GlObject::State oldState =
@@ -48,12 +39,13 @@ void Framebuffer::init(const FramebufferInitInfo& init)
 		}
 		}
 	};
 	};
 
 
-	m_impl.reset(getAllocator().newInstance<FramebufferImpl>(&getManager()));
+	FramebufferImpl* impl = manager->getAllocator().newInstance<FramebufferImpl>(manager);
 
 
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateFramebufferCommand>(impl, init);
+	static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
-	cmdb->m_impl->pushBackNewCommand<CreateFramebufferCommand>(this, init);
-	cmdb->flush();
+	return impl;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 16 - 16
src/anki/gr/gl/FramebufferImpl.cpp

@@ -40,7 +40,7 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 		const FramebufferAttachmentInfo& att = m_in.m_colorAttachments[i];
 		const FramebufferAttachmentInfo& att = m_in.m_colorAttachments[i];
 		const GLenum binding = GL_COLOR_ATTACHMENT0 + i;
 		const GLenum binding = GL_COLOR_ATTACHMENT0 + i;
 
 
-		attachTextureInternal(binding, *att.m_texture->m_impl, att);
+		attachTextureInternal(binding, static_cast<const TextureImpl&>(*att.m_texture), att);
 
 
 		m_drawBuffers[i] = binding;
 		m_drawBuffers[i] = binding;
 
 
@@ -51,13 +51,13 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 
 
 		if(m_fbSize[0] == 0)
 		if(m_fbSize[0] == 0)
 		{
 		{
-			m_fbSize[0] = att.m_texture->m_impl->m_width;
-			m_fbSize[1] = att.m_texture->m_impl->m_height;
+			m_fbSize[0] = att.m_texture->getWidth();
+			m_fbSize[1] = att.m_texture->getHeight();
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_ASSERT(m_fbSize[0] == att.m_texture->m_impl->m_width);
-			ANKI_ASSERT(m_fbSize[1] == att.m_texture->m_impl->m_height);
+			ANKI_ASSERT(m_fbSize[0] == att.m_texture->getWidth());
+			ANKI_ASSERT(m_fbSize[1] == att.m_texture->getHeight());
 		}
 		}
 	}
 	}
 
 
@@ -65,22 +65,22 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 	if(m_in.m_depthStencilAttachment.m_texture.isCreated())
 	if(m_in.m_depthStencilAttachment.m_texture.isCreated())
 	{
 	{
 		const FramebufferAttachmentInfo& att = m_in.m_depthStencilAttachment;
 		const FramebufferAttachmentInfo& att = m_in.m_depthStencilAttachment;
-		const TextureImpl& tex = *att.m_texture->m_impl;
+		const TextureImpl& tex = static_cast<const TextureImpl&>(*att.m_texture);
 
 
 		GLenum binding;
 		GLenum binding;
-		if(tex.m_format == GL_DEPTH_COMPONENT)
+		if(tex.m_glFormat == GL_DEPTH_COMPONENT)
 		{
 		{
 			binding = GL_DEPTH_ATTACHMENT;
 			binding = GL_DEPTH_ATTACHMENT;
 			m_dsAspect = DepthStencilAspectBit::DEPTH;
 			m_dsAspect = DepthStencilAspectBit::DEPTH;
 		}
 		}
-		else if(tex.m_format == GL_STENCIL_INDEX)
+		else if(tex.m_glFormat == GL_STENCIL_INDEX)
 		{
 		{
 			binding = GL_STENCIL_ATTACHMENT;
 			binding = GL_STENCIL_ATTACHMENT;
 			m_dsAspect = DepthStencilAspectBit::STENCIL;
 			m_dsAspect = DepthStencilAspectBit::STENCIL;
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_ASSERT(tex.m_format == GL_DEPTH_STENCIL);
+			ANKI_ASSERT(tex.m_glFormat == GL_DEPTH_STENCIL);
 
 
 			if(att.m_aspect == DepthStencilAspectBit::DEPTH)
 			if(att.m_aspect == DepthStencilAspectBit::DEPTH)
 			{
 			{
@@ -112,13 +112,13 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 
 
 		if(m_fbSize[0] == 0)
 		if(m_fbSize[0] == 0)
 		{
 		{
-			m_fbSize[0] = att.m_texture->m_impl->m_width;
-			m_fbSize[1] = att.m_texture->m_impl->m_height;
+			m_fbSize[0] = att.m_texture->getWidth();
+			m_fbSize[1] = att.m_texture->getHeight();
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_ASSERT(m_fbSize[0] == att.m_texture->m_impl->m_width);
-			ANKI_ASSERT(m_fbSize[1] == att.m_texture->m_impl->m_height);
+			ANKI_ASSERT(m_fbSize[0] == att.m_texture->getWidth());
+			ANKI_ASSERT(m_fbSize[1] == att.m_texture->getHeight());
 		}
 		}
 	}
 	}
 
 
@@ -174,11 +174,11 @@ void FramebufferImpl::attachTextureInternal(
 	}
 	}
 }
 }
 
 
-void FramebufferImpl::bind(const GlState& state, U32 minx, U32 miny, U32 width, U32 height)
+void FramebufferImpl::bind(const GlState& state, U32 minx, U32 miny, U32 width, U32 height) const
 {
 {
 	ANKI_ASSERT(width > 0 && height > 0);
 	ANKI_ASSERT(width > 0 && height > 0);
 
 
-	if(m_in.getName() && getManager().getImplementation().debugMarkersEnabled())
+	if(m_in.getName() && static_cast<const GrManagerImpl&>(getManager()).debugMarkersEnabled())
 	{
 	{
 		glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, m_glName, 0, &m_in.getName()[0]);
 		glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, m_glName, 0, &m_in.getName()[0]);
 	}
 	}
@@ -302,7 +302,7 @@ void FramebufferImpl::bind(const GlState& state, U32 minx, U32 miny, U32 width,
 
 
 void FramebufferImpl::endRenderPass() const
 void FramebufferImpl::endRenderPass() const
 {
 {
-	if(m_in.getName() && getManager().getImplementation().debugMarkersEnabled())
+	if(m_in.getName() && static_cast<const GrManagerImpl&>(getManager()).debugMarkersEnabled())
 	{
 	{
 		glPopDebugGroup();
 		glPopDebugGroup();
 	}
 	}

+ 5 - 5
src/anki/gr/gl/FramebufferImpl.h

@@ -5,8 +5,8 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <anki/gr/gl/GlObject.h>
 #include <anki/gr/Framebuffer.h>
 #include <anki/gr/Framebuffer.h>
+#include <anki/gr/gl/GlObject.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -15,17 +15,17 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Framebuffer implementation.
 /// Framebuffer implementation.
-class FramebufferImpl : public GlObject
+class FramebufferImpl final : public Framebuffer, public GlObject
 {
 {
 public:
 public:
 	FramebufferImpl(GrManager* manager)
 	FramebufferImpl(GrManager* manager)
-		: GlObject(manager)
+		: Framebuffer(manager)
 	{
 	{
 	}
 	}
 
 
 	~FramebufferImpl()
 	~FramebufferImpl()
 	{
 	{
-		destroyDeferred(glDeleteFramebuffers);
+		destroyDeferred(getManager(), glDeleteFramebuffers);
 	}
 	}
 
 
 	/// Set all the attachments. It will overwrite the previous state. If the initalizer list is empty the it will bind
 	/// Set all the attachments. It will overwrite the previous state. If the initalizer list is empty the it will bind
@@ -33,7 +33,7 @@ public:
 	ANKI_USE_RESULT Error init(const FramebufferInitInfo& init);
 	ANKI_USE_RESULT Error init(const FramebufferInitInfo& init);
 
 
 	/// Bind it to the state. Call it in rendering thread
 	/// Bind it to the state. Call it in rendering thread
-	void bind(const GlState& state, U32 minx, U32 miny, U32 width, U32 height);
+	void bind(const GlState& state, U32 minx, U32 miny, U32 width, U32 height) const;
 
 
 	void endRenderPass() const;
 	void endRenderPass() const;
 
 

+ 25 - 32
src/anki/gr/gl/GlObject.cpp

@@ -13,14 +13,13 @@
 namespace anki
 namespace anki
 {
 {
 
 
-GlObject::GlObject(GrManager* manager)
-	: m_manager(manager)
-	, m_glName(0)
+GlObject::GlObject()
+	: m_glName(0)
 	, m_state(I32(State::TO_BE_CREATED))
 	, m_state(I32(State::TO_BE_CREATED))
 {
 {
 }
 }
 
 
-Error GlObject::serializeRenderingThread()
+Error GlObject::serializeRenderingThread(GrManager& manager)
 {
 {
 	Error err = Error::NONE;
 	Error err = Error::NONE;
 	State state = State(m_state.load());
 	State state = State(m_state.load());
@@ -28,7 +27,7 @@ Error GlObject::serializeRenderingThread()
 
 
 	if(state == State::TO_BE_CREATED)
 	if(state == State::TO_BE_CREATED)
 	{
 	{
-		RenderingThread& thread = m_manager->getImplementation().getRenderingThread();
+		RenderingThread& thread = static_cast<GrManagerImpl&>(manager).getRenderingThread();
 		thread.syncClientServer();
 		thread.syncClientServer();
 
 
 		state = State(m_state.load());
 		state = State(m_state.load());
@@ -44,42 +43,41 @@ Error GlObject::serializeRenderingThread()
 	return err;
 	return err;
 }
 }
 
 
-class DeleteGlObjectCommand final : public GlCommand
+void GlObject::destroyDeferred(GrManager& manager, GlDeleteFunction deleteCallback)
 {
 {
-public:
-	GlObject::GlDeleteFunction m_callback;
-	GLuint m_glName;
-
-	DeleteGlObjectCommand(GlObject::GlDeleteFunction callback, GLuint name)
-		: m_callback(callback)
-		, m_glName(name)
+	class DeleteGlObjectCommand final : public GlCommand
 	{
 	{
-	}
+	public:
+		GlObject::GlDeleteFunction m_callback;
+		GLuint m_glName;
 
 
-	Error operator()(GlState&)
-	{
-		m_callback(1, &m_glName);
-		return Error::NONE;
-	}
-};
+		DeleteGlObjectCommand(GlObject::GlDeleteFunction callback, GLuint name)
+			: m_callback(callback)
+			, m_glName(name)
+		{
+		}
+
+		Error operator()(GlState&)
+		{
+			m_callback(1, &m_glName);
+			return Error::NONE;
+		}
+	};
 
 
-void GlObject::destroyDeferred(GlDeleteFunction deleteCallback)
-{
 	if(m_glName == 0)
 	if(m_glName == 0)
 	{
 	{
 		return;
 		return;
 	}
 	}
 
 
-	GrManager& manager = getManager();
-	RenderingThread& thread = manager.getImplementation().getRenderingThread();
+	RenderingThread& thread = static_cast<GrManagerImpl&>(manager).getRenderingThread();
 
 
 	if(!thread.isServerThread())
 	if(!thread.isServerThread())
 	{
 	{
 		CommandBufferPtr commands;
 		CommandBufferPtr commands;
 
 
-		commands = manager.newInstance<CommandBuffer>(CommandBufferInitInfo());
-		commands->m_impl->pushBackNewCommand<DeleteGlObjectCommand>(deleteCallback, m_glName);
-		commands->flush();
+		commands = manager.newCommandBuffer(CommandBufferInitInfo());
+		static_cast<CommandBufferImpl&>(*commands).pushBackNewCommand<DeleteGlObjectCommand>(deleteCallback, m_glName);
+		static_cast<CommandBufferImpl&>(*commands).flush();
 	}
 	}
 	else
 	else
 	{
 	{
@@ -89,9 +87,4 @@ void GlObject::destroyDeferred(GlDeleteFunction deleteCallback)
 	m_glName = 0;
 	m_glName = 0;
 }
 }
 
 
-GrAllocator<U8> GlObject::getAllocator() const
-{
-	return m_manager->getAllocator();
-}
-
 } // end namespace anki
 } // end namespace anki

+ 3 - 17
src/anki/gr/gl/GlObject.h

@@ -32,7 +32,7 @@ public:
 	using GlDeleteFunction = void (*)(GLsizei, const GLuint*);
 	using GlDeleteFunction = void (*)(GLsizei, const GLuint*);
 
 
 	/// Default
 	/// Default
-	GlObject(GrManager* manager);
+	GlObject();
 
 
 	~GlObject()
 	~GlObject()
 	{
 	{
@@ -59,26 +59,12 @@ public:
 	}
 	}
 
 
 	/// Check if the object has been created and if not serialize the thread.
 	/// Check if the object has been created and if not serialize the thread.
-	ANKI_USE_RESULT Error serializeRenderingThread();
+	ANKI_USE_RESULT Error serializeRenderingThread(GrManager& manager);
 
 
 	/// Should be called from GL objects for deferred deletion.
 	/// Should be called from GL objects for deferred deletion.
-	void destroyDeferred(GlDeleteFunction deleteCallback);
-
-	/// Get the allocator.
-	GrAllocator<U8> getAllocator() const;
-
-	GrManager& getManager()
-	{
-		return *m_manager;
-	}
-
-	const GrManager& getManager() const
-	{
-		return *m_manager;
-	}
+	void destroyDeferred(GrManager& manager, GlDeleteFunction deleteCallback);
 
 
 protected:
 protected:
-	GrManager* m_manager = nullptr;
 	GLuint m_glName = 0; ///< OpenGL name
 	GLuint m_glName = 0; ///< OpenGL name
 	mutable Atomic<I32> m_state;
 	mutable Atomic<I32> m_state;
 };
 };

+ 100 - 20
src/anki/gr/gl/GrManager.cpp

@@ -9,6 +9,17 @@
 #include <anki/gr/gl/TextureImpl.h>
 #include <anki/gr/gl/TextureImpl.h>
 #include <anki/gr/gl/GlState.h>
 #include <anki/gr/gl/GlState.h>
 #include <anki/core/Timestamp.h>
 #include <anki/core/Timestamp.h>
+
+#include <anki/gr/Buffer.h>
+#include <anki/gr/Texture.h>
+#include <anki/gr/Sampler.h>
+#include <anki/gr/Shader.h>
+#include <anki/gr/ShaderProgram.h>
+#include <anki/gr/CommandBuffer.h>
+#include <anki/gr/Framebuffer.h>
+#include <anki/gr/OcclusionQuery.h>
+#include <anki/gr/RenderGraph.h>
+
 #include <cstring>
 #include <cstring>
 
 
 namespace anki
 namespace anki
@@ -21,20 +32,36 @@ GrManager::GrManager()
 GrManager::~GrManager()
 GrManager::~GrManager()
 {
 {
 	// Destroy in reverse order
 	// Destroy in reverse order
-	m_impl.reset(nullptr);
 	m_cacheDir.destroy(m_alloc);
 	m_cacheDir.destroy(m_alloc);
 }
 }
 
 
-Error GrManager::init(GrManagerInitInfo& init)
+Error GrManager::newInstance(GrManagerInitInfo& init, GrManager*& gr)
 {
 {
-	m_alloc = HeapAllocator<U8>(init.m_allocCallback, init.m_allocCallbackUserData);
-
-	m_cacheDir.create(m_alloc, init.m_cacheDirectory);
+	auto alloc = GrAllocator<U8>(init.m_allocCallback, init.m_allocCallbackUserData);
+
+	GrManagerImpl* impl = alloc.newInstance<GrManagerImpl>();
+	Error err = impl->init(init, alloc);
+
+	if(err)
+	{
+		alloc.deleteInstance(impl);
+		gr = nullptr;
+	}
+	else
+	{
+		gr = impl;
+	}
+
+	return err;
+}
 
 
-	m_impl.reset(m_alloc.newInstance<GrManagerImpl>(this));
-	ANKI_CHECK(m_impl->init(init));
+void GrManager::deleteInstance(GrManager* gr)
+{
+	ANKI_ASSERT(gr);
 
 
-	return Error::NONE;
+	auto alloc = gr->m_alloc;
+	gr->~GrManager();
+	alloc.deallocate(gr, 1);
 }
 }
 
 
 void GrManager::beginFrame()
 void GrManager::beginFrame()
@@ -44,55 +71,108 @@ void GrManager::beginFrame()
 
 
 void GrManager::swapBuffers()
 void GrManager::swapBuffers()
 {
 {
-	m_impl->getRenderingThread().swapBuffers();
+	ANKI_GL_SELF(GrManagerImpl);
+	self.getRenderingThread().swapBuffers();
 }
 }
 
 
 void GrManager::finish()
 void GrManager::finish()
 {
 {
-	m_impl->getRenderingThread().syncClientServer();
+	ANKI_GL_SELF(GrManagerImpl);
+	self.getRenderingThread().syncClientServer();
+}
+
+BufferPtr GrManager::newBuffer(const BufferInitInfo& init)
+{
+	return BufferPtr(Buffer::newInstance(this, init));
+}
+
+TexturePtr GrManager::newTexture(const TextureInitInfo& init)
+{
+	return TexturePtr(Texture::newInstance(this, init));
+}
+
+SamplerPtr GrManager::newSampler(const SamplerInitInfo& init)
+{
+	return SamplerPtr(Sampler::newInstance(this, init));
+}
+
+ShaderPtr GrManager::newShader(const ShaderInitInfo& init)
+{
+	return ShaderPtr(Shader::newInstance(this, init));
+}
+
+ShaderProgramPtr GrManager::newShaderProgram(const ShaderProgramInitInfo& init)
+{
+	return ShaderProgramPtr(ShaderProgram::newInstance(this, init));
+}
+
+CommandBufferPtr GrManager::newCommandBuffer(const CommandBufferInitInfo& init)
+{
+	return CommandBufferPtr(CommandBuffer::newInstance(this, init));
+}
+
+FramebufferPtr GrManager::newFramebuffer(const FramebufferInitInfo& init)
+{
+	return FramebufferPtr(Framebuffer::newInstance(this, init));
+}
+
+OcclusionQueryPtr GrManager::newOcclusionQuery()
+{
+	return OcclusionQueryPtr(OcclusionQuery::newInstance(this));
+}
+
+RenderGraphPtr GrManager::newRenderGraph()
+{
+	return RenderGraphPtr(RenderGraph::newInstance(this));
 }
 }
 
 
 void GrManager::getTextureSurfaceUploadInfo(TexturePtr tex, const TextureSurfaceInfo& surf, PtrSize& allocationSize)
 void GrManager::getTextureSurfaceUploadInfo(TexturePtr tex, const TextureSurfaceInfo& surf, PtrSize& allocationSize)
 {
 {
-	const TextureImpl& impl = *tex->m_impl;
+	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
 	impl.checkSurfaceOrVolume(surf);
 	impl.checkSurfaceOrVolume(surf);
 
 
 	U width = impl.m_width >> surf.m_level;
 	U width = impl.m_width >> surf.m_level;
 	U height = impl.m_height >> surf.m_level;
 	U height = impl.m_height >> surf.m_level;
-	allocationSize = computeSurfaceSize(width, height, impl.m_pformat);
+	allocationSize = computeSurfaceSize(width, height, impl.m_format);
 }
 }
 
 
 void GrManager::getTextureVolumeUploadInfo(TexturePtr tex, const TextureVolumeInfo& vol, PtrSize& allocationSize)
 void GrManager::getTextureVolumeUploadInfo(TexturePtr tex, const TextureVolumeInfo& vol, PtrSize& allocationSize)
 {
 {
-	const TextureImpl& impl = *tex->m_impl;
+	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
 	impl.checkSurfaceOrVolume(vol);
 	impl.checkSurfaceOrVolume(vol);
 
 
 	U width = impl.m_width >> vol.m_level;
 	U width = impl.m_width >> vol.m_level;
 	U height = impl.m_height >> vol.m_level;
 	U height = impl.m_height >> vol.m_level;
 	U depth = impl.m_depth >> vol.m_level;
 	U depth = impl.m_depth >> vol.m_level;
-	allocationSize = computeVolumeSize(width, height, depth, impl.m_pformat);
+	allocationSize = computeVolumeSize(width, height, depth, impl.m_format);
 }
 }
 
 
 void GrManager::getUniformBufferInfo(U32& bindOffsetAlignment, PtrSize& maxUniformBlockSize) const
 void GrManager::getUniformBufferInfo(U32& bindOffsetAlignment, PtrSize& maxUniformBlockSize) const
 {
 {
-	bindOffsetAlignment = m_impl->getState().m_uboAlignment;
-	maxUniformBlockSize = m_impl->getState().m_uniBlockMaxSize;
+	ANKI_GL_SELF_CONST(GrManagerImpl);
+
+	bindOffsetAlignment = self.getState().m_uboAlignment;
+	maxUniformBlockSize = self.getState().m_uniBlockMaxSize;
 
 
 	ANKI_ASSERT(bindOffsetAlignment > 0 && maxUniformBlockSize > 0);
 	ANKI_ASSERT(bindOffsetAlignment > 0 && maxUniformBlockSize > 0);
 }
 }
 
 
 void GrManager::getStorageBufferInfo(U32& bindOffsetAlignment, PtrSize& maxStorageBlockSize) const
 void GrManager::getStorageBufferInfo(U32& bindOffsetAlignment, PtrSize& maxStorageBlockSize) const
 {
 {
-	bindOffsetAlignment = m_impl->getState().m_ssboAlignment;
-	maxStorageBlockSize = m_impl->getState().m_storageBlockMaxSize;
+	ANKI_GL_SELF_CONST(GrManagerImpl);
+
+	bindOffsetAlignment = self.getState().m_ssboAlignment;
+	maxStorageBlockSize = self.getState().m_storageBlockMaxSize;
 
 
 	ANKI_ASSERT(bindOffsetAlignment > 0 && maxStorageBlockSize > 0);
 	ANKI_ASSERT(bindOffsetAlignment > 0 && maxStorageBlockSize > 0);
 }
 }
 
 
 void GrManager::getTextureBufferInfo(U32& bindOffsetAlignment, PtrSize& maxRange) const
 void GrManager::getTextureBufferInfo(U32& bindOffsetAlignment, PtrSize& maxRange) const
 {
 {
-	bindOffsetAlignment = m_impl->getState().m_tboAlignment;
-	maxRange = m_impl->getState().m_tboMaxRange;
+	ANKI_GL_SELF_CONST(GrManagerImpl);
+
+	bindOffsetAlignment = self.getState().m_tboAlignment;
+	maxRange = self.getState().m_tboMaxRange;
 
 
 	ANKI_ASSERT(bindOffsetAlignment > 0 && maxRange > 0);
 	ANKI_ASSERT(bindOffsetAlignment > 0 && maxRange > 0);
 }
 }

+ 8 - 10
src/anki/gr/gl/GrManagerImpl.cpp

@@ -17,37 +17,35 @@ GrManagerImpl::~GrManagerImpl()
 	if(m_thread)
 	if(m_thread)
 	{
 	{
 		m_thread->stop();
 		m_thread->stop();
-		m_manager->getAllocator().deleteInstance(m_thread);
+		m_alloc.deleteInstance(m_thread);
 		m_thread = nullptr;
 		m_thread = nullptr;
 	}
 	}
 
 
 	if(m_state)
 	if(m_state)
 	{
 	{
-		m_manager->getAllocator().deleteInstance(m_state);
+		m_alloc.deleteInstance(m_state);
 	}
 	}
 
 
 	destroyBackend();
 	destroyBackend();
-	m_manager = nullptr;
 }
 }
 
 
-GrAllocator<U8> GrManagerImpl::getAllocator() const
+Error GrManagerImpl::init(GrManagerInitInfo& init, GrAllocator<U8> alloc)
 {
 {
-	return m_manager->getAllocator();
-}
+	m_alloc = HeapAllocator<U8>(init.m_allocCallback, init.m_allocCallbackUserData);
+
+	m_cacheDir.create(m_alloc, init.m_cacheDirectory);
 
 
-Error GrManagerImpl::init(GrManagerInitInfo& init)
-{
 	m_debugMarkers = init.m_config->getNumber("window.debugMarkers");
 	m_debugMarkers = init.m_config->getNumber("window.debugMarkers");
 
 
 	// Init the backend of the backend
 	// Init the backend of the backend
 	ANKI_CHECK(createBackend(init));
 	ANKI_CHECK(createBackend(init));
 
 
 	// First create the state
 	// First create the state
-	m_state = m_manager->getAllocator().newInstance<GlState>(m_manager);
+	m_state = m_alloc.newInstance<GlState>(this);
 	m_state->initMainThread(*init.m_config);
 	m_state->initMainThread(*init.m_config);
 
 
 	// Create thread
 	// Create thread
-	m_thread = m_manager->getAllocator().newInstance<RenderingThread>(m_manager);
+	m_thread = m_alloc.newInstance<RenderingThread>(this);
 
 
 	// Start it
 	// Start it
 	m_thread->start();
 	m_thread->start();

+ 4 - 8
src/anki/gr/gl/GrManagerImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/GrManager.h>
 #include <anki/gr/gl/Common.h>
 #include <anki/gr/gl/Common.h>
 
 
 namespace anki
 namespace anki
@@ -19,18 +20,16 @@ class GlState;
 /// @{
 /// @{
 
 
 /// Graphics manager backend specific.
 /// Graphics manager backend specific.
-class GrManagerImpl
+class GrManagerImpl final : public GrManager
 {
 {
 public:
 public:
-	GrManagerImpl(GrManager* manager)
-		: m_manager(manager)
+	GrManagerImpl()
 	{
 	{
-		ANKI_ASSERT(manager);
 	}
 	}
 
 
 	~GrManagerImpl();
 	~GrManagerImpl();
 
 
-	ANKI_USE_RESULT Error init(GrManagerInitInfo& init);
+	ANKI_USE_RESULT Error init(GrManagerInitInfo& init, GrAllocator<U8> alloc);
 
 
 	const RenderingThread& getRenderingThread() const
 	const RenderingThread& getRenderingThread() const
 	{
 	{
@@ -56,8 +55,6 @@ public:
 		return *m_state;
 		return *m_state;
 	}
 	}
 
 
-	GrAllocator<U8> getAllocator() const;
-
 	void swapBuffers();
 	void swapBuffers();
 
 
 	void pinContextToCurrentThread(Bool pin);
 	void pinContextToCurrentThread(Bool pin);
@@ -68,7 +65,6 @@ public:
 	}
 	}
 
 
 private:
 private:
-	GrManager* m_manager;
 	GlState* m_state = nullptr;
 	GlState* m_state = nullptr;
 	RenderingThread* m_thread = nullptr;
 	RenderingThread* m_thread = nullptr;
 	WindowingBackend* m_backend = nullptr; ///< The backend of the backend.
 	WindowingBackend* m_backend = nullptr; ///< The backend of the backend.

+ 7 - 15
src/anki/gr/gl/OcclusionQuery.cpp

@@ -11,16 +11,7 @@
 namespace anki
 namespace anki
 {
 {
 
 
-OcclusionQuery::OcclusionQuery(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
-{
-}
-
-OcclusionQuery::~OcclusionQuery()
-{
-}
-
-void OcclusionQuery::init()
+OcclusionQuery* OcclusionQuery::newInstance(GrManager* manager)
 {
 {
 	class CreateOqCommand final : public GlCommand
 	class CreateOqCommand final : public GlCommand
 	{
 	{
@@ -34,7 +25,7 @@ void OcclusionQuery::init()
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			OcclusionQueryImpl& impl = *m_q->m_impl;
+			OcclusionQueryImpl& impl = static_cast<OcclusionQueryImpl&>(*m_q);
 
 
 			impl.init();
 			impl.init();
 
 
@@ -47,12 +38,13 @@ void OcclusionQuery::init()
 		}
 		}
 	};
 	};
 
 
-	m_impl.reset(getAllocator().newInstance<OcclusionQueryImpl>(&getManager()));
+	OcclusionQueryImpl* impl = manager->getAllocator().newInstance<OcclusionQueryImpl>(manager);
 
 
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateOqCommand>(impl);
+	static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
-	cmdb->m_impl->pushBackNewCommand<CreateOqCommand>(this);
-	cmdb->flush();
+	return impl;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 4 - 3
src/anki/gr/gl/OcclusionQueryImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/OcclusionQuery.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/gl/GlObject.h>
 
 
 namespace anki
 namespace anki
@@ -14,17 +15,17 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Occlusion query.
 /// Occlusion query.
-class OcclusionQueryImpl : public GlObject
+class OcclusionQueryImpl final : public OcclusionQuery, public GlObject
 {
 {
 public:
 public:
 	OcclusionQueryImpl(GrManager* manager)
 	OcclusionQueryImpl(GrManager* manager)
-		: GlObject(manager)
+		: OcclusionQuery(manager)
 	{
 	{
 	}
 	}
 
 
 	~OcclusionQueryImpl()
 	~OcclusionQueryImpl()
 	{
 	{
-		destroyDeferred(glDeleteQueries);
+		destroyDeferred(getManager(), glDeleteQueries);
 	}
 	}
 
 
 	/// Create the query.
 	/// Create the query.

+ 22 - 22
src/anki/gr/gl/RenderingThread.cpp

@@ -63,7 +63,7 @@ public:
 	}
 	}
 };
 };
 
 
-RenderingThread::RenderingThread(GrManager* manager)
+RenderingThread::RenderingThread(GrManagerImpl* manager)
 	: m_manager(manager)
 	: m_manager(manager)
 	, m_tail(0)
 	, m_tail(0)
 	, m_head(0)
 	, m_head(0)
@@ -84,9 +84,8 @@ void RenderingThread::flushCommandBuffer(CommandBufferPtr cmdb, FencePtr* fence)
 	if(fence)
 	if(fence)
 	{
 	{
 		FencePtr& f = *fence;
 		FencePtr& f = *fence;
-
-		f.reset(m_manager->getImplementation().getAllocator().newInstance<Fence>(m_manager.get()));
-		f->m_impl.reset(m_manager->getAllocator().newInstance<FenceImpl>(m_manager.get()));
+		FenceImpl* fenceImpl = m_manager->getAllocator().newInstance<FenceImpl>(m_manager.get());
+		f.reset(fenceImpl);
 
 
 		class CreateFenceCmd final : public GlCommand
 		class CreateFenceCmd final : public GlCommand
 		{
 		{
@@ -100,15 +99,15 @@ void RenderingThread::flushCommandBuffer(CommandBufferPtr cmdb, FencePtr* fence)
 
 
 			Error operator()(GlState&)
 			Error operator()(GlState&)
 			{
 			{
-				m_fence->m_impl->m_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+				static_cast<FenceImpl&>(*m_fence).m_fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 				return Error::NONE;
 				return Error::NONE;
 			}
 			}
 		};
 		};
 
 
-		cmdb->m_impl->pushBackNewCommand<CreateFenceCmd>(f);
+		static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateFenceCmd>(f);
 	}
 	}
 
 
-	cmdb->m_impl->makeImmutable();
+	static_cast<CommandBufferImpl&>(*cmdb).makeImmutable();
 
 
 	{
 	{
 		LockGuard<Mutex> lock(m_mtx);
 		LockGuard<Mutex> lock(m_mtx);
@@ -145,22 +144,23 @@ void RenderingThread::start()
 	m_queue.create(m_manager->getAllocator(), QUEUE_SIZE);
 	m_queue.create(m_manager->getAllocator(), QUEUE_SIZE);
 
 
 	// Swap buffers stuff
 	// Swap buffers stuff
-	m_swapBuffersCommands = m_manager->newInstance<CommandBuffer>(CommandBufferInitInfo());
-	m_swapBuffersCommands->m_impl->pushBackNewCommand<SwapBuffersCommand>(this);
+	m_swapBuffersCommands = m_manager->newCommandBuffer(CommandBufferInitInfo());
+
+	static_cast<CommandBufferImpl&>(*m_swapBuffersCommands).pushBackNewCommand<SwapBuffersCommand>(this);
 	// Just in case noone swaps
 	// Just in case noone swaps
-	m_swapBuffersCommands->m_impl->makeExecuted();
+	static_cast<CommandBufferImpl&>(*m_swapBuffersCommands).makeExecuted();
 
 
-	m_manager->getImplementation().pinContextToCurrentThread(false);
+	m_manager->pinContextToCurrentThread(false);
 
 
 	// Start thread
 	// Start thread
 	m_thread.start(this, threadCallback);
 	m_thread.start(this, threadCallback);
 
 
 	// Create sync command buffer
 	// Create sync command buffer
-	m_syncCommands = m_manager->newInstance<CommandBuffer>(CommandBufferInitInfo());
-	m_syncCommands->m_impl->pushBackNewCommand<SyncCommand>(this);
+	m_syncCommands = m_manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*m_syncCommands).pushBackNewCommand<SyncCommand>(this);
 
 
-	m_emptyCmdb = m_manager->newInstance<CommandBuffer>(CommandBufferInitInfo());
-	m_emptyCmdb->m_impl->pushBackNewCommand<EmptyCommand>();
+	m_emptyCmdb = m_manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*m_emptyCmdb).pushBackNewCommand<EmptyCommand>();
 }
 }
 
 
 void RenderingThread::stop()
 void RenderingThread::stop()
@@ -175,7 +175,7 @@ void RenderingThread::stop()
 
 
 void RenderingThread::prepare()
 void RenderingThread::prepare()
 {
 {
-	m_manager->getImplementation().pinContextToCurrentThread(true);
+	m_manager->pinContextToCurrentThread(true);
 
 
 	// Ignore the first error
 	// Ignore the first error
 	glGetError();
 	glGetError();
@@ -188,7 +188,7 @@ void RenderingThread::prepare()
 	m_serverThreadId = Thread::getCurrentThreadId();
 	m_serverThreadId = Thread::getCurrentThreadId();
 
 
 	// Init state
 	// Init state
-	m_manager->getImplementation().getState().initRenderThread();
+	m_manager->getState().initRenderThread();
 }
 }
 
 
 void RenderingThread::finish()
 void RenderingThread::finish()
@@ -199,7 +199,7 @@ void RenderingThread::finish()
 		if(m_queue[i].isCreated())
 		if(m_queue[i].isCreated())
 		{
 		{
 			// Fake that it's executed to avoid warnings
 			// Fake that it's executed to avoid warnings
-			m_queue[i]->m_impl->makeExecuted();
+			static_cast<CommandBufferImpl&>(*m_queue[i]).makeExecuted();
 
 
 			// Release
 			// Release
 			m_queue[i] = CommandBufferPtr();
 			m_queue[i] = CommandBufferPtr();
@@ -207,11 +207,11 @@ void RenderingThread::finish()
 	}
 	}
 
 
 	// Cleanup GL
 	// Cleanup GL
-	m_manager->getImplementation().getState().destroy();
+	m_manager->getState().destroy();
 
 
 	// Cleanup
 	// Cleanup
 	glFinish();
 	glFinish();
-	m_manager->getImplementation().pinContextToCurrentThread(false);
+	m_manager->pinContextToCurrentThread(false);
 }
 }
 
 
 Error RenderingThread::threadCallback(ThreadCallbackInfo& info)
 Error RenderingThread::threadCallback(ThreadCallbackInfo& info)
@@ -253,7 +253,7 @@ void RenderingThread::threadLoop()
 		}
 		}
 
 
 		ANKI_TRACE_START_EVENT(GL_THREAD);
 		ANKI_TRACE_START_EVENT(GL_THREAD);
-		Error err = cmd->m_impl->executeAllCommands();
+		Error err = static_cast<CommandBufferImpl&>(*cmd).executeAllCommands();
 		ANKI_TRACE_STOP_EVENT(GL_THREAD);
 		ANKI_TRACE_STOP_EVENT(GL_THREAD);
 
 
 		if(err)
 		if(err)
@@ -281,7 +281,7 @@ void RenderingThread::swapBuffersInternal()
 	ANKI_TRACE_START_EVENT(SWAP_BUFFERS);
 	ANKI_TRACE_START_EVENT(SWAP_BUFFERS);
 
 
 	// Do the swap buffers
 	// Do the swap buffers
-	m_manager->getImplementation().swapBuffers();
+	m_manager->swapBuffers();
 
 
 	// Notify the main thread that we are done
 	// Notify the main thread that we are done
 	{
 	{

+ 2 - 2
src/anki/gr/gl/RenderingThread.h

@@ -21,7 +21,7 @@ class RenderingThread
 	friend class SwapBuffersCommand;
 	friend class SwapBuffersCommand;
 
 
 public:
 public:
-	RenderingThread(GrManager* device);
+	RenderingThread(GrManagerImpl* device);
 
 
 	~RenderingThread();
 	~RenderingThread();
 
 
@@ -51,7 +51,7 @@ public:
 	void swapBuffers();
 	void swapBuffers();
 
 
 private:
 private:
-	WeakPtr<GrManager> m_manager;
+	WeakPtr<GrManagerImpl> m_manager;
 
 
 	static const U QUEUE_SIZE = 1024 * 2;
 	static const U QUEUE_SIZE = 1024 * 2;
 	DynamicArray<CommandBufferPtr> m_queue; ///< Command queue
 	DynamicArray<CommandBufferPtr> m_queue; ///< Command queue

+ 7 - 16
src/anki/gr/gl/Sampler.cpp

@@ -11,16 +11,7 @@
 namespace anki
 namespace anki
 {
 {
 
 
-Sampler::Sampler(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
-{
-}
-
-Sampler::~Sampler()
-{
-}
-
-void Sampler::init(const SamplerInitInfo& init)
+Sampler* Sampler::newInstance(GrManager* manager, const SamplerInitInfo& init)
 {
 {
 	class CreateSamplerCommand : public GlCommand
 	class CreateSamplerCommand : public GlCommand
 	{
 	{
@@ -36,12 +27,11 @@ void Sampler::init(const SamplerInitInfo& init)
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			SamplerImpl& impl = *m_sampler->m_impl;
+			SamplerImpl& impl = static_cast<SamplerImpl&>(*m_sampler);
 
 
 			impl.init(m_init);
 			impl.init(m_init);
 
 
 			GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
 			GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
-
 			(void)oldState;
 			(void)oldState;
 			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
 			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
 
 
@@ -49,12 +39,13 @@ void Sampler::init(const SamplerInitInfo& init)
 		}
 		}
 	};
 	};
 
 
-	m_impl.reset(getAllocator().newInstance<SamplerImpl>(&getManager()));
+	SamplerImpl* impl = manager->getAllocator().newInstance<SamplerImpl>(manager);
 
 
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateSamplerCommand>(impl, init);
+	static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
-	cmdb->m_impl->pushBackNewCommand<CreateSamplerCommand>(this, init);
-	cmdb->flush();
+	return impl;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 4 - 3
src/anki/gr/gl/SamplerImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/Sampler.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/gl/GlObject.h>
 
 
 namespace anki
 namespace anki
@@ -14,17 +15,17 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Sampler GL object.
 /// Sampler GL object.
-class SamplerImpl : public GlObject
+class SamplerImpl final : public Sampler, public GlObject
 {
 {
 public:
 public:
 	SamplerImpl(GrManager* manager)
 	SamplerImpl(GrManager* manager)
-		: GlObject(manager)
+		: Sampler(manager)
 	{
 	{
 	}
 	}
 
 
 	~SamplerImpl()
 	~SamplerImpl()
 	{
 	{
-		destroyDeferred(glDeleteSamplers);
+		destroyDeferred(getManager(), glDeleteSamplers);
 	}
 	}
 
 
 	void init(const SamplerInitInfo& sinit);
 	void init(const SamplerInitInfo& sinit);

+ 33 - 45
src/anki/gr/gl/Shader.cpp

@@ -11,63 +11,51 @@
 namespace anki
 namespace anki
 {
 {
 
 
-Shader::Shader(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
+Shader* Shader::newInstance(GrManager* manager, const ShaderInitInfo& init)
 {
 {
-}
-
-Shader::~Shader()
-{
-}
-
-class ShaderCreateCommand final : public GlCommand
-{
-public:
-	ShaderPtr m_shader;
-	ShaderType m_type;
-	char* m_source;
-	CommandBufferAllocator<char> m_alloc;
-
-	ShaderCreateCommand(Shader* shader, ShaderType type, char* source, const CommandBufferAllocator<char>& alloc)
-		: m_shader(shader)
-		, m_type(type)
-		, m_source(source)
-		, m_alloc(alloc)
+	class ShaderCreateCommand final : public GlCommand
 	{
 	{
-	}
+	public:
+		ShaderPtr m_shader;
+		ShaderType m_type;
+		StringAuto m_source;
 
 
-	Error operator()(GlState&)
-	{
-		ShaderImpl& impl = *m_shader->m_impl;
+		ShaderCreateCommand(Shader* shader, ShaderType type, CString source, const CommandBufferAllocator<U8>& alloc)
+			: m_shader(shader)
+			, m_type(type)
+			, m_source(alloc)
+		{
+			m_source.create(source);
+		}
 
 
-		Error err = impl.init(m_type, m_source);
+		Error operator()(GlState&)
+		{
+			ShaderImpl& impl = static_cast<ShaderImpl&>(*m_shader);
 
 
-		GlObject::State oldState = impl.setStateAtomically((err) ? GlObject::State::ERROR : GlObject::State::CREATED);
-		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
-		(void)oldState;
+			Error err = impl.init(m_type, m_source.toCString());
 
 
-		// Delete source
-		m_alloc.deallocate(m_source, 1);
+			GlObject::State oldState =
+				impl.setStateAtomically((err) ? GlObject::State::ERROR : GlObject::State::CREATED);
+			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
+			(void)oldState;
 
 
-		return err;
-	}
-};
+			return err;
+		}
+	};
 
 
-void Shader::init(ShaderType shaderType, const CString& source)
-{
-	ANKI_ASSERT(!source.isEmpty());
+	ANKI_ASSERT(!init.m_source.isEmpty() && init.m_source.getLength() > 0);
 
 
-	m_impl.reset(getAllocator().newInstance<ShaderImpl>(&getManager()));
-
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
+	ShaderImpl* impl = manager->getAllocator().newInstance<ShaderImpl>(manager);
 
 
 	// Copy source to the command buffer
 	// Copy source to the command buffer
-	CommandBufferAllocator<char> alloc = cmdb->m_impl->getInternalAllocator();
-	char* src = alloc.allocate(source.getLength() + 1);
-	memcpy(src, &source[0], source.getLength() + 1);
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	CommandBufferImpl& cmdbimpl = static_cast<CommandBufferImpl&>(*cmdb);
+	CommandBufferAllocator<U8> alloc = cmdbimpl.getInternalAllocator();
+
+	cmdbimpl.pushBackNewCommand<ShaderCreateCommand>(impl, init.m_shaderType, init.m_source, alloc);
+	cmdbimpl.flush();
 
 
-	cmdb->m_impl->pushBackNewCommand<ShaderCreateCommand>(this, shaderType, src, alloc);
-	cmdb->flush();
+	return impl;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 4 - 4
src/anki/gr/gl/ShaderImpl.cpp

@@ -51,7 +51,7 @@ static const char* SHADER_HEADER = R"(#version %u %s
 
 
 ShaderImpl::~ShaderImpl()
 ShaderImpl::~ShaderImpl()
 {
 {
-	destroyDeferred(deleteShaders);
+	destroyDeferred(getManager(), deleteShaders);
 }
 }
 
 
 Error ShaderImpl::init(ShaderType type, const CString& source)
 Error ShaderImpl::init(ShaderType type, const CString& source)
@@ -97,7 +97,7 @@ Error ShaderImpl::init(ShaderType type, const CString& source)
 	fullSrc.sprintf(SHADER_HEADER,
 	fullSrc.sprintf(SHADER_HEADER,
 		version,
 		version,
 		versionType,
 		versionType,
-		&GPU_VENDOR_STR[getManager().getImplementation().getState().m_gpu][0],
+		&GPU_VENDOR_STR[static_cast<const GrManagerImpl&>(getManager()).getState().m_gpu][0],
 		shaderName[U(type)],
 		shaderName[U(type)],
 		MAX_UNIFORM_BUFFER_BINDINGS,
 		MAX_UNIFORM_BUFFER_BINDINGS,
 		MAX_STORAGE_BUFFER_BINDINGS,
 		MAX_STORAGE_BUFFER_BINDINGS,
@@ -105,7 +105,7 @@ Error ShaderImpl::init(ShaderType type, const CString& source)
 		MAX_IMAGE_BINDINGS,
 		MAX_IMAGE_BINDINGS,
 		MAX_TEXTURE_BINDINGS * MAX_DESCRIPTOR_SETS,
 		MAX_TEXTURE_BINDINGS * MAX_DESCRIPTOR_SETS,
 		MAX_TEXTURE_BUFFER_BINDINGS,
 		MAX_TEXTURE_BUFFER_BINDINGS,
-		!!(getManager().getImplementation().getState().m_extensions & GlExtensions::ARB_SHADER_BALLOT),
+		!!(static_cast<const GrManagerImpl&>(getManager()).getState().m_extensions & GlExtensions::ARB_SHADER_BALLOT),
 		&source[0]);
 		&source[0]);
 
 
 	// 2) Gen name, create, compile and link
 	// 2) Gen name, create, compile and link
@@ -146,7 +146,7 @@ Error ShaderImpl::init(ShaderType type, const CString& source)
 		}
 		}
 
 
 		StringAuto fname(alloc);
 		StringAuto fname(alloc);
-		CString cacheDir = m_manager->getCacheDirectory();
+		CString cacheDir = getManager().getCacheDirectory();
 		fname.sprintf("%s/%05u.%s", &cacheDir[0], static_cast<U32>(m_glName), ext);
 		fname.sprintf("%s/%05u.%s", &cacheDir[0], static_cast<U32>(m_glName), ext);
 
 
 		File file;
 		File file;

+ 2 - 2
src/anki/gr/gl/ShaderImpl.h

@@ -19,14 +19,14 @@ class String;
 /// @{
 /// @{
 
 
 /// Shader program. It only contains a single shader and it can be combined with other programs in a program pipiline.
 /// Shader program. It only contains a single shader and it can be combined with other programs in a program pipiline.
-class ShaderImpl : public GlObject
+class ShaderImpl final : public Shader, public GlObject
 {
 {
 public:
 public:
 	GLenum m_glType = 0;
 	GLenum m_glType = 0;
 	ShaderType m_type;
 	ShaderType m_type;
 
 
 	ShaderImpl(GrManager* manager)
 	ShaderImpl(GrManager* manager)
-		: GlObject(manager)
+		: Shader(manager)
 	{
 	{
 	}
 	}
 
 

+ 30 - 75
src/anki/gr/gl/ShaderProgram.cpp

@@ -12,74 +12,7 @@
 namespace anki
 namespace anki
 {
 {
 
 
-ShaderProgram::ShaderProgram(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
-{
-}
-
-ShaderProgram::~ShaderProgram()
-{
-}
-
-void ShaderProgram::init(ShaderPtr vert, ShaderPtr frag)
-{
-	class CreateCommand final : public GlCommand
-	{
-	public:
-		ShaderProgramPtr m_prog;
-		ShaderPtr m_vert;
-		ShaderPtr m_frag;
-
-		CreateCommand(ShaderProgram* prog, ShaderPtr vert, ShaderPtr frag)
-			: m_prog(prog)
-			, m_vert(vert)
-			, m_frag(frag)
-		{
-		}
-
-		Error operator()(GlState&)
-		{
-			ShaderPtr none;
-			return m_prog->m_impl->initGraphics(m_vert, none, none, none, m_frag);
-		}
-	};
-
-	m_impl.reset(getAllocator().newInstance<ShaderProgramImpl>(&getManager()));
-
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
-	cmdb->m_impl->pushBackNewCommand<CreateCommand>(this, vert, frag);
-	cmdb->flush();
-}
-
-void ShaderProgram::init(ShaderPtr comp)
-{
-	class CreateCommand final : public GlCommand
-	{
-	public:
-		ShaderProgramPtr m_prog;
-		ShaderPtr m_comp;
-
-		CreateCommand(ShaderProgram* prog, ShaderPtr comp)
-			: m_prog(prog)
-			, m_comp(comp)
-		{
-		}
-
-		Error operator()(GlState&)
-		{
-			ShaderPtr none;
-			return m_prog->m_impl->initCompute(m_comp);
-		}
-	};
-
-	m_impl.reset(getAllocator().newInstance<ShaderProgramImpl>(&getManager()));
-
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
-	cmdb->m_impl->pushBackNewCommand<CreateCommand>(this, comp);
-	cmdb->flush();
-}
-
-void ShaderProgram::init(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
+ShaderProgram* ShaderProgram::newInstance(GrManager* manager, const ShaderProgramInitInfo& init)
 {
 {
 	class CreateCommand final : public GlCommand
 	class CreateCommand final : public GlCommand
 	{
 	{
@@ -90,29 +23,51 @@ void ShaderProgram::init(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, Shade
 		ShaderPtr m_tesse;
 		ShaderPtr m_tesse;
 		ShaderPtr m_geom;
 		ShaderPtr m_geom;
 		ShaderPtr m_frag;
 		ShaderPtr m_frag;
+		ShaderPtr m_comp;
 
 
-		CreateCommand(
-			ShaderProgram* prog, ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
+		CreateCommand(ShaderProgram* prog,
+			ShaderPtr vert,
+			ShaderPtr tessc,
+			ShaderPtr tesse,
+			ShaderPtr geom,
+			ShaderPtr frag,
+			ShaderPtr comp)
 			: m_prog(prog)
 			: m_prog(prog)
 			, m_vert(vert)
 			, m_vert(vert)
 			, m_tessc(tesse)
 			, m_tessc(tesse)
 			, m_tesse(tesse)
 			, m_tesse(tesse)
 			, m_geom(geom)
 			, m_geom(geom)
 			, m_frag(frag)
 			, m_frag(frag)
+			, m_comp(comp)
 		{
 		{
 		}
 		}
 
 
 		Error operator()(GlState&)
 		Error operator()(GlState&)
 		{
 		{
-			return m_prog->m_impl->initGraphics(m_vert, m_tessc, m_tesse, m_geom, m_frag);
+			if(m_comp)
+			{
+				return static_cast<ShaderProgramImpl&>(*m_prog).initCompute(m_comp);
+			}
+			else
+			{
+				return static_cast<ShaderProgramImpl&>(*m_prog).initGraphics(m_vert, m_tessc, m_tesse, m_geom, m_frag);
+			}
 		}
 		}
 	};
 	};
 
 
-	m_impl.reset(getAllocator().newInstance<ShaderProgramImpl>(&getManager()));
+	ShaderProgramImpl* impl = manager->getAllocator().newInstance<ShaderProgramImpl>(manager);
+
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateCommand>(impl,
+		init.m_shaders[ShaderType::VERTEX],
+		init.m_shaders[ShaderType::TESSELLATION_CONTROL],
+		init.m_shaders[ShaderType::TESSELLATION_EVALUATION],
+		init.m_shaders[ShaderType::GEOMETRY],
+		init.m_shaders[ShaderType::FRAGMENT],
+		init.m_shaders[ShaderType::COMPUTE]);
+	static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
-	cmdb->m_impl->pushBackNewCommand<CreateCommand>(this, vert, tessc, tesse, geom, frag);
-	cmdb->flush();
+	return impl;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 8 - 13
src/anki/gr/gl/ShaderProgramImpl.cpp

@@ -17,14 +17,9 @@ static void deletePrograms(GLsizei n, const GLuint* progs)
 	glDeleteProgram(*progs);
 	glDeleteProgram(*progs);
 }
 }
 
 
-ShaderProgramImpl::ShaderProgramImpl(GrManager* manager)
-	: GlObject(manager)
-{
-}
-
 ShaderProgramImpl::~ShaderProgramImpl()
 ShaderProgramImpl::~ShaderProgramImpl()
 {
 {
-	destroyDeferred(deletePrograms);
+	destroyDeferred(getManager(), deletePrograms);
 }
 }
 
 
 Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
 Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
@@ -32,31 +27,31 @@ Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr
 	m_glName = glCreateProgram();
 	m_glName = glCreateProgram();
 	ANKI_ASSERT(m_glName != 0);
 	ANKI_ASSERT(m_glName != 0);
 
 
-	glAttachShader(m_glName, vert->m_impl->getGlName());
+	glAttachShader(m_glName, static_cast<const ShaderImpl&>(*vert).getGlName());
 	m_shaders[ShaderType::VERTEX] = vert;
 	m_shaders[ShaderType::VERTEX] = vert;
 
 
 	if(tessc)
 	if(tessc)
 	{
 	{
-		glAttachShader(m_glName, tessc->m_impl->getGlName());
+		glAttachShader(m_glName, static_cast<const ShaderImpl&>(*tessc).getGlName());
 		m_shaders[ShaderType::TESSELLATION_CONTROL] = tessc;
 		m_shaders[ShaderType::TESSELLATION_CONTROL] = tessc;
 	}
 	}
 
 
 	if(tesse)
 	if(tesse)
 	{
 	{
-		glAttachShader(m_glName, tesse->m_impl->getGlName());
+		glAttachShader(m_glName, static_cast<const ShaderImpl&>(*tesse).getGlName());
 		m_shaders[ShaderType::TESSELLATION_EVALUATION] = tesse;
 		m_shaders[ShaderType::TESSELLATION_EVALUATION] = tesse;
 	}
 	}
 
 
 	if(geom)
 	if(geom)
 	{
 	{
-		glAttachShader(m_glName, geom->m_impl->getGlName());
+		glAttachShader(m_glName, static_cast<const ShaderImpl&>(*geom).getGlName());
 		m_shaders[ShaderType::GEOMETRY] = geom;
 		m_shaders[ShaderType::GEOMETRY] = geom;
 	}
 	}
 
 
-	glAttachShader(m_glName, frag->m_impl->getGlName());
+	glAttachShader(m_glName, static_cast<const ShaderImpl&>(*frag).getGlName());
 	m_shaders[ShaderType::FRAGMENT] = frag;
 	m_shaders[ShaderType::FRAGMENT] = frag;
 
 
-	return link(vert->m_impl->getGlName(), frag->m_impl->getGlName());
+	return link(static_cast<const ShaderImpl&>(*vert).getGlName(), static_cast<const ShaderImpl&>(*frag).getGlName());
 }
 }
 
 
 Error ShaderProgramImpl::initCompute(ShaderPtr comp)
 Error ShaderProgramImpl::initCompute(ShaderPtr comp)
@@ -64,7 +59,7 @@ Error ShaderProgramImpl::initCompute(ShaderPtr comp)
 	m_glName = glCreateProgram();
 	m_glName = glCreateProgram();
 	ANKI_ASSERT(m_glName != 0);
 	ANKI_ASSERT(m_glName != 0);
 
 
-	glAttachShader(m_glName, comp->m_impl->getGlName());
+	glAttachShader(m_glName, static_cast<const ShaderImpl&>(*comp).getGlName());
 	m_shaders[ShaderType::COMPUTE] = comp;
 	m_shaders[ShaderType::COMPUTE] = comp;
 
 
 	return link(0, 0);
 	return link(0, 0);

+ 6 - 2
src/anki/gr/gl/ShaderProgramImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/ShaderProgram.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/gl/GlObject.h>
 
 
 namespace anki
 namespace anki
@@ -14,10 +15,13 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Shader program implementation.
 /// Shader program implementation.
-class ShaderProgramImpl : public GlObject
+class ShaderProgramImpl final : public ShaderProgram, public GlObject
 {
 {
 public:
 public:
-	ShaderProgramImpl(GrManager* manager);
+	ShaderProgramImpl(GrManager* manager)
+		: ShaderProgram(manager)
+	{
+	}
 
 
 	~ShaderProgramImpl();
 	~ShaderProgramImpl();
 
 

+ 19 - 12
src/anki/gr/gl/StateTracker.h

@@ -11,8 +11,14 @@
 #include <anki/gr/gl/FramebufferImpl.h>
 #include <anki/gr/gl/FramebufferImpl.h>
 #include <anki/gr/Buffer.h>
 #include <anki/gr/Buffer.h>
 #include <anki/gr/gl/BufferImpl.h>
 #include <anki/gr/gl/BufferImpl.h>
+#include <anki/gr/Texture.h>
+#include <anki/gr/gl/TextureImpl.h>
 #include <anki/gr/Sampler.h>
 #include <anki/gr/Sampler.h>
 #include <anki/gr/gl/SamplerImpl.h>
 #include <anki/gr/gl/SamplerImpl.h>
+#include <anki/gr/ShaderProgram.h>
+#include <anki/gr/gl/ShaderProgramImpl.h>
+#include <anki/gr/Framebuffer.h>
+#include <anki/gr/gl/FramebufferImpl.h>
 #include <anki/gr/common/Misc.h>
 #include <anki/gr/common/Misc.h>
 
 
 namespace anki
 namespace anki
@@ -72,7 +78,7 @@ public:
 	Bool bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate)
 	Bool bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate)
 	{
 	{
 		VertexBuffer& b = m_vertBuffs[binding];
 		VertexBuffer& b = m_vertBuffs[binding];
-		b.m_buff = buff->m_impl.get();
+		b.m_buff = static_cast<BufferImpl*>(buff.get());
 		b.m_offset = offset;
 		b.m_offset = offset;
 		b.m_stride = stride;
 		b.m_stride = stride;
 		b.m_stepRate = stepRate;
 		b.m_stepRate = stepRate;
@@ -89,7 +95,7 @@ public:
 
 
 	Bool bindIndexBuffer(BufferPtr buff, PtrSize offset, IndexType type)
 	Bool bindIndexBuffer(BufferPtr buff, PtrSize offset, IndexType type)
 	{
 	{
-		m_idx.m_buff = buff->m_impl.get();
+		m_idx.m_buff = static_cast<BufferImpl*>(buff.get());
 		m_idx.m_offset = offset;
 		m_idx.m_offset = offset;
 		m_idx.m_indexType = convertIndexType(type);
 		m_idx.m_indexType = convertIndexType(type);
 		return true;
 		return true;
@@ -452,7 +458,7 @@ public:
 		U32 set, U32 binding, TexturePtr tex, DepthStencilAspectBit aspect, Bool& texChanged, Bool& samplerChanged)
 		U32 set, U32 binding, TexturePtr tex, DepthStencilAspectBit aspect, Bool& texChanged, Bool& samplerChanged)
 	{
 	{
 		TextureBinding& b = m_textures[set][binding];
 		TextureBinding& b = m_textures[set][binding];
-		TextureImpl* texi = tex->m_impl.get();
+		TextureImpl* texi = static_cast<TextureImpl*>(tex.get());
 
 
 		texChanged = false;
 		texChanged = false;
 		samplerChanged = false;
 		samplerChanged = false;
@@ -476,8 +482,8 @@ public:
 	Bool bindTextureAndSampler(U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, DepthStencilAspectBit aspect)
 	Bool bindTextureAndSampler(U32 set, U32 binding, TexturePtr tex, SamplerPtr sampler, DepthStencilAspectBit aspect)
 	{
 	{
 		TextureBinding& b = m_textures[set][binding];
 		TextureBinding& b = m_textures[set][binding];
-		b.m_tex = tex->m_impl.get();
-		b.m_sampler = sampler->m_impl.get();
+		b.m_tex = static_cast<TextureImpl*>(tex.get());
+		b.m_sampler = static_cast<SamplerImpl*>(sampler.get());
 		b.m_aspect = aspect;
 		b.m_aspect = aspect;
 		return true;
 		return true;
 	}
 	}
@@ -495,7 +501,7 @@ public:
 	Bool bindUniformBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
 	Bool bindUniformBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
 	{
 	{
 		ShaderBufferBinding& b = m_ubos[set][binding];
 		ShaderBufferBinding& b = m_ubos[set][binding];
-		b.m_buff = buff->m_impl.get();
+		b.m_buff = static_cast<BufferImpl*>(buff.get());
 		b.m_offset = offset;
 		b.m_offset = offset;
 		b.m_range = range;
 		b.m_range = range;
 		return true;
 		return true;
@@ -506,7 +512,7 @@ public:
 	Bool bindStorageBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
 	Bool bindStorageBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
 	{
 	{
 		ShaderBufferBinding& b = m_ssbos[set][binding];
 		ShaderBufferBinding& b = m_ssbos[set][binding];
-		b.m_buff = buff->m_impl.get();
+		b.m_buff = static_cast<BufferImpl*>(buff.get());
 		b.m_offset = offset;
 		b.m_offset = offset;
 		b.m_range = range;
 		b.m_range = range;
 		return true;
 		return true;
@@ -524,7 +530,7 @@ public:
 	Bool bindImage(U32 set, U32 binding, TexturePtr img, U32 level)
 	Bool bindImage(U32 set, U32 binding, TexturePtr img, U32 level)
 	{
 	{
 		ImageBinding& b = m_images[set][binding];
 		ImageBinding& b = m_images[set][binding];
-		b.m_tex = img->m_impl.get();
+		b.m_tex = static_cast<TextureImpl*>(img.get());
 		b.m_level = level;
 		b.m_level = level;
 		return true;
 		return true;
 	}
 	}
@@ -533,9 +539,10 @@ public:
 
 
 	Bool bindShaderProgram(ShaderProgramPtr prog)
 	Bool bindShaderProgram(ShaderProgramPtr prog)
 	{
 	{
-		if(prog->m_impl.get() != m_prog)
+		ShaderProgramImpl* const progimpl = static_cast<ShaderProgramImpl*>(prog.get());
+		if(progimpl != m_prog)
 		{
 		{
-			m_prog = prog->m_impl.get();
+			m_prog = progimpl;
 			return true;
 			return true;
 		}
 		}
 		return false;
 		return false;
@@ -544,12 +551,12 @@ public:
 
 
 	/// @name other
 	/// @name other
 	/// @{
 	/// @{
-	FramebufferImpl* m_fb = nullptr;
+	const FramebufferImpl* m_fb = nullptr;
 
 
 	Bool beginRenderPass(const FramebufferPtr& fb)
 	Bool beginRenderPass(const FramebufferPtr& fb)
 	{
 	{
 		ANKI_ASSERT(!insideRenderPass() && "Already inside a renderpass");
 		ANKI_ASSERT(!insideRenderPass() && "Already inside a renderpass");
-		m_fb = fb->m_impl.get();
+		m_fb = static_cast<const FramebufferImpl*>(fb.get());
 		m_lastSecondLevelCmdb = nullptr;
 		m_lastSecondLevelCmdb = nullptr;
 		return true;
 		return true;
 	}
 	}

+ 28 - 38
src/anki/gr/gl/Texture.cpp

@@ -11,54 +11,44 @@
 namespace anki
 namespace anki
 {
 {
 
 
-Texture::Texture(GrManager* manager)
-	: GrObject(manager, CLASS_TYPE)
+Texture* Texture::newInstance(GrManager* manager, const TextureInitInfo& init)
 {
 {
-}
-
-Texture::~Texture()
-{
-}
-
-class CreateTextureCommand final : public GlCommand
-{
-public:
-	IntrusivePtr<Texture> m_tex;
-	TextureInitInfo m_init;
-
-	CreateTextureCommand(Texture* tex, const TextureInitInfo& init)
-		: m_tex(tex)
-		, m_init(init)
+	class CreateTextureCommand final : public GlCommand
 	{
 	{
-	}
+	public:
+		TexturePtr m_tex;
+		TextureInitInfo m_init;
 
 
-	Error operator()(GlState&)
-	{
-		TextureImpl& impl = *m_tex->m_impl;
+		CreateTextureCommand(Texture* tex, const TextureInitInfo& init)
+			: m_tex(tex)
+			, m_init(init)
+		{
+		}
 
 
-		impl.init(m_init);
+		Error operator()(GlState&)
+		{
+			TextureImpl& impl = static_cast<TextureImpl&>(*m_tex);
 
 
-		GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
-		ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
-		(void)oldState;
+			impl.init(m_init);
 
 
-		return Error::NONE;
-	}
-};
+			GlObject::State oldState = impl.setStateAtomically(GlObject::State::CREATED);
+			ANKI_ASSERT(oldState == GlObject::State::TO_BE_CREATED);
+			(void)oldState;
 
 
-void Texture::init(const TextureInitInfo& init)
-{
-	ANKI_ASSERT(textureInitInfoValid(init));
-	m_impl.reset(getAllocator().newInstance<TextureImpl>(&getManager()));
+			return Error::NONE;
+		}
+	};
+
+	TextureImpl* impl = manager->getAllocator().newInstance<TextureImpl>(manager);
 
 
-	// Need to pre-init because some funcs ask for members and we don't want
-	// to serialize
-	m_impl->preInit(init);
+	// Need to pre-init because some funcs ask for members and we don't want to serialize
+	impl->preInit(init);
 
 
-	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
+	CommandBufferPtr cmdb = manager->newCommandBuffer(CommandBufferInitInfo());
+	static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CreateTextureCommand>(impl, init);
+	static_cast<CommandBufferImpl&>(*cmdb).flush();
 
 
-	cmdb->m_impl->pushBackNewCommand<CreateTextureCommand>(this, init);
-	cmdb->flush();
+	return impl;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 36 - 32
src/anki/gr/gl/TextureImpl.cpp

@@ -39,6 +39,8 @@ static GLenum convertTextureType(TextureType type)
 	case TextureType::CUBE_ARRAY:
 	case TextureType::CUBE_ARRAY:
 		out = GL_TEXTURE_CUBE_MAP_ARRAY;
 		out = GL_TEXTURE_CUBE_MAP_ARRAY;
 		break;
 		break;
+	default:
+		ANKI_ASSERT(0);
 	};
 	};
 
 
 	return out;
 	return out;
@@ -86,26 +88,27 @@ public:
 TextureImpl::~TextureImpl()
 TextureImpl::~TextureImpl()
 {
 {
 	GrManager& manager = getManager();
 	GrManager& manager = getManager();
-	RenderingThread& thread = manager.getImplementation().getRenderingThread();
+	RenderingThread& thread = static_cast<GrManagerImpl&>(manager).getRenderingThread();
 
 
 	if(!thread.isServerThread())
 	if(!thread.isServerThread())
 	{
 	{
 		CommandBufferPtr commands;
 		CommandBufferPtr commands;
 
 
-		commands = manager.newInstance<CommandBuffer>(CommandBufferInitInfo());
-		commands->m_impl->pushBackNewCommand<DeleteTextureCommand>(m_glName, m_texViews, getAllocator());
-		commands->flush();
+		commands = manager.newCommandBuffer(CommandBufferInitInfo());
+		static_cast<CommandBufferImpl&>(*commands).pushBackNewCommand<DeleteTextureCommand>(
+			m_glName, m_texViews, getAllocator());
+		static_cast<CommandBufferImpl&>(*commands).flush();
 	}
 	}
 	else
 	else
 	{
 	{
 		DeleteTextureCommand cmd(m_glName, m_texViews, getAllocator());
 		DeleteTextureCommand cmd(m_glName, m_texViews, getAllocator());
-		cmd(manager.getImplementation().getState());
+		cmd(static_cast<GrManagerImpl&>(manager).getState());
 	}
 	}
 
 
 	m_glName = 0;
 	m_glName = 0;
 }
 }
 
 
-void TextureImpl::bind()
+void TextureImpl::bind() const
 {
 {
 	glActiveTexture(GL_TEXTURE0);
 	glActiveTexture(GL_TEXTURE0);
 	glBindTexture(m_target, m_glName);
 	glBindTexture(m_target, m_glName);
@@ -121,17 +124,17 @@ void TextureImpl::preInit(const TextureInitInfo& init)
 	m_layerCount = init.m_layerCount;
 	m_layerCount = init.m_layerCount;
 	m_target = convertTextureType(init.m_type);
 	m_target = convertTextureType(init.m_type);
 	m_texType = init.m_type;
 	m_texType = init.m_type;
-	m_pformat = init.m_format;
+	m_format = init.m_format;
 
 
-	convertTextureInformation(init.m_format, m_compressed, m_format, m_internalFormat, m_type, m_dsAspect);
+	convertTextureInformation(init.m_format, m_compressed, m_glFormat, m_internalFormat, m_glType, m_dsAspect);
 
 
 	if(m_target != GL_TEXTURE_3D)
 	if(m_target != GL_TEXTURE_3D)
 	{
 	{
-		m_mipsCount = min<U>(init.m_mipmapsCount, computeMaxMipmapCount2d(m_width, m_height));
+		m_mipCount = min<U>(init.m_mipmapsCount, computeMaxMipmapCount2d(m_width, m_height));
 	}
 	}
 	else
 	else
 	{
 	{
-		m_mipsCount = min<U>(init.m_mipmapsCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
+		m_mipCount = min<U>(init.m_mipmapsCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
 	}
 	}
 
 
 	// Surface count
 	// Surface count
@@ -183,16 +186,16 @@ void TextureImpl::init(const TextureInitInfo& init)
 	{
 	{
 	case GL_TEXTURE_2D:
 	case GL_TEXTURE_2D:
 	case GL_TEXTURE_CUBE_MAP:
 	case GL_TEXTURE_CUBE_MAP:
-		glTexStorage2D(m_target, m_mipsCount, m_internalFormat, m_width, m_height);
+		glTexStorage2D(m_target, m_mipCount, m_internalFormat, m_width, m_height);
 		break;
 		break;
 	case GL_TEXTURE_CUBE_MAP_ARRAY:
 	case GL_TEXTURE_CUBE_MAP_ARRAY:
-		glTexStorage3D(m_target, m_mipsCount, m_internalFormat, m_width, m_height, m_layerCount * 6);
+		glTexStorage3D(m_target, m_mipCount, m_internalFormat, m_width, m_height, m_layerCount * 6);
 		break;
 		break;
 	case GL_TEXTURE_2D_ARRAY:
 	case GL_TEXTURE_2D_ARRAY:
-		glTexStorage3D(m_target, m_mipsCount, m_internalFormat, m_width, m_height, m_layerCount);
+		glTexStorage3D(m_target, m_mipCount, m_internalFormat, m_width, m_height, m_layerCount);
 		break;
 		break;
 	case GL_TEXTURE_3D:
 	case GL_TEXTURE_3D:
-		glTexStorage3D(m_target, m_mipsCount, m_internalFormat, m_width, m_height, m_depth);
+		glTexStorage3D(m_target, m_mipCount, m_internalFormat, m_width, m_height, m_depth);
 		break;
 		break;
 	case GL_TEXTURE_2D_MULTISAMPLE:
 	case GL_TEXTURE_2D_MULTISAMPLE:
 		glTexStorage2DMultisample(m_target, init.m_samples, m_internalFormat, m_width, m_height, GL_FALSE);
 		glTexStorage2DMultisample(m_target, init.m_samples, m_internalFormat, m_width, m_height, GL_FALSE);
@@ -218,7 +221,7 @@ void TextureImpl::init(const TextureInitInfo& init)
 		}
 		}
 
 
 		// Make sure that the texture is complete
 		// Make sure that the texture is complete
-		glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, m_mipsCount - 1);
+		glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, m_mipCount - 1);
 
 
 		// Set filtering type
 		// Set filtering type
 		GLenum minFilter = GL_NONE;
 		GLenum minFilter = GL_NONE;
@@ -269,33 +272,34 @@ void TextureImpl::writeSurface(const TextureSurfaceInfo& surf, GLuint pbo, PtrSi
 	case GL_TEXTURE_2D:
 	case GL_TEXTURE_2D:
 		if(!m_compressed)
 		if(!m_compressed)
 		{
 		{
-			glTexSubImage2D(m_target, mipmap, 0, 0, w, h, m_format, m_type, ptrOffset);
+			glTexSubImage2D(m_target, mipmap, 0, 0, w, h, m_glFormat, m_glType, ptrOffset);
 		}
 		}
 		else
 		else
 		{
 		{
-			glCompressedTexSubImage2D(m_target, mipmap, 0, 0, w, h, m_format, dataSize, ptrOffset);
+			glCompressedTexSubImage2D(m_target, mipmap, 0, 0, w, h, m_glFormat, dataSize, ptrOffset);
 		}
 		}
 		break;
 		break;
 	case GL_TEXTURE_CUBE_MAP:
 	case GL_TEXTURE_CUBE_MAP:
 		if(!m_compressed)
 		if(!m_compressed)
 		{
 		{
-			glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + surfIdx, mipmap, 0, 0, w, h, m_format, m_type, ptrOffset);
+			glTexSubImage2D(
+				GL_TEXTURE_CUBE_MAP_POSITIVE_X + surfIdx, mipmap, 0, 0, w, h, m_glFormat, m_glType, ptrOffset);
 		}
 		}
 		else
 		else
 		{
 		{
 			glCompressedTexSubImage2D(
 			glCompressedTexSubImage2D(
-				GL_TEXTURE_CUBE_MAP_POSITIVE_X + surfIdx, mipmap, 0, 0, w, h, m_format, dataSize, ptrOffset);
+				GL_TEXTURE_CUBE_MAP_POSITIVE_X + surfIdx, mipmap, 0, 0, w, h, m_glFormat, dataSize, ptrOffset);
 		}
 		}
 		break;
 		break;
 	case GL_TEXTURE_2D_ARRAY:
 	case GL_TEXTURE_2D_ARRAY:
 	case GL_TEXTURE_3D:
 	case GL_TEXTURE_3D:
 		if(!m_compressed)
 		if(!m_compressed)
 		{
 		{
-			glTexSubImage3D(m_target, mipmap, 0, 0, surfIdx, w, h, 1, m_format, m_type, ptrOffset);
+			glTexSubImage3D(m_target, mipmap, 0, 0, surfIdx, w, h, 1, m_glFormat, m_glType, ptrOffset);
 		}
 		}
 		else
 		else
 		{
 		{
-			glCompressedTexSubImage3D(m_target, mipmap, 0, 0, surfIdx, w, h, 1, m_format, dataSize, ptrOffset);
+			glCompressedTexSubImage3D(m_target, mipmap, 0, 0, surfIdx, w, h, 1, m_glFormat, dataSize, ptrOffset);
 		}
 		}
 		break;
 		break;
 	default:
 	default:
@@ -306,7 +310,7 @@ void TextureImpl::writeSurface(const TextureSurfaceInfo& surf, GLuint pbo, PtrSi
 	ANKI_CHECK_GL_ERROR();
 	ANKI_CHECK_GL_ERROR();
 }
 }
 
 
-void TextureImpl::writeVolume(const TextureVolumeInfo& vol, GLuint pbo, PtrSize offset, PtrSize dataSize)
+void TextureImpl::writeVolume(const TextureVolumeInfo& vol, GLuint pbo, PtrSize offset, PtrSize dataSize) const
 {
 {
 	checkSurfaceOrVolume(vol);
 	checkSurfaceOrVolume(vol);
 	ANKI_ASSERT(dataSize > 0);
 	ANKI_ASSERT(dataSize > 0);
@@ -326,11 +330,11 @@ void TextureImpl::writeVolume(const TextureVolumeInfo& vol, GLuint pbo, PtrSize
 
 
 	if(!m_compressed)
 	if(!m_compressed)
 	{
 	{
-		glTexSubImage3D(m_target, mipmap, 0, 0, 0, w, h, d, m_format, m_type, ptrOffset);
+		glTexSubImage3D(m_target, mipmap, 0, 0, 0, w, h, d, m_glFormat, m_glType, ptrOffset);
 	}
 	}
 	else
 	else
 	{
 	{
-		glCompressedTexSubImage3D(m_target, mipmap, 0, 0, 0, w, h, d, m_format, dataSize, ptrOffset);
+		glCompressedTexSubImage3D(m_target, mipmap, 0, 0, 0, w, h, d, m_glFormat, dataSize, ptrOffset);
 	}
 	}
 
 
 	glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 	glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
@@ -369,7 +373,7 @@ void TextureImpl::generateMipmaps2d(U face, U layer)
 				ANKI_ASSERT(0);
 				ANKI_ASSERT(0);
 			}
 			}
 
 
-			glTextureView(m_texViews[surface], target, m_glName, m_internalFormat, 0, m_mipsCount, surface, 1);
+			glTextureView(m_texViews[surface], target, m_glName, m_internalFormat, 0, m_mipCount, surface, 1);
 		}
 		}
 
 
 		glGenerateTextureMipmap(m_texViews[surface]);
 		glGenerateTextureMipmap(m_texViews[surface]);
@@ -386,8 +390,8 @@ void TextureImpl::copy(const TextureImpl& src,
 	const TextureSurfaceInfo& destSurf)
 	const TextureSurfaceInfo& destSurf)
 {
 {
 	ANKI_ASSERT(src.m_internalFormat == dest.m_internalFormat);
 	ANKI_ASSERT(src.m_internalFormat == dest.m_internalFormat);
-	ANKI_ASSERT(src.m_format == dest.m_format);
-	ANKI_ASSERT(src.m_type == dest.m_type);
+	ANKI_ASSERT(src.m_glFormat == dest.m_glFormat);
+	ANKI_ASSERT(src.m_glType == dest.m_glType);
 
 
 	U width = src.m_width >> srcSurf.m_level;
 	U width = src.m_width >> srcSurf.m_level;
 	U height = src.m_height >> srcSurf.m_level;
 	U height = src.m_height >> srcSurf.m_level;
@@ -418,29 +422,29 @@ void TextureImpl::copy(const TextureImpl& src,
 void TextureImpl::clear(const TextureSurfaceInfo& surf, const ClearValue& clearValue, DepthStencilAspectBit aspect)
 void TextureImpl::clear(const TextureSurfaceInfo& surf, const ClearValue& clearValue, DepthStencilAspectBit aspect)
 {
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(isCreated());
-	ANKI_ASSERT(surf.m_level < m_mipsCount);
+	ANKI_ASSERT(surf.m_level < m_mipCount);
 	ANKI_ASSERT((aspect & m_dsAspect) == aspect);
 	ANKI_ASSERT((aspect & m_dsAspect) == aspect);
 
 
 	// Find the aspect to clear
 	// Find the aspect to clear
 	GLenum format;
 	GLenum format;
 	if(aspect == DepthStencilAspectBit::DEPTH)
 	if(aspect == DepthStencilAspectBit::DEPTH)
 	{
 	{
-		ANKI_ASSERT(m_format == GL_DEPTH_COMPONENT || m_format == GL_DEPTH_STENCIL);
+		ANKI_ASSERT(m_glFormat == GL_DEPTH_COMPONENT || m_glFormat == GL_DEPTH_STENCIL);
 		format = GL_DEPTH_COMPONENT;
 		format = GL_DEPTH_COMPONENT;
 	}
 	}
 	else if(aspect == DepthStencilAspectBit::STENCIL)
 	else if(aspect == DepthStencilAspectBit::STENCIL)
 	{
 	{
-		ANKI_ASSERT(m_format == GL_STENCIL_INDEX || m_format == GL_DEPTH_STENCIL);
+		ANKI_ASSERT(m_glFormat == GL_STENCIL_INDEX || m_glFormat == GL_DEPTH_STENCIL);
 		format = GL_STENCIL_INDEX;
 		format = GL_STENCIL_INDEX;
 	}
 	}
 	else if(aspect == DepthStencilAspectBit::DEPTH_STENCIL)
 	else if(aspect == DepthStencilAspectBit::DEPTH_STENCIL)
 	{
 	{
-		ANKI_ASSERT(m_format == GL_DEPTH_STENCIL);
+		ANKI_ASSERT(m_glFormat == GL_DEPTH_STENCIL);
 		format = GL_DEPTH_STENCIL;
 		format = GL_DEPTH_STENCIL;
 	}
 	}
 	else
 	else
 	{
 	{
-		format = m_format;
+		format = m_glFormat;
 	}
 	}
 
 
 	U surfaceIdx = computeSurfaceIdx(surf);
 	U surfaceIdx = computeSurfaceIdx(surf);

+ 9 - 15
src/anki/gr/gl/TextureImpl.h

@@ -5,6 +5,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <anki/gr/Texture.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/gl/GlObject.h>
 #include <anki/gr/common/Misc.h>
 #include <anki/gr/common/Misc.h>
 #include <anki/util/DynamicArray.h>
 #include <anki/util/DynamicArray.h>
@@ -16,28 +17,21 @@ namespace anki
 /// @{
 /// @{
 
 
 /// Texture container.
 /// Texture container.
-class TextureImpl : public GlObject
+class TextureImpl final : public Texture, public GlObject
 {
 {
 public:
 public:
 	GLenum m_target = GL_NONE; ///< GL_TEXTURE_2D, GL_TEXTURE_3D... etc
 	GLenum m_target = GL_NONE; ///< GL_TEXTURE_2D, GL_TEXTURE_3D... etc
 	GLenum m_internalFormat = GL_NONE; ///< GL_COMPRESSED_RED, GL_RGB16 etc
 	GLenum m_internalFormat = GL_NONE; ///< GL_COMPRESSED_RED, GL_RGB16 etc
-	GLenum m_format = GL_NONE;
-	GLenum m_type = GL_NONE;
-	TextureType m_texType = TextureType::_1D;
-	U32 m_width = 0;
-	U32 m_height = 0;
-	U32 m_depth = 0;
-	U32 m_layerCount = 0;
+	GLenum m_glFormat = GL_NONE;
+	GLenum m_glType = GL_NONE;
 	U32 m_surfaceCountPerLevel = 0;
 	U32 m_surfaceCountPerLevel = 0;
-	U8 m_mipsCount = 0;
 	U8 m_faceCount = 0; ///< 6 for cubes and 1 for the rest
 	U8 m_faceCount = 0; ///< 6 for cubes and 1 for the rest
 	Bool8 m_compressed = false;
 	Bool8 m_compressed = false;
-	PixelFormat m_pformat;
 	DynamicArray<GLuint> m_texViews; ///< Temp views for gen mips.
 	DynamicArray<GLuint> m_texViews; ///< Temp views for gen mips.
 	DepthStencilAspectBit m_dsAspect = DepthStencilAspectBit::NONE;
 	DepthStencilAspectBit m_dsAspect = DepthStencilAspectBit::NONE;
 
 
 	TextureImpl(GrManager* manager)
 	TextureImpl(GrManager* manager)
-		: GlObject(manager)
+		: Texture(manager)
 	{
 	{
 	}
 	}
 
 
@@ -45,13 +39,13 @@ public:
 
 
 	void checkSurfaceOrVolume(const TextureSurfaceInfo& surf) const
 	void checkSurfaceOrVolume(const TextureSurfaceInfo& surf) const
 	{
 	{
-		checkTextureSurface(m_texType, m_depth, m_mipsCount, m_layerCount, surf);
+		checkTextureSurface(m_texType, m_depth, m_mipCount, m_layerCount, surf);
 	}
 	}
 
 
 	void checkSurfaceOrVolume(const TextureVolumeInfo& vol) const
 	void checkSurfaceOrVolume(const TextureVolumeInfo& vol) const
 	{
 	{
 		ANKI_ASSERT(m_texType == TextureType::_3D);
 		ANKI_ASSERT(m_texType == TextureType::_3D);
-		ANKI_ASSERT(vol.m_level < m_mipsCount);
+		ANKI_ASSERT(vol.m_level < m_mipCount);
 	}
 	}
 
 
 	/// Init some stuff.
 	/// Init some stuff.
@@ -64,7 +58,7 @@ public:
 	void writeSurface(const TextureSurfaceInfo& surf, GLuint pbo, PtrSize offset, PtrSize dataSize);
 	void writeSurface(const TextureSurfaceInfo& surf, GLuint pbo, PtrSize offset, PtrSize dataSize);
 
 
 	/// Write texture data.
 	/// Write texture data.
-	void writeVolume(const TextureVolumeInfo& vol, GLuint pbo, PtrSize offset, PtrSize dataSize);
+	void writeVolume(const TextureVolumeInfo& vol, GLuint pbo, PtrSize offset, PtrSize dataSize) const;
 
 
 	/// Generate mipmaps.
 	/// Generate mipmaps.
 	void generateMipmaps2d(U face, U layer);
 	void generateMipmaps2d(U face, U layer);
@@ -75,7 +69,7 @@ public:
 		const TextureImpl& dest,
 		const TextureImpl& dest,
 		const TextureSurfaceInfo& destSurf);
 		const TextureSurfaceInfo& destSurf);
 
 
-	void bind();
+	void bind() const;
 
 
 	void clear(const TextureSurfaceInfo& surf, const ClearValue& clearValue, DepthStencilAspectBit aspect);
 	void clear(const TextureSurfaceInfo& surf, const ClearValue& clearValue, DepthStencilAspectBit aspect);
 
 

+ 0 - 3
src/anki/gr/vulkan/BufferImpl.h

@@ -68,10 +68,7 @@ public:
 private:
 private:
 	VkBuffer m_handle = VK_NULL_HANDLE;
 	VkBuffer m_handle = VK_NULL_HANDLE;
 	GpuMemoryHandle m_memHandle;
 	GpuMemoryHandle m_memHandle;
-	BufferMapAccessBit m_access = BufferMapAccessBit::NONE;
-	U32 m_size = 0;
 	VkMemoryPropertyFlags m_memoryFlags = 0;
 	VkMemoryPropertyFlags m_memoryFlags = 0;
-	BufferUsageBit m_usage = BufferUsageBit::NONE;
 
 
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 	Bool8 m_mapped = false;
 	Bool8 m_mapped = false;

+ 19 - 19
src/anki/gr/vulkan/CommandBufferImpl.cpp

@@ -292,9 +292,9 @@ void CommandBufferImpl::generateMipmaps2d(TexturePtr tex, U face, U layer)
 	commandCommon();
 	commandCommon();
 
 
 	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
 	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
-	ANKI_ASSERT(impl.m_type != TextureType::_3D && "Not for 3D");
+	ANKI_ASSERT(impl.getTextureType() != TextureType::_3D && "Not for 3D");
 
 
-	for(U i = 0; i < impl.m_mipCount - 1u; ++i)
+	for(U i = 0; i < impl.getMipmapCount() - 1u; ++i)
 	{
 	{
 		// Transition source
 		// Transition source
 		if(i > 0)
 		if(i > 0)
@@ -328,16 +328,16 @@ void CommandBufferImpl::generateMipmaps2d(TexturePtr tex, U face, U layer)
 		}
 		}
 
 
 		// Setup the blit struct
 		// Setup the blit struct
-		I32 srcWidth = impl.m_width >> i;
-		I32 srcHeight = impl.m_height >> i;
+		I32 srcWidth = impl.getWidth() >> i;
+		I32 srcHeight = impl.getHeight() >> i;
 
 
-		I32 dstWidth = impl.m_width >> (i + 1);
-		I32 dstHeight = impl.m_height >> (i + 1);
+		I32 dstWidth = impl.getWidth() >> (i + 1);
+		I32 dstHeight = impl.getHeight() >> (i + 1);
 
 
 		ANKI_ASSERT(srcWidth > 0 && srcHeight > 0 && dstWidth > 0 && dstHeight > 0);
 		ANKI_ASSERT(srcWidth > 0 && srcHeight > 0 && dstWidth > 0 && dstHeight > 0);
 
 
 		U vkLayer = 0;
 		U vkLayer = 0;
-		switch(impl.m_type)
+		switch(impl.getTextureType())
 		{
 		{
 		case TextureType::_2D:
 		case TextureType::_2D:
 		case TextureType::_2D_ARRAY:
 		case TextureType::_2D_ARRAY:
@@ -654,9 +654,9 @@ void CommandBufferImpl::copyBufferToTextureSurface(
 
 
 	if(!impl.m_workarounds)
 	if(!impl.m_workarounds)
 	{
 	{
-		U width = impl.m_width >> surf.m_level;
-		U height = impl.m_height >> surf.m_level;
-		ANKI_ASSERT(range == computeSurfaceSize(width, height, impl.m_format));
+		U width = impl.getWidth() >> surf.m_level;
+		U height = impl.getHeight() >> surf.m_level;
+		ANKI_ASSERT(range == computeSurfaceSize(width, height, impl.getPixelFormat()));
 
 
 		// Copy
 		// Copy
 		VkBufferImageCopy region;
 		VkBufferImageCopy region;
@@ -679,8 +679,8 @@ void CommandBufferImpl::copyBufferToTextureSurface(
 	}
 	}
 	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
 	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
 	{
 	{
-		U width = impl.m_width >> surf.m_level;
-		U height = impl.m_height >> surf.m_level;
+		U width = impl.getWidth() >> surf.m_level;
+		U height = impl.getHeight() >> surf.m_level;
 
 
 		// Create a new shadow buffer
 		// Create a new shadow buffer
 		const PtrSize shadowSize =
 		const PtrSize shadowSize =
@@ -760,10 +760,10 @@ void CommandBufferImpl::copyBufferToTextureVolume(
 
 
 	if(!impl.m_workarounds)
 	if(!impl.m_workarounds)
 	{
 	{
-		U width = impl.m_width >> vol.m_level;
-		U height = impl.m_height >> vol.m_level;
-		U depth = impl.m_depth >> vol.m_level;
-		ANKI_ASSERT(range == computeVolumeSize(width, height, depth, impl.m_format));
+		U width = impl.getWidth() >> vol.m_level;
+		U height = impl.getHeight() >> vol.m_level;
+		U depth = impl.getDepth() >> vol.m_level;
+		ANKI_ASSERT(range == computeVolumeSize(width, height, depth, impl.getPixelFormat()));
 
 
 		// Copy
 		// Copy
 		VkBufferImageCopy region;
 		VkBufferImageCopy region;
@@ -787,9 +787,9 @@ void CommandBufferImpl::copyBufferToTextureVolume(
 	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
 	else if(!!(impl.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
 	{
 	{
 		// Find the offset to the RGBA staging buff
 		// Find the offset to the RGBA staging buff
-		U width = impl.m_width >> vol.m_level;
-		U height = impl.m_height >> vol.m_level;
-		U depth = impl.m_depth >> vol.m_level;
+		U width = impl.getWidth() >> vol.m_level;
+		U height = impl.getHeight() >> vol.m_level;
+		U depth = impl.getDepth() >> vol.m_level;
 
 
 		// Create a new shadow buffer
 		// Create a new shadow buffer
 		const PtrSize shadowSize =
 		const PtrSize shadowSize =

+ 2 - 2
src/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -403,7 +403,7 @@ inline void CommandBufferImpl::clearTextureSurface(
 	TexturePtr tex, const TextureSurfaceInfo& surf, const ClearValue& clearValue, DepthStencilAspectBit aspect)
 	TexturePtr tex, const TextureSurfaceInfo& surf, const ClearValue& clearValue, DepthStencilAspectBit aspect)
 {
 {
 	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
 	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
-	ANKI_ASSERT(impl.m_type != TextureType::_3D && "Not for 3D");
+	ANKI_ASSERT(impl.getTextureType() != TextureType::_3D && "Not for 3D");
 
 
 	VkImageSubresourceRange range;
 	VkImageSubresourceRange range;
 	impl.computeSubResourceRange(surf, aspect, range);
 	impl.computeSubResourceRange(surf, aspect, range);
@@ -414,7 +414,7 @@ inline void CommandBufferImpl::clearTextureVolume(
 	TexturePtr tex, const TextureVolumeInfo& vol, const ClearValue& clearValue, DepthStencilAspectBit aspect)
 	TexturePtr tex, const TextureVolumeInfo& vol, const ClearValue& clearValue, DepthStencilAspectBit aspect)
 {
 {
 	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
 	const TextureImpl& impl = static_cast<const TextureImpl&>(*tex);
-	ANKI_ASSERT(impl.m_type == TextureType::_3D && "Only for 3D");
+	ANKI_ASSERT(impl.getTextureType() == TextureType::_3D && "Only for 3D");
 
 
 	VkImageSubresourceRange range;
 	VkImageSubresourceRange range;
 	impl.computeSubResourceRange(vol, aspect, range);
 	impl.computeSubResourceRange(vol, aspect, range);

+ 5 - 5
src/anki/gr/vulkan/FramebufferImpl.cpp

@@ -146,8 +146,8 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 
 
 		if(m_noDflt.m_width == 0)
 		if(m_noDflt.m_width == 0)
 		{
 		{
-			m_noDflt.m_width = tex.m_width >> att.m_surface.m_level;
-			m_noDflt.m_height = tex.m_height >> att.m_surface.m_level;
+			m_noDflt.m_width = tex.getWidth() >> att.m_surface.m_level;
+			m_noDflt.m_height = tex.getHeight() >> att.m_surface.m_level;
 		}
 		}
 
 
 		m_noDflt.m_refs[i] = att.m_texture;
 		m_noDflt.m_refs[i] = att.m_texture;
@@ -162,8 +162,8 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 
 
 		if(m_noDflt.m_width == 0)
 		if(m_noDflt.m_width == 0)
 		{
 		{
-			m_noDflt.m_width = tex.m_width >> att.m_surface.m_level;
-			m_noDflt.m_height = tex.m_height >> att.m_surface.m_level;
+			m_noDflt.m_width = tex.getWidth() >> att.m_surface.m_level;
+			m_noDflt.m_height = tex.getHeight() >> att.m_surface.m_level;
 		}
 		}
 
 
 		m_noDflt.m_refs[MAX_COLOR_ATTACHMENTS] = att.m_texture;
 		m_noDflt.m_refs[MAX_COLOR_ATTACHMENTS] = att.m_texture;
@@ -186,7 +186,7 @@ void FramebufferImpl::setupAttachmentDescriptor(
 	const FramebufferAttachmentInfo& att, VkAttachmentDescription& desc, VkImageLayout layout) const
 	const FramebufferAttachmentInfo& att, VkAttachmentDescription& desc, VkImageLayout layout) const
 {
 {
 	desc = {};
 	desc = {};
-	desc.format = convertFormat(static_cast<const TextureImpl&>(*att.m_texture).m_format);
+	desc.format = convertFormat(att.m_texture->getPixelFormat());
 	desc.samples = VK_SAMPLE_COUNT_1_BIT;
 	desc.samples = VK_SAMPLE_COUNT_1_BIT;
 	desc.loadOp = convertLoadOp(att.m_loadOperation);
 	desc.loadOp = convertLoadOp(att.m_loadOperation);
 	desc.storeOp = convertStoreOp(att.m_storeOperation);
 	desc.storeOp = convertStoreOp(att.m_storeOperation);

+ 4 - 6
src/anki/gr/vulkan/TextureImpl.cpp

@@ -58,7 +58,7 @@ Error TextureImpl::init(const TextureInitInfo& init_)
 	m_width = init.m_width;
 	m_width = init.m_width;
 	m_height = init.m_height;
 	m_height = init.m_height;
 	m_depth = init.m_depth;
 	m_depth = init.m_depth;
-	m_type = init.m_type;
+	m_texType = init.m_type;
 	if(init.getName())
 	if(init.getName())
 	{
 	{
 		strcpy(&m_name[0], init.getName().cstr());
 		strcpy(&m_name[0], init.getName().cstr());
@@ -68,7 +68,7 @@ Error TextureImpl::init(const TextureInitInfo& init_)
 		m_name[0] = '\0';
 		m_name[0] = '\0';
 	}
 	}
 
 
-	if(m_type == TextureType::_3D)
+	if(m_texType == TextureType::_3D)
 	{
 	{
 		m_mipCount = min<U>(init.m_mipmapsCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
 		m_mipCount = min<U>(init.m_mipmapsCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
 	}
 	}
@@ -85,8 +85,6 @@ Error TextureImpl::init(const TextureInitInfo& init_)
 	m_depthStencil = formatIsDepthStencil(m_format);
 	m_depthStencil = formatIsDepthStencil(m_format);
 	m_aspect = convertImageAspect(m_format);
 	m_aspect = convertImageAspect(m_format);
 	m_usage = init.m_usage;
 	m_usage = init.m_usage;
-	m_usageWhenEncountered = init.m_usageWhenEncountered;
-	ANKI_ASSERT((m_usageWhenEncountered | m_usage) == m_usage);
 
 
 	if(m_aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
 	if(m_aspect & VK_IMAGE_ASPECT_DEPTH_BIT)
 	{
 	{
@@ -264,12 +262,12 @@ Error TextureImpl::initImage(const TextureInitInfo& init_)
 	VkImageCreateInfo ci = {};
 	VkImageCreateInfo ci = {};
 	ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 	ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 	ci.flags = calcCreateFlags(init);
 	ci.flags = calcCreateFlags(init);
-	ci.imageType = convertTextureType(m_type);
+	ci.imageType = convertTextureType(m_texType);
 	ci.format = m_vkFormat;
 	ci.format = m_vkFormat;
 	ci.extent.width = init.m_width;
 	ci.extent.width = init.m_width;
 	ci.extent.height = init.m_height;
 	ci.extent.height = init.m_height;
 
 
-	switch(m_type)
+	switch(m_texType)
 	{
 	{
 	case TextureType::_1D:
 	case TextureType::_1D:
 	case TextureType::_2D:
 	case TextureType::_2D:

+ 2 - 11
src/anki/gr/vulkan/TextureImpl.h

@@ -40,18 +40,9 @@ public:
 
 
 	GpuMemoryHandle m_memHandle;
 	GpuMemoryHandle m_memHandle;
 
 
-	U32 m_width = 0;
-	U32 m_height = 0;
-	U32 m_depth = 0;
-	TextureType m_type = TextureType::CUBE;
-	U8 m_mipCount = 0;
-	U32 m_layerCount = 0;
 	U32 m_surfaceOrVolumeCount = 0;
 	U32 m_surfaceOrVolumeCount = 0;
 	VkImageAspectFlags m_aspect = 0;
 	VkImageAspectFlags m_aspect = 0;
 	DepthStencilAspectBit m_akAspect = DepthStencilAspectBit::NONE;
 	DepthStencilAspectBit m_akAspect = DepthStencilAspectBit::NONE;
-	TextureUsageBit m_usage = TextureUsageBit::NONE;
-	TextureUsageBit m_usageWhenEncountered = TextureUsageBit::NONE;
-	PixelFormat m_format;
 	VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
 	VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
 
 
 	Bool m_depthStencil = false;
 	Bool m_depthStencil = false;
@@ -68,12 +59,12 @@ public:
 
 
 	void checkSurfaceOrVolume(const TextureSurfaceInfo& surf) const
 	void checkSurfaceOrVolume(const TextureSurfaceInfo& surf) const
 	{
 	{
-		checkTextureSurface(m_type, m_depth, m_mipCount, m_layerCount, surf);
+		checkTextureSurface(m_texType, m_depth, m_mipCount, m_layerCount, surf);
 	}
 	}
 
 
 	void checkSurfaceOrVolume(const TextureVolumeInfo& vol) const
 	void checkSurfaceOrVolume(const TextureVolumeInfo& vol) const
 	{
 	{
-		ANKI_ASSERT(m_type == TextureType::_3D);
+		ANKI_ASSERT(m_texType == TextureType::_3D);
 		ANKI_ASSERT(vol.m_level < m_mipCount);
 		ANKI_ASSERT(vol.m_level < m_mipCount);
 	}
 	}
 
 

+ 3 - 3
src/anki/gr/vulkan/TextureImpl.inl.h

@@ -33,7 +33,7 @@ inline void TextureImpl::computeSubResourceRange(
 	range.aspectMask = convertAspect(aspect);
 	range.aspectMask = convertAspect(aspect);
 	range.baseMipLevel = surf.m_level;
 	range.baseMipLevel = surf.m_level;
 	range.levelCount = 1;
 	range.levelCount = 1;
-	switch(m_type)
+	switch(m_texType)
 	{
 	{
 	case TextureType::_2D:
 	case TextureType::_2D:
 		range.baseArrayLayer = 0;
 		range.baseArrayLayer = 0;
@@ -72,7 +72,7 @@ inline U TextureImpl::computeVkArrayLayer(const TextureSurfaceInfo& surf) const
 {
 {
 	checkSurfaceOrVolume(surf);
 	checkSurfaceOrVolume(surf);
 	U layer = 0;
 	U layer = 0;
-	switch(m_type)
+	switch(m_texType)
 	{
 	{
 	case TextureType::_2D:
 	case TextureType::_2D:
 		layer = 0;
 		layer = 0;
@@ -100,7 +100,7 @@ inline U TextureImpl::computeSubresourceIdx(const TextureSurfaceInfo& surf) cons
 {
 {
 	checkSurfaceOrVolume(surf);
 	checkSurfaceOrVolume(surf);
 
 
-	switch(m_type)
+	switch(m_texType)
 	{
 	{
 	case TextureType::_1D:
 	case TextureType::_1D:
 	case TextureType::_2D:
 	case TextureType::_2D:

+ 0 - 2
src/anki/renderer/Indirect.cpp

@@ -207,7 +207,6 @@ Error Indirect::initLightShading(const ConfigSet& config)
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-		texinit.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
 
 
 		m_lightShading.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
 		m_lightShading.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
 	}
 	}
@@ -259,7 +258,6 @@ Error Indirect::initIrradiance(const ConfigSet& config)
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-		texinit.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
 
 
 		m_irradiance.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
 		m_irradiance.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
 	}
 	}

+ 0 - 1
src/anki/renderer/Renderer.cpp

@@ -92,7 +92,6 @@ Error Renderer::initInternal(const ConfigSet& config)
 		texinit.m_width = texinit.m_height = 4;
 		texinit.m_width = texinit.m_height = 4;
 		texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 		texinit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
-		texinit.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		m_dummyTex = getGrManager().newTexture(texinit);
 		m_dummyTex = getGrManager().newTexture(texinit);
 	}
 	}

+ 0 - 1
src/anki/resource/TextureResource.cpp

@@ -70,7 +70,6 @@ Error TextureResource::load(const ResourceFilename& filename, Bool async)
 	TextureInitInfo init("RsrcTex");
 	TextureInitInfo init("RsrcTex");
 	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION
 	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION
 		| TextureUsageBit::TRANSFER_DESTINATION;
 		| TextureUsageBit::TRANSFER_DESTINATION;
-	init.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_TESSELLATION_EVALUATION;
 	U faces = 0;
 	U faces = 0;
 
 
 	ResourceFilePtr file;
 	ResourceFilePtr file;

+ 0 - 1
src/anki/ui/Font.cpp

@@ -83,7 +83,6 @@ void Font::createTexture(const void* data, U32 width, U32 height)
 	texInit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	texInit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	texInit.m_usage =
 	texInit.m_usage =
 		TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::GENERATE_MIPMAPS;
 		TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::GENERATE_MIPMAPS;
-	texInit.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
 	texInit.m_mipmapsCount = 4;
 	texInit.m_mipmapsCount = 4;
 	texInit.m_sampling.m_minMagFilter = SamplingFilter::NEAREST;
 	texInit.m_sampling.m_minMagFilter = SamplingFilter::NEAREST;
 	texInit.m_sampling.m_mipmapFilter = SamplingFilter::NEAREST;
 	texInit.m_sampling.m_mipmapFilter = SamplingFilter::NEAREST;

+ 2 - 3
tests/framework/Framework.cpp

@@ -247,14 +247,13 @@ NativeWindow* createWindow(const Config& cfg)
 
 
 GrManager* createGrManager(const Config& cfg, NativeWindow* win)
 GrManager* createGrManager(const Config& cfg, NativeWindow* win)
 {
 {
-	GrManager* gr = new GrManager();
-
 	GrManagerInitInfo inf;
 	GrManagerInitInfo inf;
 	inf.m_allocCallback = allocAligned;
 	inf.m_allocCallback = allocAligned;
 	inf.m_cacheDirectory = "./";
 	inf.m_cacheDirectory = "./";
 	inf.m_config = &cfg;
 	inf.m_config = &cfg;
 	inf.m_window = win;
 	inf.m_window = win;
-	ANKI_TEST_EXPECT_NO_ERR(gr->init(inf));
+	GrManager* gr;
+	ANKI_TEST_EXPECT_NO_ERR(GrManager::newInstance(inf, gr));
 
 
 	return gr;
 	return gr;
 }
 }

+ 21 - 16
tests/gr/Gr.cpp

@@ -300,15 +300,15 @@ static StagingGpuMemoryManager* stagingMem = nullptr;
 	ANKI_TEST_EXPECT_NO_ERR(transfAlloc->init(128_MB, gr, gr->getAllocator())); \
 	ANKI_TEST_EXPECT_NO_ERR(transfAlloc->init(128_MB, gr, gr->getAllocator())); \
 	{
 	{
 
 
-#define COMMON_END()    \
-	}                   \
-	gr->finish();       \
-	delete transfAlloc; \
-	delete stagingMem;  \
-	delete gr;          \
-	delete win;         \
-	win = nullptr;      \
-	gr = nullptr;       \
+#define COMMON_END()               \
+	}                              \
+	gr->finish();                  \
+	delete transfAlloc;            \
+	delete stagingMem;             \
+	GrManager::deleteInstance(gr); \
+	delete win;                    \
+	win = nullptr;                 \
+	gr = nullptr;                  \
 	stagingMem = nullptr;
 	stagingMem = nullptr;
 
 
 static void* setUniforms(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
 static void* setUniforms(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
@@ -352,9 +352,13 @@ const PixelFormat DS_FORMAT = PixelFormat(ComponentFormat::D24S8, TransformForma
 
 
 static ShaderProgramPtr createProgram(CString vertSrc, CString fragSrc, GrManager& gr)
 static ShaderProgramPtr createProgram(CString vertSrc, CString fragSrc, GrManager& gr)
 {
 {
-	ShaderPtr vert = gr.newShader(ShaderType::VERTEX, vertSrc);
-	ShaderPtr frag = gr.newShader(ShaderType::FRAGMENT, fragSrc);
-	return gr.newShaderProgram(vert, frag);
+	ShaderPtr vert = gr.newShader({ShaderType::VERTEX, vertSrc});
+	ShaderPtr frag = gr.newShader({ShaderType::FRAGMENT, fragSrc});
+
+	ShaderProgramInitInfo inf;
+	inf.m_shaders[ShaderType::VERTEX] = vert;
+	inf.m_shaders[ShaderType::FRAGMENT] = frag;
+	return gr.newShaderProgram(inf);
 }
 }
 
 
 static FramebufferPtr createDefaultFb(GrManager& gr)
 static FramebufferPtr createDefaultFb(GrManager& gr)
@@ -392,7 +396,7 @@ ANKI_TEST(Gr, Shader)
 {
 {
 	COMMON_BEGIN()
 	COMMON_BEGIN()
 
 
-	ShaderPtr shader = gr->newShader(ShaderType::FRAGMENT, FRAG_MRT_SRC);
+	ShaderPtr shader = gr->newShader({ShaderType::FRAGMENT, FRAG_MRT_SRC});
 
 
 	COMMON_END()
 	COMMON_END()
 }
 }
@@ -1294,8 +1298,10 @@ ANKI_TEST(Gr, ImageLoadStore)
 	ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_SIMPLE_TEX_SRC, *gr);
 	ShaderProgramPtr prog = createProgram(VERT_QUAD_SRC, FRAG_SIMPLE_TEX_SRC, *gr);
 
 
 	// Create shader & compute prog
 	// Create shader & compute prog
-	ShaderPtr shader = gr->newShader(ShaderType::COMPUTE, COMP_WRITE_IMAGE_SRC);
-	ShaderProgramPtr compProg = gr->newShaderProgram(shader);
+	ShaderPtr shader = gr->newShader({ShaderType::COMPUTE, COMP_WRITE_IMAGE_SRC});
+	ShaderProgramInitInfo sprogInit;
+	sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
+	ShaderProgramPtr compProg = gr->newShaderProgram(sprogInit);
 
 
 	// FB
 	// FB
 	FramebufferPtr dfb = createDefaultFb(*gr);
 	FramebufferPtr dfb = createDefaultFb(*gr);
@@ -1386,7 +1392,6 @@ ANKI_TEST(Gr, 3DTextures)
 	init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	init.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
 	init.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::TRANSFER_DESTINATION;
 	init.m_initialUsage = TextureUsageBit::TRANSFER_DESTINATION;
 	init.m_initialUsage = TextureUsageBit::TRANSFER_DESTINATION;
-	init.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
 	init.m_height = 2;
 	init.m_height = 2;
 	init.m_width = 2;
 	init.m_width = 2;
 	init.m_mipmapsCount = 2;
 	init.m_mipmapsCount = 2;

+ 1 - 1
tests/ui/Ui.cpp

@@ -128,7 +128,7 @@ ANKI_TEST(Ui, Ui)
 	delete resource;
 	delete resource;
 	delete physics;
 	delete physics;
 	delete fs;
 	delete fs;
-	delete gr;
+	GrManager::deleteInstance(gr);
 	delete in;
 	delete in;
 	delete win;
 	delete win;
 }
 }