Просмотр исходного кода

Added support for immediate command buffers to avoid overhead with render API's that don't support multithreaded command generation natively

BearishSun 9 лет назад
Родитель
Сommit
5d91653c2b

+ 114 - 84
Source/BansheeCore/Include/BsRenderAPI.h

@@ -227,10 +227,12 @@ namespace BansheeEngine
 	{
 	public:
 		RenderAPIInfo(float horzTexelOffset, float vertTexelOffset, float minDepth, float maxDepth, 
-			VertexElementType vertexColorType, bool vertexColorFlip, bool ndcVerticalTopToBottom, bool columnMajorMatrices)
+			VertexElementType vertexColorType, bool vertexColorFlip, bool ndcVerticalTopToBottom, bool columnMajorMatrices, 
+				bool multiThreadedCB)
 			: mHorizontalTexelOffset(horzTexelOffset), mVerticalTexelOffset(vertTexelOffset), mMinDepth(minDepth)
 			, mMaxDepth(maxDepth), mVertexColorType(vertexColorType), mVertexColorFlip(vertexColorFlip)
 			, mNDCYAxisDown(ndcVerticalTopToBottom), mColumnMajorMatrices(columnMajorMatrices)
+			, mMultiThreadedCB(multiThreadedCB)
 		{
 			
 		}
@@ -262,6 +264,12 @@ namespace BansheeEngine
 		 */
 		bool getNDCYAxisDown() const { return mNDCYAxisDown; }
 
+		/**
+		 * Checks if the API supports native multi-threaded command buffer generation. On APIs that don't support it 
+		 * command buffers can still be used, but it will be more efficient to use the immediate rendering operations.
+		 */
+		bool getMultiThreadedCBGeneration() const { return mMultiThreadedCB; }
+
 	private:
 		float mHorizontalTexelOffset = 0.0f;
 		float mVerticalTexelOffset = 0.0f;
@@ -271,6 +279,7 @@ namespace BansheeEngine
 		bool mVertexColorFlip = false;
 		bool mNDCYAxisDown = true;
 		bool mColumnMajorMatrices = false;
+		bool mMultiThreadedCB = false;
 	};
 
 	/** @} */
@@ -278,19 +287,15 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** 
-	 * Primary command buffer. Always available as long as RenderAPI is initialized. 
-	 * 
-	 * @note	Accessible on core thread only, or rendering worker threads if externally synchronized.
-	 */
-	extern BS_CORE_EXPORT SPtr<CommandBuffer> gMainCommandBuffer;
-
 	/**
 	 * Provides low-level API access to rendering commands (internally wrapping DirectX/OpenGL/Vulkan or similar). 
 	 * 
 	 * Methods that accept a CommandBuffer parameter get queued in the provided command buffer, and don't get executed until
 	 * executeCommands() method is called. User is allowed to populate command buffers from non-core threads, but they all 
-	 * must get executed from the core thread.
+	 * must get executed from the core thread. 
+	 * 
+	 * If a command buffer is not provivided to such methods, they execute immediately. Without a command buffer the methods
+	 * are only allowed to be called from the core thread.
 	 *
 	 * @note	Accessible on any thread for methods accepting a CommandBuffer. Otherwise core thread unless specifically
 	 *			noted otherwise on per-method basis.
@@ -322,50 +327,54 @@ namespace BansheeEngine
 		 * @param[in]	gptype			Determines to which GPU program slot to bind the sampler state.
 		 * @param[in]	texUnit			Texture unit index to bind the state to.
 		 * @param[in]	samplerState	Sampler state to bind, or null to unbind.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer
-		 *								must support graphics or compute operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations.
 		 *
 		 * @see		SamplerState
 		 */
 		virtual void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets a blend state used for all active render targets.
 		 *
 		 * @param[in]	blendState		Blend state to bind, or null to unbind.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer
-		 *								must support graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 *
 		 * @see		BlendState
 		 */
 		virtual void setBlendState(const SPtr<BlendStateCore>& blendState, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets a state that controls various rasterizer options. 
 		 *
 		 * @param[in]	rasterizerState		Rasterizer state to bind, or null to unbind.
-		 * @param[in]	commandBuffer		Buffer whose subsequent commands will be affected by the state change. Buffer
-		 *									must support graphics operations.
+		 * @param[in]	commandBuffer		Optional command buffer to queue the operation on. If not provided operation
+		 *									is executed immediately. Otherwise it is executed when executeCommands() is 
+		 *									called. Buffer must support graphics operations.
 		 *
 		 * @see		RasterizerState
 		 */
 		virtual void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets a state that controls depth & stencil buffer options.
 		 *
 		 * @param[in]	depthStencilState	Depth-stencil state to bind, or null to unbind.
 		 * @param[in]	stencilRefValue		Stencil reference value to be used for stencil comparisons, if enabled.
-		 * @param[in]	commandBuffer		Buffer whose subsequent commands will be affected by the state change. Buffer
-		 *									must support graphics operations.
+		 * @param[in]	commandBuffer		Optional command buffer to queue the operation on. If not provided operation
+		 *									is executed immediately. Otherwise it is executed when executeCommands() is 
+		 *									called. Buffer must support graphics operations.
 		 *
 		 * @see		DepthStencilState
 		 */
 		virtual void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Binds a texture to the pipeline for the specified GPU program type at the specified slot. If the slot matches 
@@ -374,11 +383,12 @@ namespace BansheeEngine
 		 * @param[in]	gptype			Determines to which GPU program slot to bind the texture.
 		 * @param[in]	texUnit			Texture unit index to bind the texture to.
 		 * @param[in]	texture			Texture to bind.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics or compute operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations.
 		 */
 		virtual void setTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**	
 		 * Binds a texture that can be used for random load/store operations from a GPU program. 
@@ -387,11 +397,12 @@ namespace BansheeEngine
 		 * @param[in]	texUnit			Texture unit index to bind the texture to.
 		 * @param[in]	texture			Texture to bind.
 		 * @param[in]	surface			Determines which surface of the texture to bind.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics or compute operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations.
 		 */
 		virtual void setLoadStoreTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture, 
-			const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Binds a buffer that can be used for read or write operations on the GPU.
@@ -401,37 +412,41 @@ namespace BansheeEngine
 		 * @param[in]	buffer			Buffer to bind.
 		 * @param[in]	loadStore		If true the buffer will be bound with support for unordered reads and writes, 
 		 *								otherwise it will only be bound for reads.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics or compute operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations.
 		 */
 		virtual void setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, 
-			bool loadStore = false, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			bool loadStore = false, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Signals that rendering for a specific viewport has started. Any draw calls need to be called between beginFrame()
 		 * and endFrame(). 
 		 * 
-		 * @param[in]	commandBuffer	Command buffer in which to start rendering. Buffer must support graphics
-		 *								operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
-		virtual void beginFrame(const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+		virtual void beginFrame(const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 		
 		/** 
 		 * Ends that rendering to a specific viewport has ended. 
 		 *
-		 * @param[in]	commandBuffer	Command buffer in which to start rendering. Buffer must support graphics
-		 *								operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
-		virtual void endFrame(const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+		virtual void endFrame(const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets the active viewport that will be used for all render operations.
 		 *
 		 * @param[in]	area			Area of the viewport, in normalized ([0,1] range) coordinates.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
-		virtual void setViewport(const Rect2& area, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+		virtual void setViewport(const Rect2& area, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Allows you to set up a region in which rendering can take place. Coordinates are in pixels. No rendering will be
@@ -441,11 +456,12 @@ namespace BansheeEngine
 		 * @param[in]	top				Top border of the scissor rectangle, in pixels.
 		 * @param[in]	right			Right border of the scissor rectangle, in pixels.
 		 * @param[in]	bottom			Bottom border of the scissor rectangle, in pixels.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets the provided vertex buffers starting at the specified source index.	Set buffer to nullptr to clear the 
@@ -454,22 +470,24 @@ namespace BansheeEngine
 		 * @param[in]	index			Index at which to start binding the vertex buffers.
 		 * @param[in]	buffers			A list of buffers to bind to the pipeline.
 		 * @param[in]	numBuffers		Number of buffers in the @p buffers list.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets an index buffer to use when drawing. Indices in an index buffer reference vertices in the vertex buffer, 
 		 * which increases cache coherency and reduces the size of vertex buffers by eliminating duplicate data.
 		 *
 		 * @param[in]	buffer			Index buffer to bind, null to unbind.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void setIndexBuffer(const SPtr<IndexBufferCore>& buffer, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Assigns a parameter buffer containing constants (uniforms) for use in a GPU program.
@@ -480,32 +498,35 @@ namespace BansheeEngine
 		 * @param[in]	buffer			Buffer containing constants (uniforms) for use by the shader.
 		 * @param[in]	paramDesc		Description of all parameters in the buffer. Required mostly for backwards 
 		 *								compatibility.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must
-		 *								support graphics or compute operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations.
 		 */
 		virtual void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
-			const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Sets the vertex declaration to use when drawing. Vertex declaration is used to decode contents of a single 
 		 * vertex in a vertex buffer.
 		 *
 		 * @param[in]	vertexDeclaration	Vertex declaration to bind.
-		 * @param[in]	commandBuffer		Buffer whose subsequent commands will be affected by the state change. Buffer
-		 *									must support graphics operations.
+		 * @param[in]	commandBuffer		Optional command buffer to queue the operation on. If not provided operation
+		 *									is executed immediately. Otherwise it is executed when executeCommands() is 
+		 *									called. Buffer must support graphics operations.
 		 */
 		virtual void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/** 
 		 * Sets the draw operation that determines how to interpret the elements of the index or vertex buffers. 
 		 *
 		 * @param[in]	op				Draw operation to enable.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must 
-		 *								support graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void setDrawOperation(DrawOperationType op, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Draw an object based on currently bound GPU programs, vertex declaration and vertex buffers. Draws directly from
@@ -515,11 +536,12 @@ namespace BansheeEngine
 		 * @param[in]	vertexCount		Number of vertices to draw.
 		 * @param[in]	instanceCount	Number of times to draw the provided geometry, each time with an (optionally)
 		 *								separate per-instance data.
-		 * @param[in]	commandBuffer	Command buffer in which to queue the draw operation on. Buffer must support graphics
-		 *								operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/** 
 		 * Draw an object based on currently bound GPU programs, vertex declaration, vertex and index buffers. 
@@ -530,11 +552,12 @@ namespace BansheeEngine
 		 * @param[in]	vertexCount		Number of vertices to draw.
 		 * @param[in]	instanceCount	Number of times to draw the provided geometry, each time with an (optionally)
 		 *								separate per-instance data.
-		 * @param[in]	commandBuffer	Command buffer in which to queue the draw operation on. Buffer must support graphics
-		 *								operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount, 
-			UINT32 instanceCount = 0, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			UINT32 instanceCount = 0, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/** 
 		 * Executes the currently bound compute shader. 
@@ -542,43 +565,47 @@ namespace BansheeEngine
 		 * @param[in]	numGroupsX		Number of groups to start in the X direction. Must be in range [1, 65535].
 		 * @param[in]	numGroupsY		Number of groups to start in the Y direction. Must be in range [1, 65535].
 		 * @param[in]	numGroupsZ		Number of groups to start in the Z direction. Must be in range [1, 64].
-		 * @param[in]	commandBuffer	Command buffer in which to queue the dispatch operation on. Buffer must support
-		 *								compute or graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support compute or graphics operations.
 		 */
 		virtual void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/** 
 		 * Swap the front and back buffer of the specified render target. 
 		 *
 		 * @param[in]	target			Render target to perform the buffer swap on.
-		 * @param[in]	commandBuffer	Command buffer in which to queue the swap buffer operation on. Buffer must support
-		 *								graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void swapBuffers(const SPtr<RenderTargetCore>& target, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Binds the provided GPU program to the pipeline. Any following draw operations will use this program. 
 		 *
 		 * @param[in]	prg				GPU program to bind. Slot it is bound to is determined by the program type.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must 
-		 *								support graphics or compute operations (depending on program type).
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations (depending on program type).
 		 *
 		 * @note	You need to bind at least a vertex and a fragment program in order to draw something.
 		 */
 		virtual void bindGpuProgram(const SPtr<GpuProgramCore>& prg, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**	
 		 * Unbinds a program of a given type. 
 		 *
 		 * @param[in]	gptype			GPU program slot to unbind the program from.
-		 * @param[in]	commandBuffer	Buffer whose subsequent commands will be affected by the state change. Buffer must 
-		 *								support graphics or compute operations (depending on program type).
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics or compute operations (depending on program type).
 		 */
 		virtual void unbindGpuProgram(GpuProgramType gptype,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Change the render target into which we want to draw.
@@ -587,11 +614,12 @@ namespace BansheeEngine
 		 * @param[in]	readOnlyDepthStencil	If true the caller guarantees he won't write to the depth/stencil buffer 
 		 *										(if any was provided). This allows the depth buffer to be bound for depth 
 		 *										testing, as well as reading in a shader, at the same time.
-		 * @param[in]	commandBuffer			Buffer whose subsequent commands will be affected by the state change. 
-		 *										Buffer must support graphics operations.
+		 * @param[in]	commandBuffer			Optional command buffer to queue the operation on. If not provided operation
+		 *										is executed immediately. Otherwise it is executed when executeCommands() is
+		 *										called. Buffer must support graphics operations.
 		 */
         virtual void setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil = false,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Clears the currently active render target.
@@ -603,11 +631,12 @@ namespace BansheeEngine
 		 * @param[in]	stencil			The value to initialize the stencil buffer with, if enabled.
 		 * @param[in]	targetMask		In case multiple render targets are bound, this allows you to control which ones to
 		 *									clear (0x01 first, 0x02 second, 0x04 third, etc., and combinations).
-		 * @param[in]	commandBuffer	Command buffer in which to queue the clear operation on. Buffer must support
-		 *								graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
-			UINT16 stencil = 0, UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			UINT16 stencil = 0, UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**
 		 * Clears the currently active viewport (meaning it clears just a sub-area of a render-target that is covered by the 
@@ -620,11 +649,12 @@ namespace BansheeEngine
 		 * @param[in]	stencil			The value to initialize the stencil buffer with, if enabled.
 		 * @param[in]	targetMask		In case multiple render targets are bound, this allows you to control which ones to
 		 *								clear (0x01 first, 0x02 second, 0x04 third, etc., and combinations).
-		 * @param[in]	commandBuffer	Command buffer in which to queue the clear operation on. Buffer must support
-		 *								graphics operations.
+		 * @param[in]	commandBuffer	Optional command buffer to queue the operation on. If not provided operation
+		 *								is executed immediately. Otherwise it is executed when executeCommands() is called.
+		 *								Buffer must support graphics operations.
 		 */
 		virtual void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, 
-			UINT16 stencil = 0, UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) = 0;
+			UINT16 stencil = 0, UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/** Appends all commands from the provided secondary command buffer into the primary command buffer. */
 		virtual void addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary) = 0;

+ 23 - 27
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -22,51 +22,49 @@ using namespace std::placeholders;
 
 namespace BansheeEngine 
 {
-	BS_CORE_EXPORT SPtr<CommandBuffer> gMainCommandBuffer = nullptr;
-
 	void RenderAPI::setTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, const SPtr<Texture> &texPtr)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setTexture, RenderAPICore::instancePtr(), gptype, unit, 
-			texPtr->getCore(), gMainCommandBuffer));
+			texPtr->getCore(), nullptr));
 	}
 
 	void RenderAPI::setLoadStoreTexture(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, 
 		const SPtr<Texture>& texPtr, const TextureSurface& surface)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setLoadStoreTexture, RenderAPICore::instancePtr(), gptype, unit, 
-			texPtr->getCore(), surface, gMainCommandBuffer));
+			texPtr->getCore(), surface, nullptr));
 	}
 
 	void RenderAPI::setBuffer(CoreAccessor& accessor, GpuProgramType gptype, UINT16 unit, const SPtr<GpuBuffer>& buffer,
 		bool loadStore)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setBuffer, RenderAPICore::instancePtr(), gptype, unit, 
-			buffer->getCore(), loadStore, gMainCommandBuffer));
+			buffer->getCore(), loadStore, nullptr));
 	}
 
 	void RenderAPI::setSamplerState(CoreAccessor& accessor, GpuProgramType gptype, UINT16 texUnit, 
 		const SPtr<SamplerState>& samplerState)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setSamplerState, RenderAPICore::instancePtr(), gptype, texUnit, 
-			samplerState->getCore(), gMainCommandBuffer));
+			samplerState->getCore(), nullptr));
 	}
 
 	void RenderAPI::setBlendState(CoreAccessor& accessor, const SPtr<BlendState>& blendState)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setBlendState, RenderAPICore::instancePtr(), blendState->getCore(), 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::setRasterizerState(CoreAccessor& accessor, const SPtr<RasterizerState>& rasterizerState)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setRasterizerState, RenderAPICore::instancePtr(), 
-			rasterizerState->getCore(), gMainCommandBuffer));
+			rasterizerState->getCore(), nullptr));
 	}
 
 	void RenderAPI::setDepthStencilState(CoreAccessor& accessor, const SPtr<DepthStencilState>& depthStencilState, UINT32 stencilRefValue)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setDepthStencilState, RenderAPICore::instancePtr(), 
-			depthStencilState->getCore(), stencilRefValue, gMainCommandBuffer));
+			depthStencilState->getCore(), stencilRefValue, nullptr));
 	}
 
 	void RenderAPI::setVertexBuffers(CoreAccessor& accessor, UINT32 index, const Vector<SPtr<VertexBuffer>>& buffers)
@@ -87,98 +85,98 @@ namespace BansheeEngine
 	void RenderAPI::setIndexBuffer(CoreAccessor& accessor, const SPtr<IndexBuffer>& buffer)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setIndexBuffer, RenderAPICore::instancePtr(), buffer->getCore(), 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::setVertexDeclaration(CoreAccessor& accessor, const SPtr<VertexDeclaration>& vertexDeclaration)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setVertexDeclaration, RenderAPICore::instancePtr(), 
-			vertexDeclaration->getCore(), gMainCommandBuffer));
+			vertexDeclaration->getCore(), nullptr));
 	}
 
 	void RenderAPI::setViewport(CoreAccessor& accessor, const Rect2& vp)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp, gMainCommandBuffer));
+		accessor.queueCommand(std::bind(&RenderAPICore::setViewport, RenderAPICore::instancePtr(), vp, nullptr));
 	}
 
 	void RenderAPI::setDrawOperation(CoreAccessor& accessor, DrawOperationType op)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setDrawOperation, RenderAPICore::instancePtr(), op, 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::setScissorRect(CoreAccessor& accessor, UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setScissorRect, RenderAPICore::instancePtr(), left, top, right, bottom, 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::setRenderTarget(CoreAccessor& accessor, const SPtr<RenderTarget>& target, bool readOnlyDepthStencil)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::setRenderTarget, 
-			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil, gMainCommandBuffer));
+			RenderAPICore::instancePtr(), target->getCore(), readOnlyDepthStencil, nullptr));
 	}
 
 	void RenderAPI::bindGpuProgram(CoreAccessor& accessor, const SPtr<GpuProgram>& prg)
 	{
 		prg->syncToCore(accessor);
 		accessor.queueCommand(std::bind(&RenderAPICore::bindGpuProgram, RenderAPICore::instancePtr(), prg->getCore(), 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::unbindGpuProgram(CoreAccessor& accessor, GpuProgramType gptype)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::unbindGpuProgram, RenderAPICore::instancePtr(), gptype, 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::beginRender(CoreAccessor& accessor)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr(), gMainCommandBuffer));
+		accessor.queueCommand(std::bind(&RenderAPICore::beginFrame, RenderAPICore::instancePtr(), nullptr));
 	}
 
 	void RenderAPI::endRender(CoreAccessor& accessor)
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::endFrame, RenderAPICore::instancePtr(), gMainCommandBuffer));
+		accessor.queueCommand(std::bind(&RenderAPICore::endFrame, RenderAPICore::instancePtr(), nullptr));
 	}
 
 	void RenderAPI::clearRenderTarget(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, 
 		UINT16 stencil, UINT8 targetMask)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::clearRenderTarget, RenderAPICore::instancePtr(), buffers, color,
-			depth, stencil, targetMask, gMainCommandBuffer));
+			depth, stencil, targetMask, nullptr));
 	}
 
 	void RenderAPI::clearViewport(CoreAccessor& accessor, UINT32 buffers, const Color& color, float depth, UINT16 stencil, 
 		UINT8 targetMask)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::clearViewport, RenderAPICore::instancePtr(), buffers, color, depth,
-			stencil, targetMask, gMainCommandBuffer));
+			stencil, targetMask, nullptr));
 	}
 
 	void RenderAPI::swapBuffers(CoreAccessor& accessor, const SPtr<RenderTarget>& target)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore(), 
-			gMainCommandBuffer));
+			nullptr));
 	}
 
 	void RenderAPI::draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, 
-			vertexCount, instanceCount, gMainCommandBuffer));
+			vertexCount, instanceCount, nullptr));
 	}
 
 	void RenderAPI::drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, 
 		UINT32 vertexCount, UINT32 instanceCount)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::drawIndexed, RenderAPICore::instancePtr(), startIndex, indexCount, 
-			vertexOffset, vertexCount, instanceCount, gMainCommandBuffer));
+			vertexOffset, vertexCount, instanceCount, nullptr));
 	}
 
 	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
 	{
 		accessor.queueCommand(std::bind(&RenderAPICore::dispatchCompute, RenderAPICore::instancePtr(), numGroupsX, 
-			numGroupsY, numGroupsZ, gMainCommandBuffer));
+			numGroupsY, numGroupsZ, nullptr));
 	}
 
 	const VideoModeInfo& RenderAPI::getVideoModeInfo()
@@ -207,8 +205,6 @@ namespace BansheeEngine
 
 		bs_delete(mCurrentCapabilities);
 		mCurrentCapabilities = nullptr;
-
-		gMainCommandBuffer = nullptr;
     }
 
 	SPtr<RenderWindow> RenderAPICore::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)

+ 25 - 25
Source/BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -29,98 +29,98 @@ namespace BansheeEngine
 
 		/** @copydoc RenderAPICore::setSamplerState() */
 		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SPtr<SamplerStateCore>& samplerState, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setBlendState() */
 		void setBlendState(const SPtr<BlendStateCore>& blendState, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setRasterizerState() */
 		void setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setDepthStencilState() */
 		void setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setTexture() */
 		void setTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setLoadStoreTexture */
 		void setLoadStoreTexture(GpuProgramType gptype, UINT16 texUnit, const SPtr<TextureCore>& texture,
-			const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setBuffer */
 		void setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, bool loadStore = false,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::beginFrame() */
-		void beginFrame(const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+		void beginFrame(const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::endFrame() */
-		void endFrame(const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+		void endFrame(const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setViewport() */
-		void setViewport(const Rect2& area, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+		void setViewport(const Rect2& area, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setScissorRect() */
 		void setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setVertexBuffers() */
 		void setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setIndexBuffer() */
 		void setIndexBuffer(const SPtr<IndexBufferCore>& buffer,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setParamBuffer */
 		void setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer,
-			const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setVertexDeclaration() */
 		void setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setDrawOperation() */
-		void setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+		void setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::draw() */
 		void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::drawIndexed() */
 		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount
-			, UINT32 instanceCount = 0, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			, UINT32 instanceCount = 0, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::dispatchCompute() */
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::swapBuffers() */
 		void swapBuffers(const SPtr<RenderTargetCore>& target,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::bindGpuProgram() */
 		void bindGpuProgram(const SPtr<GpuProgramCore>& prg, 
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::unbindGpuProgram() */
-		void unbindGpuProgram(GpuProgramType gptype, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+		void unbindGpuProgram(GpuProgramType gptype, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::setRenderTarget() */
 		void setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil = false,
-			const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::clearRenderTarget() */
 		void clearRenderTarget(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, 
-			UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::clearViewport() */
 		void clearViewport(UINT32 buffers, const Color& color = Color::Black, float depth = 1.0f, UINT16 stencil = 0, 
-			UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = gMainCommandBuffer) override;
+			UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPICore::addCommands() */
 		void addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary) override;

+ 259 - 78
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -104,8 +104,6 @@ namespace BansheeEngine
 		mVideoModeInfo = mGLSupport->getVideoModeInfo();
 
 		CommandBufferManager::startUp<GLCommandBufferManager>();
-		gMainCommandBuffer = CommandBuffer::create(CBT_GRAPHICS);
-
 		RenderWindowManager::startUp<GLRenderWindowManager>(this);
 		RenderWindowCoreManager::startUp<GLRenderWindowCoreManager>(this);
 
@@ -217,7 +215,7 @@ namespace BansheeEngine
 
 	void GLRenderAPI::bindGpuProgram(const SPtr<GpuProgramCore>& prg, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<GpuProgramCore>& prg)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -227,8 +225,15 @@ namespace BansheeEngine
 			setActiveProgram(type, glprg);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(prg);
+		else
+		{
+			auto execute = [=]() { executeRef(prg); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::unbindGpuProgram(GpuProgramType gptype, const SPtr<CommandBuffer>& commandBuffer)
@@ -240,14 +245,20 @@ namespace BansheeEngine
 			setActiveProgram(gptype, nullptr);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			execute();
+		else
+		{
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::setParamBuffer(GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer, 
 		const SPtr<GpuParamDesc>& paramDesc, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](GpuProgramType gptype, UINT32 slot, const SPtr<GpuParamBlockBufferCore>& buffer,
+			const SPtr<GpuParamDesc>& paramDesc)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -361,8 +372,15 @@ namespace BansheeEngine
 			}
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(gptype, slot, buffer, paramDesc);
+		else
+		{
+			auto execute = [=]() { executeRef(gptype, slot, buffer, paramDesc); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
 	}
@@ -370,7 +388,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setTexture(GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -410,8 +428,15 @@ namespace BansheeEngine
 			activateGLTextureUnit(0);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(gptype, unit, texPtr);
+		else
+		{
+			auto execute = [=]() { executeRef(gptype, unit, texPtr); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumTextureBinds);
 	}
@@ -419,7 +444,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setSamplerState(GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<SamplerStateCore>& state)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -449,8 +474,15 @@ namespace BansheeEngine
 			mMaxBoundTexUnits[gptype] = std::max(mMaxBoundTexUnits[gptype], (UINT32)texUnit + 1);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(gptype, unit, state);
+		else
+		{
+			auto execute = [=]() { executeRef(gptype, unit, state); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumSamplerBinds);
 	}
@@ -458,7 +490,8 @@ namespace BansheeEngine
 	void GLRenderAPI::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr,
 		const TextureSurface& surface, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<TextureCore>& texPtr,
+			const TextureSurface& surface)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -489,8 +522,15 @@ namespace BansheeEngine
 			}
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(gptype, unit, texPtr, surface);
+		else
+		{
+			auto execute = [=]() { executeRef(gptype, unit, texPtr, surface); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumTextureBinds);
 	}
@@ -499,7 +539,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setBuffer(GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, bool loadStore,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](GpuProgramType gptype, UINT16 unit, const SPtr<GpuBufferCore>& buffer, bool loadStore)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -565,8 +605,15 @@ namespace BansheeEngine
 			}
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(gptype, unit, buffer, loadStore);
+		else
+		{
+			auto execute = [=]() { executeRef(gptype, unit, buffer, loadStore); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumTextureBinds);
 	}
@@ -574,7 +621,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setBlendState(const SPtr<BlendStateCore>& blendState,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<BlendStateCore>& blendState)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -600,8 +647,15 @@ namespace BansheeEngine
 			setColorBufferWriteEnabled((writeMask & 0x1) != 0, (writeMask & 0x2) != 0, (writeMask & 0x4) != 0, (writeMask & 0x8) != 0);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(blendState);
+		else
+		{
+			auto execute = [=]() { executeRef(blendState); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumBlendStateChanges);
 	}
@@ -609,7 +663,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setRasterizerState(const SPtr<RasterizerStateCore>& rasterizerState,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<RasterizerStateCore>& rasterizerState)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -624,8 +678,15 @@ namespace BansheeEngine
 			setAntialiasedLineEnable(stateProps.getAntialiasedLineEnable());
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(rasterizerState);
+		else
+		{
+			auto execute = [=]() { executeRef(rasterizerState); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumRasterizerStateChanges);
 	}
@@ -633,7 +694,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setDepthStencilState(const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<DepthStencilStateCore>& depthStencilState, UINT32 stencilRefValue)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -659,8 +720,15 @@ namespace BansheeEngine
 			setStencilRefValue(stencilRefValue);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(depthStencilState, stencilRefValue);
+		else
+		{
+			auto execute = [=]() { executeRef(depthStencilState, stencilRefValue); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
 	}
@@ -668,7 +736,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setViewport(const Rect2& area,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const Rect2& area)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -676,14 +744,21 @@ namespace BansheeEngine
 			applyViewport();
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(area);
+		else
+		{
+			auto execute = [=]() { executeRef(area); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::setRenderTarget(const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil, 
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<RenderTargetCore>& target, bool readOnlyDepthStencil)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -722,8 +797,15 @@ namespace BansheeEngine
 			applyViewport();
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(target, readOnlyDepthStencil);
+		else
+		{
+			auto execute = [=]() { executeRef(target, readOnlyDepthStencil); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumRenderTargetChanges);
 	}
@@ -738,8 +820,13 @@ namespace BansheeEngine
 			glEnable(GL_SCISSOR_TEST);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			execute();
+		else
+		{
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::endFrame(const SPtr<CommandBuffer>& commandBuffer)
@@ -752,8 +839,13 @@ namespace BansheeEngine
 			glDisable(GL_SCISSOR_TEST);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			execute();
+		else
+		{
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::setVertexBuffers(UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers, 
@@ -773,7 +865,7 @@ namespace BansheeEngine
 		for(UINT32 i = 0; i < numBuffers; i++)
 			boundBuffers[index + i] = buffers[i];
 
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 index, SPtr<VertexBufferCore>* buffers, UINT32 numBuffers)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -781,55 +873,84 @@ namespace BansheeEngine
 				mBoundVertexBuffers[index + i] = boundBuffers[index + i];
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(index, buffers, numBuffers);
+		else
+		{
+			auto execute = [=]() { executeRef(index, buffers, numBuffers); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::setVertexDeclaration(const SPtr<VertexDeclarationCore>& vertexDeclaration,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<VertexDeclarationCore>& vertexDeclaration)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
 			mBoundVertexDeclaration = vertexDeclaration;
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(vertexDeclaration);
+		else
+		{
+			auto execute = [=]() { executeRef(vertexDeclaration); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::setDrawOperation(DrawOperationType op, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](DrawOperationType op)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
 			mCurrentDrawOperation = op;
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
-		cb->mCurrentDrawOperation = op;
+		if (commandBuffer == nullptr)
+			executeRef(op);
+		else
+		{
+			auto execute = [=]() { executeRef(op); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+
+			cb->mCurrentDrawOperation = op;
+		}
 	}
 
 	void GLRenderAPI::setIndexBuffer(const SPtr<IndexBufferCore>& buffer, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<IndexBufferCore>& buffer)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
 			mBoundIndexBuffer = buffer;
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(buffer);
+		else
+		{
+			auto execute = [=]() { executeRef(buffer); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount, 
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -845,10 +966,22 @@ namespace BansheeEngine
 			endDraw();
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		UINT32 primCount;
+		if (commandBuffer == nullptr)
+		{
+			executeRef(vertexOffset, vertexCount, instanceCount);
 
-		UINT32 primCount = vertexCountToPrimCount(cb->mCurrentDrawOperation, vertexCount);
+			primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
+		}
+		else
+		{
+			auto execute = [=]() { executeRef(vertexOffset, vertexCount, instanceCount); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+
+			primCount = vertexCountToPrimCount(cb->mCurrentDrawOperation, vertexCount);
+		}
 
 		BS_INC_RENDER_STAT(NumDrawCalls);
 		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
@@ -858,7 +991,8 @@ namespace BansheeEngine
 	void GLRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
 		UINT32 instanceCount, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
+			UINT32 instanceCount)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -893,10 +1027,22 @@ namespace BansheeEngine
 			endDraw();
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		UINT32 primCount;
+		if (commandBuffer == nullptr)
+		{
+			executeRef(startIndex, indexCount, vertexOffset, vertexCount, instanceCount);
+
+			primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
+		}
+		else
+		{
+			auto execute = [=]() { executeRef(startIndex, indexCount, vertexOffset, vertexCount, instanceCount); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
 
-		UINT32 primCount = vertexCountToPrimCount(cb->mCurrentDrawOperation, vertexCount);
+			primCount = vertexCountToPrimCount(cb->mCurrentDrawOperation, vertexCount);
+		}
 
 		BS_INC_RENDER_STAT(NumDrawCalls);
 		BS_ADD_RENDER_STAT(NumVertices, vertexCount);
@@ -908,7 +1054,7 @@ namespace BansheeEngine
 	void GLRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ, 
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -922,8 +1068,15 @@ namespace BansheeEngine
 			glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(numGroupsX, numGroupsY, numGroupsZ);
+		else
+		{
+			auto execute = [=]() { executeRef(numGroupsX, numGroupsY, numGroupsZ); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumGpuProgramBinds);
 		BS_INC_RENDER_STAT(NumComputeCalls);
@@ -932,7 +1085,7 @@ namespace BansheeEngine
 	void GLRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom, 
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -942,14 +1095,21 @@ namespace BansheeEngine
 			mScissorRight = right;
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(left, top, right, bottom);
+		else
+		{
+			auto execute = [=]() { executeRef(left, top, right, bottom); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
 		{
 			if (mActiveRenderTarget == nullptr)
 				return;
@@ -960,34 +1120,55 @@ namespace BansheeEngine
 			clearArea(buffers, color, depth, stencil, clearRect, targetMask);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(buffers, color, depth, stencil, targetMask);
+		else
+		{
+			auto execute = [=]() { executeRef(buffers, color, depth, stencil, targetMask); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask,
 		const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask)
 		{
 			Rect2I clearRect(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
 
 			clearArea(buffers, color, depth, stencil, clearRect, targetMask);
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(buffers, color, depth, stencil, targetMask);
+		else
+		{
+			auto execute = [=]() { executeRef(buffers, color, depth, stencil, targetMask); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 	}
 
 	void GLRenderAPI::swapBuffers(const SPtr<RenderTargetCore>& target, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto execute = [=]()
+		auto executeRef = [&](const SPtr<RenderTargetCore>& target)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 			target->swapBuffers();
 		};
 
-		SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
-		cb->queueCommand(execute);
+		if (commandBuffer == nullptr)
+			executeRef(target);
+		else
+		{
+			auto execute = [=]() { executeRef(target); };
+
+			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
+			cb->queueCommand(execute);
+		}
 
 		BS_INC_RENDER_STAT(NumPresents);
 	}
@@ -2433,7 +2614,7 @@ namespace BansheeEngine
 
 	const RenderAPIInfo& GLRenderAPI::getAPIInfo() const
 	{
-		static RenderAPIInfo info(0.0f, 0.0f, -1.0f, 1.0f, VET_COLOR_ABGR, false, false, true);
+		static RenderAPIInfo info(0.0f, 0.0f, -1.0f, 1.0f, VET_COLOR_ABGR, false, false, true, false);
 
 		return info;
 	}

+ 0 - 1
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -603,7 +603,6 @@ namespace BansheeEngine
 			}
 
 			RenderAPICore::instance().endFrame();
-			RenderAPICore::instance().executeCommands(gMainCommandBuffer);
 			RenderAPICore::instance().swapBuffers(target);
 		}