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

Neater creation of GpuPrograms

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

+ 20 - 16
Source/BansheeCore/Include/BsGpuProgram.h

@@ -45,6 +45,17 @@ namespace BansheeEngine
 		GPP_CS_5_0 /**< Compute program 5.0 profile. */
 	};
 
+	/** Descriptor structure used for initialization of a GpuProgram. */
+	struct GPU_PROGRAM_DESC
+	{
+		String source; /**< Source code to compile the program from. */
+		String entryPoint; /**< Name of the entry point function, for example "main". */
+		String language; /**< Language the source is written in, for example "hlsl" or "glsl". */
+		GpuProgramType type = GPT_VERTEX_PROGRAM; /**< Type of the program, for example vertex or fragment. */
+		GpuProgramProfile profile = GPP_NONE; /**< Program profile specifying supported feature-set. Must match the type. */
+		bool requiresAdjacency = false; /**< If true then adjacency information will be provided when rendering. */
+	};
+
 	/** Data describing a GpuProgram. */
 	class BS_CORE_EXPORT GpuProgramProperties
 	{
@@ -116,22 +127,14 @@ namespace BansheeEngine
 		 * Creates a new GPU program using the provided source code. If compilation fails or program is not supported
 		 * isCompiled() with return false, and you will be able to retrieve the error message via getCompileErrorMessage().
 		 *
-		 * @param[in]	source				Source code to compile the program from.
-		 * @param[in]	entryPoint			Name of the entry point function, for example "main".
-		 * @param[in]	language			Language the source is written in, for example "hlsl" or "glsl".
-		 * @param[in]	gptype				Type of the program, for example vertex or fragment.
-		 * @param[in]	profile				Program profile specifying supported feature-set. Must match the type.
-		 * @param[in]	requiresAdjacency	If true then adjacency information will be provided when rendering using this 
-		 *									program.
+		 * @param[in]	desc				Description of the program to create.
 		 */
-		static SPtr<GpuProgram> create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
-			GpuProgramProfile profile, bool requiresAdjacency = false);
+		static SPtr<GpuProgram> create(const GPU_PROGRAM_DESC& desc);
 
 	protected:
 		friend class GpuProgramManager;
 
-		GpuProgram(const String& source, const String& entryPoint, const String& language,
-			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
+		GpuProgram(const GPU_PROGRAM_DESC& desc);
 
 		/** @copydoc CoreObject::createCore */
 		SPtr<CoreObjectCore> createCore() const override;
@@ -198,13 +201,14 @@ namespace BansheeEngine
 		/**	Returns properties that contain information about the GPU program. */
 		const GpuProgramProperties& getProperties() const { return mProperties; }
 
-		/** @copydoc GpuProgram::create */
-		static SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
-			GpuProgramProfile profile, bool requiresAdjacency = false);
+		/** 
+		 * @copydoc GpuProgram::create 
+		 * @param[in]	deviceMask		Mask that determines on which GPU devices should the object be created on.
+		 */
+		static SPtr<GpuProgramCore> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT);
 
 	protected:
-		GpuProgramCore(const String& source, const String& entryPoint,
-			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
+		GpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** Returns whether required capabilities for this program is supported. */
 		bool isRequiredCapabilitiesSupported() const;

+ 8 - 47
Source/BansheeCore/Include/BsGpuProgramManager.h

@@ -23,23 +23,11 @@ namespace BansheeEngine
 		/**	Returns GPU program language this factory is capable creating GPU programs from. */
 		virtual const String& getLanguage() const = 0;
 
-		/**
-		 * Creates a new GPU program using the provided source code. If compilation fails or program is not supported
-		 * GpuProgram::isCompiled() method on the returned program will return false, and you will be able to retrieve 
-		 * the error message via GpuProgram::getCompileErrorMessage().
-		 *
-		 * @param[in]	source				Source code to compile the shader from.
-		 * @param[in]	entryPoint			Name of the entry point function, for example "main".
-		 * @param[in]	gptype				Type of the program, for example vertex or fragment.
-		 * @param[in]	profile				Program profile specifying supported feature-set. Must match the type.
-		 * @param[in]	requiresAdjacency	If true then adjacency information will be provided when rendering using this 
-		 *									program.
-		 */
-		virtual SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, bool requiresAdjacency) = 0;
+		/** @copydoc GpuProgramCore::create */
+		virtual SPtr<GpuProgramCore> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT) = 0;
 
 		/** @copydoc GpuProgramManager::createEmpty */
-		virtual SPtr<GpuProgramCore> create(GpuProgramType type) = 0;
+		virtual SPtr<GpuProgramCore> create(GpuProgramType type, GpuDeviceFlags deviceMask = GDF_DEFAULT) = 0;
 	};
 
 	/**
@@ -51,21 +39,8 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT GpuProgramManager : public Module<GpuProgramManager>
 	{
 	public:
-		/**
-		 * Creates a new GPU program using the provided source code. If compilation fails or program is not supported
-		 * GpuProgram::isCompiled() method on the returned program will return false, and you will be able to retrieve the 
-		 * error message via GpuProgram::getCompileErrorMessage().
-		 *
-		 * @param[in]	source				Source code to compile the shader from.
-		 * @param[in]	entryPoint			Name of the entry point function, for example "main".
-		 * @param[in]	language			Language the source is written in, for example "hlsl" or "glsl".
-		 * @param[in]	gptype				Type of the program, for example vertex or fragment.
-		 * @param[in]	profile				Program profile specifying supported feature-set. Must match the type.
-		 * @param[in]	requiresAdjacency	If true then adjacency information will be provided when rendering using this 
-		 *									program.
-		 */
-		SPtr<GpuProgram> create(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, bool requiresAdjacency = false);
+		/** @copydoc GpuProgram::create */
+		SPtr<GpuProgram> create(const GPU_PROGRAM_DESC& desc);
 
 		/**
 		 * Creates a completely empty and uninitialized GpuProgram. Should only be used for specific purposes, like 
@@ -101,21 +76,8 @@ namespace BansheeEngine
 		/** Query if a GPU program language is supported (for example "hlsl", "glsl"). */
 		bool isLanguageSupported(const String& lang);
 
-		/**
-		 * Creates a new GPU program using the provided source code. If compilation fails or program is not supported
-		 * GpuProgramCore::isCompiled() method on the returned program will return false, and you will be able to retrieve 
-		 * the error message via GpuProgramCore::getCompileErrorMessage().
-		 *
-		 * @param[in]	source				Source code to compile the shader from.
-		 * @param[in]	entryPoint			Name of the entry point function, for example "main".
-		 * @param[in]	language			Language the source is written in, for example "hlsl" or "glsl".
-		 * @param[in]	gptype				Type of the program, for example vertex or fragment.
-		 * @param[in]	profile				Program profile specifying supported feature-set. Must match the type.
-		 * @param[in]	requiresAdjacency	If true then adjacency information will be provided when rendering using this 
-		 *									program.
-		 */
-		SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, const String& language, 
-			GpuProgramType gptype, GpuProgramProfile profile, bool requiresAdjacency = false);
+		/** @copydoc GpuProgramCore::create */
+		SPtr<GpuProgramCore> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT);
 
 	protected:
 		friend class GpuProgram;
@@ -125,8 +87,7 @@ namespace BansheeEngine
 		 *
 		 * @see		create
 		 */
-		SPtr<GpuProgramCore> createInternal(const String& source, const String& entryPoint, const String& language,
-			GpuProgramType gptype, GpuProgramProfile profile, bool requiresAdjacency = false);
+		SPtr<GpuProgramCore> createInternal(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT);
 
 		/** Attempts to find a factory for the specified language. Returns null if it cannot find one. */
 		GpuProgramFactory* getFactory(const String& language);

+ 19 - 15
Source/BansheeCore/Source/BsGpuProgram.cpp

@@ -15,9 +15,9 @@ namespace BansheeEngine
 		:mType(gptype), mEntryPoint(entryPoint), mProfile(profile), mSource(source)
 	{ }
 		
-	GpuProgramCore::GpuProgramCore(const String& source, const String& entryPoint,
-		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
-		:mNeedsAdjacencyInfo(isAdjacencyInfoRequired), mIsCompiled(false), mProperties(source, entryPoint, gptype, profile)
+	GpuProgramCore::GpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		:mNeedsAdjacencyInfo(desc.requiresAdjacency), mIsCompiled(false), mProperties(desc.source, desc.entryPoint, 
+			desc.type, desc.profile)
 	{
 		mParametersDesc = bs_shared_ptr_new<GpuParamDesc>();
 	}
@@ -38,16 +38,14 @@ namespace BansheeEngine
 		return true;
 	}
 
-	SPtr<GpuProgramCore> GpuProgramCore::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
-		GpuProgramProfile profile, bool requiresAdjacency)
+	SPtr<GpuProgramCore> GpuProgramCore::create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
 	{
-		return GpuProgramCoreManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
+		return GpuProgramCoreManager::instance().create(desc, deviceMask);
 	}
 
-	GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language,
-		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired) 
-		: mNeedsAdjacencyInfo(isAdjacencyInfoRequired), mLanguage(language)
-		, mProperties(source, entryPoint, gptype, profile)
+	GpuProgram::GpuProgram(const GPU_PROGRAM_DESC& desc)
+		: mNeedsAdjacencyInfo(desc.requiresAdjacency), mLanguage(desc.language)
+		, mProperties(desc.source, desc.entryPoint, desc.type, desc.profile)
     {
 
     }
@@ -74,14 +72,20 @@ namespace BansheeEngine
 
 	SPtr<CoreObjectCore> GpuProgram::createCore() const
 	{
-		return GpuProgramCoreManager::instance().createInternal(mProperties.getSource(), mProperties.getEntryPoint(),
-			mLanguage, mProperties.getType(), mProperties.getProfile(), mNeedsAdjacencyInfo);
+		GPU_PROGRAM_DESC desc;
+		desc.source = mProperties.getSource();
+		desc.entryPoint = mProperties.getEntryPoint();
+		desc.language = mLanguage;
+		desc.type = mProperties.getType();
+		desc.profile = mProperties.getProfile();
+		desc.requiresAdjacency = mNeedsAdjacencyInfo;
+
+		return GpuProgramCoreManager::instance().createInternal(desc);
 	}
 
-	SPtr<GpuProgram> GpuProgram::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype,
-		GpuProgramProfile profile, bool requiresAdjacency)
+	SPtr<GpuProgram> GpuProgram::create(const GPU_PROGRAM_DESC& desc)
 	{
-		return GpuProgramManager::instance().create(source, entryPoint, language, gptype, profile, requiresAdjacency);
+		return GpuProgramManager::instance().create(desc);
 	}
 
 	/************************************************************************/

+ 16 - 16
Source/BansheeCore/Source/BsGpuProgramManager.cpp

@@ -12,7 +12,7 @@ namespace BansheeEngine
 	{
 	public:
 		NullProgramCore()
-			:GpuProgramCore("", "", GPT_VERTEX_PROGRAM, GPP_NONE, false)
+			:GpuProgramCore(GPU_PROGRAM_DESC(), GDF_DEFAULT)
 		{ }
 
 		~NullProgramCore() { }
@@ -38,8 +38,7 @@ namespace BansheeEngine
 			return sNullLang;
 		}
 
-		SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, bool requiresAdjacencyInformation) override
+		SPtr<GpuProgramCore> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask) override
 		{
 			SPtr<NullProgramCore> ret = bs_shared_ptr_new<NullProgramCore>();
 			ret->_setThisPtr(ret);
@@ -47,7 +46,7 @@ namespace BansheeEngine
 			return ret;
 		}
 
-		SPtr<GpuProgramCore> create(GpuProgramType type) override
+		SPtr<GpuProgramCore> create(GpuProgramType type, GpuDeviceFlags deviceMask) override
 		{
 			SPtr<NullProgramCore> ret = bs_shared_ptr_new<NullProgramCore>();
 			ret->_setThisPtr(ret);
@@ -56,11 +55,9 @@ namespace BansheeEngine
 		}
 	};
 
-	SPtr<GpuProgram> GpuProgramManager::create(const String& source, const String& entryPoint, const String& language,
-		GpuProgramType gptype, GpuProgramProfile profile,
-		bool requiresAdjacencyInformation)
+	SPtr<GpuProgram> GpuProgramManager::create(const GPU_PROGRAM_DESC& desc)
 	{
-		GpuProgram* program = new (bs_alloc<GpuProgram>()) GpuProgram(source, entryPoint, language, gptype, profile, requiresAdjacencyInformation);
+		GpuProgram* program = new (bs_alloc<GpuProgram>()) GpuProgram(desc);
 		SPtr<GpuProgram> ret = bs_core_ptr<GpuProgram>(program);
 		ret->_setThisPtr(ret);
 		ret->initialize();
@@ -70,7 +67,12 @@ namespace BansheeEngine
 
 	SPtr<GpuProgram> GpuProgramManager::createEmpty(const String& language, GpuProgramType type)
 	{
-		GpuProgram* program = new (bs_alloc<GpuProgram>()) GpuProgram("", "", language, GPT_VERTEX_PROGRAM, GPP_VS_1_1, false);
+		GPU_PROGRAM_DESC desc;
+		desc.language = language;
+		desc.type = type;
+		desc.profile = GPP_VS_1_1;
+
+		GpuProgram* program = new (bs_alloc<GpuProgram>()) GpuProgram(desc);
 		SPtr<GpuProgram> ret = bs_core_ptr<GpuProgram>(program);
 		ret->_setThisPtr(ret);
 
@@ -119,20 +121,18 @@ namespace BansheeEngine
 		return i != mFactories.end();
 	}
 
-	SPtr<GpuProgramCore> GpuProgramCoreManager::create(const String& source, const String& entryPoint, const String& language,
-		GpuProgramType gptype, GpuProgramProfile profile, bool requiresAdjacencyInformation)
+	SPtr<GpuProgramCore> GpuProgramCoreManager::create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
     {
-		SPtr<GpuProgramCore> ret = createInternal(source, entryPoint, language, gptype, profile, requiresAdjacencyInformation);
+		SPtr<GpuProgramCore> ret = createInternal(desc, deviceMask);
 		ret->initialize();
 
         return ret;
     }
 
-	SPtr<GpuProgramCore> GpuProgramCoreManager::createInternal(const String& source, const String& entryPoint, const String& language,
-		GpuProgramType gptype, GpuProgramProfile profile, bool requiresAdjacencyInformation)
+	SPtr<GpuProgramCore> GpuProgramCoreManager::createInternal(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
 	{
-		GpuProgramFactory* factory = getFactory(language);
-		SPtr<GpuProgramCore> ret = factory->create(source, entryPoint, gptype, profile, requiresAdjacencyInformation);
+		GpuProgramFactory* factory = getFactory(desc.language);
+		SPtr<GpuProgramCore> ret = factory->create(desc, deviceMask);
 
 		return ret;
 	}

+ 7 - 14
Source/BansheeD3D11RenderAPI/Include/BsD3D11GpuProgram.h

@@ -24,8 +24,7 @@ namespace BansheeEngine
 		UINT32 getProgramId() const { return mProgramId; }
 
 	protected:
-		D3D11GpuProgramCore(const String& source, const String& entryPoint, GpuProgramType gptype,
-			GpuProgramProfile profile, bool isAdjacencyInfoRequired);
+		D3D11GpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc GpuProgramCore::initialize */
 		void initialize() override;
@@ -65,8 +64,7 @@ namespace BansheeEngine
 	protected:
 		friend class D3D11HLSLProgramFactory;
 
-		D3D11GpuVertexProgramCore(const String& source, const String& entryPoint,
-			GpuProgramProfile profile);
+		D3D11GpuVertexProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc D3D11GpuProgramCore::loadFromMicrocode */
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode) override;
@@ -87,8 +85,7 @@ namespace BansheeEngine
 	protected:
 		friend class D3D11HLSLProgramFactory;
 
-		D3D11GpuFragmentProgramCore(const String& source, const String& entryPoint,
-			GpuProgramProfile profile);
+		D3D11GpuFragmentProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc D3D11GpuProgramCore::loadFromMicrocode */
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode) override;
@@ -109,8 +106,7 @@ namespace BansheeEngine
 	protected:
 		friend class D3D11HLSLProgramFactory;
 
-		D3D11GpuDomainProgramCore(const String& source, const String& entryPoint,
-			GpuProgramProfile profile);
+		D3D11GpuDomainProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc D3D11GpuProgramCore::loadFromMicrocode */
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode) override;
@@ -131,8 +127,7 @@ namespace BansheeEngine
 	protected:
 		friend class D3D11HLSLProgramFactory;
 
-		D3D11GpuHullProgramCore(const String& source, const String& entryPoint,
-			GpuProgramProfile profile);
+		D3D11GpuHullProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc D3D11GpuProgramCore::loadFromMicrocode */
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode) override;
@@ -153,8 +148,7 @@ namespace BansheeEngine
 	protected:
 		friend class D3D11HLSLProgramFactory;
 
-		D3D11GpuGeometryProgramCore(const String& source, const String& entryPoint,
-			GpuProgramProfile profile, bool isAdjacencyInfoRequired);
+		D3D11GpuGeometryProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc D3D11GpuProgramCore::loadFromMicrocode */
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode) override;
@@ -175,8 +169,7 @@ namespace BansheeEngine
 	protected:
 		friend class D3D11HLSLProgramFactory;
 
-		D3D11GpuComputeProgramCore(const String& source, const String& entryPoint,
-			GpuProgramProfile profile);
+		D3D11GpuComputeProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc D3D11GpuProgramCore::loadFromMicrocode */
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode) override;

+ 4 - 5
Source/BansheeD3D11RenderAPI/Include/BsD3D11HLSLProgramFactory.h

@@ -21,12 +21,11 @@ namespace BansheeEngine
 		/** @copydoc GpuProgramFactory::getLanguage */
 		const String& getLanguage() const override;
 
-		/** @copydoc GpuProgramFactory::create(const String&, const String&, GpuProgramType, GpuProgramProfile, bool) */
-		SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, bool requiresAdjacency) override;
+		/** @copydoc GpuProgramFactory::create(const GPU_PROGRAM_DESC&, GpuDeviceFlags) */
+		SPtr<GpuProgramCore> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT) override;
 
-		/** @copydoc GpuProgramFactory::create(GpuProgramType) */
-		SPtr<GpuProgramCore> create(GpuProgramType type) override;
+		/** @copydoc GpuProgramFactory::create(GpuProgramType, GpuDeviceFlags) */
+		SPtr<GpuProgramCore> create(GpuProgramType type, GpuDeviceFlags deviceMask = GDF_DEFAULT) override;
 
 	protected:
 		static const String LANGUAGE_NAME;

+ 15 - 28
Source/BansheeD3D11RenderAPI/Source/BsD3D11GpuProgram.cpp

@@ -16,12 +16,11 @@ namespace BansheeEngine
 {
 	UINT32 D3D11GpuProgramCore::GlobalProgramId = 0;
 
-	D3D11GpuProgramCore::D3D11GpuProgramCore(const String& source, const String& entryPoint, GpuProgramType gptype,
-		GpuProgramProfile profile, bool isAdjacencyInfoRequired)
-		: GpuProgramCore(source, entryPoint, gptype, profile, isAdjacencyInfoRequired),
+	D3D11GpuProgramCore::D3D11GpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: GpuProgramCore(desc, deviceMask),
 		mEnableBackwardsCompatibility(false), mProgramId(0)
 	{
-
+		assert((deviceMask == GDF_DEFAULT || deviceMask == GDF_PRIMARY) && "Multiple GPUs not supported natively on DirectX 11.");
 	}
 
 	D3D11GpuProgramCore::~D3D11GpuProgramCore()
@@ -166,10 +165,8 @@ namespace BansheeEngine
 		}
 	}
 
-	D3D11GpuVertexProgramCore::D3D11GpuVertexProgramCore(const String& source, const String& entryPoint,
-		GpuProgramProfile profile)
-		: D3D11GpuProgramCore(source, entryPoint, GPT_VERTEX_PROGRAM, profile, false)
-		, mVertexShader(nullptr)
+	D3D11GpuVertexProgramCore::D3D11GpuVertexProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: D3D11GpuProgramCore(desc, deviceMask), mVertexShader(nullptr)
 	{ }
 
 	D3D11GpuVertexProgramCore::~D3D11GpuVertexProgramCore()
@@ -197,10 +194,8 @@ namespace BansheeEngine
 		return mVertexShader;
 	}
 
-	D3D11GpuFragmentProgramCore::D3D11GpuFragmentProgramCore(const String& source, const String& entryPoint,
-		GpuProgramProfile profile)
-		: D3D11GpuProgramCore(source, entryPoint, GPT_FRAGMENT_PROGRAM, profile, false)
-		, mPixelShader(nullptr)
+	D3D11GpuFragmentProgramCore::D3D11GpuFragmentProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: D3D11GpuProgramCore(desc, deviceMask), mPixelShader(nullptr)
 	{ }
 
 	D3D11GpuFragmentProgramCore::~D3D11GpuFragmentProgramCore()
@@ -228,10 +223,8 @@ namespace BansheeEngine
 	}
 
 
-	D3D11GpuGeometryProgramCore::D3D11GpuGeometryProgramCore(const String& source, const String& entryPoint,
-		GpuProgramProfile profile, bool isAdjacencyInfoRequired)
-		: D3D11GpuProgramCore(source, entryPoint, GPT_GEOMETRY_PROGRAM, profile, isAdjacencyInfoRequired)
-		, mGeometryShader(nullptr)
+	D3D11GpuGeometryProgramCore::D3D11GpuGeometryProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: D3D11GpuProgramCore(desc, deviceMask), mGeometryShader(nullptr)
 	{ }
 
 	D3D11GpuGeometryProgramCore::~D3D11GpuGeometryProgramCore()
@@ -258,10 +251,8 @@ namespace BansheeEngine
 		return mGeometryShader;
 	}
 
-	D3D11GpuDomainProgramCore::D3D11GpuDomainProgramCore(const String& source, const String& entryPoint,
-		GpuProgramProfile profile)
-		: D3D11GpuProgramCore(source, entryPoint, GPT_DOMAIN_PROGRAM, profile, false)
-		, mDomainShader(nullptr)
+	D3D11GpuDomainProgramCore::D3D11GpuDomainProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: D3D11GpuProgramCore(desc, deviceMask), mDomainShader(nullptr)
 	{ }
 
 	D3D11GpuDomainProgramCore::~D3D11GpuDomainProgramCore()
@@ -288,10 +279,8 @@ namespace BansheeEngine
 		return mDomainShader;
 	}
 
-	D3D11GpuHullProgramCore::D3D11GpuHullProgramCore(const String& source, const String& entryPoint,
-		GpuProgramProfile profile)
-		: D3D11GpuProgramCore(source, entryPoint, GPT_HULL_PROGRAM, profile, false)
-		, mHullShader(nullptr)
+	D3D11GpuHullProgramCore::D3D11GpuHullProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: D3D11GpuProgramCore(desc, deviceMask), mHullShader(nullptr)
 	{ }
 
 	D3D11GpuHullProgramCore::~D3D11GpuHullProgramCore()
@@ -320,10 +309,8 @@ namespace BansheeEngine
 	}
 
 
-	D3D11GpuComputeProgramCore::D3D11GpuComputeProgramCore(const String& source, const String& entryPoint,
-		GpuProgramProfile profile)
-		: D3D11GpuProgramCore(source, entryPoint, GPT_COMPUTE_PROGRAM, profile, false)
-		, mComputeShader(nullptr)
+	D3D11GpuComputeProgramCore::D3D11GpuComputeProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		: D3D11GpuProgramCore(desc, deviceMask), mComputeShader(nullptr)
 	{ }
 
 	D3D11GpuComputeProgramCore::~D3D11GpuComputeProgramCore()

+ 18 - 16
Source/BansheeD3D11RenderAPI/Source/BsD3D11HLSLProgramFactory.cpp

@@ -20,36 +20,35 @@ namespace BansheeEngine
         return LANGUAGE_NAME;
     }
 
-	SPtr<GpuProgramCore> D3D11HLSLProgramFactory::create(const String& source, const String& entryPoint,
-		GpuProgramType gptype, GpuProgramProfile profile, bool requireAdjacencyInfo)
+	SPtr<GpuProgramCore> D3D11HLSLProgramFactory::create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
     {
 		SPtr<GpuProgramCore> gpuProg;
 
-		switch (gptype)
+		switch (desc.type)
 		{
 		case GPT_VERTEX_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuVertexProgramCore>(new (bs_alloc<D3D11GpuVertexProgramCore>())
-				D3D11GpuVertexProgramCore(source, entryPoint, profile));
+				D3D11GpuVertexProgramCore(desc, deviceMask));
 			break;
 		case GPT_FRAGMENT_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuFragmentProgramCore>(new (bs_alloc<D3D11GpuFragmentProgramCore>())
-				D3D11GpuFragmentProgramCore(source, entryPoint, profile));
+				D3D11GpuFragmentProgramCore(desc, deviceMask));
 			break;
 		case GPT_HULL_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuHullProgramCore>(new (bs_alloc<D3D11GpuHullProgramCore>())
-				D3D11GpuHullProgramCore(source, entryPoint, profile));
+				D3D11GpuHullProgramCore(desc, deviceMask));
 			break;
 		case GPT_DOMAIN_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuDomainProgramCore>(new (bs_alloc<D3D11GpuDomainProgramCore>())
-				D3D11GpuDomainProgramCore(source, entryPoint, profile));
+				D3D11GpuDomainProgramCore(desc, deviceMask));
 			break;
 		case GPT_GEOMETRY_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuGeometryProgramCore>(new (bs_alloc<D3D11GpuGeometryProgramCore>())
-				D3D11GpuGeometryProgramCore(source, entryPoint, profile, requireAdjacencyInfo));
+				D3D11GpuGeometryProgramCore(desc, deviceMask));
 			break;
 		case GPT_COMPUTE_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuComputeProgramCore>(new (bs_alloc<D3D11GpuComputeProgramCore>())
-				D3D11GpuComputeProgramCore(source, entryPoint, profile));
+				D3D11GpuComputeProgramCore(desc, deviceMask));
 			break;
 		}
 
@@ -59,35 +58,38 @@ namespace BansheeEngine
 		return gpuProg;
     }
 
-	SPtr<GpuProgramCore> D3D11HLSLProgramFactory::create(GpuProgramType type)
+	SPtr<GpuProgramCore> D3D11HLSLProgramFactory::create(GpuProgramType type, GpuDeviceFlags deviceMask)
 	{
 		SPtr<GpuProgramCore> gpuProg;
 
+		GPU_PROGRAM_DESC desc;
+		desc.type = type;
+
 		switch (type)
 		{
 		case GPT_VERTEX_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuVertexProgramCore>(new (bs_alloc<D3D11GpuVertexProgramCore>())
-				D3D11GpuVertexProgramCore("", "", GPP_NONE));
+				D3D11GpuVertexProgramCore(desc, deviceMask));
 			break;
 		case GPT_FRAGMENT_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuFragmentProgramCore>(new (bs_alloc<D3D11GpuFragmentProgramCore>())
-				D3D11GpuFragmentProgramCore("", "", GPP_NONE));
+				D3D11GpuFragmentProgramCore(desc, deviceMask));
 			break;
 		case GPT_HULL_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuHullProgramCore>(new (bs_alloc<D3D11GpuHullProgramCore>())
-				D3D11GpuHullProgramCore("", "", GPP_NONE));
+				D3D11GpuHullProgramCore(desc, deviceMask));
 			break;
 		case GPT_DOMAIN_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuDomainProgramCore>(new (bs_alloc<D3D11GpuDomainProgramCore>())
-				D3D11GpuDomainProgramCore("", "", GPP_NONE));
+				D3D11GpuDomainProgramCore(desc, deviceMask));
 			break;
 		case GPT_GEOMETRY_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuGeometryProgramCore>(new (bs_alloc<D3D11GpuGeometryProgramCore>())
-				D3D11GpuGeometryProgramCore("", "", GPP_NONE, false));
+				D3D11GpuGeometryProgramCore(desc, deviceMask));
 			break;
 		case GPT_COMPUTE_PROGRAM:
 			gpuProg = bs_shared_ptr<D3D11GpuComputeProgramCore>(new (bs_alloc<D3D11GpuComputeProgramCore>())
-				D3D11GpuComputeProgramCore("", "", GPP_NONE));
+				D3D11GpuComputeProgramCore(desc, deviceMask));
 			break;
 		}
 

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

@@ -29,8 +29,7 @@ namespace BansheeEngine
 	private:
 		friend class GLSLProgramFactory;
 
-		GLSLGpuProgramCore(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, bool isAdjacencyInfoRequired);
+		GLSLGpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask);
 
 		/** @copydoc GpuProgramCore::initialize */
 		void initialize() override;

+ 4 - 8
Source/BansheeGLRenderAPI/Source/GLSL/include/BsGLSLProgramFactory.h

@@ -18,15 +18,11 @@ namespace BansheeEngine
 		/** @copydoc GpuProgramFactory::getLanguage */
 		const String& getLanguage() const override;
 
-		/**
-		 * @copydoc	GpuProgramFactory::getLanguage(const String&, const String&, GpuProgramType,
-		 *			GpuProgramProfile, bool)
-		 */
-        SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, GpuProgramType gptype, 
-			GpuProgramProfile profile, bool requireAdjacency) override;
+		/** @copydoc GpuProgramFactory::create(const GPU_PROGRAM_DESC&, GpuDeviceFlags) */
+		SPtr<GpuProgramCore> create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT) override;
 
-		/** @copydoc GpuProgramFactory::create(GpuProgramType) */
-		SPtr<GpuProgramCore> create(GpuProgramType type) override;
+		/** @copydoc GpuProgramFactory::create(GpuProgramType, GpuDeviceFlags) */
+		SPtr<GpuProgramCore> create(GpuProgramType type, GpuDeviceFlags deviceMask = GDF_DEFAULT) override;
 
 	protected:
 		static const String LANGUAGE_NAME;

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

@@ -69,10 +69,8 @@ namespace BansheeEngine
 		return errorsFound || !linkCompileSuccess;
 	}
 	
-	GLSLGpuProgramCore::GLSLGpuProgramCore(const String& source, const String& entryPoint, GpuProgramType gptype,
-		GpuProgramProfile profile, bool isAdjacencyInfoRequired)
-		:GpuProgramCore(source, entryPoint, gptype, profile, isAdjacencyInfoRequired),
-		mProgramID(0), mGLHandle(0)
+	GLSLGpuProgramCore::GLSLGpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
+		:GpuProgramCore(desc, deviceMask), mProgramID(0), mGLHandle(0)
     { }
 
 	GLSLGpuProgramCore::~GLSLGpuProgramCore()

+ 7 - 5
Source/BansheeGLRenderAPI/Source/GLSL/src/BsGLSLProgramFactory.cpp

@@ -12,10 +12,9 @@ namespace BansheeEngine
         return LANGUAGE_NAME;
     }
 
-	SPtr<GpuProgramCore> GLSLProgramFactory::create(const String& source, const String& entryPoint,
-		GpuProgramType gptype, GpuProgramProfile profile, bool requireAdjacency)
+	SPtr<GpuProgramCore> GLSLProgramFactory::create(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
     {
-		GLSLGpuProgramCore* prog = new (bs_alloc<GLSLGpuProgramCore>()) GLSLGpuProgramCore(source, entryPoint, gptype, profile, requireAdjacency);
+		GLSLGpuProgramCore* prog = new (bs_alloc<GLSLGpuProgramCore>()) GLSLGpuProgramCore(desc, deviceMask);
 
 		SPtr<GLSLGpuProgramCore> gpuProg = bs_shared_ptr<GLSLGpuProgramCore>(prog);
 		gpuProg->_setThisPtr(gpuProg);
@@ -23,9 +22,12 @@ namespace BansheeEngine
 		return gpuProg;
     }
 
-	SPtr<GpuProgramCore> GLSLProgramFactory::create(GpuProgramType type)
+	SPtr<GpuProgramCore> GLSLProgramFactory::create(GpuProgramType type, GpuDeviceFlags deviceMask)
 	{
-		GLSLGpuProgramCore* prog = new (bs_alloc<GLSLGpuProgramCore>()) GLSLGpuProgramCore("", "", type, GPP_NONE, false);
+		GPU_PROGRAM_DESC desc;
+		desc.type = type;
+
+		GLSLGpuProgramCore* prog = new (bs_alloc<GLSLGpuProgramCore>()) GLSLGpuProgramCore(desc, deviceMask);
 
 		SPtr<GLSLGpuProgramCore> gpuProg = bs_shared_ptr<GLSLGpuProgramCore>(prog);
 		gpuProg->_setThisPtr(gpuProg);

+ 34 - 12
Source/BansheeSL/Source/BsSLFXCompiler.cpp

@@ -1364,40 +1364,62 @@ namespace BansheeEngine
 				if (!passData.depthStencilIsDefault)
 					passDesc.depthStencilState = DepthStencilState::create(passData.depthStencilDesc);
 
+				GPU_PROGRAM_DESC desc;
+				desc.entryPoint = "main";
+				desc.language = metaData.language;
+
 				if (!passData.vertexCode.empty())
 				{
-					passDesc.vertexProgram = GpuProgram::create(passData.commonCode + passData.vertexCode, "main", 
-						metaData.language, GPT_VERTEX_PROGRAM, getProfile(metaData.renderAPI, GPT_VERTEX_PROGRAM));
+					desc.source = passData.commonCode + passData.vertexCode;
+					desc.type = GPT_VERTEX_PROGRAM;
+					desc.profile = getProfile(metaData.renderAPI, GPT_VERTEX_PROGRAM);
+
+					passDesc.vertexProgram = GpuProgram::create(desc);
 				}
 
 				if (!passData.fragmentCode.empty())
 				{
-					passDesc.fragmentProgram = GpuProgram::create(passData.commonCode + passData.fragmentCode, "main", 
-						metaData.language, GPT_FRAGMENT_PROGRAM, getProfile(metaData.renderAPI, GPT_FRAGMENT_PROGRAM));
+					desc.source = passData.commonCode + passData.fragmentCode;
+					desc.type = GPT_FRAGMENT_PROGRAM;
+					desc.profile = getProfile(metaData.renderAPI, GPT_FRAGMENT_PROGRAM);
+
+					passDesc.fragmentProgram = GpuProgram::create(desc);
 				}
 
 				if (!passData.geometryCode.empty())
 				{
-					passDesc.geometryProgram = GpuProgram::create(passData.commonCode + passData.geometryCode, "main", 
-						metaData.language, GPT_GEOMETRY_PROGRAM, getProfile(metaData.renderAPI, GPT_GEOMETRY_PROGRAM));
+					desc.source = passData.commonCode + passData.geometryCode;
+					desc.type = GPT_GEOMETRY_PROGRAM;
+					desc.profile = getProfile(metaData.renderAPI, GPT_GEOMETRY_PROGRAM);
+
+					passDesc.geometryProgram = GpuProgram::create(desc);
 				}
 
 				if (!passData.hullCode.empty())
 				{
-					passDesc.hullProgram = GpuProgram::create(passData.commonCode + passData.hullCode, "main", 
-						metaData.language, GPT_HULL_PROGRAM, getProfile(metaData.renderAPI, GPT_HULL_PROGRAM));
+					desc.source = passData.commonCode + passData.hullCode;
+					desc.type = GPT_HULL_PROGRAM;
+					desc.profile = getProfile(metaData.renderAPI, GPT_HULL_PROGRAM);
+
+					passDesc.hullProgram = GpuProgram::create(desc);
 				}
 
 				if (!passData.domainCode.empty())
 				{
-					passDesc.domainProgram = GpuProgram::create(passData.commonCode + passData.domainCode, "main", 
-						metaData.language, GPT_DOMAIN_PROGRAM, getProfile(metaData.renderAPI, GPT_DOMAIN_PROGRAM));
+					desc.source = passData.commonCode + passData.domainCode;
+					desc.type = GPT_DOMAIN_PROGRAM;
+					desc.profile = getProfile(metaData.renderAPI, GPT_DOMAIN_PROGRAM);
+
+					passDesc.domainProgram = GpuProgram::create(desc);
 				}
 
 				if (!passData.computeCode.empty())
 				{
-					passDesc.computeProgram = GpuProgram::create(passData.commonCode + passData.computeCode, "main", 
-						metaData.language, GPT_COMPUTE_PROGRAM, getProfile(metaData.renderAPI, GPT_COMPUTE_PROGRAM));
+					desc.source = passData.commonCode + passData.computeCode;
+					desc.type = GPT_COMPUTE_PROGRAM;
+					desc.profile = getProfile(metaData.renderAPI, GPT_COMPUTE_PROGRAM);
+
+					passDesc.computeProgram = GpuProgram::create(desc);
 				}
 
 				passDesc.stencilRefValue = passData.stencilRefValue;