瀏覽代碼

Starting work on better gpu resource updates

Marko Pintera 12 年之前
父節點
當前提交
d0301de9c9

+ 1 - 1
BansheeEngine/Include/BsPrerequisites.h

@@ -71,7 +71,7 @@ namespace BansheeEngine
 	typedef CM::GameObjectHandle<Camera> HCamera;
 	typedef CM::GameObjectHandle<Renderable> HRenderable;
 
-	enum TypeID_Banshe
+	enum TypeID_Banshee
 	{
 		TID_Camera = 30000,
 		TID_Renderable = 30001

+ 5 - 3
CamelotCore/CamelotCore.vcxproj

@@ -179,8 +179,10 @@
     <ClInclude Include="Include\CmGameObjectHandle.h" />
     <ClInclude Include="Include\CmGameObject.h" />
     <ClInclude Include="Include\CmGameObjectRTTI.h" />
-    <ClInclude Include="Include\CmGpuBufferData.h" />
+    <ClInclude Include="Include\CmGpuResourceData.h" />
     <ClInclude Include="Include\CmGpuParamBlockBuffer.h" />
+    <ClInclude Include="Include\CmGpuResource.h" />
+    <ClInclude Include="Include\CmGpuResourceRTTI.h" />
     <ClInclude Include="Include\CmSceneObjectRTTI.h" />
     <ClInclude Include="Include\CmMemAllocCategories.h" />
     <ClInclude Include="Include\CmApplication.h" />
@@ -281,7 +283,6 @@
     <ClInclude Include="Include\CmComponent.h" />
     <ClInclude Include="Include\CmShader.h" />
     <ClInclude Include="Include\CmBlendState.h" />
-    <ClInclude Include="Include\CmIGpuBuffer.h" />
     <ClInclude Include="Include\stdafx.h" />
     <ClInclude Include="Include\targetver.h" />
     <ClInclude Include="Include\CmVertexDeclarationRTTI.h" />
@@ -306,7 +307,6 @@
     <ClCompile Include="Source\CmFontImportOptions.cpp" />
     <ClCompile Include="Source\CmFontManager.cpp" />
     <ClCompile Include="Source\CmGpuBuffer.cpp" />
-    <ClCompile Include="Source\CmGpuBufferData.cpp" />
     <ClCompile Include="Source\CmGpuBufferView.cpp" />
     <ClCompile Include="Source\CmGpuParamBlock.cpp" />
     <ClCompile Include="Source\CmGpuParamBlockBuffer.cpp" />
@@ -317,6 +317,8 @@
     <ClCompile Include="Source\CmGpuProgramImportOptions.cpp" />
     <ClCompile Include="Source\CmGpuProgramManager.cpp" />
     <ClCompile Include="Source\CmGpuProgramParams.cpp" />
+    <ClCompile Include="Source\CmGpuResource.cpp" />
+    <ClCompile Include="Source\CmGpuResourceData.cpp" />
     <ClCompile Include="Source\CmHardwareBufferManager.cpp" />
     <ClCompile Include="Source\CmImportOptions.cpp" />
     <ClCompile Include="Source\CmIndexBuffer.cpp" />

+ 15 - 9
CamelotCore/CamelotCore.vcxproj.filters

@@ -414,15 +414,18 @@
     <ClInclude Include="Include\CmGameObjectRTTI.h">
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
-    <ClInclude Include="Include\CmIGpuBuffer.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\CmGpuBufferData.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmGpuParamBlockBuffer.h">
       <Filter>Header Files\RenderSystem</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmGpuResource.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmGpuResourceData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmGpuResourceRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmApplication.cpp">
@@ -647,11 +650,14 @@
     <ClCompile Include="Source\CmGameObject.cpp">
       <Filter>Source Files\Scene</Filter>
     </ClCompile>
-    <ClCompile Include="Source\CmGpuBufferData.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="Source\CmGpuParamBlockBuffer.cpp">
       <Filter>Source Files\RenderSystem</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmGpuResourceData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmGpuResource.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 18 - 0
CamelotCore/Include/CmDeferredRenderContext.h

@@ -98,6 +98,24 @@ namespace CamelotFramework
 		/** @copydoc RenderSystem::swapBuffers() */
 		void swapBuffers(RenderTargetPtr target);
 
+		/**
+		 * @copydoc RenderSystem::writeSubresource()
+		 *
+		 * @note Resource is updated with data from "data" parameter when the async operation completes. 
+		 * 		 Until the async operation completes "data" is owned by the render thread and you won't
+		 * 		 be able to access it. 
+		 */
+		AsyncOp writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data);
+
+		/**
+		 * @copydoc RenderSystem::writeSubresource()
+		 *
+		 * @note "data" parameter is populated with subresource data when the async operation completes. 
+		 * 		 Until the async operation completes "data" is owned by the render thread and you won't
+		 * 		 be able to access it.
+		 */
+		AsyncOp readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data);
+
 		/**
 		 * @brief	Makes all the currently queued commands available to the GPU. They will be executed
 		 * 			as soon as the render thread is ready.

+ 0 - 24
CamelotCore/Include/CmGpuBufferData.h

@@ -1,24 +0,0 @@
-#pragma once
-
-#include "CmPrerequisites.h"
-
-namespace CamelotFramework
-{
-	class CM_EXPORT GpuBufferData
-	{
-	public:
-		GpuBufferData();
-		~GpuBufferData();
-
-		UINT8* getData() const;
-
-	protected:
-		void initialize(UINT32 size);
-
-		void lock();
-		void unlock();
-
-		UINT8* mData;
-		bool mLocked;
-	};
-}

+ 22 - 0
CamelotCore/Include/CmGpuResource.h

@@ -0,0 +1,22 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmResource.h"
+
+namespace CamelotFramework
+{
+	class CM_EXPORT GpuResource : public Resource
+	{
+	public:
+		virtual void writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data) = 0;
+		virtual void readSubresource(UINT32 subresourceIdx, GpuResourceData& data) = 0;
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class GpuResourceRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
+	};
+}

+ 28 - 0
CamelotCore/Include/CmGpuResourceData.h

@@ -0,0 +1,28 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotFramework
+{
+	class CM_EXPORT GpuResourceData
+	{
+	public:
+		GpuResourceData();
+		~GpuResourceData();
+
+	protected:
+		friend class DeferredRenderContext;
+		friend class RenderSystem;
+
+		void initialize(UINT32 size);
+
+		UINT8* getData() const;
+
+		void lock() const;
+		void unlock() const;
+
+	private:
+		UINT8* mData;
+		mutable bool mLocked;
+	};
+}

+ 33 - 0
CamelotCore/Include/CmGpuResourceRTTI.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmRTTIType.h"
+#include "CmGpuResource.h"
+
+namespace CamelotFramework
+{
+	class CM_EXPORT GpuResourceRTTI : public RTTIType<GpuResource, Resource, GpuResourceRTTI>
+	{
+	public:
+		GpuResourceRTTI()
+		{
+
+		}
+
+		virtual const String& getRTTIName()
+		{
+			static String name = "GpuResource";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return TID_GpuResource;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject()
+		{
+			CM_EXCEPT(InternalErrorException, "Cannot instantiate an abstract class.");
+		}
+	};
+}

+ 0 - 13
CamelotCore/Include/CmIGpuBuffer.h

@@ -1,13 +0,0 @@
-#pragma once
-
-#include "CmPrerequisites.h"
-
-namespace CamelotFramework
-{
-	class CM_EXPORT IGpuBuffer
-	{
-	public:
-		virtual void setData(GpuBufferDataPtr data) = 0;
-		virtual GpuBufferDataPtr getData() const = 0;
-	};
-}

+ 5 - 3
CamelotCore/Include/CmPrerequisites.h

@@ -149,7 +149,8 @@ namespace CamelotFramework {
 	class ImportOptions;
 	struct FontData;
 	class GameObject;
-	class GpuBufferData;
+	class GpuResource;
+	class GpuResourceData;
 	class BindableGpuParams;
 	// Asset import
 	class SpecificImporter;
@@ -222,7 +223,7 @@ namespace CamelotFramework
 	typedef std::shared_ptr<const ImportOptions> ConstImportOptionsPtr;
 	typedef std::shared_ptr<Font> FontPtr;
 	typedef std::shared_ptr<InputHandler> InputHandlerPtr;
-	typedef std::shared_ptr<GpuBufferData> GpuBufferDataPtr;
+	typedef std::shared_ptr<GpuResource> GpuResourcePtr;
 }
 
 /************************************************************************/
@@ -279,7 +280,8 @@ namespace CamelotFramework
 		TID_FontData = 1057,
 		TID_IndexElementData = 1058,
 		TID_SceneObject = 1059,
-		TID_GameObject = 1060
+		TID_GameObject = 1060,
+		TID_GpuResource = 1061
 	};
 
 	/**

+ 10 - 0
CamelotCore/Include/CmRenderSystem.h

@@ -283,6 +283,16 @@ namespace CamelotFramework
          */
         virtual void setRenderTarget(RenderTargetPtr target) = 0;
 
+		/**
+		 * @brief	Updates the resource with the specified data.
+		 */
+		void writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data, AsyncOp& asyncOp);
+
+		/**
+		 * @brief	Reads data from a resource into a pre-allocated GpuResourceData instance.
+		 */
+		void readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data, AsyncOp& asyncOp);
+
 		/************************************************************************/
 		/* 								UTILITY METHODS                    		*/
 		/************************************************************************/

+ 15 - 0
CamelotCore/Source/CmDeferredRenderContext.cpp

@@ -4,6 +4,7 @@
 #include "CmBlendState.h"
 #include "CmRasterizerState.h"
 #include "CmDepthStencilState.h"
+#include "CmGpuResourceData.h"
 #include "CmGpuParams.h"
 
 namespace CamelotFramework
@@ -155,6 +156,20 @@ namespace CamelotFramework
 		mCommandQueue->queue(boost::bind(&RenderSystem::drawIndexed, mRenderSystem, startIndex, indexCount, vertexCount));
 	}
 
+	AsyncOp DeferredRenderContext::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data)
+	{
+		data.lock();
+
+		return mCommandQueue->queueReturn(boost::bind(&RenderSystem::writeSubresource, mRenderSystem, resource, subresourceIdx, boost::cref(data), _1));
+	}
+
+	AsyncOp DeferredRenderContext::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data)
+	{
+		data.lock();
+
+		return mCommandQueue->queueReturn(boost::bind(&RenderSystem::readSubresource, mRenderSystem, resource, subresourceIdx, boost::ref(data), _1));
+	}
+
 	void DeferredRenderContext::submitToGpu()
 	{
 		std::queue<CommandQueue::Command>* commands = mCommandQueue->flush();

+ 15 - 0
CamelotCore/Source/CmGpuResource.cpp

@@ -0,0 +1,15 @@
+#include "CmGpuResource.h"
+#include "CmGpuResourceRTTI.h"
+
+namespace CamelotFramework
+{
+	RTTITypeBase* GpuResource::getRTTIStatic()
+	{
+		return GpuResourceRTTI::instance();
+	}
+
+	RTTITypeBase* GpuResource::getRTTI() const
+	{
+		return GpuResource::getRTTIStatic();
+	}
+}

+ 7 - 7
CamelotCore/Source/CmGpuBufferData.cpp → CamelotCore/Source/CmGpuResourceData.cpp

@@ -1,21 +1,21 @@
-#include "CmGpuBufferData.h"
+#include "CmGpuResourceData.h"
 #include "CmException.h"
 
 namespace CamelotFramework
 {
-	GpuBufferData::GpuBufferData()
+	GpuResourceData::GpuResourceData()
 		:mData(nullptr), mLocked(false)
 	{
 
 	}
 
-	GpuBufferData::~GpuBufferData()
+	GpuResourceData::~GpuResourceData()
 	{
 		if(mData != nullptr)
 			CM_DELETE_BYTES(mData, ScratchAlloc);
 	}
 
-	UINT8* GpuBufferData::getData() const
+	UINT8* GpuResourceData::getData() const
 	{
 		if(mLocked)
 			CM_EXCEPT(InternalErrorException, "You are not allowed to access buffer data when the buffer is locked.");
@@ -23,17 +23,17 @@ namespace CamelotFramework
 		return mData;
 	}
 
-	void GpuBufferData::initialize(UINT32 size)
+	void GpuResourceData::initialize(UINT32 size)
 	{
 		mData = CM_NEW_BYTES(size, ScratchAlloc);
 	}
 
-	void GpuBufferData::lock()
+	void GpuResourceData::lock() const
 	{
 		mLocked = true;
 	}
 
-	void GpuBufferData::unlock()
+	void GpuResourceData::unlock() const
 	{
 		mLocked = false;
 	}

+ 35 - 18
CamelotCore/Source/CmRenderSystem.cpp

@@ -41,6 +41,7 @@ THE SOFTWARE.
 #include "CmOcclusionQuery.h"
 #include "CmCommandQueue.h"
 #include "CmDeferredRenderContext.h"
+#include "CmGpuResource.h"
 #include "boost/bind.hpp"
 
 #if CM_DEBUG_MODE
@@ -53,7 +54,6 @@ namespace CamelotFramework {
 
     static const TexturePtr sNullTexPtr;
 
-    //-----------------------------------------------------------------------
     RenderSystem::RenderSystem()
         : mCullingMode(CULL_COUNTERCLOCKWISE)
         , mInvertVertexWinding(false)
@@ -71,7 +71,6 @@ namespace CamelotFramework {
     {
     }
 
-    //-----------------------------------------------------------------------
     RenderSystem::~RenderSystem()
     {
 		// Base classes need to call virtual destroy_internal method (queue it on render thread)
@@ -88,7 +87,7 @@ namespace CamelotFramework {
 		CM_DELETE(mCurrentCapabilities, RenderSystemCapabilities, GenAlloc);
 		mCurrentCapabilities = nullptr;
     }
-	//-----------------------------------------------------------------------
+
 	RenderWindowPtr RenderSystem::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
 	{
 		mRenderThreadId = CM_THREAD_CURRENT_ID;
@@ -100,7 +99,7 @@ namespace CamelotFramework {
 		AsyncOp op = queueReturnCommand(boost::bind(&RenderSystem::initialize_internal, this, _1), true);
 		return op.getReturnValue<RenderWindowPtr>();
 	}
-	//-----------------------------------------------------------------------
+
 	void RenderSystem::initialize_internal(AsyncOp& asyncOp)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -109,39 +108,39 @@ namespace CamelotFramework {
 		mGeometryProgramBound = false;
 		mFragmentProgramBound = false;
 	}
-	//-----------------------------------------------------------------------
+
 	void RenderSystem::destroy_internal()
 	{
 		mActiveRenderTarget = nullptr;
 	}
-    //---------------------------------------------------------------------------------------------
+
     void RenderSystem::_notifyWindowCreated(RenderWindow& window)
     {
 		THROW_IF_NOT_RENDER_THREAD;
 
     }
-	//---------------------------------------------------------------------------------------------
+
 	const RenderSystemCapabilities* RenderSystem::getCapabilities(void) const 
 	{ 
 		THROW_IF_NOT_RENDER_THREAD;
 
 		return mCurrentCapabilities; 
 	}
-	//---------------------------------------------------------------------------------------------
+
 	const DriverVersion& RenderSystem::getDriverVersion(void) const 
 	{ 
 		THROW_IF_NOT_RENDER_THREAD;
 
 		return mDriverVersion; 
 	}
-    //-----------------------------------------------------------------------
+
     void RenderSystem::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
     {
 		THROW_IF_NOT_RENDER_THREAD;
 
         setTexture(gptype, texUnit, false, sNullTexPtr);
     }
-	//---------------------------------------------------------------------
+
 	void RenderSystem::addClipPlane (const Plane &p)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -149,14 +148,14 @@ namespace CamelotFramework {
 		mClipPlanes.push_back(p);
 		mClipPlanesDirty = true;
 	}
-	//---------------------------------------------------------------------
+
 	void RenderSystem::addClipPlane (float A, float B, float C, float D)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 
 		addClipPlane(Plane(A, B, C, D));
 	}
-	//---------------------------------------------------------------------
+
 	void RenderSystem::setClipPlanes(const PlaneList& clipPlanes)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -167,7 +166,7 @@ namespace CamelotFramework {
 			mClipPlanesDirty = true;
 		}
 	}
-	//---------------------------------------------------------------------
+
 	void RenderSystem::resetClipPlanes()
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -178,7 +177,7 @@ namespace CamelotFramework {
 			mClipPlanesDirty = true;
 		}
 	}
-	//-----------------------------------------------------------------------
+
 	void RenderSystem::bindGpuProgram(HGpuProgram prg)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -200,7 +199,7 @@ namespace CamelotFramework {
 			break;
 		}
 	}
-	//-----------------------------------------------------------------------
+
 	void RenderSystem::unbindGpuProgram(GpuProgramType gptype)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -221,7 +220,7 @@ namespace CamelotFramework {
 			break;
 		}
 	}
-	//-----------------------------------------------------------------------
+
 	bool RenderSystem::isGpuProgramBound(GpuProgramType gptype)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -238,7 +237,7 @@ namespace CamelotFramework {
         // Make compiler happy
         return false;
 	}
-	//-----------------------------------------------------------------------
+
 	void RenderSystem::render(const RenderOperation& op)
 	{
 		THROW_IF_NOT_RENDER_THREAD;
@@ -267,12 +266,30 @@ namespace CamelotFramework {
 		else
 			draw(op.vertexData->vertexCount);
 	}
-	//-----------------------------------------------------------------------
+
 	void RenderSystem::swapBuffers(RenderTargetPtr target)
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		target->swapBuffers();
 	}
 
+	void RenderSystem::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceData& data, AsyncOp& asyncOp)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		resource->writeSubresource(subresourceIdx, data);
+		asyncOp.completeOperation();
+	}
+
+	void RenderSystem::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceData& data, AsyncOp& asyncOp)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		resource->readSubresource(subresourceIdx, data);
+		asyncOp.completeOperation();
+	}
+
 	/************************************************************************/
 	/* 								PRIVATE		                     		*/
 	/************************************************************************/