Răsfoiți Sursa

Added compute dispatch to OpenGL and DX11

BearishSun 9 ani în urmă
părinte
comite
2be3578d8a

+ 12 - 0
BansheeCore/Include/BsRenderAPI.h

@@ -119,6 +119,9 @@ namespace BansheeEngine
 		/** @copydoc RenderAPICore::drawIndexed() */
 		static void drawIndexed(CoreAccessor& accessor, UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount);
 
+		/** @copydoc RenderAPICore::dispatchCompute() */
+		static void dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1);
+
 		/** @copydoc RenderAPICore::getVideoModeInfo */
 		static const VideoModeInfo& getVideoModeInfo();
 
@@ -259,6 +262,15 @@ namespace BansheeEngine
 		/** Draw an object based on currently bound GPU programs, vertex declaration, vertex and index buffers. */
 		virtual void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) = 0;
 
+		/** 
+		 * Executes the currently bound compute shader. 
+		 *
+		 * @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].
+		 */
+		virtual void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) = 0;
+
 		/** Swap the front and back buffer of the specified render target. */
 		virtual void swapBuffers(const SPtr<RenderTargetCore>& target);
 

+ 5 - 1
BansheeCore/Include/BsRenderStats.h

@@ -28,13 +28,14 @@ namespace BansheeEngine
 	struct BS_CORE_EXPORT RenderStatsData
 	{
 		RenderStatsData()
-		: numDrawCalls(0), numRenderTargetChanges(0), numPresents(0), numClears(0),
+		: numDrawCalls(0), numComputeCalls(0), numRenderTargetChanges(0), numPresents(0), numClears(0),
 		  numVertices(0), numPrimitives(0), numBlendStateChanges(0), numRasterizerStateChanges(0), 
 		  numDepthStencilStateChanges(0), numTextureBinds(0), numSamplerBinds(0), numVertexBufferBinds(0), 
 		  numIndexBufferBinds(0), numGpuParamBufferBinds(0), numGpuProgramBinds(0)
 		{ }
 
 		UINT64 numDrawCalls;
+		UINT64 numComputeCalls;
 		UINT64 numRenderTargetChanges;
 		UINT64 numPresents;
 		UINT64 numClears;
@@ -71,6 +72,9 @@ namespace BansheeEngine
 		/** Increments draw call counter indicating how many times were render system API Draw methods called. */
 		void incNumDrawCalls() { mData.numDrawCalls++; }
 
+		/** Increments compute call counter indicating how many times were compute shaders dispatched. */
+		void incNumComputeCalls() { mData.numComputeCalls++; }
+
 		/** Increments render target change counter indicating how many times did the active render target change. */
 		void incNumRenderTargetChanges() { mData.numRenderTargetChanges++; }
 

+ 6 - 0
BansheeCore/Source/BsRenderAPI.cpp

@@ -176,6 +176,12 @@ namespace BansheeEngine
 			vertexOffset, vertexCount));
 	}
 
+	void RenderAPI::dispatchCompute(CoreAccessor& accessor, UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		accessor.queueCommand(std::bind(&RenderAPICore::dispatchCompute, RenderAPICore::instancePtr(), numGroupsX, 
+			numGroupsY, numGroupsZ));
+	}
+
 	const VideoModeInfo& RenderAPI::getVideoModeInfo()
 	{
 		return RenderAPICore::instance().getVideoModeInfo();

+ 5 - 0
BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -130,6 +130,11 @@ namespace BansheeEngine
 		 */
 		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
 
+		/**
+		 * @copydoc RenderAPICore::drawIndexed()
+		 */
+		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;
+
 		/** 
 		 * @copydoc RenderAPICore::bindGpuProgram
 		 */

+ 12 - 0
BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -648,6 +648,18 @@ namespace BansheeEngine
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 	}
 
+	void D3D11RenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		mDevice->getImmediateContext()->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
+
+#if BS_DEBUG_MODE
+		if (mDevice->hasError())
+			LOGWRN(mDevice->getErrorDescription());
+#endif
+
+		BS_INC_RENDER_STAT(NumComputeCalls);
+	}
+
 	void D3D11RenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 5 - 0
BansheeD3D9RenderAPI/Include/BsD3D9RenderAPI.h

@@ -128,6 +128,11 @@ namespace BansheeEngine
 		 */
 		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
 
+		/**
+		 * @copydoc RenderAPICore::drawIndexed()
+		 */
+		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;
+
 		/**
 		 * @copydoc RenderAPICore::setScissorRect()
 		 */

+ 5 - 0
BansheeD3D9RenderAPI/Source/BsD3D9RenderAPI.cpp

@@ -1204,6 +1204,11 @@ namespace BansheeEngine
 		BS_ADD_RENDER_STAT(NumPrimitives, primCount);
 	}
 
+	void D3D9RenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		// Not supported on DX9
+	}
+
 	void D3D9RenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 6 - 0
BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -131,6 +131,11 @@ namespace BansheeEngine
 		 */
 		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount) override;
 
+		/**
+		 * @copydoc RenderAPICore::drawIndexed()
+		 */
+		void dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY = 1, UINT32 numGroupsZ = 1) override;
+
 		/**
 		 * @copydoc RenderAPICore::clearRenderTarget()
 		 */
@@ -581,6 +586,7 @@ namespace BansheeEngine
 		SPtr<GLSLGpuProgramCore> mCurrentGeometryProgram;
 		SPtr<GLSLGpuProgramCore> mCurrentHullProgram;
 		SPtr<GLSLGpuProgramCore> mCurrentDomainProgram;
+		SPtr<GLSLGpuProgramCore> mCurrentComputeProgram;
 
 		const GLSLProgramPipeline* mActivePipeline;
 

+ 24 - 5
BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -184,6 +184,7 @@ namespace BansheeEngine
 		mCurrentGeometryProgram = nullptr;
 		mCurrentHullProgram = nullptr;
 		mCurrentDomainProgram = nullptr;
+		mCurrentComputeProgram = nullptr;
 
 		mGLSupport->stop();
 
@@ -230,6 +231,8 @@ namespace BansheeEngine
 		case GPT_HULL_PROGRAM:
 			mCurrentHullProgram = glprg;
 			break;
+		case GPT_COMPUTE_PROGRAM:
+			mCurrentComputeProgram = glprg;
 		}
 
 		RenderAPICore::bindGpuProgram(prg);
@@ -696,6 +699,21 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumIndexBufferBinds);
 	}
 
+	void GLRenderAPI::dispatchCompute(UINT32 numGroupsX, UINT32 numGroupsY, UINT32 numGroupsZ)
+	{
+		if (mCurrentComputeProgram == nullptr)
+		{
+			LOGWRN("Cannot dispatch compute without a set compute program.");
+			return;
+		}
+
+		glUseProgram(mCurrentComputeProgram->getGLHandle());
+		glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+
+		BS_INC_RENDER_STAT(NumGpuProgramBinds);
+		BS_INC_RENDER_STAT(NumComputeCalls);
+	}
+
 	void GLRenderAPI::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -1681,6 +1699,9 @@ namespace BansheeEngine
 		case GPT_HULL_PROGRAM:
 			mCurrentHullProgram = program;
 			break;
+		case GPT_COMPUTE_PROGRAM:
+			mCurrentComputeProgram = program;
+			break;
 		}
 	}
 
@@ -1690,19 +1711,16 @@ namespace BansheeEngine
 		{
 		case GPT_VERTEX_PROGRAM:
 			return mCurrentVertexProgram;
-			break;
 		case GPT_FRAGMENT_PROGRAM:
 			return mCurrentFragmentProgram;
-			break;
 		case GPT_GEOMETRY_PROGRAM:
 			return mCurrentGeometryProgram;
-			break;
 		case GPT_DOMAIN_PROGRAM:
 			return mCurrentDomainProgram;
-			break;
 		case GPT_HULL_PROGRAM:
 			return mCurrentHullProgram;
-			break;
+		case GPT_COMPUTE_PROGRAM:
+			return mCurrentComputeProgram;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Insupported gpu program type: " + toString(gptype));
 		}
@@ -1801,6 +1819,7 @@ namespace BansheeEngine
 		unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
 		unbindGpuProgram(GPT_HULL_PROGRAM);
 		unbindGpuProgram(GPT_DOMAIN_PROGRAM);
+		unbindGpuProgram(GPT_COMPUTE_PROGRAM);
 
 		// It's ready for switching
 		if (mCurrentContext)

+ 1 - 0
BansheeGLRenderAPI/Source/GLSL/include/BsGLSLGpuProgram.h

@@ -51,5 +51,6 @@ namespace BansheeEngine
 		static UINT32 mGeometryShaderCount;
 		static UINT32 mHullShaderCount;
 		static UINT32 mDomainShaderCount;
+		static UINT32 mComputeShaderCount;
     };
 }

+ 4 - 0
BansheeGLRenderAPI/Source/GLSL/src/BsGLSLGpuProgram.cpp

@@ -17,6 +17,7 @@ namespace BansheeEngine
 	UINT32 GLSLGpuProgramCore::mGeometryShaderCount = 0;
 	UINT32 GLSLGpuProgramCore::mDomainShaderCount = 0;
 	UINT32 GLSLGpuProgramCore::mHullShaderCount = 0;
+	UINT32 GLSLGpuProgramCore::mComputeShaderCount = 0;
 
 	bool checkForGLSLError(const GLuint programObj, String& outErrorMsg)
 	{
@@ -122,6 +123,9 @@ namespace BansheeEngine
 		case GPT_DOMAIN_PROGRAM:
 			shaderType = GL_TESS_EVALUATION_SHADER;
 			mProgramID = ++mHullShaderCount;
+		case GPT_COMPUTE_PROGRAM:
+			shaderType = GL_COMPUTE_SHADER;
+			mProgramID = ++mComputeShaderCount;
 			break;
 		}
 

+ 2 - 0
RenderBeast/Source/BsRenderBeast.cpp

@@ -583,6 +583,7 @@ namespace BansheeEngine
 				mDirLightMat->setParameters(light.internal);
 
 				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
+				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
 				setPassParams(dirMaterial->getPassParameters(0), nullptr);
 				gRendererUtility().drawScreenQuad();
 			}
@@ -611,6 +612,7 @@ namespace BansheeEngine
 				mPointLightInMat->setParameters(light.internal);
 
 				// TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
+				//  - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
 				setPassParams(pointInsideMaterial->getPassParameters(0), nullptr);
 				SPtr<MeshCore> mesh = light.internal->getMesh();
 				gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));