فهرست منبع

Refactoring render API in order to support command buffers (WIP)

BearishSun 9 سال پیش
والد
کامیت
512a345d3b

+ 3 - 0
Source/BansheeCore/CMakeSources.cmake

@@ -159,6 +159,8 @@ set(BS_BANSHEECORE_INC_RENDERAPI
 	"Include/BsRenderAPIFactory.h"
 	"Include/BsRenderAPIFactory.h"
 	"Include/BsRenderAPICapabilities.h"
 	"Include/BsRenderAPICapabilities.h"
 	"Include/BsViewport.h"
 	"Include/BsViewport.h"
+	"Include/BsCommandBufferManager.h"
+	"Include/BsCommandBuffer.h"
 )
 )
 
 
 set(BS_BANSHEECORE_SRC_CORETHREAD
 set(BS_BANSHEECORE_SRC_CORETHREAD
@@ -447,6 +449,7 @@ set(BS_BANSHEECORE_SRC_RENDERAPI
 	"Source/BsRenderAPIManager.cpp"
 	"Source/BsRenderAPIManager.cpp"
 	"Source/BsRenderAPICapabilities.cpp"
 	"Source/BsRenderAPICapabilities.cpp"
 	"Source/BsViewport.cpp"
 	"Source/BsViewport.cpp"
+	"Source/BsCommandBuffer.cpp"
 )
 )
 
 
 set(BS_BANSHEECORE_SRC_NOFILTER
 set(BS_BANSHEECORE_SRC_NOFILTER

+ 70 - 0
Source/BansheeCore/Include/BsCommandBuffer.h

@@ -0,0 +1,70 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	/** 
+	 * Contains a list of render API commands that can be queued for execution on the GPU. User is allowed to populate the
+	 * command buffer from any thread, ensuring render API command generation can be multi-threaded. Command buffers
+	 * must always be created on the core thread. Same command buffer cannot be used on multiple threads simulateously
+	 * without external synchronization.
+	 */
+	class BS_CORE_EXPORT CommandBuffer
+	{
+	public:
+		/** @copydoc CommandBufferManager::create */
+		static SPtr<CommandBuffer> create(CommandBufferType type, UINT32 deviceIdx = 0, UINT32 syncMask = 0xFFFFFFFF, 
+			bool secondary = false);
+
+	protected:
+		CommandBuffer(CommandBufferType type, UINT32 syncMask, bool secondary);
+
+		CommandBufferType mType;
+		UINT32 mSyncMask;
+		bool mIsSecondary;
+	};
+
+	/** @} */
+
+	/** @addtogroup RenderAPI-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Command buffer implementation for render API's that do not support multi-threaded command generation. Instead all
+	 * commands are stored in an internal buffer, and then sent to the actual render API when the buffer is executed.
+	 */
+	class BS_CORE_EXPORT SimpleCommandBuffer : CommandBuffer
+	{
+	public:
+		/** Registers a new command in the command buffer. */
+		void queueCommand(const std::function<void()> command);
+
+		/** Appends all commands from the secondary buffer into this command buffer. */
+		void appendSecondary(const SPtr<SimpleCommandBuffer>& secondaryBuffer);
+
+		/** Executes all commands in the command buffer. Not supported on secondary buffer. */
+		void executeCommands();
+
+		/** Removes all commands from the command buffer. */
+		void clear();
+
+	private:
+		friend class CommandBufferManager;
+
+		SimpleCommandBuffer(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask, bool secondary);
+
+		UINT32 mDeviceIdx;
+		Vector<std::function<void()>> mCommands;
+	};
+
+	/** @} */
+}

+ 43 - 0
Source/BansheeCore/Include/BsCommandBufferManager.h

@@ -0,0 +1,43 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RenderAPI-Internal
+	 *  @{
+	 */
+
+	/** 
+	 * Handles creation of command buffers. See CommandBuffer. 
+	 *
+	 * @note Core thread only.
+	 */
+	class BS_CORE_EXPORT CommandBufferManager : public Module<CommandBufferManager>
+	{
+	public:
+		/**
+		 * Creates a new CommandBuffer.
+		 * 
+		 * @param[in]	type		Determines what type of commands can be added to the command buffer.
+		 * @param[in]	deviceIdx	Index of the GPU the command buffer will be used to queue commands on. 0 is always
+		 *							the primary available GPU.
+		 * @param[in]	syncMask	Determines how is concurrency handled between multiple command buffers on the same 
+		 *							device. If buffers don't share the same bits in the sync mask they are allowed to
+		 *							execute concurrently on the GPU, however it is up to the user to ensure that they
+		 *							do not contain any resources depended on each other. Leave on default to ensure
+		 *							no concurrency is possible (safest).
+		 * @param[in]	secondary	If true the command buffer will not be allowed to execute on its own, but it can
+		 *							be appended to a primary command buffer. 
+		 * @return					New CommandBuffer instance.
+		 * 
+		 */
+		virtual SPtr<CommandBuffer> create(CommandBufferType type, UINT32 deviceIdx = 0, UINT32 syncMask = 0xFFFFFFFF, 
+			bool secondary = false) = 0;
+	};
+
+	/** @} */
+}

+ 14 - 0
Source/BansheeCore/Include/BsCommonTypes.h

@@ -353,6 +353,20 @@ namespace BansheeEngine
 		GPOT_UNKNOWN = 0xffff
 		GPOT_UNKNOWN = 0xffff
 	};
 	};
 
 
+	/** Types of command buffers. */
+	enum CommandBufferType
+	{
+		/** 
+		 * Command buffer used for rendering. Allows the use of draw commands, but also all commands supported by compute
+		 * or upload buffers. 
+		 */
+		CBT_GRAPHICS,
+		/** Command buffer used for compute operations. Allows the use of dispatch and upload commands. */
+		CBT_COMPUTE,
+		/** Command buffer used for memory transfer operations only. No rendering or compute dispatch allowed. */
+		CBT_UPLOAD
+	};
+
 	/** These values represent a hint to the driver when writing to a GPU buffer. */
 	/** These values represent a hint to the driver when writing to a GPU buffer. */
 	enum class BufferWriteType
 	enum class BufferWriteType
 	{
 	{

+ 1 - 0
Source/BansheeCore/Include/BsCorePrerequisites.h

@@ -378,6 +378,7 @@ namespace BansheeEngine
 	class MorphShapes;
 	class MorphShapes;
 	class MorphShape;
 	class MorphShape;
 	class MorphChannel;
 	class MorphChannel;
+	class CommandBuffer;
 	// Asset import
 	// Asset import
 	class SpecificImporter;
 	class SpecificImporter;
 	class Importer;
 	class Importer;

+ 69 - 0
Source/BansheeCore/Source/BsCommandBuffer.cpp

@@ -0,0 +1,69 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsCommandBuffer.h"
+#include "BsCommandBufferManager.h"
+
+namespace BansheeEngine
+{
+	CommandBuffer::CommandBuffer(CommandBufferType type, UINT32 syncMask, bool secondary)
+		:mType(type), mSyncMask(syncMask), mIsSecondary(secondary)
+	{
+
+	}
+
+	SPtr<CommandBuffer> CommandBuffer::create(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask,
+		bool secondary)
+	{
+		return CommandBufferManager::instance().create(type, deviceIdx, syncMask, secondary);
+	}
+
+	SimpleCommandBuffer::SimpleCommandBuffer(CommandBufferType type, UINT32 deviceIdx, UINT32 syncMask, bool secondary)
+		: CommandBuffer(type, syncMask, secondary), mDeviceIdx(deviceIdx)
+	{
+
+	}
+
+	void SimpleCommandBuffer::queueCommand(const std::function<void()> command)
+	{
+		mCommands.push_back(command);
+	}
+
+	void SimpleCommandBuffer::appendSecondary(const SPtr<SimpleCommandBuffer>& secondaryBuffer)
+	{
+#if BS_DEBUG_MODE
+		if(!secondaryBuffer->mIsSecondary)
+		{
+			LOGERR("Cannot append a command buffer that is not secondary.");
+			return;
+		}
+
+		if(mIsSecondary)
+		{
+			LOGERR("Cannot append a buffer to a secondary command buffer.");
+			return;
+		}
+#endif
+
+		for (auto& entry : secondaryBuffer->mCommands)
+			mCommands.push_back(entry);
+	}
+
+	void SimpleCommandBuffer::executeCommands()
+	{
+#if BS_DEBUG_MODE
+		if (mIsSecondary)
+		{
+			LOGERR("Cannot execute commands on a secondary buffer.");
+			return;
+		}
+#endif
+
+		for (auto& entry : mCommands)
+			entry();
+	}
+
+	void SimpleCommandBuffer::clear()
+	{
+		mCommands.clear();
+	}
+}