Bläddra i källkod

Added C# RenderTarget

Marko Pintera 11 år sedan
förälder
incheckning
93e2eff9b6

+ 21 - 0
BansheeCore/Include/BsMultiRenderTexture.h

@@ -92,6 +92,20 @@ namespace BansheeEngine
 	public:
 		virtual ~MultiRenderTexture() { }
 
+		/**
+		 * @brief	Returns a color surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
+		const HTexture& getBindableColorTexture(UINT32 idx) const { return mBindableColorTex[idx]; }
+
+		/**
+		 * @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note		Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
+		const HTexture& getBindableDepthStencilTexture() const { return mBindableDepthStencilTex; }
+
 		/**
 		 * @brief	Retrieves a core implementation of a render texture usable only from the
 		 *			core thread.
@@ -108,6 +122,11 @@ namespace BansheeEngine
 		 */
 		const MultiRenderTextureProperties& getProperties() const;
 
+		/**
+		 * @brief	Returns the number of color surfaces used by the render texture.
+		 */
+		UINT32 getColorSurfaceCount() const;
+
 	protected:
 		MultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc);
 
@@ -127,5 +146,7 @@ namespace BansheeEngine
 		virtual void syncFromCore(const CoreSyncData& data);
 
 		MULTI_RENDER_TEXTURE_DESC mDesc;
+		Vector<HTexture> mBindableColorTex;
+		HTexture mBindableDepthStencilTex;
 	};
 }

+ 1 - 1
BansheeCore/Include/BsRenderTarget.h

@@ -191,7 +191,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc RenderTargetCore::setPriority
 		 */
-		void setPriority(CoreAccessor& accessor, UINT32 priority);
+		void setPriority(CoreAccessor& accessor, INT32 priority);
 
 		/**
 		 * @brief	Returns properties that describe the render target.

+ 5 - 1
BansheeCore/Include/BsResourceListenerManager.h

@@ -72,7 +72,7 @@ namespace BansheeEngine
 		HEvent mResourceLoadedConn;
 		HEvent mResourceDestroyedConn;
 
-		Set<IResourceListener*> mActiveListeners;
+		
 		Set<IResourceListener*> mDirtyListeners;
 		Map<UINT64, Vector<IResourceListener*>> mResourceToListenerMap;
 		Map<IResourceListener*, Vector<UINT64>> mListenerToResourceMap;
@@ -83,5 +83,9 @@ namespace BansheeEngine
 		Vector<HResource> mTempResourceBuffer;
 
 		BS_MUTEX(mMutex)
+
+#if BS_DEBUG_MODE
+		Set<IResourceListener*> mActiveListeners;
+#endif
 	};
 }

+ 17 - 0
BansheeCore/Source/BsMultiRenderTexture.cpp

@@ -5,6 +5,7 @@
 #include "BsCoreThread.h"
 #include "BsTextureManager.h"
 #include "BsFrameAlloc.h"
+#include "BsResources.h"
 
 namespace BansheeEngine
 {
@@ -185,7 +186,18 @@ namespace BansheeEngine
 	MultiRenderTexture::MultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc)
 		:mDesc(desc)
 	{
+		// Create non-persistent resource handles for the used textures (we only need them because a lot of the code accepts only handles,
+		// since they're non persistent they don't really have any benefit over shared pointers)
 
+		for (UINT32 i = 0; i < (UINT32)desc.colorSurfaces.size(); i++)
+		{
+			if (desc.colorSurfaces[i].texture != nullptr)
+				mBindableColorTex.push_back(static_resource_cast<Texture>(gResources()._createResourceHandle(desc.colorSurfaces[i].texture)));
+		}
+
+
+		if (desc.depthStencilSurface.texture != nullptr)
+			mBindableDepthStencilTex = static_resource_cast<Texture>(gResources()._createResourceHandle(desc.depthStencilSurface.texture));
 	}
 
 	SPtr<CoreObjectCore> MultiRenderTexture::createCore() const
@@ -224,4 +236,9 @@ namespace BansheeEngine
 	{
 		return static_cast<const MultiRenderTextureProperties&>(getPropertiesInternal());
 	}
+
+	UINT32 MultiRenderTexture::getColorSurfaceCount() const
+	{
+		return (UINT32)mDesc.colorSurfaces.size();
+	}
 }

+ 3 - 3
BansheeCore/Source/BsRenderTarget.cpp

@@ -38,10 +38,10 @@ namespace BansheeEngine
 		BS_EXCEPT(InvalidParametersException, "Attribute not found.");
 	}
 
-	void RenderTarget::setPriority(CoreAccessor& accessor, UINT32 priority)
+	void RenderTarget::setPriority(CoreAccessor& accessor, INT32 priority)
 	{
-		std::function<void(SPtr<RenderTargetCore>, UINT32)> windowedFunc =
-			[](SPtr<RenderTargetCore> renderTarget, UINT32 priority)
+		std::function<void(SPtr<RenderTargetCore>, INT32)> windowedFunc =
+			[](SPtr<RenderTargetCore> renderTarget, INT32 priority)
 		{
 			renderTarget->setPriority(priority);
 		};

+ 16 - 1
BansheeCore/Source/BsResourceListenerManager.cpp

@@ -22,12 +22,21 @@ namespace BansheeEngine
 
 	void ResourceListenerManager::registerListener(IResourceListener* listener)
 	{
+#if BS_DEBUG_MODE
+		BS_LOCK_MUTEX(mMutex);
 		mActiveListeners.insert(listener);
+#endif
 	}
 
 	void ResourceListenerManager::unregisterListener(IResourceListener* listener)
 	{
-		mActiveListeners.erase(listener);
+#if BS_DEBUG_MODE
+		{
+			BS_LOCK_MUTEX(mMutex);
+			mActiveListeners.erase(listener);
+		}
+#endif
+		
 		mDirtyListeners.erase(listener);
 
 		clearDependencies(listener);
@@ -87,7 +96,10 @@ namespace BansheeEngine
 		const Vector<IResourceListener*> relevantListeners = iterFind->second;
 		for (auto& listener : relevantListeners)
 		{
+#if BS_DEBUG_MODE
+			BS_LOCK_MUTEX(mMutex);
 			assert(mActiveListeners.find(listener) != mActiveListeners.end() && "Attempting to notify a destroyed IResourceListener");
+#endif
 
 			listener->notifyResourceLoaded(resource);
 		}
@@ -104,7 +116,10 @@ namespace BansheeEngine
 		const Vector<IResourceListener*> relevantListeners = iterFind->second;
 		for (auto& listener : relevantListeners)
 		{
+#if BS_DEBUG_MODE
+			BS_LOCK_MUTEX(mMutex);
 			assert(mActiveListeners.find(listener) != mActiveListeners.end() && "Attempting to notify a destroyed IResourceListener");
+#endif
 
 			listener->notifyResourceDestroyed(resource);
 		}

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -11,7 +11,7 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	)
 {
-	EditorApplication::startUp(RenderSystemPlugin::DX11);
+	EditorApplication::startUp(RenderSystemPlugin::OpenGL);
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::shutDown();
 

+ 2 - 0
BansheeMono/BansheeMono.vcxproj

@@ -234,6 +234,7 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="Include\BsMonoArray.h" />
     <ClInclude Include="Include\BsMonoAssembly.h" />
     <ClInclude Include="Include\BsMonoClass.h" />
     <ClInclude Include="Include\BsMonoField.h" />
@@ -246,6 +247,7 @@
     <ClInclude Include="Include\BsScriptMeta.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="Source\BsMonoArray.cpp" />
     <ClCompile Include="Source\BsMonoAssembly.cpp" />
     <ClCompile Include="Source\BsMonoClass.cpp" />
     <ClCompile Include="Source\BsMonoField.cpp" />

+ 6 - 0
BansheeMono/BansheeMono.vcxproj.filters

@@ -45,6 +45,9 @@
     <ClInclude Include="Include\BsScriptMeta.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsMonoArray.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsMonoAssembly.cpp">
@@ -77,5 +80,8 @@
     <ClCompile Include="Source\BsMonoUtil.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsMonoArray.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 42 - 0
BansheeMono/Include/BsMonoArray.h

@@ -0,0 +1,42 @@
+#pragma once
+
+#include "BsMonoPrerequisites.h"
+#include "BsScriptMeta.h"
+#include <mono/jit/jit.h>
+
+namespace BansheeEngine
+{
+	class BS_MONO_EXPORT ScriptArray
+	{
+	public:
+		ScriptArray(MonoArray* existingArray);
+		ScriptArray(MonoClass& klass, UINT32 size);
+
+		template<class T>
+		T get(UINT32 idx)
+		{
+			return mono_array_get(mInternal, T, idx);
+		}
+
+		template<class T>
+		void set(UINT32 idx, const T& value)
+		{
+			mono_array_set(mInternal, T, idx, value);
+		}
+
+		template<class T>
+		static ScriptArray create(UINT32 size)
+		{
+			return ScriptArray(*T::getMetaData()->scriptClass, size);
+		}
+
+		UINT32 size() const;
+
+		MonoArray* getInternal() const { return mInternal; }
+
+	private:
+		MonoArray* createArray(MonoClass& klass, UINT32 size);
+
+		MonoArray* mInternal;
+	};
+}

+ 1 - 0
BansheeMono/Include/BsMonoUtil.h

@@ -3,6 +3,7 @@
 #include "BsMonoPrerequisites.h"
 #include "BsException.h"
 #include "BsDebug.h"
+#include "BsMonoArray.h"
 #include <mono/jit/jit.h>
 
 namespace BansheeEngine

+ 29 - 0
BansheeMono/Source/BsMonoArray.cpp

@@ -0,0 +1,29 @@
+#include "BsMonoArray.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+
+namespace BansheeEngine
+{
+	ScriptArray::ScriptArray(MonoArray* existingArray)
+		:mInternal(existingArray)
+	{
+
+	}
+
+	ScriptArray::ScriptArray(MonoClass& klass, UINT32 size)
+		: mInternal(nullptr)
+	{
+		mInternal = createArray(klass, size);
+	}
+
+	UINT32 ScriptArray::size() const
+	{
+		return (UINT32)mono_array_length(mInternal);
+	}
+
+	MonoArray* ScriptArray::createArray(MonoClass& klass, UINT32 size)
+	{
+		return mono_array_new(MonoManager::instance().getDomain(),
+			klass._getInternalClass(), size);
+	}
+}

+ 3 - 0
MBansheeEngine/MBansheeEngine.csproj

@@ -98,6 +98,9 @@
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Math\Quaternion.cs" />
+    <Compile Include="RenderTarget.cs" />
+    <Compile Include="RenderTexture.cs" />
+    <Compile Include="RenderTexture2D.cs" />
     <Compile Include="Resource.cs" />
     <Compile Include="SceneObject.cs" />
     <Compile Include="ScriptObject.cs" />

+ 84 - 0
MBansheeEngine/RenderTarget.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    public class RenderTarget : ScriptObject
+    {
+        public int Width
+        {
+            get
+            {
+                int value;
+                Internal_GetWidth(mCachedPtr, out value);
+                return value;
+            }
+        }
+
+        public int Height
+        {
+            get
+            {
+                int value;
+                Internal_GetHeight(mCachedPtr, out value);
+                return value;
+            }
+        }
+
+        public bool GammaCorrection
+        {
+            get
+            {
+                bool value;
+                Internal_GetGammaCorrection(mCachedPtr, out value);
+                return value;
+            }
+        }
+
+        public int SampleCount
+        {
+            get
+            {
+                int value;
+                Internal_GetSampleCount(mCachedPtr, out value);
+                return value;
+            }
+        }
+
+        public int Priority
+        {
+            get
+            {
+                int value;
+                Internal_GetPriority(mCachedPtr, out value);
+                return value;
+            }
+
+            set
+            {
+                Internal_SetPriority(mCachedPtr, value);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetWidth(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetHeight(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetGammaCorrection(IntPtr thisPtr, out bool value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetSampleCount(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetPriority(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetPriority(IntPtr thisPtr, int value);
+    }
+}

+ 12 - 0
MBansheeEngine/RenderTexture.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BansheeEngine
+{
+    public class RenderTexture : RenderTarget
+    {
+
+    }
+}

+ 86 - 0
MBansheeEngine/RenderTexture2D.cs

@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    public class RenderTexture2D : RenderTexture
+    {
+        public RenderTexture2D(PixelFormat format, int width, int height, int numSamples = 1, 
+            bool gammaCorrection = false, bool createDepth = true, PixelFormat depthStencilFormat = PixelFormat.D24S8)
+        {
+            Internal_CreateDetailed(this, format, width, height, numSamples, gammaCorrection, createDepth, depthStencilFormat);
+        }
+
+        public RenderTexture2D(Texture2D colorSurface, Texture2D depthStencilSurface = null)
+        {
+            IntPtr[] colorSurfaceInstances = new IntPtr[1];
+            colorSurfaceInstances[0] = colorSurface.GetCachedPtr();
+
+            IntPtr depthStencilInstance = IntPtr.Zero;
+            if (depthStencilSurface != null)
+                depthStencilInstance = depthStencilSurface.GetCachedPtr();
+
+            Internal_Create(this, colorSurfaceInstances, depthStencilInstance);
+        }
+
+        public RenderTexture2D(Texture2D[] colorSurfaces, Texture2D depthStencilSurface = null)
+        {
+            IntPtr[] colorSurfaceInstances = new IntPtr[colorSurfaces.Length];
+
+            for(int i = 0; i < colorSurfaces.Length; i++)
+                colorSurfaceInstances[i] = colorSurfaces[i] != null ? colorSurfaces[i].GetCachedPtr() : IntPtr.Zero;
+
+            IntPtr depthStencilInstance = IntPtr.Zero;
+            if (depthStencilSurface != null)
+                depthStencilInstance = depthStencilSurface.GetCachedPtr();
+
+            Internal_Create(this, colorSurfaceInstances, depthStencilInstance);
+        }
+
+        public Texture2D colorSurface
+        {
+            get
+            {
+                Texture2D[] surfaces;
+                Internal_GetColorSurfaces(mCachedPtr, out surfaces);
+                return surfaces[0];
+            }
+        }
+
+        public Texture2D[] colorSurfaces
+        {
+            get
+            {
+                Texture2D[] surfaces;
+                Internal_GetColorSurfaces(mCachedPtr, out surfaces);
+                return surfaces;
+            }
+        }
+
+        public Texture2D depthStencilSurface
+        {
+            get
+            {
+                Texture2D surface;
+                Internal_GetDepthStencilSurface(mCachedPtr, out surface);
+                return surface;
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateDetailed(RenderTexture2D instance, PixelFormat format, 
+            int width, int height, int numSamples, bool gammaCorrection, bool createDepth, PixelFormat depthStencilFormat);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Create(RenderTexture2D instance, IntPtr[] colorSurfaces, IntPtr depthStencilSurface);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetColorSurfaces(IntPtr thisPtr, out Texture2D[] surfaces);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetDepthStencilSurface(IntPtr thisPtr, out Texture2D surface);
+    }
+}

+ 37 - 0
SBansheeEngine/Include/BsScriptRenderTarget.h

@@ -0,0 +1,37 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptRenderTargetBase : public ScriptObjectBase
+	{
+	protected:
+		friend class ScriptResourceManager;
+
+		ScriptRenderTargetBase(MonoObject* instance)
+			:ScriptObjectBase(instance)
+		{ }
+
+		virtual ~ScriptRenderTargetBase() {}
+
+		virtual RenderTargetPtr getNativeValue() const = 0;
+	};
+
+	class BS_SCR_BE_EXPORT ScriptRenderTarget : public ScriptObject<ScriptRenderTarget, ScriptRenderTargetBase>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "RenderTarget")
+
+	private:
+		ScriptRenderTarget(MonoObject* instance);
+
+		static void internal_getWidth(ScriptRenderTarget* thisPtr, int* value);
+		static void internal_getHeight(ScriptRenderTarget* thisPtr, int* value);
+		static void internal_getGammaCorrection(ScriptRenderTarget* thisPtr, bool* value);
+		static void internal_getSampleCount(ScriptRenderTarget* thisPtr, int* value);
+		static void internal_getPriority(ScriptRenderTarget* thisPtr, int* value);
+		static void internal_setPriority(ScriptRenderTarget* thisPtr, int value);
+	};
+}

+ 16 - 0
SBansheeEngine/Include/BsScriptRenderTexture.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptRenderTarget.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptRenderTexture : public ScriptObject <ScriptRenderTexture, ScriptRenderTargetBase>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "RenderTexture")
+
+	private:
+		ScriptRenderTexture(MonoObject* instance);
+	};
+}

+ 31 - 0
SBansheeEngine/Include/BsScriptRenderTexture2D.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptRenderTarget.h"
+#include "BsPixelUtil.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptRenderTexture2D : public ScriptObject < ScriptRenderTexture2D, ScriptRenderTargetBase >
+	{
+	public:
+		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "RenderTexture2D")
+
+		RenderTargetPtr getNativeValue() const { return mRenderTarget; }
+		RenderTexturePtr getRenderTexture() const;
+		MultiRenderTexturePtr getMultiRenderTexture() const;
+
+	private:
+		ScriptRenderTexture2D(const RenderTargetPtr& target, bool isMulti, MonoObject* instance);
+
+		static void internal_createDetailed(MonoObject* instance, PixelFormat format, UINT32 width, UINT32 height, 
+			UINT32 numSamples, bool gammaCorrection, bool createDepth, PixelFormat depthStencilFormat);
+		static void internal_create(MonoObject* instance, MonoArray* colorSurfaces, MonoObject* depthStencilSurface);
+
+		static void internal_getColorSurfaces(ScriptRenderTexture2D* thisPtr, MonoArray** value);
+		static void internal_getDepthStencilSurface(ScriptRenderTexture2D* thisPtr, MonoObject** value);
+
+		RenderTargetPtr mRenderTarget;
+		bool mIsMulti;
+	};
+}

+ 2 - 0
SBansheeEngine/Include/BsScriptTexture2D.h

@@ -16,6 +16,8 @@ namespace BansheeEngine
 
 		HResource getNativeHandle() const { return mTexture; }
 		void setNativeHandle(const HResource& resource);
+
+		HTexture getTextureHandle() const { return mTexture; }
 	private:
 		friend class ScriptResourceManager;
 

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -285,6 +285,9 @@
     <ClInclude Include="Include\BsScriptObjectImpl.h" />
     <ClInclude Include="Include\BsScriptPixelData.h" />
     <ClInclude Include="Include\BsScriptPixelUtility.h" />
+    <ClInclude Include="Include\BsScriptRenderTarget.h" />
+    <ClInclude Include="Include\BsScriptRenderTexture.h" />
+    <ClInclude Include="Include\BsScriptRenderTexture2D.h" />
     <ClInclude Include="Include\BsScriptResource.h" />
     <ClInclude Include="Include\BsScriptResourceManager.h" />
     <ClInclude Include="Include\BsScriptSceneObject.h" />
@@ -348,6 +351,9 @@
     <ClCompile Include="Source\BsScriptObjectImpl.cpp" />
     <ClCompile Include="Source\BsScriptPixelData.cpp" />
     <ClCompile Include="Source\BsScriptPixelUtility.cpp" />
+    <ClCompile Include="Source\BsScriptRenderTarget.cpp" />
+    <ClCompile Include="Source\BsScriptRenderTexture.cpp" />
+    <ClCompile Include="Source\BsScriptRenderTexture2D.cpp" />
     <ClCompile Include="Source\BsScriptResourceManager.cpp" />
     <ClCompile Include="Source\BsScriptSceneObject.cpp" />
     <ClCompile Include="Source\BsManagedSerializableArray.cpp" />

+ 18 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -258,6 +258,15 @@
     <ClInclude Include="Include\BsScriptPixelUtility.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptRenderTarget.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptRenderTexture.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptRenderTexture2D.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -449,5 +458,14 @@
     <ClCompile Include="Source\BsScriptPixelUtility.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptRenderTarget.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptRenderTexture.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptRenderTexture2D.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 62 - 0
SBansheeEngine/Source/BsScriptRenderTarget.cpp

@@ -0,0 +1,62 @@
+#include "BsScriptRenderTarget.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsRenderTarget.h"
+#include "BsCoreThread.h"
+
+namespace BansheeEngine
+{
+	ScriptRenderTarget::ScriptRenderTarget(MonoObject* instance)
+		:ScriptObject(instance)
+	{
+
+	}
+
+	void ScriptRenderTarget::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetWidth", &ScriptRenderTarget::internal_getWidth);
+		metaData.scriptClass->addInternalCall("Internal_GetHeight", &ScriptRenderTarget::internal_getHeight);
+		metaData.scriptClass->addInternalCall("Internal_GetGammaCorrection", &ScriptRenderTarget::internal_getGammaCorrection);
+		metaData.scriptClass->addInternalCall("Internal_GetSampleCount", &ScriptRenderTarget::internal_getSampleCount);
+		metaData.scriptClass->addInternalCall("Internal_GetPriority", &ScriptRenderTarget::internal_getPriority);
+		metaData.scriptClass->addInternalCall("Internal_SetPriority", &ScriptRenderTarget::internal_setPriority);
+	}
+
+	void ScriptRenderTarget::internal_getWidth(ScriptRenderTarget* thisPtr, int* value)
+	{
+		RenderTargetPtr rt = thisPtr->getNativeValue();
+		*value = rt->getProperties().getWidth();
+	}
+
+	void ScriptRenderTarget::internal_getHeight(ScriptRenderTarget* thisPtr, int* value)
+	{
+		RenderTargetPtr rt = thisPtr->getNativeValue();
+		*value = rt->getProperties().getHeight();
+	}
+
+	void ScriptRenderTarget::internal_getGammaCorrection(ScriptRenderTarget* thisPtr, bool* value)
+	{
+		RenderTargetPtr rt = thisPtr->getNativeValue();
+		*value = rt->getProperties().isHwGammaEnabled();
+	}
+
+	void ScriptRenderTarget::internal_getSampleCount(ScriptRenderTarget* thisPtr, int* value)
+	{
+		RenderTargetPtr rt = thisPtr->getNativeValue();
+		*value = rt->getProperties().getMultisampleCount();
+	}
+
+	void ScriptRenderTarget::internal_getPriority(ScriptRenderTarget* thisPtr, int* value)
+	{
+		RenderTargetPtr rt = thisPtr->getNativeValue();
+		*value = rt->getProperties().getPriority();
+	}
+
+	void ScriptRenderTarget::internal_setPriority(ScriptRenderTarget* thisPtr, int value)
+	{
+		RenderTargetPtr rt = thisPtr->getNativeValue();
+		rt->setPriority(gCoreAccessor(), value);
+	}
+}

+ 19 - 0
SBansheeEngine/Source/BsScriptRenderTexture.cpp

@@ -0,0 +1,19 @@
+#include "BsScriptRenderTexture.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+
+namespace BansheeEngine
+{
+	ScriptRenderTexture::ScriptRenderTexture(MonoObject* instance)
+		:ScriptObject(instance)
+	{
+
+	}
+
+	void ScriptRenderTexture::initRuntimeData()
+	{
+
+	}
+}

+ 196 - 0
SBansheeEngine/Source/BsScriptRenderTexture2D.cpp

@@ -0,0 +1,196 @@
+#include "BsScriptRenderTexture2D.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsRenderTexture.h"
+#include "BsScriptTexture2D.h"
+#include "BsMultiRenderTexture.h"
+#include "BsMonoUtil.h"
+#include "BsScriptResourceManager.h"
+
+namespace BansheeEngine
+{
+	ScriptRenderTexture2D::ScriptRenderTexture2D(const RenderTargetPtr& target, bool isMulti, MonoObject* instance)
+		:ScriptObject(instance), mRenderTarget(target), mIsMulti(isMulti)
+	{
+
+	}
+
+	void ScriptRenderTexture2D::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateDetailed", &ScriptRenderTexture2D::internal_createDetailed);
+		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptRenderTexture2D::internal_create);
+		metaData.scriptClass->addInternalCall("Internal_GetColorSurfaces", &ScriptRenderTexture2D::internal_getColorSurfaces);
+		metaData.scriptClass->addInternalCall("Internal_GetDepthStencilSurface", &ScriptRenderTexture2D::internal_getDepthStencilSurface);
+	}
+
+	RenderTexturePtr ScriptRenderTexture2D::getRenderTexture() const
+	{
+		if (!mIsMulti)
+			return std::static_pointer_cast<RenderTexture>(mRenderTarget);
+
+		return nullptr;
+	}
+
+	MultiRenderTexturePtr ScriptRenderTexture2D::getMultiRenderTexture() const
+	{
+		if (mIsMulti)
+			return std::static_pointer_cast<MultiRenderTexture>(mRenderTarget);
+
+		return nullptr;
+	}
+
+	void ScriptRenderTexture2D::internal_createDetailed(MonoObject* instance, PixelFormat format, UINT32 width, UINT32 height,
+		UINT32 numSamples, bool gammaCorrection, bool createDepth, PixelFormat depthStencilFormat)
+	{
+		RenderTexturePtr tex = RenderTexture::create(TEX_TYPE_2D, width, height, format, gammaCorrection, numSamples, createDepth, depthStencilFormat);
+
+		ScriptRenderTexture2D* scriptResource = new (bs_alloc<ScriptRenderTexture2D>()) ScriptRenderTexture2D(tex, false, instance);
+	}
+
+	void ScriptRenderTexture2D::internal_create(MonoObject* instance, MonoArray* colorSurfaces, MonoObject* depthStencilSurface)
+	{
+		ScriptArray colorSurfacesList(colorSurfaces);
+
+		RENDER_SURFACE_DESC depthStencilSurfaceDesc;
+		ScriptTexture2D* scriptDepthStencilSurface = ScriptTexture2D::toNative(depthStencilSurface);
+		if (scriptDepthStencilSurface != nullptr)
+		{
+			depthStencilSurfaceDesc.face = 0;
+			depthStencilSurfaceDesc.mipLevel = 0;
+
+			HTexture textureHandle = scriptDepthStencilSurface->getTextureHandle();
+			if (!textureHandle.isLoaded())
+			{
+				LOGERR("Render texture must be created using a fully loaded texture.");
+			}
+			else
+				depthStencilSurfaceDesc.texture = textureHandle.getInternalPtr();
+		}
+
+		RenderTargetPtr tex;
+
+		UINT32 numSurfaces = colorSurfacesList.size();
+		bool isMulti = numSurfaces > 1;
+		if (isMulti)
+		{
+			MULTI_RENDER_TEXTURE_DESC desc;
+
+			for (UINT32 i = 0; i < numSurfaces; i++)
+			{
+				RENDER_SURFACE_DESC surfaceDesc;
+				surfaceDesc.face = 0;
+				surfaceDesc.mipLevel = 0;
+
+				MonoObject* surfaceObj = colorSurfacesList.get<MonoObject*>(i);
+				ScriptTexture2D* scriptSurface = ScriptTexture2D::toNative(surfaceObj);
+
+				if (scriptSurface != nullptr)
+				{
+					HTexture textureHandle = scriptSurface->getTextureHandle();
+					if (!textureHandle.isLoaded())
+					{
+						LOGERR("Render texture must be created using a fully loaded texture.");
+					}
+					else
+						surfaceDesc.texture = textureHandle.getInternalPtr();
+				}
+
+				desc.colorSurfaces.push_back(surfaceDesc);
+			}
+
+			desc.depthStencilSurface = depthStencilSurfaceDesc;
+
+			tex = MultiRenderTexture::create(desc);
+		}
+		else
+		{
+			RENDER_SURFACE_DESC surfaceDesc;
+			surfaceDesc.face = 0;
+			surfaceDesc.mipLevel = 0;
+
+			if (colorSurfacesList.size() > 0)
+			{
+				MonoObject* surfaceObj = colorSurfacesList.get<MonoObject*>(0);
+				ScriptTexture2D* scriptSurface = ScriptTexture2D::toNative(surfaceObj);
+
+				if (scriptSurface != nullptr)
+				{
+					HTexture textureHandle = scriptSurface->getTextureHandle();
+					if (!textureHandle.isLoaded())
+					{
+						LOGERR("Render texture must be created using a fully loaded texture.");
+					}
+					else
+						surfaceDesc.texture = textureHandle.getInternalPtr();
+				}
+			}
+
+			RENDER_TEXTURE_DESC desc;
+			desc.colorSurface = surfaceDesc;
+			desc.depthStencilSurface = depthStencilSurfaceDesc;
+			tex = RenderTexture::create(desc);
+		}
+
+		ScriptRenderTexture2D* scriptResource = new (bs_alloc<ScriptRenderTexture2D>()) ScriptRenderTexture2D(tex, isMulti, instance);
+	}
+
+	void ScriptRenderTexture2D::internal_getColorSurfaces(ScriptRenderTexture2D* thisPtr, MonoArray** value)
+	{
+		if (thisPtr->mIsMulti)
+		{
+			MultiRenderTexturePtr tex = thisPtr->getMultiRenderTexture();
+
+			UINT32 numColorSurfaces = tex->getColorSurfaceCount();
+			ScriptArray outArray = ScriptArray::create<ScriptTexture2D>(numColorSurfaces);
+
+			for (UINT32 i = 0; i < numColorSurfaces; i++)
+			{
+				HTexture colorTex = tex->getBindableColorTexture(i);
+
+				ScriptTexture2D* scriptSurface = ScriptResourceManager::instance().getScriptTexture(colorTex);
+				if (scriptSurface == nullptr)
+					scriptSurface = ScriptResourceManager::instance().createScriptTexture2D(colorTex);
+
+				outArray.set(i, scriptSurface->getManagedInstance());
+				*value = outArray.getInternal();
+			}
+		}
+		else
+		{
+			RenderTexturePtr tex = thisPtr->getRenderTexture();
+			ScriptArray outArray = ScriptArray::create<ScriptTexture2D>(1);
+
+			HTexture colorTex = tex->getBindableColorTexture();
+
+			ScriptTexture2D* scriptSurface = ScriptResourceManager::instance().getScriptTexture(colorTex);
+			if (scriptSurface == nullptr)
+				scriptSurface = ScriptResourceManager::instance().createScriptTexture2D(colorTex);
+
+			outArray.set(0, scriptSurface->getManagedInstance());
+			*value = outArray.getInternal();
+		}
+	}
+
+	void ScriptRenderTexture2D::internal_getDepthStencilSurface(ScriptRenderTexture2D* thisPtr, MonoObject** value)
+	{
+		HTexture colorTex;
+		if (thisPtr->mIsMulti)
+		{
+			MultiRenderTexturePtr tex = thisPtr->getMultiRenderTexture();
+			colorTex = tex->getBindableDepthStencilTexture();
+		}
+		else
+		{
+			RenderTexturePtr tex = thisPtr->getRenderTexture();
+			colorTex = tex->getBindableDepthStencilTexture();
+		}
+
+		ScriptTexture2D* scriptSurface = ScriptResourceManager::instance().getScriptTexture(colorTex);
+		if (scriptSurface == nullptr)
+			scriptSurface = ScriptResourceManager::instance().createScriptTexture2D(colorTex);
+
+		*value = scriptSurface->getManagedInstance();
+	}
+}

+ 39 - 19
TODO.txt

@@ -3,25 +3,45 @@
  New issues:
   - Since Mesh refactor when I select/deselect a gizmo the entire render texture flashes white for one frame (might be related to RT refactor instead)
 
-  Crash on shutdown: RenderStateManager gets initialize on core thread and it holds some references
- - Happened after i selected something in scene and then shutdown
-
-Fix crash on shutdown with OpenGL
-
-Try to figure out how to deal with material and its references:
- - It references a ShaderPtr but it should be referencing a HShader
- - It calls synchronize on all GpuPrograms before getting initialized because (same would apply to shader if it was using a HShader as it should):
-    - It needs to ensure they're loaded in case they were loaded asynchronously
-	- It needs to ensure they're initialize on core thread to retrieve gpu param desc which is used for creating gpu param buffers and param name/type checking
- - I cannot delay this init until those are initialized because user expects to be able to set material params right after creation
- - OPTIMAL approach would be to generate shader desc on sim thread or during import and allow delayed initialization
-   - If user uses async loading then it's his fault if material hasn't been initialized
-
-NEW IDEA (needs work)
-Allow the material to be initialized ONLY from synced data
- - While at it modify its shader from ShaderPtr to HShader
-Do the same for Pass
-But when loading a material from disk asynchronously ensure that its handle is not initialized as loaded until all dependencies are loaded async as well
+1. Make sure shader create() methods returns a HShader
+2. Make sure material uses HShader
+3. Make sure material listens for HShader load event (derives from IResourceListener)
+4. Delay material initialization until its shader and gpu programs are fully loaded (keep the core thread sync there as is for now)
+
+Resource saving
+ - Keep save as is, only the exact resource is saved without any dependencies
+ - However to each resource append InternalResourceMeta as a header which keeps a
+   list of dependant resources which is generated whenever a resource is saved
+   (Use the method described below to find dependencies)
+
+Resource import
+ - Extend Resource meta-data to contain a list of CONTAINED(not the same as dependant) resources
+   - So that ProjectLibrary knows to save that resource upon reimport
+
+Resource unload
+ - Still unloads just a single resource
+ - However refactor unloadUnused to be better (essentially a garbage collector):
+   - Find all resources referenced by the item we're unloading (Use method described below)
+   - Find ones that have no references left and unload them
+     - This is similar to what Unity does
+
+Resource load
+ - Use the dependant resource list described above to find a list of assets to load (load the list synchronously)
+ - Start loading all the assets using chosen method (sync/async)
+   - I'll have to disable/modify current method of loading resource handles as soon as they're deserialized
+     as they call load (sync) which will overwrite any async behavior.
+ - Only when loading of all dependant resources is done should the resource handles be marked as loaded
+   (To prevent having loaded a Material but not its Shader)
+ - Need to disable async loading for certain types (like SceneObject/Component and possibly others) - Just a flag in Resource
+
+I think I will most definitely need an utility method that walks entire scene hierarchy and returns all
+dependant resources (including from scripts)
+ - Go over all RTTI fields recursively. Make sure to iterate over arrays and go inside IReflectable objects.
+ - Refactor ManagedComponent and ManagedResource so they include a list of their fields in their RTTI
+   - They already do but currently it's only generated upon serialization. I need it to be available always and I'll probably want to decouple it from field values.
+ - This way I find all fields using normal RTTI methods.
+ - Possible problem: If RTTI has special callbacks for deserialization and its "get" method doesn't work without them. But deal with that on a case by case basis
+   - This might be a problem with managed obj serialization as its field data is generated in a callback, consider generating it in "get()" method instead.
 
 -----------------