浏览代码

More multithreaded changes, mostly to GpuPrograms

Marko Pintera 13 年之前
父节点
当前提交
d87a5e8fc4
共有 42 个文件被更改,包括 215 次插入90 次删除
  1. 0 2
      CamelotClient/CamelotClient.cpp
  2. 2 2
      CamelotD3D9Renderer/Include/CmD3D9GpuProgram.h
  3. 1 1
      CamelotD3D9Renderer/Include/CmD3D9HLSLProgramRTTI.h
  4. 7 5
      CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp
  5. 1 1
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  6. 3 1
      CamelotD3D9Renderer/Source/CmD3D9Texture.cpp
  7. 2 2
      CamelotForwardRenderer/Source/CmForwardRenderer.cpp
  8. 1 1
      CamelotGLRenderer/Include/CmGLSLProgramRTTI.h
  9. 1 1
      CamelotGLRenderer/Source/CmGLRenderSystem.cpp
  10. 2 1
      CamelotGLRenderer/Source/CmGLTexture.cpp
  11. 1 1
      CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h
  12. 2 1
      CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp
  13. 1 0
      CamelotRenderer/CamelotRenderer.vcxproj
  14. 1 0
      CamelotRenderer/CamelotRenderer.vcxproj.filters
  15. 1 1
      CamelotRenderer/Include/CmCgProgramRTTI.h
  16. 13 2
      CamelotRenderer/Include/CmGpuProgram.h
  17. 6 0
      CamelotRenderer/Include/CmGpuProgramRTTI.h
  18. 15 2
      CamelotRenderer/Include/CmHighLevelGpuProgram.h
  19. 9 4
      CamelotRenderer/Include/CmHighLevelGpuProgramManager.h
  20. 1 1
      CamelotRenderer/Include/CmMaterial.h
  21. 1 1
      CamelotRenderer/Include/CmMesh.h
  22. 19 4
      CamelotRenderer/Include/CmResource.h
  23. 7 7
      CamelotRenderer/Include/CmResourceHandle.h
  24. 1 1
      CamelotRenderer/Include/CmShader.h
  25. 7 2
      CamelotRenderer/Include/CmTexture.h
  26. 7 0
      CamelotRenderer/Include/CmTextureManager.h
  27. 11 9
      CamelotRenderer/Include/CmTextureRTTI.h
  28. 1 1
      CamelotRenderer/Source/CmCgProgram.cpp
  29. 8 2
      CamelotRenderer/Source/CmGpuProgram.cpp
  30. 1 1
      CamelotRenderer/Source/CmGpuProgramManager.cpp
  31. 11 2
      CamelotRenderer/Source/CmHighLevelGpuProgram.cpp
  32. 9 0
      CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp
  33. 0 1
      CamelotRenderer/Source/CmImporter.cpp
  34. 1 1
      CamelotRenderer/Source/CmMesh.cpp
  35. 4 1
      CamelotRenderer/Source/CmRenderSystem.cpp
  36. 3 8
      CamelotRenderer/Source/CmResource.cpp
  37. 6 1
      CamelotRenderer/Source/CmResourceHandle.cpp
  38. 3 1
      CamelotRenderer/Source/CmResources.cpp
  39. 1 1
      CamelotRenderer/Source/CmShader.cpp
  40. 7 0
      CamelotRenderer/Source/CmTextureManager.cpp
  41. 30 17
      CamelotRenderer/TODO.txt
  42. 7 0
      TODODoc.txt

+ 0 - 2
CamelotClient/CamelotClient.cpp

@@ -86,7 +86,6 @@ int _tmain(int argc, _TCHAR* argv[])
 							}";
 							}";
 
 
 	fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "cg", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
 	fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "cg", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
-	fragProg->init();
 
 
 	String vertShaderCode = "float4x4 matViewProjection;	\
 	String vertShaderCode = "float4x4 matViewProjection;	\
 							void vs_main(										\
 							void vs_main(										\
@@ -100,7 +99,6 @@ int _tmain(int argc, _TCHAR* argv[])
 							}";
 							}";
 
 
 	vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 	vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
-	vertProg->init();
 
 
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 
 

+ 2 - 2
CamelotD3D9Renderer/Include/CmD3D9GpuProgram.h

@@ -42,9 +42,9 @@ namespace CamelotEngine {
         D3D9GpuProgram();
         D3D9GpuProgram();
         ~D3D9GpuProgram();
         ~D3D9GpuProgram();
 
 
-		virtual void initImpl(void);
+		virtual void initialize_internal(void);
 		/** Loads this program to specified device */
 		/** Loads this program to specified device */
-		virtual void initImpl(IDirect3DDevice9* d3d9Device);
+		virtual void initialize_internal(IDirect3DDevice9* d3d9Device);
 		/** Overridden from GpuProgram */
 		/** Overridden from GpuProgram */
 		virtual void unload(void);
 		virtual void unload(void);
 
 

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9HLSLProgramRTTI.h

@@ -27,7 +27,7 @@ namespace CamelotEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return HighLevelGpuProgramManager::instance().create("hlsl");
+			return HighLevelGpuProgramManager::instance().createEmpty("hlsl");
 		}
 		}
 	};
 	};
 }
 }

+ 7 - 5
CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp

@@ -73,7 +73,7 @@ namespace CamelotEngine {
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-    void D3D9GpuProgram::initImpl(void)
+    void D3D9GpuProgram::initialize_internal(void)
     {
     {
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
 
@@ -81,12 +81,14 @@ namespace CamelotEngine {
 		{
 		{
 			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
 			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
 
 
-			initImpl(d3d9Device);
+			initialize_internal(d3d9Device);
 		}		       
 		}		       
+
+		Resource::initialize_internal();
     }
     }
 
 
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-	void D3D9GpuProgram::initImpl(IDirect3DDevice9* d3d9Device)
+	void D3D9GpuProgram::initialize_internal(IDirect3DDevice9* d3d9Device)
 	{
 	{
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
 
@@ -263,7 +265,7 @@ namespace CamelotEngine {
 		// Shader was not found -> load it.
 		// Shader was not found -> load it.
 		if (it == mMapDeviceToVertexShader.end())		
 		if (it == mMapDeviceToVertexShader.end())		
 		{
 		{
-			initImpl(d3d9Device);		
+			initialize_internal(d3d9Device);		
 			it = mMapDeviceToVertexShader.find(d3d9Device);
 			it = mMapDeviceToVertexShader.find(d3d9Device);
 		}
 		}
 	
 	
@@ -366,7 +368,7 @@ namespace CamelotEngine {
 		// Shader was not found -> load it.
 		// Shader was not found -> load it.
 		if (it == mMapDeviceToPixelShader.end())		
 		if (it == mMapDeviceToPixelShader.end())		
 		{
 		{
-			initImpl(d3d9Device);			
+			initialize_internal(d3d9Device);			
 			it = mMapDeviceToPixelShader.find(d3d9Device);
 			it = mMapDeviceToPixelShader.find(d3d9Device);
 		}
 		}
 
 

+ 1 - 1
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -273,7 +273,7 @@ namespace CamelotEngine
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		GpuProgram* bindingPrg = prg->_getBindingDelegate();
+		GpuProgram* bindingPrg = prg->getBindingDelegate_internal();
 
 
 		HRESULT hr;
 		HRESULT hr;
 		switch (bindingPrg->getType())
 		switch (bindingPrg->getType())

+ 3 - 1
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -215,7 +215,9 @@ namespace CamelotEngine
 				createInternalResourcesImpl(d3d9Device);
 				createInternalResourcesImpl(d3d9Device);
 				return;
 				return;
 			}	
 			}	
-		}		
+		}	
+
+		Resource::initialize_internal();
 	}
 	}
 	/****************************************************************************************/
 	/****************************************************************************************/
 	void D3D9Texture::freeInternalResources(void)
 	void D3D9Texture::freeInternalResources(void)

+ 2 - 2
CamelotForwardRenderer/Source/CmForwardRenderer.cpp

@@ -63,12 +63,12 @@ namespace CamelotEngine
 		{
 		{
 			MaterialHandle material = (*iter)->getMaterial();
 			MaterialHandle material = (*iter)->getMaterial();
 
 
-			if(material == nullptr || !material.isResolved())
+			if(material == nullptr || !material.isLoaded())
 				continue;
 				continue;
 
 
 			MeshHandle mesh = (*iter)->getMesh();
 			MeshHandle mesh = (*iter)->getMesh();
 
 
-			if(mesh == nullptr || !mesh.isResolved())
+			if(mesh == nullptr || !mesh.isLoaded())
 				continue;
 				continue;
 
 
 			// TODO - Renderer should ensure shader is compatible with it, and it contains all the needed parameters
 			// TODO - Renderer should ensure shader is compatible with it, and it contains all the needed parameters

+ 1 - 1
CamelotGLRenderer/Include/CmGLSLProgramRTTI.h

@@ -27,7 +27,7 @@ namespace CamelotEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return HighLevelGpuProgramManager::instance().create("glsl");
+			return HighLevelGpuProgramManager::instance().createEmpty("glsl");
 		}
 		}
 	};
 	};
 }
 }

+ 1 - 1
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -258,7 +258,7 @@ namespace CamelotEngine {
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		GpuProgram* bindingPrg = prg->_getBindingDelegate();
+		GpuProgram* bindingPrg = prg->getBindingDelegate_internal();
 		GLGpuProgram* glprg = static_cast<GLGpuProgram*>(bindingPrg);
 		GLGpuProgram* glprg = static_cast<GLGpuProgram*>(bindingPrg);
 
 
 		// Unbind previous gpu program first.
 		// Unbind previous gpu program first.

+ 2 - 1
CamelotGLRenderer/Source/CmGLTexture.cpp

@@ -78,8 +78,9 @@ namespace CamelotEngine {
 		if( mUsage & TU_RENDERTARGET )
 		if( mUsage & TU_RENDERTARGET )
 		{
 		{
 			createRenderTexture();
 			createRenderTexture();
-			return;
 		}
 		}
+
+		Resource::initialize_internal();
 	}
 	}
 
 
     GLenum GLTexture::getGLTextureTarget_internal(void) const
     GLenum GLTexture::getGLTextureTarget_internal(void) const

+ 1 - 1
CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h

@@ -90,7 +90,7 @@ namespace CamelotEngine {
 		/// @copydoc Resource::unloadImpl
 		/// @copydoc Resource::unloadImpl
 		void unloadImpl(void);
 		void unloadImpl(void);
 		/// @copydoc Resource::loadImpl
 		/// @copydoc Resource::loadImpl
-		void initImpl(void);
+		void initialize_internal(void);
 
 
 
 
     };
     };

+ 2 - 1
CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp

@@ -66,8 +66,9 @@ namespace CamelotEngine {
         unload(); 
         unload(); 
     }
     }
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
-    void GLSLGpuProgram::initImpl(void)
+    void GLSLGpuProgram::initialize_internal(void)
     {
     {
+		Resource::initialize_internal();
 		// nothing to load
 		// nothing to load
     }
     }
 
 

+ 1 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -90,6 +90,7 @@
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemGroup>
   <ItemGroup>
+    <Text Include="..\TODODoc.txt" />
     <Text Include="HighLevelTODO.txt" />
     <Text Include="HighLevelTODO.txt" />
     <Text Include="TODO.txt" />
     <Text Include="TODO.txt" />
   </ItemGroup>
   </ItemGroup>

+ 1 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -86,6 +86,7 @@
   <ItemGroup>
   <ItemGroup>
     <Text Include="TODO.txt" />
     <Text Include="TODO.txt" />
     <Text Include="HighLevelTODO.txt" />
     <Text Include="HighLevelTODO.txt" />
+    <Text Include="..\TODODoc.txt" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\CmConfigOptionMap.h">
     <ClInclude Include="Include\CmConfigOptionMap.h">

+ 1 - 1
CamelotRenderer/Include/CmCgProgramRTTI.h

@@ -27,7 +27,7 @@ namespace CamelotEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			return HighLevelGpuProgramManager::instance().create("cg");
+			return HighLevelGpuProgramManager::instance().createEmpty("cg");
 		}
 		}
 	};
 	};
 }
 }

+ 13 - 2
CamelotRenderer/Include/CmGpuProgram.h

@@ -118,7 +118,18 @@ namespace CamelotEngine {
 
 
 		virtual ~GpuProgram() {}
 		virtual ~GpuProgram() {}
 
 
-		virtual void initImpl();
+		/**
+		 * @brief	Initializes the gpu program. This must be called right after the program is constructed. 
+		 * 			Called by GpuProgramManager upon creation, so usually you don't want to call this manually. 
+		 * 			
+		 * @note	Initialization is not done immediately, and is instead just scheduled on the render thread.
+		 */
+		void initialize();
+
+		/**
+		 * @brief	Performs GpuProgram initialization. Only callable from the render thread.
+		 */
+		virtual void initialize_internal();
 		virtual void unload() {}
 		virtual void unload() {}
 
 
 		/** Sets the source assembly for this program from an in-memory string.
 		/** Sets the source assembly for this program from an in-memory string.
@@ -150,7 +161,7 @@ namespace CamelotEngine {
         @remarks
         @remarks
             This method is simply to allow some subclasses of GpuProgram to delegate
             This method is simply to allow some subclasses of GpuProgram to delegate
             the program which is bound to the pipeline to a delegate, if required. */
             the program which is bound to the pipeline to a delegate, if required. */
-        virtual GpuProgram* _getBindingDelegate(void) { return this; }
+        virtual GpuProgram* getBindingDelegate_internal(void) { return this; }
 
 
         /** Returns whether this program can be supported on the current renderer and hardware. */
         /** Returns whether this program can be supported on the current renderer and hardware. */
         virtual bool isSupported(void) const;
         virtual bool isSupported(void) const;

+ 6 - 0
CamelotRenderer/Include/CmGpuProgramRTTI.h

@@ -33,6 +33,12 @@ namespace CamelotEngine
 			CM_ADD_PLAINFIELD(mSyntaxCode, 7, GpuProgramRTTI)
 			CM_ADD_PLAINFIELD(mSyntaxCode, 7, GpuProgramRTTI)
 		}
 		}
 
 
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			GpuProgram* gpuProgram = static_cast<GpuProgram*>(obj);
+			gpuProgram->initialize();
+		}
+
 		virtual const String& getRTTIName()
 		virtual const String& getRTTIName()
 		{
 		{
 			static String name = "GpuProgram";
 			static String name = "GpuProgram";

+ 15 - 2
CamelotRenderer/Include/CmHighLevelGpuProgram.h

@@ -98,7 +98,19 @@ namespace CamelotEngine {
         HighLevelGpuProgram();
         HighLevelGpuProgram();
         ~HighLevelGpuProgram();
         ~HighLevelGpuProgram();
 
 
-		virtual void initImpl();
+		/**
+		 * @brief	Initializes the gpu program. This must be called right after the program is constructed. 
+		 * 			Called by HighLevelGpuManager upon creation, so usually you don't want to call this manually.
+		 * 			
+		 * @note	Initialization is not done immediately, and is instead just scheduled on the render thread.
+		 */
+		void initialize();
+
+		/**
+		 * @brief	Performs HighLevelGpuProgram initialization. Only callable from the render thread.
+		 */
+		virtual void initialize_internal();
+
 		virtual void unload();
 		virtual void unload();
 
 
         /** Creates a new parameters object compatible with this program definition. 
         /** Creates a new parameters object compatible with this program definition. 
@@ -109,8 +121,9 @@ namespace CamelotEngine {
             object containing the definition of the parameters this program understands.
             object containing the definition of the parameters this program understands.
         */
         */
         GpuProgramParametersSharedPtr createParameters(void);
         GpuProgramParametersSharedPtr createParameters(void);
+
         /** @copydoc GpuProgram::getBindingDelegate */
         /** @copydoc GpuProgram::getBindingDelegate */
-        GpuProgram* _getBindingDelegate(void) { return mAssemblerProgram.get(); }
+        GpuProgram* getBindingDelegate_internal(void) { return mAssemblerProgram.get(); }
 
 
 		/** Get the full list of GpuConstantDefinition instances.
 		/** Get the full list of GpuConstantDefinition instances.
 		@note
 		@note

+ 9 - 4
CamelotRenderer/Include/CmHighLevelGpuProgramManager.h

@@ -90,11 +90,9 @@ namespace CamelotEngine {
 		bool isLanguageSupported(const String& lang);
 		bool isLanguageSupported(const String& lang);
 
 
 
 
-        /** Create a new, unloaded HighLevelGpuProgram. 
+        /** Create a new HighLevelGpuProgram. 
 		@par
 		@par
 			This method creates a new program of the type specified as the second and third parameters.
 			This method creates a new program of the type specified as the second and third parameters.
-			You will have to call further methods on the returned program in order to 
-			define the program fully before you can load it.
 		@param name The identifying name of the program
 		@param name The identifying name of the program
         @param groupName The name of the resource group which this program is
         @param groupName The name of the resource group which this program is
             to be a member of
             to be a member of
@@ -103,13 +101,20 @@ namespace CamelotEngine {
 		*/
 		*/
 		HighLevelGpuProgramPtr create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile);
 		HighLevelGpuProgramPtr create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile);
 
 
-		/** Create a new, unloaded HighLevelGpuProgram. 
+		/** Create a new HighLevelGpuProgram. 
 		@par
 		@par
 			This method creates a new program of the specified language. You need to set other 
 			This method creates a new program of the specified language. You need to set other 
 			properties like source, entry point, type, profile manually.
 			properties like source, entry point, type, profile manually.
 		@param language Code of the language to use (e.g. "cg")
 		@param language Code of the language to use (e.g. "cg")
 		*/
 		*/
 		HighLevelGpuProgramPtr create(const String& language);
 		HighLevelGpuProgramPtr create(const String& language);
+
+		/**
+		 * @brief	Creates a completely empty and uninitialized HighLevelGpuProgram.
+		 * 			Should only be used for VERY specific purposes, like deserialization,
+		 * 			as it requires additional manual initialization that is not required normally.
+		 */
+		HighLevelGpuProgramPtr createEmpty(const String& language);
 	};
 	};
 	/** @} */
 	/** @} */
 	/** @} */
 	/** @} */

+ 1 - 1
CamelotRenderer/Include/CmMaterial.h

@@ -21,7 +21,7 @@ namespace CamelotEngine
 		/**
 		/**
 		 * @brief	Overridden from Resource.
 		 * @brief	Overridden from Resource.
 		 */
 		 */
-		virtual void initImpl() { }
+		virtual void initialize_internal() { }
 
 
 		/**
 		/**
 		 * @brief	Sets a shader that will be used by the material. 
 		 * @brief	Sets a shader that will be used by the material. 

+ 1 - 1
CamelotRenderer/Include/CmMesh.h

@@ -40,7 +40,7 @@ namespace CamelotEngine
 
 
 		RenderOperation getRenderOperation(UINT32 subMeshIdx = 0) const;
 		RenderOperation getRenderOperation(UINT32 subMeshIdx = 0) const;
 
 
-		virtual void initImpl();
+		virtual void initialize_internal();
 
 
 	private:
 	private:
 		MeshDataPtr mMeshData;
 		MeshDataPtr mMeshData;

+ 19 - 4
CamelotRenderer/Include/CmResource.h

@@ -14,23 +14,38 @@ namespace CamelotEngine
 		Resource();
 		Resource();
 		virtual ~Resource() {};
 		virtual ~Resource() {};
 
 
-		void init();
-		virtual void initImpl() {}
-
 		const String& getUUID() const { return mUUID; }
 		const String& getUUID() const { return mUUID; }
 
 
+		/**
+		 * @brief	Returns true if the object has been properly initialized. You are not
+		 * 			allowed to call any methods on the resource until you are sure resource is initialized.
+		 */
+		bool isInitialized() const { return mIsInitialized; }
+
 	protected:
 	protected:
 		friend class Resources;
 		friend class Resources;
 		//virtual void unload() = 0;
 		//virtual void unload() = 0;
 
 
 		//virtual void calculateSize() = 0;
 		//virtual void calculateSize() = 0;
 		//virtual void reload();
 		//virtual void reload();
+		
+		/**
+		 * @brief	Finishes up resource initialization. Usually called right after the resource is created.
+		 * 			Make sure that derived classes implement their own initialize_internal, and make sure
+		 * 			they call this implementation from it.
+		 */
+		virtual void initialize_internal();
+
+		/**
+		 * @brief	Marks the resource as initialized.
+		 */
+		void setInitialized() { mIsInitialized = true; }
 
 
 		String mUUID; 
 		String mUUID; 
 		UINT32 mSize;
 		UINT32 mSize;
 
 
 		// Transient
 		// Transient
-		bool mInitialized;
+		bool mIsInitialized;
 
 
 	/************************************************************************/
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/* 								SERIALIZATION                      		*/

+ 7 - 7
CamelotRenderer/Include/CmResourceHandle.h

@@ -10,12 +10,12 @@ namespace CamelotEngine
 	struct CM_EXPORT ResourceHandleData : public IReflectable
 	struct CM_EXPORT ResourceHandleData : public IReflectable
 	{
 	{
 		ResourceHandleData()
 		ResourceHandleData()
-			:mIsResolved(false)
+			:mIsCreated(false)
 		{ }
 		{ }
 
 
 		std::shared_ptr<Resource> mPtr;
 		std::shared_ptr<Resource> mPtr;
 		String mUUID;
 		String mUUID;
-		bool mIsResolved;
+		bool mIsCreated;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/
@@ -32,7 +32,7 @@ namespace CamelotEngine
 		/**
 		/**
 		 * @brief	Checks if the resource is loaded
 		 * @brief	Checks if the resource is loaded
 		 */
 		 */
-		bool isResolved() const { return mData->mIsResolved; }
+		bool isLoaded() const;
 
 
 	protected:
 	protected:
 		ResourceHandleBase();
 		ResourceHandleBase();
@@ -50,7 +50,7 @@ namespace CamelotEngine
 	private:
 	private:
 		friend class Resources;
 		friend class Resources;
 		/**
 		/**
-		 * @brief	Sets the resolved flag to true. Should only be called
+		 * @brief	Sets the created flag to true. Should only be called
 		 * 			by Resources class after loading of the resource is fully done.
 		 * 			by Resources class after loading of the resource is fully done.
 		 */
 		 */
 		void resolve(std::shared_ptr<Resource> ptr);
 		void resolve(std::shared_ptr<Resource> ptr);
@@ -105,7 +105,7 @@ namespace CamelotEngine
 		// TODO Low priority - User can currently try to access these even if resource ptr is not resolved
 		// TODO Low priority - User can currently try to access these even if resource ptr is not resolved
 		T* get() const 
 		T* get() const 
 		{ 
 		{ 
-			if(!isResolved()) 
+			if(!isLoaded()) 
 				return nullptr; 
 				return nullptr; 
 			
 			
 			return static_cast<T*>(mData->mPtr.get()); 
 			return static_cast<T*>(mData->mPtr.get()); 
@@ -113,7 +113,7 @@ namespace CamelotEngine
 		T* operator->() const { return get(); }
 		T* operator->() const { return get(); }
 		T& operator*() const { return *get(); }
 		T& operator*() const { return *get(); }
 
 
-		std::shared_ptr<T> getInternalPtr() { if(!isResolved()) return nullptr; return std::static_pointer_cast<T>(mData->mPtr); }
+		std::shared_ptr<T> getInternalPtr() { if(!isLoaded()) return nullptr; return std::static_pointer_cast<T>(mData->mPtr); }
 
 
 		template<class _Ty>
 		template<class _Ty>
 		struct CM_Bool_struct
 		struct CM_Bool_struct
@@ -125,7 +125,7 @@ namespace CamelotEngine
 		// (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
 		// (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
 		operator int CM_Bool_struct<T>::*() const
 		operator int CM_Bool_struct<T>::*() const
 		{
 		{
-			return ((isResolved() && (mData->mPtr.get() != 0)) ? &CM_Bool_struct<T>::_Member : 0);
+			return ((isLoaded() && (mData->mPtr.get() != 0)) ? &CM_Bool_struct<T>::_Member : 0);
 		}
 		}
 	};
 	};
 
 

+ 1 - 1
CamelotRenderer/Include/CmShader.h

@@ -22,7 +22,7 @@ namespace CamelotEngine
 		/**
 		/**
 		 * @brief	Inherited from Resource.
 		 * @brief	Inherited from Resource.
 		 */
 		 */
-		virtual void initImpl();
+		virtual void initialize_internal();
 
 
 		TechniquePtr addTechnique(const String& renderSystem, const String& renderer);
 		TechniquePtr addTechnique(const String& renderSystem, const String& renderer);
 		
 		

+ 7 - 2
CamelotRenderer/Include/CmTexture.h

@@ -246,12 +246,17 @@ namespace CamelotEngine {
 		protected:
 		protected:
 
 
 		/**
 		/**
-		 * @brief	Initializes the texture. This must be called right after the texture is constructed. Normally called by TextureManager
-		 * 			upon texture creation.
+		 * @brief	Initializes the texture. This must be called right after the texture is constructed. Called by TextureManager
+		 * 			upon texture creation, so usually you don't want to call this manually.
+		 * 			
+		 * @note	Initialization is not done immediately, and is instead just scheduled on the render thread.
 		 */
 		 */
 		void initialize(TextureType textureType, size_t width, size_t height, size_t depth, size_t numMipmaps, 
 		void initialize(TextureType textureType, size_t width, size_t height, size_t depth, size_t numMipmaps, 
 			PixelFormat format, int usage, bool hwGamma, UINT32 fsaa, const String& fsaaHint);
 			PixelFormat format, int usage, bool hwGamma, UINT32 fsaa, const String& fsaaHint);
 		
 		
+		/**
+		 * @brief	Performs GpuProgram initialization. Only callable from the render thread.
+		 */
 		virtual void initialize_internal() = 0;
 		virtual void initialize_internal() = 0;
 
 
 		/// @copydoc Resource::calculateSize
 		/// @copydoc Resource::calculateSize

+ 7 - 0
CamelotRenderer/Include/CmTextureManager.h

@@ -162,6 +162,13 @@ namespace CamelotEngine {
 				num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
 				num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
 		}
 		}
 
 
+		/**
+		 * @brief	Creates a completely empty and uninitialized Texture.
+		 * 			Should only be used for VERY specific purposes, like deserialization,
+		 * 			as it requires additional manual initialization that is not required normally.
+		 */
+		TexturePtr createEmpty();
+
 		/** Returns whether this render system can natively support the precise texture 
 		/** Returns whether this render system can natively support the precise texture 
 			format requested with the given usage options.
 			format requested with the given usage options.
 		@remarks
 		@remarks

+ 11 - 9
CamelotRenderer/Include/CmTextureRTTI.h

@@ -37,7 +37,9 @@ namespace CamelotEngine
 
 
 		void setPixelData(Texture* obj, UINT32 idx, PixelDataPtr data)
 		void setPixelData(Texture* obj, UINT32 idx, PixelDataPtr data)
 		{
 		{
-			mPixelData[idx] = data;
+			vector<PixelDataPtr>::type* pixelData = boost::any_cast<vector<PixelDataPtr>::type*>(obj->mRTTIData);
+
+			(*pixelData)[idx] = data;
 		}
 		}
 
 
 		UINT32 getPixelDataArraySize(Texture* obj)
 		UINT32 getPixelDataArraySize(Texture* obj)
@@ -86,6 +88,12 @@ namespace CamelotEngine
 			if(texture->mRTTIData.empty())
 			if(texture->mRTTIData.empty())
 				return;
 				return;
 
 
+			// A bit clumsy initializing with already set values, but I feel its better than complicating things and storing the values
+			// in mRTTIData.
+			texture->initialize(texture->getTextureType(), texture->getWidth(), texture->getHeight(), texture->getDepth(), 
+				texture->getNumMipmaps(), texture->getFormat(), texture->getUsage(), texture->isHardwareGammaEnabled(), 
+				texture->getFSAA(), texture->getFSAAHint());
+
 			vector<PixelDataPtr>::type* pixelData = boost::any_cast<vector<PixelDataPtr>::type*>(texture->mRTTIData);
 			vector<PixelDataPtr>::type* pixelData = boost::any_cast<vector<PixelDataPtr>::type*>(texture->mRTTIData);
 			for(size_t i = 0; i < pixelData->size(); i++)
 			for(size_t i = 0; i < pixelData->size(); i++)
 			{
 			{
@@ -96,7 +104,7 @@ namespace CamelotEngine
 			}
 			}
 
 
 			delete pixelData;
 			delete pixelData;
-			texture->mRTTIData = nullptr;			
+			texture->mRTTIData = nullptr;	
 		}
 		}
 
 
 		virtual const String& getRTTIName()
 		virtual const String& getRTTIName()
@@ -112,13 +120,7 @@ namespace CamelotEngine
 
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
 		{
-			// DEBUG ONLY - Remove this after I implement RTTI types for specific texture types
-			return Texture::create(TEX_TYPE_2D, 128, 128, 1, PF_A8B8G8R8);
-
-			//CM_EXCEPT(InternalErrorException, "Cannot instantiate abstract class!");
+			return TextureManager::instance().createEmpty();
 		}
 		}
-
-	private:
-		vector<PixelDataPtr>::type mPixelData;
 	};
 	};
 }
 }

+ 1 - 1
CamelotRenderer/Source/CmCgProgram.cpp

@@ -169,7 +169,7 @@ namespace CamelotEngine {
 					HighLevelGpuProgramManager::instance().create(
 					HighLevelGpuProgramManager::instance().create(
 					hlslSourceFromCg, "main", "hlsl", mType, mProfile);
 					hlslSourceFromCg, "main", "hlsl", mType, mProfile);
 
 
-				vp->init();
+				vp->initialize();
 
 
 				mAssemblerProgram = vp;
 				mAssemblerProgram = vp;
 			}
 			}

+ 8 - 2
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -60,13 +60,20 @@ namespace CamelotEngine
         mSource = source;
         mSource = source;
 		mCompileError = false;
 		mCompileError = false;
     }
     }
+	//-----------------------------------------------------------------------------
+	void GpuProgram::initialize()
+	{
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&GpuProgram::initialize_internal, this));
+	}
     //-----------------------------------------------------------------------------
     //-----------------------------------------------------------------------------
-    void GpuProgram::initImpl(void)
+    void GpuProgram::initialize_internal(void)
     {
     {
         // Call polymorphic load
         // Call polymorphic load
 		try 
 		try 
 		{
 		{
 			loadFromSource();
 			loadFromSource();
+
+			Resource::initialize_internal();
 		}
 		}
 		catch (const Exception&)
 		catch (const Exception&)
 		{
 		{
@@ -77,7 +84,6 @@ namespace CamelotEngine
 
 
 			mCompileError = true;
 			mCompileError = true;
 		}
 		}
-
     }
     }
     //-----------------------------------------------------------------------------
     //-----------------------------------------------------------------------------
     bool GpuProgram::isSupported(void) const
     bool GpuProgram::isSupported(void) const

+ 1 - 1
CamelotRenderer/Source/CmGpuProgramManager.cpp

@@ -50,7 +50,7 @@ namespace CamelotEngine {
 		{
 		{
 			prg = createProgram( code, gptype, syntaxCode);
 			prg = createProgram( code, gptype, syntaxCode);
 		}
 		}
-        prg->init();
+        prg->initialize();
         return prg;
         return prg;
     }
     }
     //---------------------------------------------------------------------------
     //---------------------------------------------------------------------------

+ 11 - 2
CamelotRenderer/Source/CmHighLevelGpuProgram.cpp

@@ -27,6 +27,8 @@ THE SOFTWARE.
 */
 */
 #include "CmHighLevelGpuProgram.h"
 #include "CmHighLevelGpuProgram.h"
 #include "CmHighLevelGpuProgramManager.h"
 #include "CmHighLevelGpuProgramManager.h"
+#include "CmRenderSystemManager.h"
+#include "CmRenderSystem.h"
 #include "CmException.h"
 #include "CmException.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
@@ -37,8 +39,13 @@ namespace CamelotEngine
         mHighLevelLoaded(false), mAssemblerProgram(0), mConstantDefsBuilt(false)
         mHighLevelLoaded(false), mAssemblerProgram(0), mConstantDefsBuilt(false)
     {
     {
     }
     }
+	//---------------------------------------------------------------------------
+	void HighLevelGpuProgram::initialize()
+	{
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&HighLevelGpuProgram::initialize_internal, this));
+	}
     //---------------------------------------------------------------------------
     //---------------------------------------------------------------------------
-    void HighLevelGpuProgram::initImpl()
+    void HighLevelGpuProgram::initialize_internal()
     {
     {
 		if (isSupported())
 		if (isSupported())
 		{
 		{
@@ -51,8 +58,10 @@ namespace CamelotEngine
 			// load constructed assembler program (if it exists)
 			// load constructed assembler program (if it exists)
 			if (mAssemblerProgram != nullptr && mAssemblerProgram.get() != this)
 			if (mAssemblerProgram != nullptr && mAssemblerProgram.get() != this)
 			{
 			{
-				mAssemblerProgram->init();
+				mAssemblerProgram->initialize_internal();
 			}
 			}
+
+			Resource::initialize_internal();
 		}
 		}
     }
     }
     //---------------------------------------------------------------------------
     //---------------------------------------------------------------------------

+ 9 - 0
CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp

@@ -152,11 +152,20 @@ namespace CamelotEngine {
         HighLevelGpuProgramPtr prg = ret;
         HighLevelGpuProgramPtr prg = ret;
         prg->setType(gptype);
         prg->setType(gptype);
         prg->setSyntaxCode(language);
         prg->setSyntaxCode(language);
+		ret->initialize();
 
 
         return prg;
         return prg;
     }
     }
 	//---------------------------------------------------------------------------
 	//---------------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& language)
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& language)
+	{
+		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(getFactory(language)->create());
+		ret->initialize();
+
+		return ret;
+	}
+	//---------------------------------------------------------------------------
+	HighLevelGpuProgramPtr HighLevelGpuProgramManager::createEmpty(const String& language)
 	{
 	{
 		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(getFactory(language)->create());
 		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(getFactory(language)->create());
 
 

+ 0 - 1
CamelotRenderer/Source/CmImporter.cpp

@@ -71,7 +71,6 @@ namespace CamelotEngine
 		}
 		}
 
 
 		BaseResourceHandle importedResource = importer->import(inputFilePath);
 		BaseResourceHandle importedResource = importer->import(inputFilePath);
-		importedResource->init();
 
 
 		return importedResource;
 		return importedResource;
 	}
 	}

+ 1 - 1
CamelotRenderer/Source/CmMesh.cpp

@@ -160,7 +160,7 @@ namespace CamelotEngine
 		return ro;
 		return ro;
 	}
 	}
 
 
-	void Mesh::initImpl()
+	void Mesh::initialize_internal()
 	{
 	{
 		if(mMeshData == nullptr)
 		if(mMeshData == nullptr)
 		{
 		{

+ 4 - 1
CamelotRenderer/Source/CmRenderSystem.cpp

@@ -732,7 +732,7 @@ namespace CamelotEngine {
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		switch(prg->_getBindingDelegate()->getType())
+		switch(prg->getBindingDelegate_internal()->getType())
 		{
 		{
 		case GPT_VERTEX_PROGRAM:
 		case GPT_VERTEX_PROGRAM:
 			// mark clip planes dirty if changed (programmable can change space)
 			// mark clip planes dirty if changed (programmable can change space)
@@ -989,6 +989,9 @@ namespace CamelotEngine {
 
 
 	void RenderSystem::submitToGpu(RenderSystemContextPtr context, bool blockUntilComplete)
 	void RenderSystem::submitToGpu(RenderSystemContextPtr context, bool blockUntilComplete)
 	{
 	{
+		if(CM_THREAD_CURRENT_ID == getRenderThreadId())
+			CM_EXCEPT(InternalErrorException, "You are not allowed to call this method on the render thread!");
+
 		{
 		{
 			CM_LOCK_MUTEX(mRSContextMutex);
 			CM_LOCK_MUTEX(mRSContextMutex);
 
 

+ 3 - 8
CamelotRenderer/Source/CmResource.cpp

@@ -5,21 +5,16 @@
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
 	Resource::Resource()
 	Resource::Resource()
-		:mSize(0), mInitialized(false)
+		:mSize(0), mIsInitialized(false)
 	{
 	{
 		// We always generate a random UUID, and then overwrite it with the actual one 
 		// We always generate a random UUID, and then overwrite it with the actual one 
 		// during loading if one was previously generated and saved.
 		// during loading if one was previously generated and saved.
 		mUUID = UUIDGenerator::generateRandom();
 		mUUID = UUIDGenerator::generateRandom();
 	}
 	}
 
 
-	void Resource::init()
+	void Resource::initialize_internal()
 	{
 	{
-		if(!mInitialized)
-		{
-			initImpl();
-
-			mInitialized = true;
-		}
+		mIsInitialized = true;
 	}
 	}
 		
 		
 	RTTITypeBase* Resource::getRTTIStatic()
 	RTTITypeBase* Resource::getRTTIStatic()

+ 6 - 1
CamelotRenderer/Source/CmResourceHandle.cpp

@@ -21,6 +21,11 @@ namespace CamelotEngine
 		mData = std::shared_ptr<ResourceHandleData>(new ResourceHandleData());
 		mData = std::shared_ptr<ResourceHandleData>(new ResourceHandleData());
 	}
 	}
 
 
+	bool ResourceHandleBase::isLoaded() const 
+	{ 
+		return (mData->mIsCreated && mData->mPtr != nullptr && mData->mPtr->isInitialized()); 
+	}
+
 	void ResourceHandleBase::resolve(std::shared_ptr<Resource> ptr) 
 	void ResourceHandleBase::resolve(std::shared_ptr<Resource> ptr) 
 	{ 
 	{ 
 		init(ptr);
 		init(ptr);
@@ -43,7 +48,7 @@ namespace CamelotEngine
 		if(mData->mPtr)
 		if(mData->mPtr)
 		{
 		{
 			mData->mUUID = mData->mPtr->getUUID();
 			mData->mUUID = mData->mPtr->getUUID();
-			mData->mIsResolved = true; 
+			mData->mIsCreated = true; 
 		}
 		}
 	}
 	}
 
 

+ 3 - 1
CamelotRenderer/Source/CmResources.cpp

@@ -44,7 +44,6 @@ namespace CamelotEngine
 		{
 		{
 			ResourceLoadResponsePtr resResponse = boost::any_cast<ResourceLoadResponsePtr>(res->getData());
 			ResourceLoadResponsePtr resResponse = boost::any_cast<ResourceLoadResponsePtr>(res->getData());
 			
 			
-			resResponse->rawResource->init();
 			resRequest->resource.resolve(resResponse->rawResource);
 			resRequest->resource.resolve(resResponse->rawResource);
 
 
 			if(!gResources().metaExists_UUID(resResponse->rawResource->getUUID()))
 			if(!gResources().metaExists_UUID(resResponse->rawResource->getUUID()))
@@ -250,6 +249,9 @@ namespace CamelotEngine
 
 
 	void Resources::save(BaseResourceHandle resource)
 	void Resources::save(BaseResourceHandle resource)
 	{
 	{
+		// TODO - Check if the resource is fully loaded or not. If its not loaded either wait for it to be loaded,
+		// or break out
+
 		assert(resource.get() != nullptr);
 		assert(resource.get() != nullptr);
 
 
 		if(!metaExists_UUID(resource->getUUID()))
 		if(!metaExists_UUID(resource->getUUID()))

+ 1 - 1
CamelotRenderer/Source/CmShader.cpp

@@ -12,7 +12,7 @@ namespace CamelotEngine
 
 
 	}
 	}
 
 
-	void Shader::initImpl()
+	void Shader::initialize_internal()
 	{	}
 	{	}
 
 
 	TechniquePtr Shader::addTechnique(const String& renderSystem, const String& renderer)
 	TechniquePtr Shader::addTechnique(const String& renderSystem, const String& renderer)

+ 7 - 0
CamelotRenderer/Source/CmTextureManager.cpp

@@ -50,6 +50,13 @@ namespace CamelotEngine {
 
 
 		return ret;
 		return ret;
     }
     }
+	//-----------------------------------------------------------------------
+	TexturePtr TextureManager::createEmpty()
+	{
+		TexturePtr ret = TexturePtr(createImpl());
+
+		return ret;
+	}
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
 	bool TextureManager::isFormatSupported(TextureType ttype, PixelFormat format, int usage)
 	bool TextureManager::isFormatSupported(TextureType ttype, PixelFormat format, int usage)
 	{
 	{

+ 30 - 17
CamelotRenderer/TODO.txt

@@ -19,12 +19,11 @@ Command buffer TODO:
  - My current approach doesn't allow multiple threads to use the RenderSystem (contexts should be handled differently)
  - My current approach doesn't allow multiple threads to use the RenderSystem (contexts should be handled differently)
    - Instead of requiring the user to constantly call setActiveContext, make the call peristent per thread. 
    - Instead of requiring the user to constantly call setActiveContext, make the call peristent per thread. 
    - Store sequential thread idx in local thread storage, and then we can easily look up a context for a thread and
    - Store sequential thread idx in local thread storage, and then we can easily look up a context for a thread and
-     automatically use it, if it's set.
- - Make sure the user knows resources are shared between contexts. All resource updates are executed before rendering a frame, so whichever context updated the resource last,
-   was the version that will be used.
+     automatically use it, if it's set. (Use boost::thread_specific_ptr for local thread storage)
+ - Doing setPixels_async in the texture doesn't make sure that the user doesn't actually modify the provided PixelData after
+    that call.
 
 
  Texture updates:
  Texture updates:
-   - Make TextureData private to FreeImgImporter (as its not used anywhere else)
    - Make this per texture and apply when texture is applied:
    - Make this per texture and apply when texture is applied:
 	 filterMode
 	 filterMode
 	 anisoLevel
 	 anisoLevel
@@ -32,8 +31,31 @@ Command buffer TODO:
 	 mipMapBias
 	 mipMapBias
    - Make sure resource deletion is handled on the proper thread
    - Make sure resource deletion is handled on the proper thread
 
 
+Mesh
+ - Add initialize and initialize_internal
+ - Make sure MeshRTTI calls initialize properly
+ - Make sure FBX importer calls initialize properly
+
+GpuProgram/HighLevelGpuProgram
+ - Do a pass of refactoring
+ - Fix it up for multithreading
+  - In general everything needs to be checked
+  - Specifically HighLevelGpuParam::createParameters
+  - Add thread checks
+
+Make initialize & initialize_internal protected?
+ - Only their factories and RTTI classes need to access it (and they can be friends)
+ - Would need to modify HighLevelGpuProgram::mAssemblerProgram
+
+When saving a resource, make sure resource is properly loaded before saving
+ - Add blockUntilLoaded method to Resource
+  - Probably need a flag to make sure loading even started?
+    (Or not if I make Resource constructors and initialize methods protected)
+  - Make sure this is never called on the render thread
+  - Add doc to Resources::save that says it will block until render thread updates the resource
+  - Remove Response handlers from Resources
+
  Immediate:
  Immediate:
-  - Resource updates shouldn't happen once per frame. Resources should be submitted to render thread immediately.
   - Port resource creation to use RenderContext (texture/mesh/shader/etc initialization and updates)
   - Port resource creation to use RenderContext (texture/mesh/shader/etc initialization and updates)
   - Make sure to add thread checks (surrounded by #if DEBUG) to Vertex/Index/Pixel buffers, textures, meshes, etc.
   - Make sure to add thread checks (surrounded by #if DEBUG) to Vertex/Index/Pixel buffers, textures, meshes, etc.
 
 
@@ -51,19 +73,11 @@ HIGH PRIORITY TODO:
 
 
 Mid priority TODO:
 Mid priority TODO:
  - Add a field that tracks % of resource deserialization in BinarySerializer
  - Add a field that tracks % of resource deserialization in BinarySerializer
-
- - Separate render thread
-   - CommandBuffer (technically it should be just a RenderQueue I think)
-   - Main thread updates components, finds visible meshes and creates render device. At end of execution it fills up render queue
-   - Render thread renders everything in the render queue, and also creates resources (although RenderQueue name doesn't make sense if its used for resources too)
-   - Before I start with this I should probably strip down render system to a bare minimum
-
  - GpuProgram default parameters might not be needed. The parameters change with each use of the gpu program anyway
  - GpuProgram default parameters might not be needed. The parameters change with each use of the gpu program anyway
  - Mesh loading:
  - Mesh loading:
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Imported FBX meshes are too big
   - Imported FBX meshes are too big
   - Search for all remaining "TODO PORT" comments and fix them
   - Search for all remaining "TODO PORT" comments and fix them
-  - How do I serialize derived classes, without rewriting all the base class serialization?
   - Ogre performed special DDS loading. I removed that. I'm not sure if I'll need to re-add it?
   - Ogre performed special DDS loading. I removed that. I'm not sure if I'll need to re-add it?
  - RTTI:
  - RTTI:
      When defining RTTIType like so: 
      When defining RTTIType like so: 
@@ -96,11 +110,10 @@ Optional TODO:
 
 
  -----------------------------------------------------------------------------------------------
  -----------------------------------------------------------------------------------------------
 
 
-After everything is polished:
- - Make sure the renderer can run on a separate thread
-  - Command buffers that allow dx9, dx11 and opengl all use a separate render thread
- - Load texture mips separately so we can unload HQ textures from far away objects (like UE3)
+After everything is polished
  - Get 64bit version working
  - Get 64bit version working
+ - DX11 render system
+ - Load texture mips separately so we can unload HQ textures from far away objects (like UE3)
  - Add Unified shader so I can easily switch between HLSL and GLSL shaders (they need same parameters usually, just different code)
  - Add Unified shader so I can easily switch between HLSL and GLSL shaders (they need same parameters usually, just different code)
     - Maybe just add support for Cg and force everyone to use that? - I'd like to be able to just switch out renderer in a single location and that everything keeps on working without 
     - Maybe just add support for Cg and force everyone to use that? - I'd like to be able to just switch out renderer in a single location and that everything keeps on working without 
 	  further modifications.
 	  further modifications.

+ 7 - 0
TODODoc.txt

@@ -0,0 +1,7 @@
+ - Render system threading:
+   - Make a list of thread-safe RenderSystem classes
+    - For example HighLevelGpuProgram is thread safe but GpuProgram itself isn't
+    - Classes that are safe to use outside of the render thread: RenderSystem, Mesh, Texture, HighLevelGpuProgram, Material, Shader, Technique
+	- Classes that are only accessible from the render thread: GpuProgram, HardwarePixelBuffer, HardwareVertexBuffer, HardwareIndexBuffer
+  - Make sure the user knows resources are shared between contexts. All resource updates are executed 
+     before rendering a frame, so whichever context updated the resource last, was the version that will be used.