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

Updated render API with support for instanced rendering

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

+ 10 - 4
Source/BansheeCore/Include/BsRenderAPI.h

@@ -230,14 +230,15 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
 		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
 		 */
 		 */
-		static void draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount);
+		static void draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0);
 
 
 		/** 
 		/** 
 		 * @copydoc RenderAPICore::drawIndexed()
 		 * @copydoc RenderAPICore::drawIndexed()
 		 *
 		 *
 		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
 		 * @param[in]	accessor	Accessor on which will this command be queued for execution.
 		 */
 		 */
-		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount);
+		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, 
+			UINT32 vertexCount, UINT32 instanceCount = 0);
 
 
 		/** 
 		/** 
 		 * @copydoc RenderAPICore::dispatchCompute()
 		 * @copydoc RenderAPICore::dispatchCompute()
@@ -463,8 +464,10 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @param[in]	vertexOffset	Offset into the currently bound vertex buffer to start drawing from.
 		 * @param[in]	vertexOffset	Offset into the currently bound vertex buffer to start drawing from.
 		 * @param[in]	vertexCount		Number of vertices to draw.
 		 * @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.
 		 */
 		 */
-		virtual void draw(UINT32 vertexOffset, UINT32 vertexCount) = 0;
+		virtual void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0) = 0;
 
 
 		/** 
 		/** 
 		 * Draw an object based on currently bound GPU programs, vertex declaration, vertex and index buffers. 
 		 * Draw an object based on currently bound GPU programs, vertex declaration, vertex and index buffers. 
@@ -473,8 +476,11 @@ namespace BansheeEngine
 		 * @param[in]	indexCount		Number of indices to draw.
 		 * @param[in]	indexCount		Number of indices to draw.
 		 * @param[in]	vertexOffset	Offset to apply to each vertex index.
 		 * @param[in]	vertexOffset	Offset to apply to each vertex index.
 		 * @param[in]	vertexCount		Number of vertices to draw.
 		 * @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.
 		 */
 		 */
-		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) = 0;
+		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount, 
+			UINT32 instanceCount = 0) = 0;
 
 
 		/** 
 		/** 
 		 * Executes the currently bound compute shader. 
 		 * Executes the currently bound compute shader. 

+ 14 - 7
Source/BansheeCore/Include/BsVertexDataDesc.h

@@ -24,14 +24,21 @@ namespace BansheeEngine
 		 * Informs the internal buffer that it needs to make room for the specified vertex element. If a vertex with same 
 		 * Informs the internal buffer that it needs to make room for the specified vertex element. If a vertex with same 
 		 * stream and semantics already exists it will just be updated. 
 		 * stream and semantics already exists it will just be updated. 
 		 *
 		 *
-		 * @param[in]	type	   	Type of the vertex element. Determines size.
-		 * @param[in]	semantic   	Semantic that allows the engine to connect the data to a shader input slot.
-		 * @param[in]	semanticIdx	(optional) If there are multiple semantics with the same name, use different index to
-		 *							differentiate between them.
-		 * @param[in]	streamIdx  	(optional) Zero-based index of the stream. Each stream will internally be represented 
-		 *							as a single vertex buffer.
+		 * @param[in]	type	   			Type of the vertex element. Determines size.
+		 * @param[in]	semantic			Semantic that allows the engine to connect the data to a shader input slot.
+		 * @param[in]	semanticIdx			(optional) If there are multiple semantics with the same name, use different
+		 *									index to differentiate between them.
+		 * @param[in]	streamIdx  			(optional) Zero-based index of the stream. Each stream will internally be
+		 *									represented as a single vertex buffer.
+		 * @param[in]	instanceStepRate	Determines at what rate does vertex element data advance. Zero means each vertex
+		 *									will advance the data pointer and receive new data (standard behaviour). Values
+		 *									larger than one are relevant for instanced rendering and determine how often do
+		 *									instances advance the vertex element (e.g. a value of 1 means each instance will
+		 *									retrieve a new value for this vertex element, a value of 2 means each second
+		 *									instance will, etc.).
 		 */
 		 */
-		void addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0);
+		void addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx = 0, 
+			UINT32 streamIdx = 0, UINT32 instanceStepRate = 0);
 
 
 		/**	Query if we have vertex data for the specified semantic. */
 		/**	Query if we have vertex data for the specified semantic. */
 		bool hasElement(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;
 		bool hasElement(VertexElementSemantic semantic, UINT32 semanticIdx = 0, UINT32 streamIdx = 0) const;

+ 11 - 2
Source/BansheeCore/Include/BsVertexDeclaration.h

@@ -52,7 +52,7 @@ namespace BansheeEngine
     public:
     public:
 		VertexElement() {}
 		VertexElement() {}
         VertexElement(UINT16 source, UINT32 offset, VertexElementType theType,
         VertexElement(UINT16 source, UINT32 offset, VertexElementType theType,
-			VertexElementSemantic semantic, UINT16 index = 0);
+			VertexElementSemantic semantic, UINT16 index = 0, UINT32 instanceStepRate = 0);
 
 
 		bool operator== (const VertexElement& rhs) const;
 		bool operator== (const VertexElement& rhs) const;
 		bool operator!= (const VertexElement& rhs) const;
 		bool operator!= (const VertexElement& rhs) const;
@@ -66,7 +66,7 @@ namespace BansheeEngine
 		 */
 		 */
         UINT32 getOffset() const { return mOffset; }
         UINT32 getOffset() const { return mOffset; }
 
 
-		/** Gets the base data type of tis element. */
+		/** Gets the base data type of this element. */
         VertexElementType getType() const { return mType; }
         VertexElementType getType() const { return mType; }
 
 
 		/**	Gets a semantic that describes what this element contains. */
 		/**	Gets a semantic that describes what this element contains. */
@@ -81,6 +81,14 @@ namespace BansheeEngine
 		/** Returns the size of this element in bytes. */
 		/** Returns the size of this element in bytes. */
 		UINT32 getSize() const;
 		UINT32 getSize() const;
 
 
+		/** 
+		 * Returns at what rate do the vertex elements advance during instanced rendering. Provide zero for default 
+		 * behaviour where each vertex receives the next value from the vertex buffer. Provide a value larger than zero
+		 * to ensure vertex data is advanced with every instance, instead of every vertex (e.g. a value of 1 means each
+		 * instance will retrieve a new value from the vertex buffer, a value of 2 means each second instance will, etc.).
+		 */
+		UINT32 getInstanceStepRate() const { return mInstanceStepRate; }
+
 		/**	Returns the size of a base element type. */
 		/**	Returns the size of a base element type. */
 		static UINT32 getTypeSize(VertexElementType etype);
 		static UINT32 getTypeSize(VertexElementType etype);
 
 
@@ -96,6 +104,7 @@ namespace BansheeEngine
 		VertexElementType mType;
 		VertexElementType mType;
 		VertexElementSemantic mSemantic;
 		VertexElementSemantic mSemantic;
 		UINT16 mIndex;
 		UINT16 mIndex;
+		UINT32 mInstanceStepRate;
     };
     };
 
 
 	/** @cond SPECIALIZATIONS */
 	/** @cond SPECIALIZATIONS */

+ 6 - 4
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -166,15 +166,17 @@ namespace BansheeEngine
 		accessor.queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore()));
 		accessor.queueCommand(std::bind(&RenderAPICore::swapBuffers, RenderAPICore::instancePtr(), target->getCore()));
 	}
 	}
 
 
-	void RenderAPI::draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount)
+	void RenderAPI::draw(CoreAccessor& accessor, UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 	{
 	{
-		accessor.queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, vertexCount));
+		accessor.queueCommand(std::bind(&RenderAPICore::draw, RenderAPICore::instancePtr(), vertexOffset, 
+			vertexCount, instanceCount));
 	}
 	}
 
 
-	void RenderAPI::drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	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, 
 		accessor.queueCommand(std::bind(&RenderAPICore::drawIndexed, RenderAPICore::instancePtr(), startIndex, indexCount, 
-			vertexOffset, vertexCount));
+			vertexOffset, vertexCount, instanceCount));
 	}
 	}
 
 
 	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
 	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)

+ 4 - 3
Source/BansheeCore/Source/BsVertexDataDesc.cpp

@@ -6,11 +6,12 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	void VertexDataDesc::addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
+	void VertexDataDesc::addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, 
+		UINT32 streamIdx, UINT32 instanceStepRate)
 	{
 	{
 		clearIfItExists(type, semantic, semanticIdx, streamIdx);
 		clearIfItExists(type, semantic, semanticIdx, streamIdx);
 
 
-		VertexElement newElement(streamIdx, 0, type, semantic, semanticIdx);
+		VertexElement newElement(streamIdx, 0, type, semantic, semanticIdx, instanceStepRate);
 
 
 		// Insert it so it is sorted by stream
 		// Insert it so it is sorted by stream
 		UINT32 insertToIndex = (UINT32)mVertexElements.size();
 		UINT32 insertToIndex = (UINT32)mVertexElements.size();
@@ -44,7 +45,7 @@ namespace BansheeEngine
 			UINT32 streamIdx = vertElem.getStreamIdx();
 			UINT32 streamIdx = vertElem.getStreamIdx();
 
 
 			declarationElements.push_back(VertexElement(streamIdx, streamOffsets[streamIdx], vertElem.getType(),
 			declarationElements.push_back(VertexElement(streamIdx, streamOffsets[streamIdx], vertElem.getType(),
-				vertElem.getSemantic(), vertElem.getSemanticIdx()));
+				vertElem.getSemantic(), vertElem.getSemanticIdx(), vertElem.getInstanceStepRate()));
 
 
 			streamOffsets[streamIdx] += vertElem.getSize();
 			streamOffsets[streamIdx] += vertElem.getSize();
 		}
 		}

+ 4 - 2
Source/BansheeCore/Source/BsVertexDeclaration.cpp

@@ -8,8 +8,9 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	VertexElement::VertexElement(UINT16 source, UINT32 offset,
 	VertexElement::VertexElement(UINT16 source, UINT32 offset,
-		VertexElementType theType, VertexElementSemantic semantic, UINT16 index)
+		VertexElementType theType, VertexElementSemantic semantic, UINT16 index, UINT32 instanceStepRate)
 		: mSource(source), mOffset(offset), mType(theType), mSemantic(semantic), mIndex(index)
 		: mSource(source), mOffset(offset), mType(theType), mSemantic(semantic), mIndex(index)
+		, mInstanceStepRate(instanceStepRate)
 	{
 	{
 	}
 	}
 
 
@@ -133,7 +134,8 @@ namespace BansheeEngine
 			if (elem.getType() == VET_COLOR)
 			if (elem.getType() == VET_COLOR)
 				type = VertexElement::getBestColorVertexElementType();
 				type = VertexElement::getBestColorVertexElementType();
 
 
-			mElementList.push_back(VertexElement(elem.getStreamIdx(), elem.getOffset(), type, elem.getSemantic(), elem.getSemanticIdx()));
+			mElementList.push_back(VertexElement(elem.getStreamIdx(), elem.getOffset(), type, elem.getSemantic(), 
+				elem.getSemanticIdx(), elem.getInstanceStepRate()));
 		}
 		}
 	}
 	}
 
 

+ 3 - 2
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -82,10 +82,11 @@ namespace BansheeEngine
 		void setDrawOperation(DrawOperationType op) override;
 		void setDrawOperation(DrawOperationType op) override;
 
 
 		/** @copydoc RenderAPICore::draw */
 		/** @copydoc RenderAPICore::draw */
-		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
+		void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0) override;
 
 
 		/** @copydoc RenderAPICore::drawIndexed */
 		/** @copydoc RenderAPICore::drawIndexed */
-		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount, 
+			UINT32 instanceCount = 0) override;
 
 
 		/** @copydoc RenderAPICore::dispatchCompute */
 		/** @copydoc RenderAPICore::dispatchCompute */
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;

+ 11 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11InputLayoutManager.cpp

@@ -101,8 +101,17 @@ namespace BansheeEngine
 			elementDesc.Format = D3D11Mappings::get(iter->getType());
 			elementDesc.Format = D3D11Mappings::get(iter->getType());
 			elementDesc.InputSlot = iter->getStreamIdx();
 			elementDesc.InputSlot = iter->getStreamIdx();
 			elementDesc.AlignedByteOffset = static_cast<WORD>(iter->getOffset());
 			elementDesc.AlignedByteOffset = static_cast<WORD>(iter->getOffset());
-			elementDesc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
-			elementDesc.InstanceDataStepRate = 0;
+
+			if (iter->getInstanceStepRate() == 0)
+			{
+				elementDesc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+				elementDesc.InstanceDataStepRate = 0;
+			}
+			else
+			{
+				elementDesc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
+				elementDesc.InstanceDataStepRate = iter->getInstanceStepRate();
+			}
 
 
 			maxStreamIdx = std::max(maxStreamIdx, (INT32)iter->getStreamIdx());
 			maxStreamIdx = std::max(maxStreamIdx, (INT32)iter->getStreamIdx());
 		}
 		}

+ 11 - 4
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -605,13 +605,16 @@ namespace BansheeEngine
 			BS_EXCEPT(RenderingAPIException, "Failed to setConstantBuffers : " + mDevice->getErrorDescription());
 			BS_EXCEPT(RenderingAPIException, "Failed to setConstantBuffers : " + mDevice->getErrorDescription());
 	}
 	}
 
 
-	void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
+	void D3D11RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
 		applyInputLayout();
 		applyInputLayout();
 
 
-		mDevice->getImmediateContext()->Draw(vertexCount, vertexOffset);
+		if(instanceCount <= 1)
+			mDevice->getImmediateContext()->Draw(vertexCount, vertexOffset);
+		else
+			mDevice->getImmediateContext()->DrawInstanced(vertexCount, instanceCount, vertexOffset, 0);
 
 
 #if BS_DEBUG_MODE
 #if BS_DEBUG_MODE
 		if(mDevice->hasError())
 		if(mDevice->hasError())
@@ -625,13 +628,17 @@ namespace BansheeEngine
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 	}
 	}
 
 
-	void D3D11RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	void D3D11RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount, 
+		UINT32 instanceCount)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 
 		applyInputLayout();
 		applyInputLayout();
 
 
-		mDevice->getImmediateContext()->DrawIndexed(indexCount, startIndex, vertexOffset);
+		if (instanceCount <= 1)
+			mDevice->getImmediateContext()->DrawIndexed(indexCount, startIndex, vertexOffset);
+		else
+			mDevice->getImmediateContext()->DrawIndexedInstanced(indexCount, instanceCount, startIndex, vertexOffset, 0);
 
 
 #if BS_DEBUG_MODE
 #if BS_DEBUG_MODE
 		if(mDevice->hasError())
 		if(mDevice->hasError())

+ 3 - 2
Source/BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h

@@ -80,10 +80,11 @@ namespace BansheeEngine
 		void endFrame() override;
 		void endFrame() override;
 
 
 		/** @copydoc RenderAPICore::draw() */
 		/** @copydoc RenderAPICore::draw() */
-		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
+		void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0) override;
 
 
 		/** @copydoc RenderAPICore::drawIndexed() */
 		/** @copydoc RenderAPICore::drawIndexed() */
-		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
+			UINT32 instanceCount = 0) override;
 
 
 		/** @copydoc RenderAPICore::dispatchCompute() */
 		/** @copydoc RenderAPICore::dispatchCompute() */
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;

+ 7 - 2
Source/BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -1162,8 +1162,10 @@ namespace BansheeEngine
 		mCurrentDrawOperation = op;
 		mCurrentDrawOperation = op;
 	}
 	}
 
 
-	void D3D9RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
+	void D3D9RenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 	{
 	{
+		// Note: Not supporting instanced drawing
+
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
 
 
 		HRESULT hr = getActiveD3D9Device()->DrawPrimitive(getD3D9PrimitiveType(), static_cast<UINT>(vertexOffset), static_cast<UINT>(primCount)); 
 		HRESULT hr = getActiveD3D9Device()->DrawPrimitive(getD3D9PrimitiveType(), static_cast<UINT>(vertexOffset), static_cast<UINT>(primCount)); 
@@ -1179,8 +1181,11 @@ namespace BansheeEngine
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 	}
 	}
 
 
-	void D3D9RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	void D3D9RenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount, 
+		UINT32 instanceCount)
 	{
 	{
+		// Note: Not supporting instanced drawing
+
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, indexCount);
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, indexCount);
 
 
 		// do indexed draw operation
 		// do indexed draw operation

+ 3 - 2
Source/BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -83,10 +83,11 @@ namespace BansheeEngine
 		void endFrame() override;
 		void endFrame() override;
 
 
 		/** @copydoc RenderAPICore::draw() */
 		/** @copydoc RenderAPICore::draw() */
-		void draw(UINT32 vertexOffset, UINT32 vertexCount) override;
+		void draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount = 0) override;
 
 
 		/** @copydoc RenderAPICore::drawIndexed() */
 		/** @copydoc RenderAPICore::drawIndexed() */
-		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
+		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount
+			, UINT32 instanceCount = 0) override;
 
 
 		/** @copydoc RenderAPICore::dispatchCompute() */
 		/** @copydoc RenderAPICore::dispatchCompute() */
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;
 		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;

+ 19 - 5
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -649,13 +649,16 @@ namespace BansheeEngine
 		mBoundIndexBuffer = buffer;
 		mBoundIndexBuffer = buffer;
 	}
 	}
 
 
-	void GLRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount)
+	void GLRenderAPI::draw(UINT32 vertexOffset, UINT32 vertexCount, UINT32 instanceCount)
 	{
 	{
 		// Find the correct type to render
 		// Find the correct type to render
 		GLint primType = getGLDrawMode();
 		GLint primType = getGLDrawMode();
 		beginDraw();
 		beginDraw();
 
 
-		glDrawArrays(primType, vertexOffset, vertexCount);
+		if (instanceCount <= 1)
+			glDrawArrays(primType, vertexOffset, vertexCount);
+		else
+			glDrawArraysInstanced(primType, vertexOffset, vertexCount, instanceCount);
 
 
 		endDraw();
 		endDraw();
 
 
@@ -666,9 +669,10 @@ namespace BansheeEngine
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 	}
 	}
 
 
-	void GLRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount)
+	void GLRenderAPI::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount,
+		UINT32 instanceCount)
 	{
 	{
-		if(mBoundIndexBuffer == nullptr)
+		if (mBoundIndexBuffer == nullptr)
 		{
 		{
 			LOGWRN("Cannot draw indexed because index buffer is not set.");
 			LOGWRN("Cannot draw indexed because index buffer is not set.");
 			return;
 			return;
@@ -684,7 +688,17 @@ namespace BansheeEngine
 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->getGLBufferId());
 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->getGLBufferId());
 
 
 		GLenum indexType = (ibProps.getType() == IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
 		GLenum indexType = (ibProps.getType() == IT_16BIT) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-		glDrawElementsBaseVertex(primType, indexCount, indexType, (GLvoid*)(UINT64)(ibProps.getIndexSize() * startIndex), vertexOffset);
+
+		if (instanceCount <= 1)
+		{
+			glDrawElementsBaseVertex(primType, indexCount, indexType,
+				(GLvoid*)(UINT64)(ibProps.getIndexSize() * startIndex), vertexOffset);
+		}
+		else
+		{
+			glDrawElementsInstancedBaseVertex(primType, indexCount, indexType,
+				(GLvoid*)(UINT64)(ibProps.getIndexSize() * startIndex), instanceCount, vertexOffset);
+		}
 
 
 		endDraw();
 		endDraw();
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);

+ 1 - 0
Source/BansheeGLRenderAPI/Source/BsGLVertexArrayObjectManager.cpp

@@ -178,6 +178,7 @@ namespace BansheeEngine
 			GLsizei vertexSize = static_cast<GLsizei>(vbProps.getVertexSize());
 			GLsizei vertexSize = static_cast<GLsizei>(vbProps.getVertexSize());
 			glVertexAttribPointer(attribLocation, typeCount, glType, normalized,
 			glVertexAttribPointer(attribLocation, typeCount, glType, normalized,
 				vertexSize, bufferData);
 				vertexSize, bufferData);
+			glVertexAttribDivisor(attribLocation, elem.getInstanceStepRate());
 
 
 			glEnableVertexAttribArray(attribLocation);
 			glEnableVertexAttribArray(attribLocation);
 		}
 		}