Bläddra i källkod

Texture refactor to comply with new CoreObject design

Marko Pintera 11 år sedan
förälder
incheckning
f256dad7d6
70 ändrade filer med 1271 tillägg och 1289 borttagningar
  1. 0 3
      BansheeCore/BansheeCore.vcxproj
  2. 0 9
      BansheeCore/BansheeCore.vcxproj.filters
  3. 1 3
      BansheeCore/Include/BsCorePrerequisites.h
  4. 0 24
      BansheeCore/Include/BsCoreThreadAccessor.h
  5. 0 50
      BansheeCore/Include/BsGpuResource.h
  6. 0 33
      BansheeCore/Include/BsGpuResourceRTTI.h
  7. 1 1
      BansheeCore/Include/BsMeshBase.h
  8. 1 1
      BansheeCore/Include/BsMeshBaseRTTI.h
  9. 2 18
      BansheeCore/Include/BsRenderSystem.h
  10. 220 167
      BansheeCore/Include/BsTexture.h
  11. 18 21
      BansheeCore/Include/BsTextureManager.h
  12. 52 45
      BansheeCore/Include/BsTextureRTTI.h
  13. 4 4
      BansheeCore/Include/BsTextureView.h
  14. 2 19
      BansheeCore/Source/BsCoreThreadAccessor.cpp
  15. 0 15
      BansheeCore/Source/BsGpuResource.cpp
  16. 0 2
      BansheeCore/Source/BsMesh.cpp
  17. 51 43
      BansheeCore/Source/BsMultiRenderTexture.cpp
  18. 2 33
      BansheeCore/Source/BsRenderSystem.cpp
  19. 30 25
      BansheeCore/Source/BsRenderTexture.cpp
  20. 272 206
      BansheeCore/Source/BsTexture.cpp
  21. 15 23
      BansheeCore/Source/BsTextureManager.cpp
  22. 1 1
      BansheeCore/Source/BsTextureView.cpp
  23. 3 3
      BansheeD3D11RenderSystem/Include/BsD3D11RenderSystem.h
  24. 1 1
      BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h
  25. 10 9
      BansheeD3D11RenderSystem/Include/BsD3D11Texture.h
  26. 8 6
      BansheeD3D11RenderSystem/Include/BsD3D11TextureManager.h
  27. 5 5
      BansheeD3D11RenderSystem/Include/BsD3D11TextureView.h
  28. 8 8
      BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp
  29. 5 5
      BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp
  30. 137 117
      BansheeD3D11RenderSystem/Source/BsD3D11Texture.cpp
  31. 9 7
      BansheeD3D11RenderSystem/Source/BsD3D11TextureManager.cpp
  32. 15 12
      BansheeD3D11RenderSystem/Source/BsD3D11TextureView.cpp
  33. 2 2
      BansheeD3D9RenderSystem/Include/BsD3D9PixelBuffer.h
  34. 1 2
      BansheeD3D9RenderSystem/Include/BsD3D9Prerequisites.h
  35. 2 2
      BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h
  36. 16 15
      BansheeD3D9RenderSystem/Include/BsD3D9Texture.h
  37. 7 5
      BansheeD3D9RenderSystem/Include/BsD3D9TextureManager.h
  38. 4 4
      BansheeD3D9RenderSystem/Source/BsD3D9MultiRenderTexture.cpp
  39. 1 1
      BansheeD3D9RenderSystem/Source/BsD3D9PixelBuffer.cpp
  40. 5 5
      BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp
  41. 2 2
      BansheeD3D9RenderSystem/Source/BsD3D9RenderTexture.cpp
  42. 162 141
      BansheeD3D9RenderSystem/Source/BsD3D9Texture.cpp
  43. 9 7
      BansheeD3D9RenderSystem/Source/BsD3D9TextureManager.cpp
  44. 3 4
      BansheeEditor/Source/BsScenePicking.cpp
  45. 1 1
      BansheeEditorExec/BsEditorExec.cpp
  46. 10 10
      BansheeEngine/Source/BsBuiltinResources.cpp
  47. 4 4
      BansheeEngine/Source/BsGUIButtonBase.cpp
  48. 2 2
      BansheeEngine/Source/BsGUIHelper.cpp
  49. 2 2
      BansheeEngine/Source/BsGUIInputBox.cpp
  50. 4 5
      BansheeEngine/Source/BsGUIManager.cpp
  51. 1 1
      BansheeEngine/Source/BsGUIScrollBarHandle.cpp
  52. 4 4
      BansheeEngine/Source/BsGUITexture.cpp
  53. 2 2
      BansheeEngine/Source/BsImageSprite.cpp
  54. 2 2
      BansheeEngine/Source/BsSpriteTexture.cpp
  55. 4 8
      BansheeFontImporter/Source/BsFontImporter.cpp
  56. 2 3
      BansheeFreeImgImporter/Source/BsFreeImgImporter.cpp
  57. 1 1
      BansheeGLRenderSystem/Include/BsGLPrerequisites.h
  58. 2 2
      BansheeGLRenderSystem/Include/BsGLRenderSystem.h
  59. 15 16
      BansheeGLRenderSystem/Include/BsGLTexture.h
  60. 7 5
      BansheeGLRenderSystem/Include/BsGLTextureManager.h
  61. 4 4
      BansheeGLRenderSystem/Source/BsGLMultiRenderTexture.cpp
  62. 6 6
      BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp
  63. 4 4
      BansheeGLRenderSystem/Source/BsGLRenderTexture.cpp
  64. 70 61
      BansheeGLRenderSystem/Source/BsGLTexture.cpp
  65. 10 8
      BansheeGLRenderSystem/Source/BsGLTextureManager.cpp
  66. 7 7
      SBansheeEngine/Source/BsScriptTexture.cpp
  67. 6 6
      SBansheeEngine/Source/BsScriptTexture2D.cpp
  68. 6 6
      SBansheeEngine/Source/BsScriptTexture3D.cpp
  69. 6 7
      SBansheeEngine/Source/BsScriptTextureCube.cpp
  70. 2 3
      TODO.txt

+ 0 - 3
BansheeCore/BansheeCore.vcxproj

@@ -292,9 +292,7 @@
     <ClInclude Include="Include\BsProfilerGPU.h" />
     <ClInclude Include="Include\BsGpuResourceData.h" />
     <ClInclude Include="Include\BsGpuParamBlockBuffer.h" />
-    <ClInclude Include="Include\BsGpuResource.h" />
     <ClInclude Include="Include\BsGpuResourceDataRTTI.h" />
-    <ClInclude Include="Include\BsGpuResourceRTTI.h" />
     <ClInclude Include="Include\BsGpuParam.h" />
     <ClInclude Include="Include\BsInputFwd.h" />
     <ClInclude Include="Include\BsMeshBase.h" />
@@ -455,7 +453,6 @@
     <ClCompile Include="Source\BsGpuProgram.cpp" />
     <ClCompile Include="Source\BsGpuProgramImporter.cpp" />
     <ClCompile Include="Source\BsGpuProgramImportOptions.cpp" />
-    <ClCompile Include="Source\BsGpuResource.cpp" />
     <ClCompile Include="Source\BsGpuResourceData.cpp" />
     <ClCompile Include="Source\BsHardwareBufferManager.cpp" />
     <ClCompile Include="Source\BsGpuParam.cpp" />

+ 0 - 9
BansheeCore/BansheeCore.vcxproj.filters

@@ -183,9 +183,6 @@
     <ClInclude Include="Include\BsGpuResourceDataRTTI.h">
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsGpuResourceRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsImportOptionsRTTI.h">
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
@@ -282,9 +279,6 @@
     <ClInclude Include="Include\BsGpuResourceData.h">
       <Filter>Header Files\Resources</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsGpuResource.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsGpuProgInclude.h">
       <Filter>Header Files\Resources</Filter>
     </ClInclude>
@@ -599,9 +593,6 @@
     <ClCompile Include="Source\BsGpuProgInclude.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsGpuResource.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsGpuResourceData.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>

+ 1 - 3
BansheeCore/Include/BsCorePrerequisites.h

@@ -122,7 +122,6 @@ namespace BansheeEngine
 	class ImportOptions;
 	struct FontData;
 	class GameObject;
-	class GpuResource;
 	class GpuResourceData;
 	struct RenderOperation;
 	class RenderQueue;
@@ -147,6 +146,7 @@ namespace BansheeEngine
 	class DrawList;
 	struct SubMesh;
 	class TransientMeshCore;
+	class TextureCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -230,7 +230,6 @@ namespace BansheeEngine
 	typedef std::shared_ptr<ImportOptions> ImportOptionsPtr;
 	typedef std::shared_ptr<const ImportOptions> ConstImportOptionsPtr;
 	typedef std::shared_ptr<Font> FontPtr;
-	typedef std::shared_ptr<GpuResource> GpuResourcePtr;
 	typedef std::shared_ptr<VertexDataDesc> VertexDataDescPtr;
 	typedef CoreThreadAccessor<CommandQueueNoSync> CoreAccessor;
 	typedef CoreThreadAccessor<CommandQueueSync> SyncedCoreAccessor;
@@ -302,7 +301,6 @@ namespace BansheeEngine
 		TID_FontData = 1057,
 		TID_SceneObject = 1059,
 		TID_GameObject = 1060,
-		TID_GpuResource = 1061,
 		TID_PixelData = 1062,
 		TID_GpuResourceData = 1063,
 		TID_VertexDataDesc = 1064,

+ 0 - 24
BansheeCore/Include/BsCoreThreadAccessor.h

@@ -102,30 +102,6 @@ namespace BansheeEngine
 		/** @copydoc RenderSystem::drawIndexed() */
 		void drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexOffset, UINT32 vertexCount);
 
-		/**
-		 * @copydoc RenderSystem::writeSubresource()
-		 *
-		 * @param discardEntireBuffer When true the existing contents of the resource you are updating will be discarded. This can make the
-		 * 							  operation faster. Resources with certain buffer types might require this flag to be in a specific state
-		 * 							  otherwise the operation will fail. 
-		 *
-		 * @note Resource is updated with data from "data" parameter when the async operation completes. 
-		 * 		 Until the async operation completes "data" is owned by the core thread and you won't
-		 * 		 be able to access it. 
-		 * 		 
-		 *		Normally dynamic buffers will require you to enable "discardEntireBuffer" flag, while static buffers require it disabled.
-		 */
-		AsyncOp writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, bool discardEntireBuffer = false);
-
-		/**
-		 * @copydoc RenderSystem::readSubresource()
-		 *
-		 * @note "data" parameter is populated with subresource data when the async operation completes. 
-		 * 		 Until the async operation completes "data" is owned by the core thread and you won't
-		 * 		 be able to access it.
-		 */
-		AsyncOp readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data);
-
 		/**
 		* @brief	Queues a new generic command that will be added to the command queue.
 		*/

+ 0 - 50
BansheeCore/Include/BsGpuResource.h

@@ -1,50 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsResource.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents a resource that in some way deals directly with the rendering
-	 *			API and the GPU.
-	 *
-	 * @note	e.g. texture, mesh, buffer, etc.
-	 */
-	class BS_CORE_EXPORT GpuResource : public Resource
-	{
-	public:
-		/**
-		 * @brief	Called just before writeSubresource is queued. Called from sim thread.
-		 *
-		 * @note	Sim thread only.
-		 */
-		virtual void _writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer) { }
-
-		/**
-		 * @brief	Updates a part of the current resource with the provided data. Specific resource
-		 * 			implementations provide a way to retrieve a subresource index.
-		 * 			
-		 * @note	Core thread only.
-		 */
-		virtual void writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer) = 0;
-
-		/**
-		 * @brief	Reads a part of the current resource into the provided "data" parameter.
-		 * 			Data buffer needs to be pre-allocated. Specific resource implementations 
-		 * 			provide a way to retrieve a subresource index and a way to allocate
-		 * 			the GpuResourceData buffer.
-		 * 			
-		 * @note	Core thread only.
-		 */
-		virtual void readSubresource(UINT32 subresourceIdx, GpuResourceData& data) = 0;
-
-		/************************************************************************/
-		/* 								SERIALIZATION                      		*/
-		/************************************************************************/
-	public:
-		friend class GpuResourceRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
-	};
-}

+ 0 - 33
BansheeCore/Include/BsGpuResourceRTTI.h

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

+ 1 - 1
BansheeCore/Include/BsMeshBase.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsGpuResource.h"
+#include "BsResource.h"
 #include "BsBounds.h"
 #include "BsDrawOps.h"
 #include "BsSubMesh.h"

+ 1 - 1
BansheeCore/Include/BsMeshBaseRTTI.h

@@ -10,7 +10,7 @@ namespace BansheeEngine
 {
 	BS_ALLOW_MEMCPY_SERIALIZATION(SubMesh);
 
-	class MeshBaseRTTI : public RTTIType<MeshBase, GpuResource, MeshBaseRTTI>
+	class MeshBaseRTTI : public RTTIType<MeshBase, Resource, MeshBaseRTTI>
 	{
 		SubMesh& getSubMesh(MeshBase* obj, UINT32 arrayIdx) { return obj->mProperties.mSubMeshes[arrayIdx]; }
 		void setSubMesh(MeshBase* obj, UINT32 arrayIdx, SubMesh& value) { obj->mProperties.mSubMeshes[arrayIdx] = value; }

+ 2 - 18
BansheeCore/Include/BsRenderSystem.h

@@ -79,7 +79,7 @@ namespace BansheeEngine
 		 *			If the slot matches the one configured in the GPU program the program will be able to access
 		 *			this texture on the GPU.
 		 */
-		virtual void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr) = 0;
+		virtual void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr) = 0;
 
 		/**
 		* @brief	Turns off a texture unit.
@@ -90,7 +90,7 @@ namespace BansheeEngine
 		 * @brief	Binds a texture that can be used for random load/store operations from a GPU program.
 		 */
 		virtual void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, 
-			const TexturePtr& texPtr, const TextureSurface& surface) = 0;
+			const SPtr<TextureCore>& texPtr, const TextureSurface& surface) = 0;
 
 		/**
 		 * @brief	Signals that rendering for a specific viewport has started. Any draw calls
@@ -239,22 +239,6 @@ namespace BansheeEngine
 		 */
         virtual void setRenderTarget(const SPtr<RenderTargetCore>& target) = 0;
 
-		/**
-		 * @brief	Updates the resource with the specified data.
-		 *
-		 * @note	It is assumed GpuResourceData has been locked before being passed here. Data will be unlocked
-		 *			when this method finishes.
-		 */
-		void writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, bool discardEntireBuffer, AsyncOp& asyncOp);
-
-		/**
-		 * @brief	Reads data from a resource into a pre-allocated GpuResourceData instance.
-		 *
-		 * @note	It is assumed GpuResourceData has been locked before being passed here. Data will be unlocked
-		 *			when this method finishes.
-		 */
-		void readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceDataPtr& data, AsyncOp& asyncOp);
-
 		/**
 		 * @brief	Returns information about available output devices and their video modes.
 		 *

+ 220 - 167
BansheeCore/Include/BsTexture.h

@@ -1,7 +1,7 @@
 #pragma once
 
 #include "BsCorePrerequisites.h"
-#include "BsGpuResource.h"
+#include "BsResource.h"
 #include "BsHardwareBuffer.h"
 #include "BsPixelUtil.h"
 #include "BsTextureView.h"
@@ -42,119 +42,72 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Abstract class representing a texture. Specific render systems have their
-	 *			own Texture implementations. Internally represented as one or more surfaces
-	 *			with pixels in a certain number of dimensions, backed by a hardware buffer.
-	 *
-	 * @note	Core thread unless specified otherwise.
+	 * @brief	Contains various information about a texture
 	 */
-    class BS_CORE_EXPORT Texture : public GpuResource
-    {
-    public:
-        /**
+	class BS_CORE_EXPORT TextureProperties
+	{
+	public:
+		TextureProperties();
+		TextureProperties(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
+
+		/**
          * @brief	Gets the type of texture.
-         * 			
-		 * @note	Thread safe.
          */
-        virtual TextureType getTextureType() const { return mTextureType; }
+        TextureType getTextureType() const { return mTextureType; }
 
         /**
 		 * @brief	Gets the number of mipmaps to be used for this texture. This number excludes the top level  
 		 *			map (which is always assumed to be present).
-         *
-         * @note	Thread safe.
          */
-        virtual UINT32 getNumMipmaps() const {return mNumMipmaps;}
+        UINT32 getNumMipmaps() const {return mNumMipmaps;}
 
 		/**
 		 * @brief	Gets whether this texture will be set up so that on sampling it,
 		 *			hardware gamma correction is applied.
-		 *
-		 * @note	Thread safe.
 		 */
-		virtual bool isHardwareGammaEnabled() const { return mHwGamma; }
+		bool isHardwareGammaEnabled() const { return mHwGamma; }
 
 		/**
 		 * @brief	Gets the number of samples used for multisampling.
 		 *			(0 if multisampling is not used).
-		 *
-		 * @note	Thread safe.
 		 */
-		virtual UINT32 getMultisampleCount() const { return mMultisampleCount; }
+		UINT32 getMultisampleCount() const { return mMultisampleCount; }
 
         /**
          * @brief	Returns the height of the texture.
-         *
-         * @note	Thread safe.
          */
-        virtual UINT32 getHeight() const { return mHeight; }
+        UINT32 getHeight() const { return mHeight; }
 
         /**
          * @brief	Returns the width of the texture.
-         *
-         * @note	Thread safe.
          */
-        virtual UINT32 getWidth() const { return mWidth; }
+        UINT32 getWidth() const { return mWidth; }
 
         /**
          * @brief	Returns the depth of the texture (only applicable for 3D textures).
-         *
-         * @note	Thread safe.
          */
-        virtual UINT32 getDepth() const { return mDepth; }
+        UINT32 getDepth() const { return mDepth; }
 
         /**
          * @brief	Returns texture usage (TextureUsage) of this texture.
-         *
-         * @note	Thread safe.
          */
-        virtual int getUsage() const { return mUsage; }
+        int getUsage() const { return mUsage; }
 
 		/**
 		 * @brief	Returns the pixel format for the texture surface.
-		 *
-		 * @note	Thread safe.
 		 */
-		virtual PixelFormat getFormat() const { return mFormat; }
+		PixelFormat getFormat() const { return mFormat; }
 
         /**
          * @brief	Returns true if the texture has an alpha layer.
-         *
-         * @note	Thread safe.
          */
-        virtual bool hasAlpha() const;
+        bool hasAlpha() const;
 
         /**
          * @brief	Return the number of faces this texture has.
-         *
-         * @note	Thread safe.
          */
-        virtual UINT32 getNumFaces() const;
-
-		/**
-		 * @copydoc GpuResource::_writeSubresourceSim
-		 */
-		virtual void _writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
-
-		/**
-		 * @copydoc GpuResource::writeSubresource
-		 */
-		virtual void writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer);
-
-		/**
-		 * @copydoc GpuResource::readSubresource
-		 */
-		virtual void readSubresource(UINT32 subresourceIdx, GpuResourceData& data);
-
-		/**
-		 * @brief	Allocates a buffer you may use for storage when reading or writing a sub-resource. You
-		 * 			need to allocate such a buffer if you are calling "readSubresource".
-		 *
-		 *			You can retrieve a sub-resource index by calling "mapToSubresourceIdx".
-		 * 			
-		 * @note	Thread safe.
-		 */
-		PixelDataPtr allocateSubresourceBuffer(UINT32 subresourceIdx) const;
+        UINT32 getNumFaces() const;
 
 		/**
 		 * @brief	Maps a sub-resource index to an exact face and mip level. Sub-resource indexes
@@ -163,8 +116,6 @@ namespace BansheeEngine
 		 * @note	Sub-resource index is only valid for the instance it was created on. You cannot use a sub-resource
 		 * 			index from a different texture and expect to get valid result. Modifying the resource so the number
 		 * 			of sub-resources changes invalidates all sub-resource indexes.
-		 * 			
-		 *			Thread safe.
 		 */
 		void mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const;
 
@@ -174,11 +125,60 @@ namespace BansheeEngine
 		 * 			
 		 * @note	Generated sub-resource index is only valid for the instance it was created on. Modifying the resource so the number
 		 * 			of sub-resources changes, invalidates all sub-resource indexes.
-		 * 			
-		 *			Thread safe.
 		 */
 		UINT32 mapToSubresourceIdx(UINT32 face, UINT32 mip) const;
 
+	protected:
+		friend class TextureRTTI;
+
+		UINT32 mHeight;
+		UINT32 mWidth;
+		UINT32 mDepth;
+
+		UINT32 mNumMipmaps;
+		bool mHwGamma;
+		UINT32 mMultisampleCount;
+
+		TextureType mTextureType;
+		PixelFormat mFormat;
+		int mUsage;
+	};
+
+	/**
+	 * @brief	Core thread version of a Texture.
+	 *
+	 * @see		Texture
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT TextureCore : public CoreObjectCore
+	{
+	public:
+		TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
+		virtual ~TextureCore() {}
+
+		/**
+		 * @brief	Updates a part of the texture with the provided data.
+		 *
+		 * @param	subresourceIdx		Index of the subresource to update, if the texture has more than one.
+		 * @param	data				Data to update the texture with.
+		 * @param	discardEntireBuffer When true the existing contents of the resource you are updating will be discarded. This can make the
+		 * 								operation faster. Resources with certain buffer types might require this flag to be in a specific state
+		 * 								otherwise the operation will fail.
+		 */
+		virtual void writeSubresource(UINT32 subresourceIdx, const PixelData& data, bool discardEntireBuffer);
+
+		/**
+		 * @brief	Reads a part of the current resource into the provided "data" parameter.
+		 * 			Data buffer needs to be pre-allocated.
+		 *
+		 * @param	subresourceIdx		Index of the subresource to update, if the texture has more than one.
+		 * @param	data				Buffer that will receive the data. Should be allocated with "allocateSubresourceBuffer"
+		 *								to ensure it is of valid type and size.
+		 */
+		virtual void readSubresource(UINT32 subresourceIdx, PixelData& data);
+
 		/**
 		 * @brief	Locks the buffer for reading or writing.
 		 *
@@ -190,16 +190,12 @@ namespace BansheeEngine
 		 * 			
 		 * @note	If you are just reading or writing one block of data use
 		 * 			readData/writeData methods as they can be much faster in certain situations.
-		 * 			
-		 *			Core thread only.
 		 */
 		PixelData lock(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 
 		/**
 		 * @brief	Unlocks a previously locked buffer. After the buffer is unlocked,
 		 * 			any data returned by lock becomes invalid.
-		 * 			
-		 * @note	Core thread only.
 		 */
 		void unlock();
 
@@ -213,28 +209,8 @@ namespace BansheeEngine
 		 * @param	srcSubresourceIdx	Index of the subresource to copy from.
 		 * @param	destSubresourceIdx	Index of the subresource to copy to.
 		 * @param	target				Texture that contains the destination subresource.
-		 * 			
-		 * @note	Core thread only.
 		 */
-		void copy(UINT32 srcSubresourceIdx, UINT32 destSubresourceIdx, TexturePtr& target);
-
-		/**
-		 * @brief	Reads data from the cached system memory texture buffer into the provided buffer. 
-		 * 		  
-		 * @param	dest		Previously allocated buffer to read data into.
-		 * @param	mipLevel	(optional) Mipmap level to read from.
-		 * @param	face		(optional) Texture face to read from.
-		 *
-		 * @note	Sim thread only.
-		 *
-		 *			The data read is the cached texture data. Any data written to the texture from the GPU 
-		 *			or core thread will not be reflected in this data. Use "readData" if you require
-		 *			those changes.
-		 *
-		 *			The texture must have been created with TU_CPUCACHED usage otherwise this method
-		 *			will not return any data.
-		 */
-		virtual void readDataSim(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
+		void copy(UINT32 srcSubresourceIdx, UINT32 destSubresourceIdx, const SPtr<TextureCore>& target);
 
 		/**
 		 * @brief	Reads data from the texture buffer into the provided buffer.
@@ -242,8 +218,6 @@ namespace BansheeEngine
 		 * @param	dest	Previously allocated buffer to read data into.
 		 * @param	mipLevel	(optional) Mipmap level to read from.
 		 * @param	face		(optional) Texture face to read from.
-		 *
-		 * @note	Core thread only.
 		 */
 		virtual void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0) = 0;
 
@@ -255,18 +229,9 @@ namespace BansheeEngine
 		 * @param	face		(optional) Texture face to write into.
 		 * @param	discardWholeBuffer (optional) If true any existing texture data will be discard. This can
 		 *							    improve performance of the write operation.
-		 *
-		 * @note	Core thread only.
 		 */
 		virtual void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false) = 0;
 
-		/**
-		 * @brief	Returns a dummy 2x2 texture. Don't modify the returned texture.
-		 * 			
-		 * @note	Thread safe.
-		 */
-		static const HTexture& dummy();
-
 		/**
 		 * @brief	Returns true if the texture can be bound to a shader.
 		 *
@@ -275,6 +240,11 @@ namespace BansheeEngine
 		 */
 		virtual bool isBindableAsShaderResource() const { return true; }
 
+		/**
+		 * @brief	Returns properties that contain information about the texture.
+		 */
+		const TextureProperties& getProperties() const { return mProperties; }
+
 		/************************************************************************/
 		/* 								TEXTURE VIEW                      		*/
 		/************************************************************************/
@@ -286,14 +256,141 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		static TextureViewPtr requestView(TexturePtr texture, UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage);
+		static TextureViewPtr requestView(const SPtr<TextureCore>& texture, UINT32 mostDetailMip, UINT32 numMips, 
+			UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage);
 
 		/**
 		 * @brief	Releases the view. View won't actually get destroyed until all references to it are released.
 		 *
 		 * @note	Core thread only.
 		 */
-		static void releaseView(TextureViewPtr view);
+		static void releaseView(const TextureViewPtr& view);
+
+	protected:
+		/**
+		 * @copydoc	lock
+		 */
+		virtual PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0) = 0;
+
+		/**
+		 * @copydoc	unlock
+		 */
+		virtual void unlockImpl() = 0;
+
+		/**
+		 * @copydoc	copy
+		 */
+		virtual void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target) = 0;
+
+		/************************************************************************/
+		/* 								TEXTURE VIEW                      		*/
+		/************************************************************************/
+
+		/**
+		 * @brief	Creates a new empty/undefined texture view.
+		 */
+		virtual TextureViewPtr createView();
+
+		/**
+		 * @brief	Releases all internal texture view references. Views won't get destroyed if there are external references still held.
+		 */
+		void clearBufferViews();
+
+		/**
+		 * @brief	Holds a single texture view with a usage reference count.
+		 */
+		struct TextureViewReference
+		{
+			TextureViewReference(TextureViewPtr _view)
+				:view(_view), refCount(0)
+			{ }
+
+			TextureViewPtr view;
+			UINT32 refCount;
+		};
+
+		UnorderedMap<TEXTURE_VIEW_DESC, TextureViewReference*, TextureView::HashFunction, TextureView::EqualFunction> mTextureViews;
+		TextureProperties mProperties;
+	};
+
+	/**
+	 * @brief	Abstract class representing a texture. Specific render systems have their
+	 *			own Texture implementations. Internally represented as one or more surfaces
+	 *			with pixels in a certain number of dimensions, backed by a hardware buffer.
+	 *
+	 * @note	Sim thread.
+	 */
+    class BS_CORE_EXPORT Texture : public Resource
+    {
+    public:
+		/**
+		 * @brief	Updates the texture with new data. The actual write will be queued for later execution on the core thread.
+		 *			Provided data buffer will be locked until the operation completes.
+		 *
+		 * @param	accessor			Accessor to queue the operation on.
+		 * 
+		 * @return	Async operation object you can use to track operation completion.
+		 *
+		 * @see		TextureCore::writeSubresource
+		 */
+		AsyncOp writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const PixelDataPtr& data, bool discardEntireBuffer);
+
+		/**
+		 * @brief	Reads internal texture data to the provided previously allocated buffer. The read is queued for execution
+		 *			on the core thread and not executed immediately. Provided data buffer will be locked until the
+		 *			operation completes.
+		 *
+		 * @param	accessor			Accessor to queue the operation on.
+		 *
+		 * @return	Async operation object you can use to track operation completion.
+		 *
+		 * @see		TextureCore::readSubresource
+		 */
+		AsyncOp readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const PixelDataPtr& data);
+
+		/**
+		 * @brief	Allocates a buffer you may use for storage when reading or writing a sub-resource. You
+		 * 			need to allocate such a buffer if you are calling "readSubresource".
+		 *
+		 *			You can retrieve a sub-resource index by calling "mapToSubresourceIdx".
+		 * 			
+		 * @note	Thread safe.
+		 */
+		PixelDataPtr allocateSubresourceBuffer(UINT32 subresourceIdx) const;
+
+		/**
+		 * @brief	Reads data from the cached system memory texture buffer into the provided buffer. 
+		 * 		  
+		 * @param	dest		Previously allocated buffer to read data into.
+		 * @param	mipLevel	(optional) Mipmap level to read from.
+		 * @param	face		(optional) Texture face to read from.
+		 *
+		 * @note	The data read is the cached texture data. Any data written to the texture from the GPU 
+		 *			or core thread will not be reflected in this data. Use "readSubresource" if you require
+		 *			those changes.
+		 *
+		 *			The texture must have been created with TU_CPUCACHED usage otherwise this method
+		 *			will not return any data.
+		 */
+		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @brief	Returns properties that contain information about the texture.
+		 */
+		const TextureProperties& getProperties() const { return mProperties; }
+
+		/**
+		 * @brief	Retrieves a core implementation of a texture usable only from the
+		 *			core thread.
+		 */
+		SPtr<TextureCore> getCore() const;
+
+		/**
+		 * @brief	Returns a dummy 2x2 texture. Don't modify the returned texture.
+		 * 			
+		 * @note	Thread safe.
+		 */
+		static const HTexture& dummy();
 
 		/************************************************************************/
 		/* 								STATICS		                     		*/
@@ -352,61 +449,21 @@ namespace BansheeEngine
 		static TexturePtr _createPtr(TextureType texType, UINT32 width, UINT32 height, int num_mips,
 			PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
 
-	protected:
-		/************************************************************************/
-		/* 								TEXTURE VIEW                      		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Creates a new empty/undefined texture view.
-		 */
-		virtual TextureViewPtr createView();
-
-		/**
-		 * @brief	Releases all internal texture view references. Views won't get destroyed if there are external references still held.
-		 */
-		void clearBufferViews();
-
-		/**
-		 * @brief	Holds a single texture view with a usage reference count.
-		 */
-		struct TextureViewReference
-		{
-			TextureViewReference(TextureViewPtr _view)
-				:view(_view), refCount(0)
-			{ }
-
-			TextureViewPtr view;
-			UINT32 refCount;
-		};
-
-		UnorderedMap<TEXTURE_VIEW_DESC, TextureViewReference*, TextureView::HashFunction, TextureView::EqualFunction> mTextureViews;
-
     protected:
 		friend class TextureManager;
 
-		Texture();
-
-		/**
-		 * @copydoc	GpuResource::initialize
-		 */
-		void initialize(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps, 
+		Texture(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
 			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
 
 		/**
-		 * @copydoc	lock
-		 */
-		virtual PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0) = 0;
-
-		/**
-		 * @copydoc	unlock
+		 * @copydoc	Resource::initialize
 		 */
-		virtual void unlockImpl() = 0;
+		void initialize();
 
 		/**
-		 * @copydoc	copy
+		 * @copydoc	CoreObject::createCore
 		 */
-		virtual void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target) = 0;
+		SPtr<CoreObjectCore> createCore() const;
 
 		/**
 		 * @copydoc	Resource::calculateSize
@@ -420,25 +477,21 @@ namespace BansheeEngine
 		 */
 		void createCPUBuffers();
 
-	protected:
-		UINT32 mHeight; // Immutable
-		UINT32 mWidth; // Immutable
-		UINT32 mDepth; // Immutable
-
-		UINT32 mNumMipmaps; // Immutable
-		bool mHwGamma; // Immutable
-		UINT32 mMultisampleCount; // Immutable
-
-		TextureType mTextureType; // Immutable
-		PixelFormat mFormat; // Immutable
-		int mUsage; // Immutable
+		/**
+		 * @brief	Updates the cached CPU buffers with new data.
+		 */
+		void updateCPUBuffers(UINT32 subresourceIdx, const PixelData& data);
 
+	protected:
 		Vector<PixelDataPtr> mCPUSubresourceData;
+		TextureProperties mProperties;
 
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/
 	public:
+		Texture(); // Serialization only
+
 		friend class TextureRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;

+ 18 - 21
BansheeCore/Include/BsTextureManager.h

@@ -20,14 +20,14 @@ namespace BansheeEngine
 		virtual ~TextureManager() { }
 
 		/**
-		 * @copydoc	Texture::create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, const String&)
+		 * @copydoc	Texture::create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32)
 		 */
         TexturePtr createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, 
 			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, 
 			UINT32 multisampleCount = 0);
 			
 		/**
-		 * @copydoc	Texture::create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, const String&)
+		 * @copydoc	Texture::create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32)
 		 */
 		TexturePtr createTexture(TextureType texType, UINT32 width, UINT32 height, int numMips,
 			PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, UINT32 multisampleCount = 0)
@@ -84,12 +84,6 @@ namespace BansheeEngine
 		virtual PixelFormat getNativeFormat(TextureType ttype, PixelFormat format, int usage, bool hwGamma) = 0;
 
 	protected:
-		/**
-		 * @brief	Creates an empty and uninitialized texture of a specific type. This is to be implemented
-		 *			by render systems with their own implementations.
-		 */
-		virtual TexturePtr createTextureImpl() = 0;
-
 		/**
 		 * @brief	Creates an empty and uninitialized render texture of a specific type. This 
 		 *			is to be implemented by render systems with their own implementations.
@@ -114,6 +108,13 @@ namespace BansheeEngine
     public:
 		virtual ~TextureCoreManager() { }
 
+		/**
+		 * @copydoc	TextureManager::createTexture(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32)
+		 */
+		SPtr<TextureCore> createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, 
+			UINT32 multisampleCount = 0);
+
 		/**
 		 * @copydoc	TextureManager::createRenderTexture(const RENDER_TEXTURE_DESC&)
 		 */
@@ -124,15 +125,19 @@ namespace BansheeEngine
 		 */
 		SPtr<MultiRenderTextureCore> createMultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc);
 
-		/**
-		 * @brief	Returns tiny dummy texture for use when no other is available.
-		 */
-		const HTexture& getDummyTexture() const { return mDummyTexture; }
-
 	protected:
+		friend class Texture;
 		friend class RenderTexture;
 		friend class MultiRenderTexture;
 
+		/**
+		 * @brief	Creates an empty and uninitialized texture of a specific type. This is to be implemented
+		 *			by render systems with their own implementations.
+		 */
+		virtual SPtr<TextureCore> createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false,
+			UINT32 multisampleCount = 0) = 0;
+
 		/**
 		 * @copydoc	TextureManager::createRenderTextureImpl
 		 */
@@ -142,13 +147,5 @@ namespace BansheeEngine
 		 * @copydoc	TextureManager::createMultiRenderTextureImpl
 		 */
 		virtual SPtr<MultiRenderTextureCore> createMultiRenderTextureInternal(const MULTI_RENDER_TEXTURE_DESC& desc) = 0;
-
-		/**
-		 * @copydoc	Module::onStartUp
-		 */
-		virtual void onStartUp();
-
-	protected:
-		HTexture mDummyTexture;
     };
 }

+ 52 - 45
BansheeCore/Include/BsTextureRTTI.h

@@ -16,25 +16,42 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TextureRTTI : public RTTIType<Texture, Resource, TextureRTTI>
 	{
 	private:
-		BS_SETGET_MEMBER(mSize, UINT32, Texture)
-		BS_SETGET_MEMBER(mHeight, UINT32, Texture)
-		BS_SETGET_MEMBER(mWidth, UINT32, Texture)
-		BS_SETGET_MEMBER(mDepth, UINT32, Texture)
-		BS_SETGET_MEMBER(mNumMipmaps, UINT32, Texture)
-		BS_SETGET_MEMBER(mHwGamma, bool, Texture)
-		BS_SETGET_MEMBER(mMultisampleCount, UINT32, Texture)
-		BS_SETGET_MEMBER(mTextureType, TextureType, Texture)
-		BS_SETGET_MEMBER(mFormat, PixelFormat, Texture)
-
-		INT32& getUsage(Texture* obj) { return obj->mUsage; }
+		UINT32& getSize(Texture* obj) { return obj->mSize; }
+		void setSize(Texture* obj, UINT32& val) { obj->mSize = val; }
+
+		UINT32& getWidth(Texture* obj) { return obj->mProperties.mWidth; }
+		void setWidth(Texture* obj, UINT32& val) { obj->mProperties.mWidth = val; }
+
+		UINT32& getHeight(Texture* obj) { return obj->mProperties.mHeight; }
+		void setHeight(Texture* obj, UINT32& val) { obj->mProperties.mHeight = val; }
+
+		UINT32& getDepth(Texture* obj) { return obj->mProperties.mDepth; }
+		void setDepth(Texture* obj, UINT32& val) { obj->mProperties.mDepth = val; }
+
+		UINT32& getNumMipmaps(Texture* obj) { return obj->mProperties.mNumMipmaps; }
+		void setNumMipmaps(Texture* obj, UINT32& val) { obj->mProperties.mNumMipmaps = val; }
+
+		bool& getHwGamma(Texture* obj) { return obj->mProperties.mHwGamma; }
+		void setHwGamma(Texture* obj, bool& val) { obj->mProperties.mHwGamma = val; }
+
+		UINT32& getMultisampleCount(Texture* obj) { return obj->mProperties.mMultisampleCount; }
+		void setMultisampleCount(Texture* obj, UINT32& val) { obj->mProperties.mMultisampleCount = val; }
+
+		TextureType& getTextureType(Texture* obj) { return obj->mProperties.mTextureType; }
+		void setTextureType(Texture* obj, TextureType& val) { obj->mProperties.mTextureType = val; }
+
+		PixelFormat& getFormat(Texture* obj) { return obj->mProperties.mFormat; }
+		void setFormat(Texture* obj, PixelFormat& val) { obj->mProperties.mFormat = val; }
+
+		INT32& getUsage(Texture* obj) { return obj->mProperties.mUsage; }
 		void setUsage(Texture* obj, INT32& val) 
 		{ 
 			// Render target and depth stencil texture formats are for in-memory use only
 			// and don't make sense when serialized
 			if (val == TU_DEPTHSTENCIL || val == TU_RENDERTARGET)
-				obj->mUsage = TU_STATIC;
+				obj->mProperties.mUsage = TU_STATIC;
 			else
-				obj->mUsage = val; 
+				obj->mProperties.mUsage = val;
 		}
 
 #define BS_ADD_PLAINFIELD(name, id, parentType) \
@@ -42,19 +59,14 @@ namespace BansheeEngine
 
 		PixelDataPtr getPixelData(Texture* obj, UINT32 idx)
 		{
-			UINT32 face = (size_t)Math::floor(idx / (float)(obj->getNumMipmaps() + 1));
-			UINT32 mipmap = idx % (obj->getNumMipmaps() + 1);
+			UINT32 face = (size_t)Math::floor(idx / (float)(obj->mProperties.getNumMipmaps() + 1));
+			UINT32 mipmap = idx % (obj->mProperties.getNumMipmaps() + 1);
 
-			UINT32 subresourceIdx = obj->mapToSubresourceIdx(face, mipmap);
+			UINT32 subresourceIdx = obj->mProperties.mapToSubresourceIdx(face, mipmap);
 			PixelDataPtr pixelData = obj->allocateSubresourceBuffer(subresourceIdx);
 
-			GpuResourcePtr sharedTexPtr = std::static_pointer_cast<GpuResource>(obj->getThisPtr());
-
-			// We want the data right away so queue directly to main core thread queue and block until we get it
-			pixelData->_lock();
-			gCoreThread().queueReturnCommand(
-				std::bind(&RenderSystem::readSubresource, RenderSystem::instancePtr(), sharedTexPtr, subresourceIdx, 
-				std::static_pointer_cast<GpuResourceData>(pixelData), std::placeholders::_1), true);
+			obj->readSubresource(gCoreAccessor(), subresourceIdx, pixelData);
+			gCoreAccessor().submitToCoreThread(true);
 
 			return pixelData;
 		}
@@ -68,7 +80,7 @@ namespace BansheeEngine
 
 		UINT32 getPixelDataArraySize(Texture* obj)
 		{
-			return obj->getNumFaces() * (obj->getNumMipmaps() + 1);
+			return obj->mProperties.getNumFaces() * (obj->mProperties.getNumMipmaps() + 1);
 		}
 
 		void setPixelDataArraySize(Texture* obj, UINT32 size)
@@ -81,16 +93,15 @@ namespace BansheeEngine
 	public:
 		TextureRTTI()
 		{
-			BS_ADD_PLAINFIELD(mSize, 0, TextureRTTI)
-			BS_ADD_PLAINFIELD(mHeight, 2, TextureRTTI)
-			BS_ADD_PLAINFIELD(mWidth, 3, TextureRTTI)
-			BS_ADD_PLAINFIELD(mDepth, 4, TextureRTTI)
-			BS_ADD_PLAINFIELD(mNumMipmaps, 5, TextureRTTI)
-			BS_ADD_PLAINFIELD(mHwGamma, 6, TextureRTTI)
-			BS_ADD_PLAINFIELD(mMultisampleCount, 7, TextureRTTI)
-			BS_ADD_PLAINFIELD(mTextureType, 9, TextureRTTI)
-			BS_ADD_PLAINFIELD(mFormat, 10, TextureRTTI)
-
+			addPlainField("mSize", 0, &TextureRTTI::getSize, &TextureRTTI::setSize);
+			addPlainField("mHeight", 2, &TextureRTTI::getHeight, &TextureRTTI::setHeight);
+			addPlainField("mWidth", 3, &TextureRTTI::getWidth, &TextureRTTI::setWidth);
+			addPlainField("mDepth", 4, &TextureRTTI::getDepth, &TextureRTTI::setDepth);
+			addPlainField("mNumMipmaps", 5, &TextureRTTI::getNumMipmaps, &TextureRTTI::setNumMipmaps);
+			addPlainField("mHwGamma", 6, &TextureRTTI::getHwGamma, &TextureRTTI::setHwGamma);
+			addPlainField("mMultisampleCount", 7, &TextureRTTI::getMultisampleCount, &TextureRTTI::setMultisampleCount);
+			addPlainField("mTextureType", 9, &TextureRTTI::getTextureType, &TextureRTTI::setTextureType);
+			addPlainField("mFormat", 10, &TextureRTTI::getFormat, &TextureRTTI::setFormat);
 			addPlainField("mUsage", 11, &TextureRTTI::getUsage, &TextureRTTI::setUsage);
 
 			addReflectablePtrArrayField("mPixelData", 12, &TextureRTTI::getPixelData, &TextureRTTI::getPixelDataArraySize, 
@@ -111,25 +122,21 @@ namespace BansheeEngine
 			if(texture->mRTTIData.empty())
 				return;
 
+			const TextureProperties texProps = texture->getProperties();
+
 			// 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->getMultisampleCount());
+			texture->initialize();
 
 			Vector<PixelDataPtr>* pixelData = any_cast<Vector<PixelDataPtr>*>(texture->mRTTIData);
 			for(size_t i = 0; i < pixelData->size(); i++)
 			{
-				UINT32 face = (size_t)Math::floor(i / (float)(texture->getNumMipmaps() + 1));
-				UINT32 mipmap = i % (texture->getNumMipmaps() + 1);
-
-				UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipmap);
+				UINT32 face = (size_t)Math::floor(i / (float)(texProps.getNumMipmaps() + 1));
+				UINT32 mipmap = i % (texProps.getNumMipmaps() + 1);
 
-				GpuResourcePtr sharedTexPtr = std::static_pointer_cast<GpuResource>(texture->getThisPtr());
+				UINT32 subresourceIdx = texProps.mapToSubresourceIdx(face, mipmap);
 
-				pixelData->at(i)->_lock();
-				gCoreThread().queueReturnCommand(std::bind(&RenderSystem::writeSubresource, RenderSystem::instancePtr(), 
-					sharedTexPtr, subresourceIdx, pixelData->at(i), false, std::placeholders::_1));
+				texture->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData->at(i), false);
 			}
 
 			bs_delete<PoolAlloc>(pixelData);

+ 4 - 4
BansheeCore/Include/BsTextureView.h

@@ -104,19 +104,19 @@ namespace BansheeEngine
 		/**
 		 * @brief	Gets the owner texture the view is referencing.
 		 */
-		TexturePtr getTexture() const { return mOwnerTexture; }
+		SPtr<TextureCore> getTexture() const { return mOwnerTexture; }
 
 	protected:
 		/**
 		 * @brief	Initializes the texture view. This must be called right after construction.
 		 */
-		virtual void initialize(TexturePtr texture, TEXTURE_VIEW_DESC& _desc);
+		virtual void initialize(const SPtr<TextureCore>& texture, TEXTURE_VIEW_DESC& _desc);
 
 	protected:
-		friend class Texture;
+		friend class TextureCore;
 
 		TEXTURE_VIEW_DESC mDesc;
-		TexturePtr mOwnerTexture;
+		SPtr<TextureCore> mOwnerTexture;
 
 		TextureView();
 	};

+ 2 - 19
BansheeCore/Source/BsCoreThreadAccessor.cpp

@@ -33,13 +33,13 @@ namespace BansheeEngine
 
 	void CoreThreadAccessorBase::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
 	{
-		mCommandQueue->queue(std::bind(&RenderSystem::setTexture, RenderSystem::instancePtr(), gptype, unit, enabled, texPtr));
+		mCommandQueue->queue(std::bind(&RenderSystem::setTexture, RenderSystem::instancePtr(), gptype, unit, enabled, texPtr->getCore()));
 	}
 
 	void CoreThreadAccessorBase::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
 		const TextureSurface& surface)
 	{
-		mCommandQueue->queue(std::bind(&RenderSystem::setLoadStoreTexture, RenderSystem::instancePtr(), gptype, unit, enabled, texPtr, 
+		mCommandQueue->queue(std::bind(&RenderSystem::setLoadStoreTexture, RenderSystem::instancePtr(), gptype, unit, enabled, texPtr->getCore(), 
 			surface));
 	}
 
@@ -173,23 +173,6 @@ namespace BansheeEngine
 		mCommandQueue->queue(std::bind(&RenderSystem::drawIndexed, RenderSystem::instancePtr(), startIndex, indexCount, vertexOffset, vertexCount));
 	}
 
-	AsyncOp CoreThreadAccessorBase::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, bool discardEntireBuffer)
-	{
-		data->_lock();
-
-		resource->_writeSubresourceSim(subresourceIdx, *data, discardEntireBuffer);
-		return mCommandQueue->queueReturn(std::bind(&RenderSystem::writeSubresource, RenderSystem::instancePtr(), resource, 
-			subresourceIdx, data, discardEntireBuffer, std::placeholders::_1));
-	}
-
-	AsyncOp CoreThreadAccessorBase::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data)
-	{
-		data->_lock();
-
-		return mCommandQueue->queueReturn(std::bind(&RenderSystem::readSubresource, RenderSystem::instancePtr(), 
-			resource, subresourceIdx, data, std::placeholders::_1));
-	}
-
 	AsyncOp CoreThreadAccessorBase::queueReturnCommand(std::function<void(AsyncOp&)> commandCallback)
 	{
 		return mCommandQueue->queueReturn(commandCallback);

+ 0 - 15
BansheeCore/Source/BsGpuResource.cpp

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

+ 0 - 2
BansheeCore/Source/BsMesh.cpp

@@ -345,8 +345,6 @@ namespace BansheeEngine
 
 	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data)
 	{
-		updateBounds(*data);
-
 		data->_lock();
 
 		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, AsyncOp&)> func =

+ 51 - 43
BansheeCore/Source/BsMultiRenderTexture.cpp

@@ -16,12 +16,14 @@ namespace BansheeEngine
 
 			if (texture != nullptr)
 			{
-				mWidth = texture->getWidth();
-				mHeight = texture->getWidth();
-				mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texture->getFormat());
+				const TextureProperties& texProps = texture->getProperties();
+
+				mWidth = texProps.getWidth();
+				mHeight = texProps.getWidth();
+				mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texProps.getFormat());
 				mActive = true;
-				mHwGamma = texture->isHardwareGammaEnabled();
-				mMultisampleCount = texture->getMultisampleCount();
+				mHwGamma = texProps.isHardwareGammaEnabled();
+				mMultisampleCount = texProps.getMultisampleCount();
 				mIsWindow = false;
 				mRequiresTextureFlipping = requiresTextureFlipping();
 
@@ -55,24 +57,24 @@ namespace BansheeEngine
 					continue;
 				}
 
-				TexturePtr texture = mDesc.colorSurfaces[i].texture;
+				SPtr<TextureCore> texture = mDesc.colorSurfaces[i].texture->getCore();
 
-				if (texture->getUsage() != TU_RENDERTARGET)
+				if (texture->getProperties().getUsage() != TU_RENDERTARGET)
 					BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
-				mColorSurfaces[i] = Texture::requestView(texture, mDesc.colorSurfaces[i].mipLevel, 1,
+				mColorSurfaces[i] = TextureCore::requestView(texture, mDesc.colorSurfaces[i].mipLevel, 1,
 					mDesc.colorSurfaces[i].face, 1, GVU_RENDERTARGET);
 			}
 		}
 
 		if (mDesc.depthStencilSurface.texture != nullptr)
 		{
-			TexturePtr texture = mDesc.depthStencilSurface.texture;
+			SPtr<TextureCore> texture = mDesc.depthStencilSurface.texture->getCore();
 
-			if (texture->getUsage() != TU_DEPTHSTENCIL)
+			if (texture->getProperties().getUsage() != TU_DEPTHSTENCIL)
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
-			mDepthStencilSurface = Texture::requestView(texture, mDesc.depthStencilSurface.mipLevel, 1,
+			mDepthStencilSurface = TextureCore::requestView(texture, mDesc.depthStencilSurface.mipLevel, 1,
 				mDesc.depthStencilSurface.face, 1, GVU_DEPTHSTENCIL);
 		}
 
@@ -84,11 +86,11 @@ namespace BansheeEngine
 		for (auto iter = mColorSurfaces.begin(); iter != mColorSurfaces.end(); ++iter)
 		{
 			if (*iter != nullptr)
-				Texture::releaseView(*iter);
+				TextureCore::releaseView(*iter);
 		}
 
 		if (mDepthStencilSurface != nullptr)
-			Texture::releaseView(mDepthStencilSurface);
+			TextureCore::releaseView(mDepthStencilSurface);
 
 		RenderTargetCore::destroy();
 	}
@@ -129,48 +131,54 @@ namespace BansheeEngine
 				continue;
 			}
 
-			if(mColorSurfaces[i]->getTexture()->getWidth() != firstSurfaceDesc->getTexture()->getWidth() ||
-				mColorSurfaces[i]->getTexture()->getHeight() != firstSurfaceDesc->getTexture()->getHeight() ||
-				mColorSurfaces[i]->getTexture()->getMultisampleCount() != firstSurfaceDesc->getTexture()->getMultisampleCount())
+			const TextureProperties& curTexProps = mColorSurfaces[i]->getTexture()->getProperties();
+			const TextureProperties& firstTexProps = firstSurfaceDesc->getTexture()->getProperties();
+
+			if (curTexProps.getWidth() != firstTexProps.getWidth() ||
+				curTexProps.getHeight() != firstTexProps.getHeight() ||
+				curTexProps.getMultisampleCount() != firstTexProps.getMultisampleCount())
 			{
-				String errorInfo = "\nWidth: " + toString(mColorSurfaces[i]->getTexture()->getWidth()) + "/" + toString(firstSurfaceDesc->getTexture()->getWidth());
-				errorInfo += "\nHeight: " + toString(mColorSurfaces[i]->getTexture()->getHeight()) + "/" + toString(firstSurfaceDesc->getTexture()->getHeight());
-				errorInfo += "\nMultisample Count: " + toString(mColorSurfaces[i]->getTexture()->getMultisampleCount()) + "/" + toString(firstSurfaceDesc->getTexture()->getMultisampleCount());
+				String errorInfo = "\nWidth: " + toString(curTexProps.getWidth()) + "/" + toString(firstTexProps.getWidth());
+				errorInfo += "\nHeight: " + toString(curTexProps.getHeight()) + "/" + toString(firstTexProps.getHeight());
+				errorInfo += "\nMultisample Count: " + toString(curTexProps.getMultisampleCount()) + "/" + toString(firstTexProps.getMultisampleCount());
 
 				BS_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
 			}
 		}
 
-		if(firstSurfaceDesc == nullptr)
-			return;
+		if (firstSurfaceDesc != nullptr)
+		{
+			const TextureProperties& firstTexProps = firstSurfaceDesc->getTexture()->getProperties();
 
-		if(firstSurfaceDesc->getTexture()->getTextureType() != TEX_TYPE_2D)
-			BS_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
+			if (firstTexProps.getTextureType() != TEX_TYPE_2D)
+				BS_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
 
-		if((firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) >= firstSurfaceDesc->getTexture()->getNumFaces())
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " + 
-				toString(firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) + ". Max num faces: " + toString(firstSurfaceDesc->getTexture()->getNumFaces()));
-		}
+			if ((firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) >= firstTexProps.getNumFaces())
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " +
+					toString(firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) + ". Max num faces: " + toString(firstTexProps.getNumFaces()));
+			}
 
-		if(firstSurfaceDesc->getMostDetailedMip() >= firstSurfaceDesc->getTexture()->getNumMipmaps())
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " + 
-				toString(firstSurfaceDesc->getMostDetailedMip()) + ". Max num mipmaps: " + toString(firstSurfaceDesc->getTexture()->getNumMipmaps()));
-		}
+			if (firstSurfaceDesc->getMostDetailedMip() >= firstTexProps.getNumMipmaps())
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " +
+					toString(firstSurfaceDesc->getMostDetailedMip()) + ". Max num mipmaps: " + toString(firstTexProps.getNumMipmaps()));
+			}
 
-		if(mDepthStencilSurface == nullptr)
-			return;
+			if (mDepthStencilSurface == nullptr)
+				return;
 
-		if(mDepthStencilSurface->getTexture()->getWidth() != firstSurfaceDesc->getTexture()->getWidth() ||
-			mDepthStencilSurface->getTexture()->getHeight() != firstSurfaceDesc->getTexture()->getHeight() ||
-			mDepthStencilSurface->getTexture()->getMultisampleCount() != firstSurfaceDesc->getTexture()->getMultisampleCount())
-		{
-			String errorInfo = "\nWidth: " + toString(mDepthStencilSurface->getTexture()->getWidth()) + "/" + toString(firstSurfaceDesc->getTexture()->getWidth());
-			errorInfo += "\nHeight: " + toString(mDepthStencilSurface->getTexture()->getHeight()) + "/" + toString(firstSurfaceDesc->getTexture()->getHeight());
-			errorInfo += "\nMultisample Count: " + toString(mDepthStencilSurface->getTexture()->getMultisampleCount()) + "/" + toString(firstSurfaceDesc->getTexture()->getMultisampleCount());
+			const TextureProperties& depthTexProps = mDepthStencilSurface->getTexture()->getProperties();
+			if (depthTexProps.getWidth() != firstTexProps.getWidth() ||
+				depthTexProps.getHeight() != firstTexProps.getHeight() ||
+				depthTexProps.getMultisampleCount() != firstTexProps.getMultisampleCount())
+			{
+				String errorInfo = "\nWidth: " + toString(depthTexProps.getWidth()) + "/" + toString(firstTexProps.getWidth());
+				errorInfo += "\nHeight: " + toString(depthTexProps.getHeight()) + "/" + toString(firstTexProps.getHeight());
+				errorInfo += "\nMultisample Count: " + toString(depthTexProps.getMultisampleCount()) + "/" + toString(firstTexProps.getMultisampleCount());
 
-			BS_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
+				BS_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
+			}
 		}
 	}
 

+ 2 - 33
BansheeCore/Source/BsRenderSystem.cpp

@@ -7,7 +7,7 @@
 #include "BsRenderWindow.h"
 #include "BsPixelBuffer.h"
 #include "BsOcclusionQuery.h"
-#include "BsGpuResource.h"
+#include "BsResource.h"
 #include "BsCoreThread.h"
 #include "BsMesh.h"
 #include "BsProfilerCPU.h"
@@ -17,7 +17,7 @@ using namespace std::placeholders;
 
 namespace BansheeEngine 
 {
-    static const TexturePtr sNullTexPtr;
+    static const SPtr<TextureCore> sNullTexPtr;
 
     RenderSystem::RenderSystem()
         : mCullingMode(CULL_COUNTERCLOCKWISE)
@@ -221,35 +221,4 @@ namespace BansheeEngine
 
 		BS_INC_RENDER_STAT(NumPresents);
 	}
-
-	void RenderSystem::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, bool discardEntireBuffer, AsyncOp& asyncOp)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		gProfilerCPU().beginSample("writeSubresource");
-
-		resource->writeSubresource(subresourceIdx, *data, discardEntireBuffer);
-
-		gProfilerCPU().endSample("writeSubresource");
-
-		gProfilerCPU().beginSample("writeSubresourceB");
-
-		data->_unlock();
-		asyncOp._completeOperation();
-
-		gProfilerCPU().endSample("writeSubresourceB");
-	}
-
-	void RenderSystem::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceDataPtr& data, AsyncOp& asyncOp)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		gProfilerCPU().beginSample("readSubresource");
-
-		resource->readSubresource(subresourceIdx, *data);
-		data->_unlock();
-		asyncOp._completeOperation();
-
-		gProfilerCPU().endSample("readSubresource");
-	}
 }

+ 30 - 25
BansheeCore/Source/BsRenderTexture.cpp

@@ -15,11 +15,13 @@ namespace BansheeEngine
 
 		if (texture != nullptr)
 		{
-			mWidth = texture->getWidth();
-			mHeight = texture->getHeight();
-			mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texture->getFormat());
-			mHwGamma = texture->isHardwareGammaEnabled();
-			mMultisampleCount = texture->getMultisampleCount();
+			const TextureProperties& props = texture->getProperties();
+
+			mWidth = props.getWidth();
+			mHeight = props.getHeight();
+			mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(props.getFormat());
+			mHwGamma = props.isHardwareGammaEnabled();
+			mMultisampleCount = props.getMultisampleCount();
 		}
 
 		mActive = true;
@@ -41,24 +43,24 @@ namespace BansheeEngine
 		const RENDER_SURFACE_DESC& colorSurface = mDesc.colorSurface;
 		if (colorSurface.texture != nullptr)
 		{
-			TexturePtr texture = colorSurface.texture;
+			SPtr<TextureCore> texture = colorSurface.texture->getCore();
 
-			if (texture->getUsage() != TU_RENDERTARGET)
+			if (texture->getProperties().getUsage() != TU_RENDERTARGET)
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
-			mColorSurface = Texture::requestView(texture, colorSurface.mipLevel, 1,
+			mColorSurface = TextureCore::requestView(texture, colorSurface.mipLevel, 1,
 				colorSurface.face, 1, GVU_RENDERTARGET);
 		}
 
 		const RENDER_SURFACE_DESC& depthStencilSurface = mDesc.depthStencilSurface;
 		if (depthStencilSurface.texture != nullptr)
 		{
-			TexturePtr texture = depthStencilSurface.texture;
+			SPtr<TextureCore> texture = depthStencilSurface.texture->getCore();
 
-			if (texture->getUsage() != TU_DEPTHSTENCIL)
+			if (texture->getProperties().getUsage() != TU_DEPTHSTENCIL)
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
-			mDepthStencilSurface = Texture::requestView(texture, depthStencilSurface.mipLevel, 1,
+			mDepthStencilSurface = TextureCore::requestView(texture, depthStencilSurface.mipLevel, 1,
 				depthStencilSurface.face, 1, GVU_DEPTHSTENCIL);
 		}
 
@@ -67,30 +69,30 @@ namespace BansheeEngine
 		assert(mColorSurface != nullptr);
 		assert(mColorSurface->getTexture() != nullptr);
 
-		if (mColorSurface->getTexture()->getTextureType() != TEX_TYPE_2D)
-			BS_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
+		SPtr<TextureCore> colorTexture = mColorSurface->getTexture();
+		const TextureProperties& texProps = colorTexture->getProperties();
 
-		if ((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > mColorSurface->getTexture()->getNumFaces())
+		if ((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > texProps.getNumFaces())
 		{
 			BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " +
 				toString(mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) +
-				". Max num faces: " + toString(mColorSurface->getTexture()->getNumFaces()));
+				". Max num faces: " + toString(texProps.getNumFaces()));
 		}
 
-		if (mColorSurface->getMostDetailedMip() > mColorSurface->getTexture()->getNumMipmaps())
+		if (mColorSurface->getMostDetailedMip() > texProps.getNumMipmaps())
 		{
 			BS_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " +
-				toString(mColorSurface->getMostDetailedMip()) + ". Max num mipmaps: " + toString(mColorSurface->getTexture()->getNumMipmaps()));
+				toString(mColorSurface->getMostDetailedMip()) + ". Max num mipmaps: " + toString(texProps.getNumMipmaps()));
 		}
 	}
 
 	void RenderTextureCore::destroy()
 	{
 		if (mColorSurface != nullptr)
-			Texture::releaseView(mColorSurface);
+			TextureCore::releaseView(mColorSurface);
 
 		if (mDepthStencilSurface != nullptr)
-			Texture::releaseView(mDepthStencilSurface);
+			TextureCore::releaseView(mDepthStencilSurface);
 
 		RenderTargetCore::destroy();
 	}
@@ -122,13 +124,16 @@ namespace BansheeEngine
 		if (mColorSurface == nullptr || mDepthStencilSurface == nullptr)
 			return;
 
-		if (mColorSurface->getTexture()->getWidth() != mDepthStencilSurface->getTexture()->getWidth() ||
-			mColorSurface->getTexture()->getHeight() != mDepthStencilSurface->getTexture()->getHeight() ||
-			mColorSurface->getTexture()->getMultisampleCount() != mDepthStencilSurface->getTexture()->getMultisampleCount())
+		const TextureProperties& colorProps = mColorSurface->getTexture()->getProperties();
+		const TextureProperties& depthProps = mDepthStencilSurface->getTexture()->getProperties();
+
+		if (colorProps.getWidth() != depthProps.getWidth() ||
+			colorProps.getHeight() != depthProps.getHeight() ||
+			colorProps.getMultisampleCount() != depthProps.getMultisampleCount())
 		{
-			String errorInfo = "\nWidth: " + toString(mColorSurface->getTexture()->getWidth()) + "/" + toString(mDepthStencilSurface->getTexture()->getWidth());
-			errorInfo += "\nHeight: " + toString(mColorSurface->getTexture()->getHeight()) + "/" + toString(mDepthStencilSurface->getTexture()->getHeight());
-			errorInfo += "\nMultisample Count: " + toString(mColorSurface->getTexture()->getMultisampleCount()) + "/" + toString(mDepthStencilSurface->getTexture()->getMultisampleCount());
+			String errorInfo = "\nWidth: " + toString(colorProps.getWidth()) + "/" + toString(depthProps.getWidth());
+			errorInfo += "\nHeight: " + toString(colorProps.getHeight()) + "/" + toString(depthProps.getHeight());
+			errorInfo += "\nMultisample Count: " + toString(colorProps.getMultisampleCount()) + "/" + toString(depthProps.getMultisampleCount());
 
 			BS_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
 		}

+ 272 - 206
BansheeCore/Source/BsTexture.cpp

@@ -11,105 +11,58 @@
 
 namespace BansheeEngine 
 {
-    Texture::Texture()
-        :mHeight(32), mWidth(32), mDepth(1), mNumMipmaps(0),
-		 mHwGamma(false), mMultisampleCount(0), mTextureType(TEX_TYPE_2D), 
-		 mFormat(PF_UNKNOWN), mUsage(TU_DEFAULT)
-    {
-        
-    }
+	TextureProperties::TextureProperties()
+		:mHeight(32), mWidth(32), mDepth(1), mNumMipmaps(0),
+		mHwGamma(false), mMultisampleCount(0), mTextureType(TEX_TYPE_2D),
+		mFormat(PF_UNKNOWN), mUsage(TU_DEFAULT)
+	{
+		mFormat = TextureManager::instance().getNativeFormat(mTextureType, mFormat, mUsage, mHwGamma);
+	}
 
-	void Texture::initialize(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps, 
+	TextureProperties::TextureProperties(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
 		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+		:mHeight(height), mWidth(width), mDepth(depth), mNumMipmaps(numMipmaps),
+		mHwGamma(hwGamma), mMultisampleCount(multisampleCount), mTextureType(textureType),
+		mFormat(format), mUsage(usage)
 	{
-		mTextureType = textureType;
-		mWidth = width;
-		mHeight = height;
-		mDepth = depth;
-		mNumMipmaps = numMipmaps;
-		mUsage = usage;
-		mHwGamma = hwGamma;
-		mMultisampleCount = multisampleCount;
-
-		// Adjust format if required
-		mFormat = TextureManager::instance().getNativeFormat(mTextureType, format, mUsage, hwGamma);
-		mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
-
-		// Allocate CPU buffers if needed
-		if ((usage & TU_CPUCACHED) != 0)
-			createCPUBuffers();
-
-		Resource::initialize();
+		mFormat = TextureManager::instance().getNativeFormat(mTextureType, mFormat, mUsage, mHwGamma);
 	}
 
-    bool Texture::hasAlpha() const
-    {
-        return PixelUtil::hasAlpha(mFormat);
-    }
-
-	UINT32 Texture::calculateSize() const
+	bool TextureProperties::hasAlpha() const
 	{
-        return getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+		return PixelUtil::hasAlpha(mFormat);
 	}
 
-	UINT32 Texture::getNumFaces() const
+	UINT32 TextureProperties::getNumFaces() const
 	{
 		return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
 	}
 
-	void Texture::_writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
+	void TextureProperties::mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const
 	{
-		if ((mUsage & TU_CPUCACHED) == 0)
-			return;
-
-		if (subresourceIdx >= (UINT32)mCPUSubresourceData.size())
-		{
-			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. " + toString(mCPUSubresourceData.size()));
-			return;
-		}
-
-		if (data.getTypeId() != TID_PixelData)
-		{
-			LOGERR("Invalid GpuResourceData type. Only PixelData is supported.");
-			return;
-		}
-
-		const PixelData& pixelData = static_cast<const PixelData&>(data);
-
-		UINT32 mipLevel;
-		UINT32 face;
-		mapFromSubresourceIdx(subresourceIdx, face, mipLevel);
-
-		UINT32 mipWidth, mipHeight, mipDepth;
-		PixelUtil::getSizeForMipLevel(getWidth(), getHeight(), getDepth(),
-			mipLevel, mipWidth, mipHeight, mipDepth);
-
-		if (pixelData.getWidth() != mipWidth || pixelData.getHeight() != mipHeight ||
-			pixelData.getDepth() != mipDepth || pixelData.getFormat() != getFormat())
-		{
-			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this texture.");
-			return;
-		}
-
-		if (mCPUSubresourceData[subresourceIdx]->getSize() != pixelData.getSize())
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+		UINT32 numMipmaps = getNumMipmaps() + 1;
 
-		UINT8* dest = mCPUSubresourceData[subresourceIdx]->getData();
-		UINT8* src = pixelData.getData();
+		face = Math::floorToInt((subresourceIdx) / (float)numMipmaps);
+		mip = subresourceIdx % numMipmaps;
+	}
 
-		memcpy(dest, src, pixelData.getSize());
+	UINT32 TextureProperties::mapToSubresourceIdx(UINT32 face, UINT32 mip) const
+	{
+		return face * (getNumMipmaps() + 1) + mip;
 	}
 
-	void Texture::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
+	TextureCore::TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+		:mProperties(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount)
+	{ }
+
+	void TextureCore::writeSubresource(UINT32 subresourceIdx, const PixelData& pixelData, bool discardEntireBuffer)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(data.getTypeId() != TID_PixelData)
-			BS_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only PixelData is supported.");
-
 		if(discardEntireBuffer)
 		{
-			if(mUsage != TU_DYNAMIC)
+			if(mProperties.getUsage() != TU_DYNAMIC)
 			{
 				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
 				discardEntireBuffer = false;
@@ -117,41 +70,36 @@ namespace BansheeEngine
 		}
 		else
 		{
-			if(mUsage == TU_DYNAMIC)
+			if (mProperties.getUsage() == TU_DYNAMIC)
 			{
 				LOGWRN("Buffer discard is not enabled but buffer was not created as dynamic. Enabling discard.");
 				discardEntireBuffer = true;
 			}
 		}
 
-		const PixelData& pixelData = static_cast<const PixelData&>(data);
-
 		UINT32 face = 0;
 		UINT32 mip = 0;
-		mapFromSubresourceIdx(subresourceIdx, face, mip);
+		mProperties.mapFromSubresourceIdx(subresourceIdx, face, mip);
 
 		writeData(pixelData, mip, face, discardEntireBuffer);
 	}
 
-	void Texture::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
+	void TextureCore::readSubresource(UINT32 subresourceIdx, PixelData& data)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(data.getTypeId() != TID_PixelData)
-			BS_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only PixelData is supported.");
-
 		UINT32 face = 0;
 		UINT32 mip = 0;
-		mapFromSubresourceIdx(subresourceIdx, face, mip);
+		mProperties.mapFromSubresourceIdx(subresourceIdx, face, mip);
 
 		PixelData& pixelData = static_cast<PixelData&>(data);
 
 		UINT32 mipWidth, mipHeight, mipDepth;
-		PixelUtil::getSizeForMipLevel(getWidth(), getHeight(), getDepth(),
+		PixelUtil::getSizeForMipLevel(mProperties.getWidth(), mProperties.getHeight(), mProperties.getDepth(),
 			mip, mipWidth, mipHeight, mipDepth);
 
 		if (pixelData.getWidth() != mipWidth || pixelData.getHeight() != mipHeight ||
-			pixelData.getDepth() != mipDepth || pixelData.getFormat() != getFormat())
+			pixelData.getDepth() != mipDepth || pixelData.getFormat() != mProperties.getFormat())
 		{
 			BS_EXCEPT(RenderingAPIException, "Provided buffer is not of valid dimensions or format in order to read from this texture.");
 		}
@@ -159,114 +107,37 @@ namespace BansheeEngine
 		readData(pixelData, mip, face);
 	}
 
-	PixelDataPtr Texture::allocateSubresourceBuffer(UINT32 subresourceIdx) const
-	{
-		UINT32 face = 0;
-		UINT32 mip = 0;
-		mapFromSubresourceIdx(subresourceIdx, face, mip);
-
-		UINT32 numMips = getNumMipmaps();
-		UINT32 width = getWidth();
-		UINT32 height = getHeight();
-		UINT32 depth = getDepth();
-
-		UINT32 totalSize = PixelUtil::getMemorySize(width, height, depth, mFormat);
-
-		for(UINT32 j = 0; j < mip; j++)
-		{
-			totalSize = PixelUtil::getMemorySize(width, height, depth, mFormat);
-
-			if(width != 1) width /= 2;
-			if(height != 1) height /= 2;
-			if(depth != 1) depth /= 2;
-		}
-
-		PixelDataPtr dst = bs_shared_ptr<PixelData, PoolAlloc>(width, height, depth, getFormat());
-
-		dst->allocateInternalBuffer();
-
-		return dst;
-	}
-
-	void Texture::mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const
-	{
-		UINT32 numMipmaps = getNumMipmaps() + 1;
-
-		face = Math::floorToInt((subresourceIdx) / (float)numMipmaps);
-		mip = subresourceIdx % numMipmaps;
-	}
-
-	UINT32 Texture::mapToSubresourceIdx(UINT32 face, UINT32 mip) const
-	{
-		return face * (getNumMipmaps() + 1) + mip;
-	}
-
-	void Texture::readDataSim(PixelData& dest, UINT32 mipLevel, UINT32 face)
-	{
-		if ((mUsage & TU_CPUCACHED) == 0)
-		{
-			LOGERR("Attempting to read CPU data from a texture that is created without CPU caching.");
-			return;
-		}
-
-		UINT32 mipWidth, mipHeight, mipDepth;
-		PixelUtil::getSizeForMipLevel(getWidth(), getHeight(), getDepth(), 
-			mipLevel, mipWidth, mipHeight, mipDepth);
-
-		if (dest.getWidth() != mipWidth || dest.getHeight() != mipHeight ||
-			dest.getDepth() != mipDepth || dest.getFormat() != getFormat())
-		{
-			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this texture.");
-			return;
-		}
-
-		UINT32 subresourceIdx = mapToSubresourceIdx(face, mipLevel);
-		if (subresourceIdx >= (UINT32)mCPUSubresourceData.size())
-		{
-			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. " + toString(mCPUSubresourceData.size()));
-			return;
-		}
-
-		if (mCPUSubresourceData[subresourceIdx]->getSize() != dest.getSize())
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
-
-		UINT8* srcPtr = mCPUSubresourceData[subresourceIdx]->getData();
-		UINT8* destPtr = dest.getData();
-
-		memcpy(destPtr, srcPtr, dest.getSize());
-	}
-
-	PixelData Texture::lock(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
+	PixelData TextureCore::lock(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(mipLevel < 0 || mipLevel > mNumMipmaps)
-			BS_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mipLevel) + ". Min is 0, max is " + toString(getNumMipmaps()));
+		if (mipLevel < 0 || mipLevel > mProperties.getNumMipmaps())
+			BS_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mipLevel) + ". Min is 0, max is " + toString(mProperties.getNumMipmaps()));
 
-		if(face < 0 || face >= getNumFaces())
-			BS_EXCEPT(InvalidParametersException, "Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(getNumFaces()));
+		if (face < 0 || face >= mProperties.getNumFaces())
+			BS_EXCEPT(InvalidParametersException, "Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(mProperties.getNumFaces()));
 
 		return lockImpl(options, mipLevel, face);
 	}
 
-	void Texture::unlock()
+	void TextureCore::unlock()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		unlockImpl();
 	}
 
-	void Texture::copy(UINT32 srcSubresourceIdx, UINT32 destSubresourceIdx, TexturePtr& target)
+	void TextureCore::copy(UINT32 srcSubresourceIdx, UINT32 destSubresourceIdx, const SPtr<TextureCore>& target)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (target->getTextureType() != this->getTextureType())
+		if (target->mProperties.getTextureType() != mProperties.getTextureType())
 			BS_EXCEPT(InvalidParametersException, "Source and destination textures must be of same type and must have the same usage and type.");
 
-		if (getFormat() != target->getFormat()) // Note: It might be okay to use different formats of the same size
+		if (mProperties.getFormat() != target->mProperties.getFormat()) // Note: It might be okay to use different formats of the same size
 			BS_EXCEPT(InvalidParametersException, "Source and destination texture formats must match.");
 
-		if (target->getMultisampleCount() > 0 && getMultisampleCount() != target->getMultisampleCount())
+		if (target->mProperties.getMultisampleCount() > 0 && mProperties.getMultisampleCount() != target->mProperties.getMultisampleCount())
 			BS_EXCEPT(InvalidParametersException, "When copying to a multisampled texture, source texture must have the same number of samples.");
 
 		UINT32 srcFace = 0;
@@ -275,28 +146,28 @@ namespace BansheeEngine
 		UINT32 destFace = 0;
 		UINT32 destMipLevel = 0;
 
-		mapFromSubresourceIdx(srcSubresourceIdx, srcFace, srcMipLevel);
-		target->mapFromSubresourceIdx(destSubresourceIdx, destFace, destMipLevel);
+		mProperties.mapFromSubresourceIdx(srcSubresourceIdx, srcFace, srcMipLevel);
+		target->mProperties.mapFromSubresourceIdx(destSubresourceIdx, destFace, destMipLevel);
 
-		if (destFace >= getNumFaces())
+		if (destFace >= mProperties.getNumFaces())
 			BS_EXCEPT(InvalidParametersException, "Invalid destination face index");
 
-		if (srcFace >= target->getNumFaces())
+		if (srcFace >= target->mProperties.getNumFaces())
 			BS_EXCEPT(InvalidParametersException, "Invalid destination face index");
 
-		if (srcMipLevel > getNumMipmaps())
-			BS_EXCEPT(InvalidParametersException, "Source mip level out of range. Valid range is [0, " + toString(getNumMipmaps()) + "]");
+		if (srcMipLevel > mProperties.getNumMipmaps())
+			BS_EXCEPT(InvalidParametersException, "Source mip level out of range. Valid range is [0, " + toString(mProperties.getNumMipmaps()) + "]");
 
-		if (destMipLevel > target->getNumMipmaps())
-			BS_EXCEPT(InvalidParametersException, "Destination mip level out of range. Valid range is [0, " + toString(target->getNumMipmaps()) + "]");
+		if (destMipLevel > target->mProperties.getNumMipmaps())
+			BS_EXCEPT(InvalidParametersException, "Destination mip level out of range. Valid range is [0, " + toString(target->mProperties.getNumMipmaps()) + "]");
 
-		UINT32 srcMipWidth = mWidth >> srcMipLevel;
-		UINT32 srcMipHeight = mHeight >> srcMipLevel;
-		UINT32 srcMipDepth = mDepth >> srcMipLevel;
+		UINT32 srcMipWidth = mProperties.getWidth() >> srcMipLevel;
+		UINT32 srcMipHeight = mProperties.getHeight() >> srcMipLevel;
+		UINT32 srcMipDepth = mProperties.getDepth() >> srcMipLevel;
 
-		UINT32 dstMipWidth = target->getWidth() >> destMipLevel;
-		UINT32 dstMipHeight = target->getHeight() >> destMipLevel;
-		UINT32 dstMipDepth = target->getDepth() >> destMipLevel;
+		UINT32 dstMipWidth = target->mProperties.getWidth() >> destMipLevel;
+		UINT32 dstMipHeight = target->mProperties.getHeight() >> destMipLevel;
+		UINT32 dstMipDepth = target->mProperties.getDepth() >> destMipLevel;
 
 		if (srcMipWidth != dstMipWidth || srcMipHeight != dstMipHeight || srcMipDepth != dstMipDepth)
 			BS_EXCEPT(InvalidParametersException, "Source and destination sizes must match");
@@ -308,7 +179,7 @@ namespace BansheeEngine
 	/* 								TEXTURE VIEW                      		*/
 	/************************************************************************/
 
-	TextureViewPtr Texture::createView()
+	TextureViewPtr TextureCore::createView()
 	{
 		TextureViewPtr viewPtr = bs_core_ptr<TextureView, PoolAlloc>(new (bs_alloc<TextureView, PoolAlloc>()) TextureView());
 		viewPtr->_setThisPtr(viewPtr);
@@ -316,12 +187,12 @@ namespace BansheeEngine
 		return viewPtr;
 	}
 
-	void Texture::clearBufferViews()
+	void TextureCore::clearBufferViews()
 	{
 		mTextureViews.clear();
 	}
 
-	TextureViewPtr Texture::requestView(TexturePtr texture, UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage)
+	TextureViewPtr TextureCore::requestView(const SPtr<TextureCore>& texture, UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -335,7 +206,7 @@ namespace BansheeEngine
 		key.usage = usage;
 
 		auto iterFind = texture->mTextureViews.find(key);
-		if(iterFind == texture->mTextureViews.end())
+		if (iterFind == texture->mTextureViews.end())
 		{
 			TextureViewPtr newView = texture->createView();
 			newView->initialize(texture, key);
@@ -348,23 +219,23 @@ namespace BansheeEngine
 		return iterFind->second->view;
 	}
 
-	void Texture::releaseView(TextureViewPtr view)
+	void TextureCore::releaseView(const TextureViewPtr& view)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		assert(view != nullptr);
 
-		TexturePtr texture = view->getTexture();
+		SPtr<TextureCore> texture = view->getTexture();
 
 		auto iterFind = texture->mTextureViews.find(view->getDesc());
-		if(iterFind == texture->mTextureViews.end())
+		if (iterFind == texture->mTextureViews.end())
 		{
 			BS_EXCEPT(InternalErrorException, "Trying to release a texture view that doesn't exist!");
 		}
 
 		iterFind->second->refCount--;
 
-		if(iterFind->second->refCount == 0)
+		if (iterFind->second->refCount == 0)
 		{
 			TextureViewReference* toRemove = iterFind->second;
 
@@ -374,25 +245,199 @@ namespace BansheeEngine
 		}
 	}
 
+	Texture::Texture()
+	{
+
+	}
+
+	Texture::Texture(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+		:mProperties(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount)
+    {
+        
+    }
+
+	void Texture::initialize()
+	{
+		mSize = calculateSize();
+
+		// Allocate CPU buffers if needed
+		if ((mProperties.getUsage() & TU_CPUCACHED) != 0)
+			createCPUBuffers();
+
+		Resource::initialize();
+	}
+
+	SPtr<CoreObjectCore> Texture::createCore() const
+	{
+		const TextureProperties& props = getProperties();
+
+		return TextureCoreManager::instance().createTextureInternal(props.getTextureType(), props.getWidth(), props.getHeight(),
+			props.getDepth(), props.getNumMipmaps(), props.getFormat(), props.getUsage(), props.isHardwareGammaEnabled(), props.getMultisampleCount());
+	}
+
+	AsyncOp Texture::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const PixelDataPtr& data, bool discardEntireBuffer)
+	{
+		updateCPUBuffers(subresourceIdx, *data);
+
+		data->_lock();
+
+		std::function<void(const SPtr<TextureCore>&, UINT32, const PixelDataPtr&, bool, AsyncOp&)> func =
+			[&](const SPtr<TextureCore>& texture, UINT32 _subresourceIdx, const PixelDataPtr& _pixData, bool _discardEntireBuffer, AsyncOp& asyncOp)
+		{
+			texture->writeSubresource(_subresourceIdx, *_pixData, _discardEntireBuffer);
+			_pixData->_unlock();
+			asyncOp._completeOperation();
+
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			data, discardEntireBuffer, std::placeholders::_1));
+	}
+
+	AsyncOp Texture::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const PixelDataPtr& data)
+	{
+		data->_lock();
+
+		std::function<void(const SPtr<TextureCore>&, UINT32, const PixelDataPtr&, AsyncOp&)> func =
+			[&](const SPtr<TextureCore>& texture, UINT32 _subresourceIdx, const PixelDataPtr& _pixData, AsyncOp& asyncOp)
+		{
+			texture->readSubresource(_subresourceIdx, *_pixData);
+			_pixData->_unlock();
+			asyncOp._completeOperation();
+
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			data, std::placeholders::_1));
+	}
+
+	UINT32 Texture::calculateSize() const
+	{
+		return mProperties.getNumFaces() * PixelUtil::getMemorySize(mProperties.getWidth(),
+			mProperties.getHeight(), mProperties.getDepth(), mProperties.getFormat());
+	}
+
+	void Texture::updateCPUBuffers(UINT32 subresourceIdx, const PixelData& pixelData)
+	{
+		if ((mProperties.getUsage() & TU_CPUCACHED) == 0)
+			return;
+
+		if (subresourceIdx >= (UINT32)mCPUSubresourceData.size())
+		{
+			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. " + toString(mCPUSubresourceData.size()));
+			return;
+		}
+
+		UINT32 mipLevel;
+		UINT32 face;
+		mProperties.mapFromSubresourceIdx(subresourceIdx, face, mipLevel);
+
+		UINT32 mipWidth, mipHeight, mipDepth;
+		PixelUtil::getSizeForMipLevel(mProperties.getWidth(), mProperties.getHeight(), mProperties.getDepth(),
+			mipLevel, mipWidth, mipHeight, mipDepth);
+
+		if (pixelData.getWidth() != mipWidth || pixelData.getHeight() != mipHeight ||
+			pixelData.getDepth() != mipDepth || pixelData.getFormat() != mProperties.getFormat())
+		{
+			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this texture.");
+			return;
+		}
+
+		if (mCPUSubresourceData[subresourceIdx]->getSize() != pixelData.getSize())
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+
+		UINT8* dest = mCPUSubresourceData[subresourceIdx]->getData();
+		UINT8* src = pixelData.getData();
+
+		memcpy(dest, src, pixelData.getSize());
+	}
+
+	PixelDataPtr Texture::allocateSubresourceBuffer(UINT32 subresourceIdx) const
+	{
+		UINT32 face = 0;
+		UINT32 mip = 0;
+		mProperties.mapFromSubresourceIdx(subresourceIdx, face, mip);
+
+		UINT32 numMips = mProperties.getNumMipmaps();
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		UINT32 depth = mProperties.getDepth();
+
+		UINT32 totalSize = PixelUtil::getMemorySize(width, height, depth, mProperties.getFormat());
+
+		for(UINT32 j = 0; j < mip; j++)
+		{
+			totalSize = PixelUtil::getMemorySize(width, height, depth, mProperties.getFormat());
+
+			if(width != 1) width /= 2;
+			if(height != 1) height /= 2;
+			if(depth != 1) depth /= 2;
+		}
+
+		PixelDataPtr dst = bs_shared_ptr<PixelData, PoolAlloc>(width, height, depth, mProperties.getFormat());
+
+		dst->allocateInternalBuffer();
+
+		return dst;
+	}
+
+
+
+	void Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	{
+		if ((mProperties.getUsage() & TU_CPUCACHED) == 0)
+		{
+			LOGERR("Attempting to read CPU data from a texture that is created without CPU caching.");
+			return;
+		}
+
+		UINT32 mipWidth, mipHeight, mipDepth;
+		PixelUtil::getSizeForMipLevel(mProperties.getWidth(), mProperties.getHeight(), mProperties.getDepth(),
+			mipLevel, mipWidth, mipHeight, mipDepth);
+
+		if (dest.getWidth() != mipWidth || dest.getHeight() != mipHeight ||
+			dest.getDepth() != mipDepth || dest.getFormat() != mProperties.getFormat())
+		{
+			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this texture.");
+			return;
+		}
+
+		UINT32 subresourceIdx = mProperties.mapToSubresourceIdx(face, mipLevel);
+		if (subresourceIdx >= (UINT32)mCPUSubresourceData.size())
+		{
+			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. " + toString(mCPUSubresourceData.size()));
+			return;
+		}
+
+		if (mCPUSubresourceData[subresourceIdx]->getSize() != dest.getSize())
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+
+		UINT8* srcPtr = mCPUSubresourceData[subresourceIdx]->getData();
+		UINT8* destPtr = dest.getData();
+
+		memcpy(destPtr, srcPtr, dest.getSize());
+	}
+
 	void Texture::createCPUBuffers()
 	{
-		UINT32 numFaces = getNumFaces();
-		UINT32 numMips = getNumMipmaps();
+		UINT32 numFaces = mProperties.getNumFaces();
+		UINT32 numMips = mProperties.getNumMipmaps();
 
 		UINT32 numSubresources = numFaces * numMips;
 		mCPUSubresourceData.resize(numSubresources);
 
 		for (UINT32 i = 0; i < numFaces; i++)
 		{
-			UINT32 curWidth = mWidth;
-			UINT32 curHeight = mHeight;
-			UINT32 curDepth = mDepth;
+			UINT32 curWidth = mProperties.getWidth();
+			UINT32 curHeight = mProperties.getHeight();
+			UINT32 curDepth = mProperties.getDepth();
 
-			for (UINT32 j = 0; j < mNumMipmaps; j++)
+			for (UINT32 j = 0; j < mProperties.getNumMipmaps(); j++)
 			{
-				UINT32 subresourceIdx = mapToSubresourceIdx(i, j);
+				UINT32 subresourceIdx = mProperties.mapToSubresourceIdx(i, j);
 
-				mCPUSubresourceData[subresourceIdx] = bs_shared_ptr<PixelData>(curWidth, curHeight, curDepth, mFormat);
+				mCPUSubresourceData[subresourceIdx] = bs_shared_ptr<PixelData>(curWidth, curHeight, curDepth, mProperties.getFormat());
 				mCPUSubresourceData[subresourceIdx]->allocateInternalBuffer();
 
 				if (curWidth > 1)
@@ -407,6 +452,11 @@ namespace BansheeEngine
 		}
 	}
 
+	SPtr<TextureCore> Texture::getCore() const
+	{
+		return std::static_pointer_cast<TextureCore>(mCoreSpecific);
+	}
+
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/************************************************************************/
@@ -458,6 +508,22 @@ namespace BansheeEngine
 
 	const HTexture& Texture::dummy()
 	{
-		return TextureCoreManager::instance().getDummyTexture();
+		static HTexture dummyTexture;
+		if (!dummyTexture)
+		{
+			dummyTexture = create(TEX_TYPE_2D, 2, 2, 0, PF_R8G8B8A8);
+
+			UINT32 subresourceIdx = dummyTexture->getProperties().mapToSubresourceIdx(0, 0);
+			PixelDataPtr data = dummyTexture->allocateSubresourceBuffer(subresourceIdx);
+
+			data->setColorAt(Color::Red, 0, 0);
+			data->setColorAt(Color::Red, 0, 1);
+			data->setColorAt(Color::Red, 1, 0);
+			data->setColorAt(Color::Red, 1, 1);
+
+			dummyTexture->writeSubresource(gCoreAccessor(), subresourceIdx, data, false);
+		}
+
+		return dummyTexture;
 	}
 }

+ 15 - 23
BansheeCore/Source/BsTextureManager.cpp

@@ -9,16 +9,19 @@ namespace BansheeEngine
     TexturePtr TextureManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, int numMipmaps,
         PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
     {
-        TexturePtr ret = createTextureImpl();
+		Texture* tex = new (bs_alloc<Texture>()) Texture(texType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount);
+		TexturePtr ret = bs_core_ptr<Texture, GenAlloc>(tex);
+
 		ret->_setThisPtr(ret);
-		ret->initialize(texType, width, height, depth, static_cast<size_t>(numMipmaps), format, usage, hwGamma, multisampleCount);
+		ret->initialize();
 
 		return ret;
     }
 
 	TexturePtr TextureManager::_createEmpty()
 	{
-		TexturePtr texture = createTextureImpl();
+		Texture* tex = new (bs_alloc<Texture>()) Texture();
+		TexturePtr texture = bs_core_ptr<Texture, GenAlloc>(tex);
 		texture->_setThisPtr(texture);
 
 		return texture;
@@ -68,39 +71,28 @@ namespace BansheeEngine
 		return newRT;
 	}
 
-	SPtr<RenderTextureCore> TextureCoreManager::createRenderTexture(const RENDER_TEXTURE_DESC& desc)
+	SPtr<TextureCore> TextureCoreManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
 	{
-		SPtr<RenderTextureCore> newRT = createRenderTextureInternal(desc);
+		SPtr<TextureCore> newRT = createTextureInternal(texType, width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
 		newRT->initialize();
 
 		return newRT;
 	}
 
-	SPtr<MultiRenderTextureCore> TextureCoreManager::createMultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc)
+	SPtr<RenderTextureCore> TextureCoreManager::createRenderTexture(const RENDER_TEXTURE_DESC& desc)
 	{
-		SPtr<MultiRenderTextureCore> newRT = createMultiRenderTextureInternal(desc);
+		SPtr<RenderTextureCore> newRT = createRenderTextureInternal(desc);
 		newRT->initialize();
 
 		return newRT;
 	}
 
-	void TextureCoreManager::onStartUp()
+	SPtr<MultiRenderTextureCore> TextureCoreManager::createMultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC& desc)
 	{
-		// Internally this will call our createTextureImpl virtual method. But since this is guaranteed
-		// to be the last class in the hierarchy, we can call a virtual method from constructor.
-		mDummyTexture = Texture::create(TEX_TYPE_2D, 2, 2, 0, PF_R8G8B8A8);
-
-		UINT32 subresourceIdx = mDummyTexture->mapToSubresourceIdx(0, 0);
-		PixelDataPtr data = mDummyTexture->allocateSubresourceBuffer(subresourceIdx);
-
-		data->setColorAt(Color::Red, 0, 0);
-		data->setColorAt(Color::Red, 0, 1);
-		data->setColorAt(Color::Red, 1, 0);
-		data->setColorAt(Color::Red, 1, 1);
-
-		AsyncOp op;
+		SPtr<MultiRenderTextureCore> newRT = createMultiRenderTextureInternal(desc);
+		newRT->initialize();
 
-		data->_lock();
-		RenderSystem::instance().writeSubresource(mDummyTexture.getInternalPtr(), mDummyTexture->mapToSubresourceIdx(0, 0), data, false, op);
+		return newRT;
 	}
 }

+ 1 - 1
BansheeCore/Source/BsTextureView.cpp

@@ -29,7 +29,7 @@ namespace BansheeEngine
 	TextureView::~TextureView()
 	{ }
 
-	void TextureView::initialize(TexturePtr texture, TEXTURE_VIEW_DESC& _desc)
+	void TextureView::initialize(const SPtr<TextureCore>& texture, TEXTURE_VIEW_DESC& _desc)
 	{
 		mOwnerTexture = texture;
 		mDesc = _desc;

+ 3 - 3
BansheeD3D11RenderSystem/Include/BsD3D11RenderSystem.h

@@ -48,12 +48,12 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	RenderSystem::setTexture
 		 */
-		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr);
 
 		/**
 		 * @copydoc	RenderSystem::setLoadStoreTexture
 		 */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
 			const TextureSurface& surface);
 
 		/**
@@ -255,7 +255,7 @@ namespace BansheeEngine
 		D3D11HLSLProgramFactory* mHLSLFactory;
 		D3D11InputLayoutManager* mIAManager;
 
-		std::pair<TexturePtr, TextureViewPtr> mBoundUAVs[D3D11_PS_CS_UAV_REGISTER_COUNT];
+		std::pair<SPtr<TextureCore>, TextureViewPtr> mBoundUAVs[D3D11_PS_CS_UAV_REGISTER_COUNT];
 
 		UINT32 mStencilRef;
 		Rect2 mViewportNorm;

+ 1 - 1
BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h

@@ -159,7 +159,7 @@ namespace BansheeEngine
 		ID3D11Texture2D* mBackBuffer;
 		ID3D11RenderTargetView*	mRenderTargetView;
 		TextureViewPtr mDepthStencilView;
-		TexturePtr mDepthStencilBuffer;
+		SPtr<TextureCore> mDepthStencilBuffer;
 
 		IDXGISwapChain*	mSwapChain;
 		DXGI_SWAP_CHAIN_DESC mSwapChainDesc;

+ 10 - 9
BansheeD3D11RenderSystem/Include/BsD3D11Texture.h

@@ -8,10 +8,10 @@ namespace BansheeEngine
 	/**
 	 * @brief	DirectX 11 implementation of a texture.
 	 */
-	class D3D11Texture : public Texture
+	class D3D11TextureCore : public TextureCore
 	{
 	public:
-		~D3D11Texture();
+		~D3D11TextureCore();
 
 		/**
 		 * @brief	Returns internal DX11 texture resource object.
@@ -29,19 +29,20 @@ namespace BansheeEngine
 		DXGI_FORMAT getDXGIFormat() const { return mDXGIFormat; }
 
 	protected:
-		friend class D3D11TextureManager;
+		friend class D3D11TextureCoreManager;
 
-		D3D11Texture();
+		D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
 
 		/**
-		* @copydoc	Texture::initialize_internal()
+		* @copydoc	CoreObjectCore::initialize()
 		*/
-		void initialize_internal();
+		void initialize();
 
 		/**
-		* @copydoc Texture::destroy_internal()
+		* @copydoc CoreObjectCore::destroy()
 		*/
-		void destroy_internal();
+		void destroy();
 
 		/**
 		 * @copydoc Texture::lockImpl
@@ -56,7 +57,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc Texture::copyImpl
 		 */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target);
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target);
 
 		/**
 		 * @copydoc Texture::readData

+ 8 - 6
BansheeD3D11RenderSystem/Include/BsD3D11TextureManager.h

@@ -17,11 +17,6 @@ namespace BansheeEngine
 		PixelFormat getNativeFormat(TextureType ttype, PixelFormat format, int usage, bool hwGamma);
 
 	protected:		
-		/**
-		 * @copydoc	TextureManager::createTextureImpl
-		 */
-		TexturePtr createTextureImpl();
-
 		/**
 		 * @copydoc	TextureManager::createRenderTextureImpl
 		 */
@@ -38,7 +33,14 @@ namespace BansheeEngine
 	 */
 	class BS_D3D11_EXPORT D3D11TextureCoreManager : public TextureCoreManager
 	{
-	protected:		
+	protected:
+		/**
+		 * @copydoc	TextureCoreManager::createTextureInternal
+		 */
+		SPtr<TextureCore> createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false,
+			UINT32 multisampleCount = 0);
+
 		/**
 		 * @copydoc	TextureCoreManager::createRenderTextureInternal
 		 */

+ 5 - 5
BansheeD3D11RenderSystem/Include/BsD3D11TextureView.h

@@ -36,7 +36,7 @@ namespace BansheeEngine
 		ID3D11DepthStencilView*	getDSV() const { return mDSV; }
 
 	protected:
-		friend class D3D11Texture;
+		friend class D3D11TextureCore;
 
 		D3D11TextureView();
 
@@ -65,7 +65,7 @@ namespace BansheeEngine
 		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
 		 *							and number of cubes for cube textures.
 		 */
-		ID3D11ShaderResourceView* createSRV(D3D11Texture* texture, 
+		ID3D11ShaderResourceView* createSRV(D3D11TextureCore* texture, 
 			UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices);
 
 		/**
@@ -81,7 +81,7 @@ namespace BansheeEngine
 		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
 		 *							and number of cubes for cube textures.
 		 */
-		ID3D11RenderTargetView* createRTV(D3D11Texture* texture, 
+		ID3D11RenderTargetView* createRTV(D3D11TextureCore* texture, 
 			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
 
 		/**
@@ -97,7 +97,7 @@ namespace BansheeEngine
 		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
 		 *							and number of cubes for cube textures.
 		 */
-		ID3D11UnorderedAccessView* createUAV(D3D11Texture* texture, 
+		ID3D11UnorderedAccessView* createUAV(D3D11TextureCore* texture, 
 			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
 
 		/**
@@ -113,7 +113,7 @@ namespace BansheeEngine
 		 *							array elements for 1D and 2D array textures, number of slices for 3D textures,
 		 *							and number of cubes for cube textures.
 		 */
-		ID3D11DepthStencilView* createDSV(D3D11Texture* texture, 
+		ID3D11DepthStencilView* createDSV(D3D11TextureCore* texture, 
 			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices);
 
 		ID3D11ShaderResourceView* mSRV;

+ 8 - 8
BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp

@@ -265,7 +265,7 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumDepthStencilStateChanges);
 	}
 
-	void D3D11RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
+	void D3D11RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -275,7 +275,7 @@ namespace BansheeEngine
 		ID3D11ShaderResourceView* viewArray[1];
 		if(texPtr != nullptr && enabled)
 		{
-			D3D11Texture* d3d11Texture = static_cast<D3D11Texture*>(texPtr.get());
+			D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
 			viewArray[0] = d3d11Texture->getSRV();
 		}
 		else
@@ -308,7 +308,7 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumTextureBinds);
 	}
 
-	void D3D11RenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+	void D3D11RenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
 		const TextureSurface& surface)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -319,8 +319,8 @@ namespace BansheeEngine
 		ID3D11UnorderedAccessView* viewArray[1];
 		if (texPtr != nullptr && enabled)
 		{
-			D3D11Texture* d3d11Texture = static_cast<D3D11Texture*>(texPtr.get());
-			TextureViewPtr texView = Texture::requestView(texPtr, surface.mipLevel, 1, 
+			D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(texPtr.get());
+			TextureViewPtr texView = TextureCore::requestView(texPtr, surface.mipLevel, 1, 
 				surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
 
 			D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
@@ -338,7 +338,7 @@ namespace BansheeEngine
 			if (mBoundUAVs[unit].second != nullptr)
 				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
 
-			mBoundUAVs[unit] = std::pair<TexturePtr, TextureViewPtr>();
+			mBoundUAVs[unit] = std::pair<SPtr<TextureCore>, TextureViewPtr>();
 		}
 
 		if (gptype == GPT_FRAGMENT_PROGRAM)
@@ -582,7 +582,7 @@ namespace BansheeEngine
 				if (!texture.isLoaded())
 					setTexture(gptype, iter->second.slot, false, nullptr);
 				else
-					setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+					setTexture(gptype, iter->second.slot, true, texture->getCore());
 			}
 			else
 			{
@@ -591,7 +591,7 @@ namespace BansheeEngine
 				if (!texture.isLoaded())
 					setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
 				else
-					setLoadStoreTexture(gptype, iter->second.slot, true, texture.getInternalPtr(), surface);
+					setLoadStoreTexture(gptype, iter->second.slot, true, texture->getCore(), surface);
 			}
 		}
 

+ 5 - 5
BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp

@@ -264,7 +264,7 @@ namespace BansheeEngine
 
 		if (mDepthStencilView != nullptr)
 		{
-			Texture::releaseView(mDepthStencilView);
+			TextureCore::releaseView(mDepthStencilView);
 			mDepthStencilView = nullptr;
 		}
 
@@ -686,17 +686,17 @@ namespace BansheeEngine
 			BS_EXCEPT(RenderingAPIException, "Unable to create rendertagert view\nError Description:" + errorDescription);
 		}
 
-		mDepthStencilBuffer = TextureManager::instance().createTexture(TEX_TYPE_2D, 
-			BBDesc.Width, BBDesc.Height, 0, PF_D24S8, TU_DEPTHSTENCIL, false, 
+		mDepthStencilBuffer = TextureCoreManager::instance().createTexture(TEX_TYPE_2D, 
+			BBDesc.Width, BBDesc.Height, 0, 0, PF_D24S8, TU_DEPTHSTENCIL, false, 
 			getProperties().getMultisampleCount());
 
 		if(mDepthStencilView != nullptr)
 		{
-			Texture::releaseView(mDepthStencilView);
+			TextureCore::releaseView(mDepthStencilView);
 			mDepthStencilView = nullptr;
 		}
 
-		mDepthStencilView = Texture::requestView(mDepthStencilBuffer, 0, 1, 0, 1, GVU_DEPTHSTENCIL);
+		mDepthStencilView = TextureCore::requestView(mDepthStencilBuffer, 0, 1, 0, 1, GVU_DEPTHSTENCIL);
 	}
 
 	void D3D11RenderWindowCore::destroySizeDependedD3DResources()

+ 137 - 117
BansheeD3D11RenderSystem/Source/BsD3D11Texture.cpp

@@ -11,20 +11,22 @@
 
 namespace BansheeEngine
 {
-	D3D11Texture::D3D11Texture()
-		: Texture(), m1DTex(nullptr), m2DTex(nullptr), m3DTex(nullptr), 
+	D3D11TextureCore::D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount),
+		m1DTex(nullptr), m2DTex(nullptr), m3DTex(nullptr), 
 		mTex(nullptr), mShaderResourceView(nullptr), mStagingBuffer(nullptr), 
 		mLockedSubresourceIdx(-1), mLockedForReading(false), mStaticBuffer(nullptr)
 	{ }
 
-	D3D11Texture::~D3D11Texture()
+	D3D11TextureCore::~D3D11TextureCore()
 	{ }
 
-	void D3D11Texture::initialize_internal()
+	void D3D11TextureCore::initialize()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		switch (getTextureType())
+		switch (mProperties.getTextureType())
 		{
 		case TEX_TYPE_1D:
 			create1DTex();
@@ -37,15 +39,14 @@ namespace BansheeEngine
 			create3DTex();
 			break;
 		default:
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Unknown texture type");
 		}
 
 		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
-		Texture::initialize_internal();
+		TextureCore::initialize();
 	}
 
-	void D3D11Texture::destroy_internal()
+	void D3D11TextureCore::destroy()
 	{
 		SAFE_RELEASE(mTex);
 		SAFE_RELEASE(mShaderResourceView);
@@ -55,20 +56,20 @@ namespace BansheeEngine
 		SAFE_RELEASE(mStagingBuffer);
 
 		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
-		Texture::destroy_internal();
+		TextureCore::destroy();
 	}
 
-	void D3D11Texture::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target)
+	void D3D11TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
 	{
-		D3D11Texture* other = static_cast<D3D11Texture*>(target.get());
+		D3D11TextureCore* other = static_cast<D3D11TextureCore*>(target.get());
 
-		UINT32 srcResIdx = D3D11CalcSubresource(srcMipLevel, srcFace, getNumMipmaps() + 1);
-		UINT32 destResIdx = D3D11CalcSubresource(destMipLevel, destFace, target->getNumMipmaps() + 1);
+		UINT32 srcResIdx = D3D11CalcSubresource(srcMipLevel, srcFace, mProperties.getNumMipmaps() + 1);
+		UINT32 destResIdx = D3D11CalcSubresource(destMipLevel, destFace, target->getProperties().getNumMipmaps() + 1);
 
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
 
-		if (getMultisampleCount() != target->getMultisampleCount()) // Resolving from MS to non-MS texture
+		if (mProperties.getMultisampleCount() != target->getProperties().getMultisampleCount()) // Resolving from MS to non-MS texture
 		{
 			device.getImmediateContext()->ResolveSubresource(other->getDX11Resource(), destResIdx, mTex, srcResIdx, mDXGIFormat);
 		}
@@ -84,9 +85,9 @@ namespace BansheeEngine
 		}
 	}
 
-	PixelData D3D11Texture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
+	PixelData D3D11TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 #if BS_PROFILING_ENABLED
@@ -101,11 +102,11 @@ namespace BansheeEngine
 		}
 #endif
 
-		UINT32 mipWidth = mWidth >> mipLevel;
-		UINT32 mipHeight = mHeight >> mipLevel;
-		UINT32 mipDepth = mDepth >> mipLevel;
+		UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
+		UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
+		UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
 
-		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mFormat);
+		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
 
 		D3D11_MAP flags = D3D11Mappings::getLockOptions(options);
 
@@ -121,7 +122,7 @@ namespace BansheeEngine
 		}
 		else
 		{
-			if(mUsage == TU_DYNAMIC)
+			if (mProperties.getUsage() == TU_DYNAMIC)
 			{
 				UINT8* data = (UINT8*)map(mTex, flags, face, mipLevel, rowPitch, slicePitch);
 				lockedArea.setExternalBuffer(data);
@@ -137,22 +138,22 @@ namespace BansheeEngine
 		return lockedArea;
 	}
 
-	void D3D11Texture::unlockImpl()
+	void D3D11TextureCore::unlockImpl()
 	{
 		if(mLockedForReading)
 			unmapstagingbuffer();
 		else
 		{
-			if(mUsage == TU_DYNAMIC)
+			if (mProperties.getUsage() == TU_DYNAMIC)
 				unmap(mTex);
 			else
 				unmapstaticbuffer();
 		}
 	}
 
-	void D3D11Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	void D3D11TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
@@ -170,31 +171,33 @@ namespace BansheeEngine
 		unlock();
 	}
 
-	void D3D11Texture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	void D3D11TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
 	{
-		if (mMultisampleCount > 0)
+		PixelFormat format = mProperties.getFormat();
+
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
-		if((mUsage & TU_DYNAMIC) != 0)
+		if ((mProperties.getUsage() & TU_DYNAMIC) != 0)
 		{
 			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
 			PixelUtil::bulkPixelConversion(src, myData);
 			unlock();
 		}
-		else if ((mUsage & TU_DEPTHSTENCIL) == 0)
+		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) == 0)
 		{
-			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
-			face = Math::clamp(face, (UINT32)0, mDepth - 1);
+			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
+			face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
 
-			if(getTextureType() == TEX_TYPE_3D)
+			if(mProperties.getTextureType() == TEX_TYPE_3D)
 				face = 0;
 
 			D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 			D3D11Device& device = rs->getPrimaryDevice();
 
-			UINT subresourceIdx = D3D11CalcSubresource(mipLevel, face, getNumMipmaps()+1);
-			UINT32 rowWidth = D3D11Mappings::getSizeInBytes(mFormat, src.getWidth());
-			UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(mFormat, src.getWidth(), src.getHeight());
+			UINT subresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1);
+			UINT32 rowWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth());
+			UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(format, src.getWidth(), src.getHeight());
 
 			device.getImmediateContext()->UpdateSubresource(mTex, subresourceIdx, nullptr, src.getData(), rowWidth, sliceWidth);
 
@@ -208,38 +211,45 @@ namespace BansheeEngine
 		}
 		else
 		{
-			BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mUsage));
+			BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
 		}
 	}
 
-	void D3D11Texture::create1DTex()
+	void D3D11TextureCore::create1DTex()
 	{
+		UINT32 width = mProperties.getWidth();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+		TextureType texType = mProperties.getTextureType();
+
 		// We must have those defined here
-		assert(mWidth > 0);
+		assert(width > 0);
 
 		// Determine which D3D11 pixel format we'll use
 		HRESULT hr;
-		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(mFormat, mHwGamma), mHwGamma);
+		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(format, hwGamma), hwGamma);
 
-		if (mFormat != D3D11Mappings::getPF(d3dPF))
+		if (format != D3D11Mappings::getPF(d3dPF))
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
 		}
 
 		D3D11_TEXTURE1D_DESC desc;
-		desc.Width			= static_cast<UINT32>(mWidth);
+		desc.Width = static_cast<UINT32>(width);
 		desc.ArraySize		= 1;
 		desc.Format			= d3dPF;
 		desc.MiscFlags		= 0;
 
-		if((mUsage & TU_RENDERTARGET) != 0)
+		if((usage & TU_RENDERTARGET) != 0)
 		{
 			desc.Usage			= D3D11_USAGE_DEFAULT;
 			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
 			desc.CPUAccessFlags = 0;
 			desc.MipLevels		= 1;
 		}
-		else if((mUsage & TU_DEPTHSTENCIL) != 0)
+		else if ((usage & TU_DEPTHSTENCIL) != 0)
 		{
 			desc.Usage			= D3D11_USAGE_DEFAULT;
 			desc.BindFlags		= D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
@@ -248,16 +258,15 @@ namespace BansheeEngine
 		}
 		else
 		{
-			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)mUsage);
+			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)usage);
 			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)mUsage);
+			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
 
 			// Determine total number of mipmaps including main one (d3d11 convention)
-			UINT32 numMips		= (mNumMipmaps == MIP_UNLIMITED || (1U << mNumMipmaps) > mWidth) ? 0 : mNumMipmaps + 1;
-			desc.MipLevels		= numMips;
+			desc.MipLevels = (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1;
 		}
 
-		if ((mUsage & TU_LOADSTORE) != 0)
+		if ((usage & TU_LOADSTORE) != 0)
 			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
 
 		// Create the texture
@@ -268,7 +277,6 @@ namespace BansheeEngine
 		// Check result and except if failed
 		if (FAILED(hr) || device.hasError())
 		{
-			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
 		}
@@ -277,24 +285,23 @@ namespace BansheeEngine
 
 		if(FAILED(hr) || device.hasError())
 		{
-			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
 		}
 
 		m1DTex->GetDesc(&desc);
 
-		if(mNumMipmaps != (desc.MipLevels - 1))
+		if(numMips != (desc.MipLevels - 1))
 		{
 			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
-				"Requested: " + toString(mNumMipmaps) + ". Got: " + toString(desc.MipLevels - 1) + ".");
+				"Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + ".");
 		}
 
 		mDXGIFormat = desc.Format;
 		mDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
 
 		// Create texture view
-		if((mUsage & TU_DEPTHSTENCIL) == 0)
+		if ((usage & TU_DEPTHSTENCIL) == 0)
 		{
 			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
 			mSRVDesc.Format = desc.Format;
@@ -310,28 +317,37 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D11Texture::create2DTex()
+	void D3D11TextureCore::create2DTex()
 	{
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+		UINT32 sampleCount = mProperties.getMultisampleCount();
+		TextureType texType = mProperties.getTextureType();
+
 		// We must have those defined here
-		assert(mWidth > 0 || mHeight > 0);
+		assert(width > 0 || height > 0);
 
 		// Determine which D3D11 pixel format we'll use
 		HRESULT hr;
-		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(mFormat, mHwGamma), mHwGamma);
+		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(format, hwGamma), hwGamma);
 
-		if (mFormat != D3D11Mappings::getPF(d3dPF))
+		if (format != D3D11Mappings::getPF(d3dPF))
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
 		}
 
 		D3D11_TEXTURE2D_DESC desc;
-		desc.Width			= static_cast<UINT32>(mWidth);
-		desc.Height			= static_cast<UINT32>(mHeight);
+		desc.Width			= static_cast<UINT32>(width);
+		desc.Height			= static_cast<UINT32>(height);
 		desc.ArraySize		= 1;
 		desc.Format			= d3dPF;
 		desc.MiscFlags		= 0;
 
-		if((mUsage & TU_RENDERTARGET) != 0)
+		if((usage & TU_RENDERTARGET) != 0)
 		{
 			desc.Usage			= D3D11_USAGE_DEFAULT;
 			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
@@ -340,15 +356,15 @@ namespace BansheeEngine
 
 			DXGI_SAMPLE_DESC sampleDesc;
 			D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
-			rs->determineMultisampleSettings(mMultisampleCount, d3dPF, &sampleDesc);
+			rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc);
 			desc.SampleDesc		= sampleDesc;
 
-			if(getTextureType() == TEX_TYPE_CUBE_MAP)
+			if (texType == TEX_TYPE_CUBE_MAP)
 			{
 				BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a render target."); // TODO: Will be once I add proper texture array support
 			}
 		}
-		else if((mUsage & TU_DEPTHSTENCIL) != 0)
+		else if((usage & TU_DEPTHSTENCIL) != 0)
 		{
 			desc.Usage			= D3D11_USAGE_DEFAULT;
 			desc.BindFlags		= D3D11_BIND_DEPTH_STENCIL;
@@ -357,23 +373,22 @@ namespace BansheeEngine
 
 			DXGI_SAMPLE_DESC sampleDesc;
 			D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
-			rs->determineMultisampleSettings(mMultisampleCount, d3dPF, &sampleDesc);
+			rs->determineMultisampleSettings(sampleCount, d3dPF, &sampleDesc);
 			desc.SampleDesc		= sampleDesc;
 
-			if(getTextureType() == TEX_TYPE_CUBE_MAP)
+			if (texType == TEX_TYPE_CUBE_MAP)
 			{
 				BS_EXCEPT(NotImplementedException, "Cube map not yet supported as a depth stencil target."); // TODO: Will be once I add proper texture array support
 			}
 		}
 		else
 		{
-			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)mUsage);
+			desc.Usage = D3D11Mappings::getUsage((GpuBufferUsage)usage);
 			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)mUsage);
+			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
 
 			// Determine total number of mipmaps including main one (d3d11 convention)
-			UINT32 numMips = (mNumMipmaps == MIP_UNLIMITED || (1U << mNumMipmaps) > mWidth) ? 0 : mNumMipmaps + 1;
-			desc.MipLevels		= numMips;
+			desc.MipLevels		= (numMips == MIP_UNLIMITED || (1U << numMips) > width) ? 0 : numMips + 1;
 
 			DXGI_SAMPLE_DESC sampleDesc;
 			sampleDesc.Count	= 1;
@@ -381,13 +396,13 @@ namespace BansheeEngine
 			desc.SampleDesc		= sampleDesc;
 		}
 
-        if (getTextureType() == TEX_TYPE_CUBE_MAP)
+		if (texType == TEX_TYPE_CUBE_MAP)
         {
             desc.MiscFlags      |= D3D11_RESOURCE_MISC_TEXTURECUBE;
             desc.ArraySize       = 6;
         }
 
-		if ((mUsage & TU_LOADSTORE) != 0)
+		if ((usage & TU_LOADSTORE) != 0)
 			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
 
 		// Create the texture
@@ -398,7 +413,6 @@ namespace BansheeEngine
 		// Check result and except if failed
 		if (FAILED(hr) || device.hasError())
 		{
-			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
 		}
@@ -407,30 +421,29 @@ namespace BansheeEngine
 
 		if(FAILED(hr) || device.hasError())
 		{
-			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
 		}
 
 		m2DTex->GetDesc(&desc);
 
-		if(mNumMipmaps != (desc.MipLevels - 1))
+		if(numMips != (desc.MipLevels - 1))
 		{
 			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
-				"Requested: " + toString(mNumMipmaps) + ". Got: " + toString(desc.MipLevels - 1) + ".");
+				"Requested: " + toString(numMips) + ". Got: " + toString(desc.MipLevels - 1) + ".");
 		}
 
 		mDXGIFormat = desc.Format;
 
 		// Create shader texture view
-		if((mUsage & TU_DEPTHSTENCIL) == 0)
+		if((usage & TU_DEPTHSTENCIL) == 0)
 		{
 			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
 			mSRVDesc.Format = desc.Format;
 
-			if((mUsage & TU_RENDERTARGET) != 0)
+			if((usage & TU_RENDERTARGET) != 0)
 			{
-				if(mMultisampleCount > 0)
+				if (sampleCount > 0)
 				{
 					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
 					mSRVDesc.Texture2D.MostDetailedMip = 0;
@@ -445,7 +458,7 @@ namespace BansheeEngine
 			}
 			else
 			{
-				switch(getTextureType())
+				switch (texType)
 				{
 				case TEX_TYPE_CUBE_MAP:
 					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
@@ -472,42 +485,51 @@ namespace BansheeEngine
 		}
 		else
 		{
-			if(mMultisampleCount > 0)
+			if (sampleCount > 0)
 				mDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
 			else
 				mDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
 		}
 	}
 
-	void D3D11Texture::create3DTex()
+	void D3D11TextureCore::create3DTex()
 	{
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		UINT32 depth = mProperties.getDepth();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+
 		// We must have those defined here
-		assert(mWidth > 0 && mHeight > 0 && mDepth > 0);
+		assert(width > 0 && height > 0 && depth > 0);
 
 		// Determine which D3D11 pixel format we'll use
 		HRESULT hr;
-		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(D3D11Mappings::getClosestSupportedPF(mFormat, mHwGamma), mHwGamma);
+		DXGI_FORMAT d3dPF = D3D11Mappings::getPF(
+			D3D11Mappings::getClosestSupportedPF(format, hwGamma), hwGamma);
 		
-		if (mFormat != D3D11Mappings::getPF(d3dPF))
+		if (format != D3D11Mappings::getPF(d3dPF))
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
 		}
 
 		D3D11_TEXTURE3D_DESC desc;
-		desc.Width			= static_cast<UINT32>(mWidth);
-		desc.Height			= static_cast<UINT32>(mHeight);
-		desc.Depth			= static_cast<UINT32>(mDepth);
+		desc.Width = static_cast<UINT32>(width);
+		desc.Height = static_cast<UINT32>(height);
+		desc.Depth = static_cast<UINT32>(depth);
 		desc.Format			= d3dPF;
 		desc.MiscFlags		= 0;
 
-		if((mUsage & TU_RENDERTARGET) != 0)
+		if ((mProperties.getUsage() & TU_RENDERTARGET) != 0)
 		{
 			desc.Usage			= D3D11_USAGE_DEFAULT;
 			desc.BindFlags		= D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
 			desc.CPUAccessFlags = 0;
 			desc.MipLevels		= 1;
 		}
-		else if((mUsage & TU_DEPTHSTENCIL) != 0)
+		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
 		{
 			desc.Usage			= D3D11_USAGE_DEFAULT;
 			desc.BindFlags		= D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
@@ -516,16 +538,16 @@ namespace BansheeEngine
 		}
 		else
 		{
-			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)mUsage);
+			desc.Usage			= D3D11Mappings::getUsage((GpuBufferUsage)usage);
 			desc.BindFlags		= D3D11_BIND_SHADER_RESOURCE;
-			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)mUsage);
+			desc.CPUAccessFlags = D3D11Mappings::getAccessFlags((GpuBufferUsage)usage);
 
 			// Determine total number of mipmaps including main one (d3d11 convention)
-			UINT numMips = (mNumMipmaps == MIP_UNLIMITED || (1U << mNumMipmaps) > std::max(std::max(mWidth, mHeight), mDepth)) ? 0 : mNumMipmaps + 1;
-			desc.MipLevels		= numMips;
+			desc.MipLevels		= (numMips == MIP_UNLIMITED || (1U << numMips)
+				> std::max(std::max(width, height), depth)) ? 0 : numMips + 1;
 		}
 
-		if ((mUsage & TU_LOADSTORE) != 0)
+		if ((usage & TU_LOADSTORE) != 0)
 			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
 
 		// Create the texture
@@ -536,7 +558,6 @@ namespace BansheeEngine
 		// Check result and except if failed
 		if (FAILED(hr) || device.hasError())
 		{
-			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
 		}
@@ -545,7 +566,6 @@ namespace BansheeEngine
 
 		if(FAILED(hr) || device.hasError())
 		{
-			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			BS_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
 		}
@@ -553,16 +573,16 @@ namespace BansheeEngine
 		// Create texture view
 		m3DTex->GetDesc(&desc);
 
-		if(mNumMipmaps != (desc.MipLevels - 1))
+		if (mProperties.getNumMipmaps() != (desc.MipLevels - 1))
 		{
 			BS_EXCEPT(RenderingAPIException, "Driver returned different number of mip maps than requested. " \
-               "Requested: " + toString(mNumMipmaps) + ". Got: " + toString(desc.MipLevels - 1) + ".");
+				"Requested: " + toString(mProperties.getNumMipmaps()) + ". Got: " + toString(desc.MipLevels - 1) + ".");
 		}
 
 		mDXGIFormat = desc.Format;
 		mDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
 
-		if((mUsage & TU_DEPTHSTENCIL) == 0)
+		if ((usage & TU_DEPTHSTENCIL) == 0)
 		{
 			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
 			mSRVDesc.Format = desc.Format;
@@ -580,21 +600,21 @@ namespace BansheeEngine
 		}
 	}
 
-	void* D3D11Texture::map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
+	void* D3D11TextureCore::map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
 	{
 		D3D11_MAPPED_SUBRESOURCE pMappedResource;
 		pMappedResource.pData = nullptr;
 
-		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
-		face = Math::clamp(face, (UINT32)0, mDepth - 1);
+		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
+		face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
 
-		if(getTextureType() == TEX_TYPE_3D)
+		if (mProperties.getTextureType() == TEX_TYPE_3D)
 			face = 0;
 
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
 
-		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, getNumMipmaps()+1);
+		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps() + 1);
 		device.getImmediateContext()->Map(res, mLockedSubresourceIdx, flags, 0, &pMappedResource);
 
 		if (device.hasError())
@@ -603,14 +623,14 @@ namespace BansheeEngine
 			BS_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
 		}
 
-		UINT32 bytesPerPixel = PixelUtil::getNumElemBytes(getFormat());
+		UINT32 bytesPerPixel = PixelUtil::getNumElemBytes(mProperties.getFormat());
 		rowPitch = pMappedResource.RowPitch / bytesPerPixel;
 		slicePitch = pMappedResource.DepthPitch / bytesPerPixel;
 
 		return pMappedResource.pData;
 	}
 
-	void D3D11Texture::unmap(ID3D11Resource* res)
+	void D3D11TextureCore::unmap(ID3D11Resource* res)
 	{
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
@@ -623,7 +643,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void* D3D11Texture::mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
+	void* D3D11TextureCore::mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
 	{
 		// Note: I am creating and destroying a staging resource every time a texture is read. 
 		// Consider offering a flag on init that will keep this active all the time (at the cost of double memory).
@@ -639,16 +659,16 @@ namespace BansheeEngine
 		return map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch);
 	}
 
-	void D3D11Texture::unmapstagingbuffer()
+	void D3D11TextureCore::unmapstagingbuffer()
 	{
 		unmap(mStagingBuffer);
 		SAFE_RELEASE(mStagingBuffer);
 	}
 
-	void* D3D11Texture::mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 face)
+	void* D3D11TextureCore::mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 face)
 	{
 		UINT32 sizeOfImage = lock.getConsecutiveSize();
-		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, getNumMipmaps()+1);
+		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, mProperties.getNumMipmaps()+1);
 
 		mStaticBuffer = bs_new<PixelData, PoolAlloc>(lock.getWidth(), lock.getHeight(), lock.getDepth(), lock.getFormat());
 		mStaticBuffer->allocateInternalBuffer();
@@ -656,7 +676,7 @@ namespace BansheeEngine
 		return mStaticBuffer->getData();
 	}
 
-	void D3D11Texture::unmapstaticbuffer()
+	void D3D11TextureCore::unmapstaticbuffer()
 	{
 		UINT32 rowWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth());
 		UINT32 sliceWidth = D3D11Mappings::getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth(), mStaticBuffer->getHeight());
@@ -675,11 +695,11 @@ namespace BansheeEngine
 			bs_delete<PoolAlloc>(mStaticBuffer);
 	}
 
-	void D3D11Texture::createStagingBuffer()
+	void D3D11TextureCore::createStagingBuffer()
 	{
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
-		switch (getTextureType())
+		switch (mProperties.getTextureType())
 		{
 		case TEX_TYPE_1D:
 			{
@@ -724,7 +744,7 @@ namespace BansheeEngine
 		}
 	}
 
-	TextureViewPtr D3D11Texture::createView()
+	TextureViewPtr D3D11TextureCore::createView()
 	{
 		TextureViewPtr viewPtr = bs_core_ptr<D3D11TextureView, PoolAlloc>(new (bs_alloc<D3D11TextureView, PoolAlloc>()) D3D11TextureView());
 		viewPtr->_setThisPtr(viewPtr);

+ 9 - 7
BansheeD3D11RenderSystem/Source/BsD3D11TextureManager.cpp

@@ -7,13 +7,6 @@
 
 namespace BansheeEngine
 {
-	TexturePtr D3D11TextureManager::createTextureImpl()
-	{
-		D3D11Texture* tex = new (bs_alloc<D3D11Texture, PoolAlloc>()) D3D11Texture(); 
-
-		return bs_core_ptr<D3D11Texture, PoolAlloc>(tex);
-	}
-
 	RenderTexturePtr D3D11TextureManager::createRenderTextureImpl(const RENDER_TEXTURE_DESC& desc)
 	{
 		D3D11RenderTexture* tex = new (bs_alloc<D3D11RenderTexture, PoolAlloc>()) D3D11RenderTexture(desc);
@@ -36,6 +29,15 @@ namespace BansheeEngine
 		return D3D11Mappings::getPF(d3dPF);
 	}
 
+	SPtr<TextureCore> D3D11TextureCoreManager::createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+	{
+		D3D11TextureCore* tex = new (bs_alloc<D3D11TextureCore>()) D3D11TextureCore(texType, 
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
+
+		return bs_shared_ptr<D3D11TextureCore, GenAlloc>(tex);
+	}
+
 	SPtr<RenderTextureCore> D3D11TextureCoreManager::createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc)
 	{
 		return bs_shared_ptr<D3D11RenderTextureCore>(desc);

+ 15 - 12
BansheeD3D11RenderSystem/Source/BsD3D11TextureView.cpp

@@ -16,7 +16,7 @@ namespace BansheeEngine
 
 	void D3D11TextureView::initialize_internal()
 	{
-		D3D11Texture* d3d11Texture = static_cast<D3D11Texture*>(mOwnerTexture.get());
+		D3D11TextureCore* d3d11Texture = static_cast<D3D11TextureCore*>(mOwnerTexture.get());
 
 		if((mDesc.usage & GVU_RANDOMWRITE) != 0)
 			mUAV = createUAV(d3d11Texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
@@ -42,13 +42,14 @@ namespace BansheeEngine
 		TextureView::destroy_internal();
 	}
 
-	ID3D11ShaderResourceView* D3D11TextureView::createSRV(D3D11Texture* texture, 
+	ID3D11ShaderResourceView* D3D11TextureView::createSRV(D3D11TextureCore* texture, 
 		UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices)
 	{
 		D3D11_SHADER_RESOURCE_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
 
-		switch(texture->getTextureType())
+		const TextureProperties& texProps = texture->getProperties();
+		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
 			desc.Texture1D.MipLevels = numMips;
@@ -56,7 +57,7 @@ namespace BansheeEngine
 			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
 			break;
 		case TEX_TYPE_2D:
-			if (texture->getMultisampleCount() > 0)
+			if (texProps.getMultisampleCount() > 0)
 			{
 				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
 			}
@@ -97,20 +98,21 @@ namespace BansheeEngine
 		return srv;
 	}
 
-	ID3D11RenderTargetView* D3D11TextureView::createRTV(D3D11Texture* texture, 
+	ID3D11RenderTargetView* D3D11TextureView::createRTV(D3D11TextureCore* texture,
 		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
 	{
 		D3D11_RENDER_TARGET_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
 
-		switch(texture->getTextureType())
+		const TextureProperties& texProps = texture->getProperties();
+		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
 			desc.Texture1D.MipSlice = mipSlice;
 			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
 			break;
 		case TEX_TYPE_2D:
-			if (texture->getMultisampleCount() > 0)
+			if (texProps.getMultisampleCount() > 0)
 			{
 				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
 			}
@@ -152,13 +154,13 @@ namespace BansheeEngine
 		return rtv;
 	}
 
-	ID3D11UnorderedAccessView* D3D11TextureView::createUAV(D3D11Texture* texture,
+	ID3D11UnorderedAccessView* D3D11TextureView::createUAV(D3D11TextureCore* texture,
 		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
 	{
 		D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
 
-		switch(texture->getTextureType())
+		switch(texture->getProperties().getTextureType())
 		{
 		case TEX_TYPE_1D:
 			desc.Texture1D.MipSlice = mipSlice;
@@ -200,20 +202,21 @@ namespace BansheeEngine
 		return uav;
 	}
 
-	ID3D11DepthStencilView* D3D11TextureView::createDSV(D3D11Texture* texture, 
+	ID3D11DepthStencilView* D3D11TextureView::createDSV(D3D11TextureCore* texture,
 		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices)
 	{
 		D3D11_DEPTH_STENCIL_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
 
-		switch(texture->getTextureType())
+		const TextureProperties& texProps = texture->getProperties();
+		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
 			desc.Texture1D.MipSlice = mipSlice;
 			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
 			break;
 		case TEX_TYPE_2D:
-			if (texture->getMultisampleCount() > 0)
+			if (texProps.getMultisampleCount() > 0)
 			{
 				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
 			}

+ 2 - 2
BansheeD3D9RenderSystem/Include/BsD3D9PixelBuffer.h

@@ -25,7 +25,7 @@ namespace BansheeEngine
 		};
 
 	public:
-		D3D9PixelBuffer(GpuBufferUsage usage, D3D9Texture* ownerTexture);
+		D3D9PixelBuffer(GpuBufferUsage usage, D3D9TextureCore* ownerTexture);
 		~D3D9PixelBuffer();
 
 		/**
@@ -137,7 +137,7 @@ namespace BansheeEngine
 		bool mDoMipmapGen;
 		bool mHWMipmaps;
 
-		D3D9Texture* mOwnerTexture;
+		D3D9TextureCore* mOwnerTexture;
 		DWORD mLockFlags;
 	};
 };

+ 1 - 2
BansheeD3D9RenderSystem/Include/BsD3D9Prerequisites.h

@@ -29,7 +29,7 @@ namespace BansheeEngine
 	class D3D9RenderSystem;
 	class D3D9RenderWindow;
 	class D3D9RenderWindowCore;
-	class D3D9Texture;
+	class D3D9TextureCore;
 	class D3D9TextureManager;
 	class D3D9Driver;
 	class D3D9DriverList;
@@ -48,7 +48,6 @@ namespace BansheeEngine
 	class D3D9Resource;
 
 	typedef std::shared_ptr<D3D9RenderWindow> D3D9RenderWindowPtr;
-	typedef std::shared_ptr<D3D9Texture> D3D9TexturePtr;
 
 	/**
 	 * @brief	Type IDs used for RTTI.

+ 2 - 2
BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h

@@ -73,12 +73,12 @@ namespace BansheeEngine
 		/**
 		 * @copydoc RenderSystem::setTexture()
 		 */
-		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr);
 
 		/**
 		 * @copydoc RenderSystem::setLoadStoreTexture()
 		 */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
 			const TextureSurface& surface);
 
 		/**

+ 16 - 15
BansheeD3D9RenderSystem/Include/BsD3D9Texture.h

@@ -12,7 +12,7 @@ namespace BansheeEngine
 	/**
 	 * @brief	DirectX 9 implementation of a texture.
 	 */
-	class BS_D3D9_EXPORT D3D9Texture : public Texture, public D3D9Resource
+	class BS_D3D9_EXPORT D3D9TextureCore : public TextureCore, public D3D9Resource
 	{
 	protected:
 		/**
@@ -29,7 +29,7 @@ namespace BansheeEngine
 		};
 
 	public:
-		~D3D9Texture();
+		~D3D9TextureCore();
 
 		/**
 		 * @copydoc Texture::isBindableAsShaderResource
@@ -54,7 +54,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Indicates whether the hardware gamma is enabled and supported.
 		 */
-		bool isHardwareGammaReadToBeUsed() const { return mHwGamma && mHwGammaReadSupported; }
+		bool isHardwareGammaReadToBeUsed() const { return mProperties.isHardwareGammaEnabled() && mHwGammaReadSupported; }
 					
 		/**
 		 * @brief	Returns a hardware pixel buffer for a certain face and level of the texture.
@@ -88,43 +88,44 @@ namespace BansheeEngine
 		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
 
 	protected:	
-		friend class D3D9TextureManager;
+		friend class D3D9TextureCoreManager;
 		friend class D3D9PixelBuffer;
 
-		D3D9Texture();
+		D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
 
 		/**
-		 * @copydoc Texture::initialize_internal()
+		 * @copydoc TextureCore::initialize
 		 */
-		void initialize_internal();	
+		void initialize();
 		
 		/**
-		 * @copydoc Texture::destroy_internal()
+		 * @copydoc TextureCore::destroy
 		 */
-		void destroy_internal();
+		void destroy();
 
 		/**
-		 * @copydoc Texture::lock
+		 * @copydoc TextureCore::lock
 		 */
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 
 		/**
-		 * @copydoc Texture::unlock
+		 * @copydoc TextureCore::unlock
 		 */
 		void unlockImpl();
 
 		/**
-		 * @copydoc Texture::copy
+		 * @copydoc TextureCore::copy
 		 */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target);
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target);
 
 		/**
-		 * @copydoc Texture::readData
+		 * @copydoc TextureCore::readData
 		 */
 		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
 
 		/**
-		 * @copydoc Texture::writeData
+		 * @copydoc TextureCore::writeData
 		 */
 		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false);
 

+ 7 - 5
BansheeD3D9RenderSystem/Include/BsD3D9TextureManager.h

@@ -21,11 +21,6 @@ namespace BansheeEngine
 		PixelFormat getNativeFormat(TextureType ttype, PixelFormat format, int usage, bool hwGamma);
 
 	protected:	
-		/**
-		 * @copydoc TextureManager::createTextureImpl
-		 */
-		TexturePtr createTextureImpl();
-
 		/**
 		 * @copydoc TextureManager::createRenderTextureImpl
 		 */
@@ -43,6 +38,13 @@ namespace BansheeEngine
 	class BS_D3D9_EXPORT D3D9TextureCoreManager : public TextureCoreManager
 	{
 	protected:		
+		/**
+		 * @copydoc	TextureCoreManager::createTextureInternal
+		 */
+		SPtr<TextureCore> createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false,
+			UINT32 multisampleCount = 0);
+
 		/**
 		 * @copydoc	TextureCoreManager::createRenderTextureInternal
 		 */

+ 4 - 4
BansheeD3D9RenderSystem/Source/BsD3D9MultiRenderTexture.cpp

@@ -21,8 +21,8 @@ namespace BansheeEngine
 		{
 			if (mColorSurfaces[i] != nullptr)
 			{
-				D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurfaces[i]->getTexture().get());
-				if (d3d9texture->getTextureType() != TEX_TYPE_3D)
+				D3D9TextureCore* d3d9texture = static_cast<D3D9TextureCore*>(mColorSurfaces[i]->getTexture().get());
+				if (d3d9texture->getProperties().getTextureType() != TEX_TYPE_3D)
 				{
 					D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
 						d3d9texture->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice, mColorSurfaces[i]->getDesc().mostDetailMip).get());
@@ -39,9 +39,9 @@ namespace BansheeEngine
 
 		if (mDepthStencilSurface != nullptr)
 		{
-			D3D9Texture* d3d9DepthStencil = static_cast<D3D9Texture*>(mDepthStencilSurface->getTexture().get());
+			D3D9TextureCore* d3d9DepthStencil = static_cast<D3D9TextureCore*>(mDepthStencilSurface->getTexture().get());
 
-			if (d3d9DepthStencil->getTextureType() != TEX_TYPE_3D)
+			if (d3d9DepthStencil->getProperties().getTextureType() != TEX_TYPE_3D)
 			{
 				D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
 					d3d9DepthStencil->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice, mDepthStencilSurface->getDesc().mostDetailMip).get());

+ 1 - 1
BansheeD3D9RenderSystem/Source/BsD3D9PixelBuffer.cpp

@@ -34,7 +34,7 @@ namespace BansheeEngine
 		return pbox;
 	}
 
-	D3D9PixelBuffer::D3D9PixelBuffer(GpuBufferUsage usage, D3D9Texture* ownerTexture)
+	D3D9PixelBuffer::D3D9PixelBuffer(GpuBufferUsage usage, D3D9TextureCore* ownerTexture)
 		:PixelBuffer(0, 0, 0, PF_UNKNOWN, usage, false),
 		 mDoMipmapGen(0), mHWMipmaps(0), mOwnerTexture(ownerTexture)
 	{ }

+ 5 - 5
BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp

@@ -299,7 +299,7 @@ namespace BansheeEngine
 			if(!texture.isLoaded())
 				setTexture(gptype, iter->second.slot, false, nullptr);
 			else
-				setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+				setTexture(gptype, iter->second.slot, true, texture->getCore());
 		}
 
 		// Read all the buffer data so we can assign it. Not the most efficient way of accessing data
@@ -438,7 +438,7 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumGpuParamBufferBinds);
 	}
 
-	void D3D9RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& tex)
+	void D3D9RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& tex)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -457,7 +457,7 @@ namespace BansheeEngine
 		}
 
 		HRESULT hr;
-		D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
+		SPtr<D3D9TextureCore> dt = std::static_pointer_cast<D3D9TextureCore>(tex);
 		if (enabled && (dt != nullptr))
 		{
 			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
@@ -472,7 +472,7 @@ namespace BansheeEngine
 
 				// set stage desc.
 				mTexStageDesc[unit].pTex = pTex;
-				mTexStageDesc[unit].texType = D3D9Mappings::get(dt->getTextureType());
+				mTexStageDesc[unit].texType = D3D9Mappings::get(dt->getProperties().getTextureType());
 
 				// Set gamma now too
 				if (dt->isHardwareGammaReadToBeUsed())
@@ -516,7 +516,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D9RenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+	void D3D9RenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
 		const TextureSurface& surface)
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 2 - 2
BansheeD3D9RenderSystem/Source/BsD3D9RenderTexture.cpp

@@ -23,12 +23,12 @@ namespace BansheeEngine
 
 	void D3D9RenderTextureCore::initializeSurfaces()
 	{
-		D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurface->getTexture().get());
+		D3D9TextureCore* d3d9texture = static_cast<D3D9TextureCore*>(mColorSurface->getTexture().get());
 		D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
 			d3d9texture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip()).get());
 		mDX9ColorSurface = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
 
-		D3D9Texture* d3d9DepthStencil = static_cast<D3D9Texture*>(mDepthStencilSurface->getTexture().get());
+		D3D9TextureCore* d3d9DepthStencil = static_cast<D3D9TextureCore*>(mDepthStencilSurface->getTexture().get());
 		D3D9PixelBuffer* depthStencilBuffer = static_cast<D3D9PixelBuffer*>(
 			d3d9DepthStencil->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip()).get());
 		mDX9DepthStencilSurface = depthStencilBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());

+ 162 - 141
BansheeD3D9RenderSystem/Source/BsD3D9Texture.cpp

@@ -13,18 +13,18 @@
 
 namespace BansheeEngine 
 {
-	
-    D3D9Texture::D3D9Texture()
-        :Texture(), mD3DPool(D3DPOOL_MANAGED), mDynamicTextures(false),
-		mHwGammaReadSupported(false), mHwGammaWriteSupported(false), mMultisampleType(D3DMULTISAMPLE_NONE),
-		mMultisampleQuality(0), mIsBindableAsShaderResource(true)
+	D3D9TextureCore::D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+		:TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount),
+		mD3DPool(D3DPOOL_MANAGED), mDynamicTextures(false), mHwGammaReadSupported(false), mHwGammaWriteSupported(false), 
+		mMultisampleType(D3DMULTISAMPLE_NONE), mMultisampleQuality(0), mIsBindableAsShaderResource(true)
 	{ }
 	
-	D3D9Texture::~D3D9Texture()
+	D3D9TextureCore::~D3D9TextureCore()
 	{	
 	}
 
-	void D3D9Texture::initialize_internal()
+	void D3D9TextureCore::initialize()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -36,10 +36,10 @@ namespace BansheeEngine
 		}
 
 		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
-		Texture::initialize_internal();
+		TextureCore::initialize();
 	}
 
-	void D3D9Texture::destroy_internal()
+	void D3D9TextureCore::destroy()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -62,25 +62,25 @@ namespace BansheeEngine
 		mSurfaceList.clear();
 
 		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
-		Texture::destroy_internal();
+		TextureCore::destroy();
 	}
 
-	PixelData D3D9Texture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
+	PixelData D3D9TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 		if(mLockedBuffer != nullptr)
 			BS_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
 
-		if(getUsage() == TU_DEPTHSTENCIL)
+		if (mProperties.getUsage() == TU_DEPTHSTENCIL)
 			BS_EXCEPT(InternalErrorException, "Cannot lock a depth stencil texture.");
 
-		UINT32 mipWidth = mWidth >> mipLevel;
-		UINT32 mipHeight = mHeight >> mipLevel;
-		UINT32 mipDepth = mDepth >> mipLevel;
+		UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
+		UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
+		UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
 
-		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mFormat);
+		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
 
 		mLockedBuffer = getBuffer(face, mipLevel);
 		lockedArea.setExternalBuffer((UINT8*)mLockedBuffer->lock(options));
@@ -88,7 +88,7 @@ namespace BansheeEngine
 		return lockedArea;
 	}
 	
-	void D3D9Texture::unlockImpl()
+	void D3D9TextureCore::unlockImpl()
 	{
 		if(mLockedBuffer == nullptr)
 			BS_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
@@ -97,19 +97,19 @@ namespace BansheeEngine
 		mLockedBuffer = nullptr;
 	}
 
-	void D3D9Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	void D3D9TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
-		if (mUsage == TU_DEPTHSTENCIL || mUsage == TU_RENDERTARGET) // Render targets cannot be locked normally
+		if (mProperties.getUsage() == TU_DEPTHSTENCIL || mProperties.getUsage() == TU_RENDERTARGET) // Render targets cannot be locked normally
 		{
 			IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
 
 			D3D9PixelBuffer* sourceBuffer = static_cast<D3D9PixelBuffer*>(getBuffer(face, mipLevel).get());
 			
-			UINT32 mipWidth = mWidth >> mipLevel;
-			UINT32 mipHeight = mHeight >> mipLevel;
+			UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
+			UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
 			D3DFORMAT format = chooseD3DFormat(device);
 
 			// Note: I'm allocating and releasing a texture every time we read.
@@ -141,7 +141,7 @@ namespace BansheeEngine
 				BS_EXCEPT(RenderingAPIException, "Failed to retrieve render target data: " + msg);
 			}
 
-			PixelData myData(mipWidth, mipHeight, 1, mFormat);
+			PixelData myData(mipWidth, mipHeight, 1, mProperties.getFormat());
 
 			D3DLOCKED_RECT lrect;
 			hr = stagingSurface->LockRect(&lrect, nullptr, D3DLOCK_READONLY);
@@ -188,12 +188,12 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D9Texture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	void D3D9TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
-		if(mUsage == TU_DYNAMIC || mUsage == TU_STATIC)
+		if (mProperties.getUsage() == TU_DYNAMIC || mProperties.getUsage() == TU_STATIC)
 		{
 			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
 			PixelUtil::bulkPixelConversion(src, myData);
@@ -201,19 +201,21 @@ namespace BansheeEngine
 		}
 		else
 		{
-			BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mUsage));
+			BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
 		}
 	}
 	
-	void D3D9Texture::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target)
+	void D3D9TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (getTextureType() == TEX_TYPE_1D || getTextureType() == TEX_TYPE_3D)
+		TextureType texType = mProperties.getTextureType();
+
+		if (texType == TEX_TYPE_1D || texType == TEX_TYPE_3D)
 			BS_EXCEPT(NotImplementedException, "Copy not implemented for 1D and 3D textures yet.");
 
         HRESULT hr;
-		D3D9Texture *other = static_cast<D3D9Texture*>(target.get());
+		D3D9TextureCore* other = static_cast<D3D9TextureCore*>(target.get());
 
 		for (auto& resPair : mMapDeviceToTextureResources)
 		{
@@ -223,7 +225,7 @@ namespace BansheeEngine
 			IDirect3DSurface9 *sourceSurface = nullptr;
 			IDirect3DSurface9 *destSurface = nullptr;
 
-			if (getTextureType() == TEX_TYPE_2D && srcTextureResource->pNormTex != nullptr && dstTextureResource->pNormTex != nullptr)
+			if (texType == TEX_TYPE_2D && srcTextureResource->pNormTex != nullptr && dstTextureResource->pNormTex != nullptr)
 			{			
 				if(FAILED(hr = srcTextureResource->pNormTex->GetSurfaceLevel(srcMipLevel, &sourceSurface)))
 				{
@@ -237,7 +239,7 @@ namespace BansheeEngine
 					BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
 				}
 			}
-			else if (getTextureType() == TEX_TYPE_CUBE_MAP && srcTextureResource->pCubeTex != nullptr && dstTextureResource->pCubeTex != nullptr)
+			else if (texType == TEX_TYPE_CUBE_MAP && srcTextureResource->pCubeTex != nullptr && dstTextureResource->pCubeTex != nullptr)
 			{				
 				IDirect3DSurface9 *sourceSurface = nullptr;
 				if (FAILED(hr = srcTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)srcFace, srcMipLevel, &sourceSurface)))
@@ -274,7 +276,7 @@ namespace BansheeEngine
 		}		
 	}
 	
-	D3D9Texture::TextureResources* D3D9Texture::getTextureResources(IDirect3DDevice9* d3d9Device)
+	D3D9TextureCore::TextureResources* D3D9TextureCore::getTextureResources(IDirect3DDevice9* d3d9Device)
 	{		
 		auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
 
@@ -284,7 +286,7 @@ namespace BansheeEngine
 		return iterFind->second;
 	}
 
-	D3D9Texture::TextureResources* D3D9Texture::allocateTextureResources(IDirect3DDevice9* d3d9Device)
+	D3D9TextureCore::TextureResources* D3D9TextureCore::allocateTextureResources(IDirect3DDevice9* d3d9Device)
 	{
 		assert(mMapDeviceToTextureResources.find(d3d9Device) == mMapDeviceToTextureResources.end());
 
@@ -302,7 +304,7 @@ namespace BansheeEngine
 		return textureResources;
 	}
 	
-	void D3D9Texture::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9Texture::TextureResources* textureResources)
+	void D3D9TextureCore::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9TextureCore::TextureResources* textureResources)
 	{		
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -323,14 +325,16 @@ namespace BansheeEngine
 		SAFE_RELEASE(textureResources->pDepthStencilSurface);
 	}
 	
-	UINT32 D3D9Texture::calculateSize() const
+	UINT32 D3D9TextureCore::calculateSize() const
 	{
-		UINT32 instanceSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+		UINT32 instanceSize = mProperties.getNumFaces() * 
+			PixelUtil::getMemorySize(mProperties.getWidth(), mProperties.getHeight(), 
+			mProperties.getDepth(), mProperties.getFormat());
 
 		return instanceSize * (UINT32)mMapDeviceToTextureResources.size();
 	}
 	
-	void D3D9Texture::determinePool()
+	void D3D9TextureCore::determinePool()
 	{
 		if (useDefaultPool())
 			mD3DPool = D3DPOOL_DEFAULT;
@@ -338,9 +342,9 @@ namespace BansheeEngine
 			mD3DPool = D3DPOOL_MANAGED;
 	}
 	
-	void D3D9Texture::createInternalResources(IDirect3DDevice9* d3d9Device)
+	void D3D9TextureCore::createInternalResources(IDirect3DDevice9* d3d9Device)
 	{		
-		switch (getTextureType())
+		switch (mProperties.getTextureType())
 		{
 		case TEX_TYPE_1D:
 		case TEX_TYPE_2D:
@@ -353,32 +357,39 @@ namespace BansheeEngine
 			createVolumeTex(d3d9Device);
 			break;
 		default:
-			destroy_internal();
 			BS_EXCEPT(InternalErrorException, "Unknown texture type.");
 		}
 	}
 
-	void D3D9Texture::createNormTex(IDirect3DDevice9* d3d9Device)
+	void D3D9TextureCore::createNormTex(IDirect3DDevice9* d3d9Device)
 	{
-		assert(mWidth > 0 || mHeight > 0);
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		int texUsage = mProperties.getUsage();
+		UINT32 origNumMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+		UINT32 sampleCount = mProperties.getMultisampleCount();
+
+		assert(width > 0 || height > 0);
 
 		D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
-		if(mFormat != D3D9Mappings::_getPF(d3dPF))
+		if (format != D3D9Mappings::_getPF(d3dPF))
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
 		}
 
 		// Use D3DX to help us create the texture, this way it can adjust any relevant sizes
-		UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ? D3DX_DEFAULT : mNumMipmaps + 1;
+		UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
 
 		DWORD usage = 0;
-		if((mUsage & TU_RENDERTARGET) != 0)
+		if ((texUsage & TU_RENDERTARGET) != 0)
 			usage = D3DUSAGE_RENDERTARGET;
-		else if((mUsage & TU_DEPTHSTENCIL) != 0)
+		else if ((texUsage & TU_DEPTHSTENCIL) != 0)
 			usage = D3DUSAGE_DEPTHSTENCIL;
 
 		// Check dynamic textures
-		if (mUsage & TU_DYNAMIC)
+		if (texUsage & TU_DYNAMIC)
 		{
 			if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF))
 			{
@@ -392,18 +403,18 @@ namespace BansheeEngine
 		}
 
 		// Check sRGB support
-		if (mHwGamma)
+		if (hwGamma)
 		{
 			mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, false);
-			if (mUsage & TU_RENDERTARGET)
+			if (texUsage & TU_RENDERTARGET)
 				mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, true);
 		}
 
 		// Check multisample level
-		if ((mUsage & TU_RENDERTARGET) != 0 || (mUsage & TU_DEPTHSTENCIL) != 0)
+		if ((texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0)
 		{
 			D3D9RenderSystem* rsys = static_cast<D3D9RenderSystem*>(BansheeEngine::RenderSystem::instancePtr());
-			rsys->determineMultisampleSettings(d3d9Device, mMultisampleCount, d3dPF, false, &mMultisampleType, &mMultisampleQuality);
+			rsys->determineMultisampleSettings(d3d9Device, sampleCount, d3dPF, false, &mMultisampleType, &mMultisampleQuality);
 		}
 		else
 		{
@@ -415,7 +426,7 @@ namespace BansheeEngine
 		const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();			
 
 		// Check if mip maps are supported on hardware
-		if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (mUsage & TU_RENDERTARGET) != 0 || (mUsage & TU_DEPTHSTENCIL) != 0))
+		if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0))
 		{
 			BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
 		}
@@ -430,10 +441,10 @@ namespace BansheeEngine
 		else
 			textureResources = allocateTextureResources(d3d9Device);
 
-		if ((mUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
+		if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
 		{
 			// Create AA surface
-			HRESULT hr = d3d9Device->CreateRenderTarget(mWidth, mHeight, d3dPF, 
+			HRESULT hr = d3d9Device->CreateRenderTarget(width, height, d3dPF, 
 				mMultisampleType, mMultisampleQuality,
 				FALSE,
 				&textureResources->pMultisampleSurface, NULL);
@@ -445,7 +456,6 @@ namespace BansheeEngine
 			hr = textureResources->pMultisampleSurface->GetDesc(&desc);
 			if (FAILED(hr))
 			{
-				destroy_internal();
 				BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -453,10 +463,10 @@ namespace BansheeEngine
 
 			mIsBindableAsShaderResource = false; // Cannot bind AA surfaces
 		}
-		else if ((mUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
+		else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
 		{
 			// Create AA depth stencil surface
-			HRESULT hr = d3d9Device->CreateDepthStencilSurface(mWidth, mHeight, d3dPF, 
+			HRESULT hr = d3d9Device->CreateDepthStencilSurface(width, height, d3dPF, 
 				mMultisampleType, mMultisampleQuality,
 				FALSE, 
 				&textureResources->pDepthStencilSurface, NULL);
@@ -469,7 +479,6 @@ namespace BansheeEngine
 			hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
 			if (FAILED(hr))
 			{
-				destroy_internal();
 				BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -480,19 +489,17 @@ namespace BansheeEngine
 		else
 		{
 			// Create normal texture
-			HRESULT hr = D3DXCreateTexture(d3d9Device, (UINT)mWidth, (UINT)mHeight,	numMips,
+			HRESULT hr = D3DXCreateTexture(d3d9Device, (UINT)width, (UINT)height, numMips,
 				usage, d3dPF, mD3DPool, &textureResources->pNormTex);
 
 			if (FAILED(hr))
 			{
-				destroy_internal();
 				BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
 			}
 
 			hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
 			if (FAILED(hr))
 			{
-				destroy_internal();
 				BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -501,7 +508,6 @@ namespace BansheeEngine
 			hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
 			if (FAILED(hr))
 			{
-				destroy_internal();
 				BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -509,24 +515,31 @@ namespace BansheeEngine
 		}
 	}
 	
-	void D3D9Texture::createCubeTex(IDirect3DDevice9* d3d9Device)
+	void D3D9TextureCore::createCubeTex(IDirect3DDevice9* d3d9Device)
 	{
-		assert(mWidth > 0 || mHeight > 0);
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		int texUsage = mProperties.getUsage();
+		UINT32 origNumMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+
+		assert(width > 0 || height > 0);
 
 		D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
-		if(mFormat != D3D9Mappings::_getPF(d3dPF))
+		if (format != D3D9Mappings::_getPF(d3dPF))
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
 		}
 
 		// Use D3DX to help us create the texture, this way it can adjust any relevant sizes
-		DWORD usage = (mUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
-		usage |= (mUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
+		DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
+		usage |= (texUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
 
-		UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ? D3DX_DEFAULT : mNumMipmaps + 1;
+		UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
 
 		// Check dynamic textures
-		if (mUsage & TU_DYNAMIC)
+		if (texUsage & TU_DYNAMIC)
 		{
 			if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF))
 			{
@@ -540,10 +553,10 @@ namespace BansheeEngine
 		}
 
 		// Check sRGB support
-		if (mHwGamma)
+		if (hwGamma)
 		{
 			mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, false);
-			if (mUsage & TU_RENDERTARGET)
+			if (texUsage & TU_RENDERTARGET)
 				mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, true);
 		}
 
@@ -571,19 +584,17 @@ namespace BansheeEngine
 			textureResources = allocateTextureResources(d3d9Device);
 
 		// Create the texture
-		HRESULT hr = D3DXCreateCubeTexture(d3d9Device, (UINT)mWidth, numMips,
+		HRESULT hr = D3DXCreateCubeTexture(d3d9Device, (UINT)width, numMips,
 				usage, d3dPF, mD3DPool, &textureResources->pCubeTex);
 
 		if (FAILED(hr))
 		{
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
 		}
 
 		hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
 		if (FAILED(hr))
 		{
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
 		}
 		
@@ -592,35 +603,42 @@ namespace BansheeEngine
 		hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
 		if (FAILED(hr))
 		{
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 		}
 
 		setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));		
 	}
 	
-	void D3D9Texture::createVolumeTex(IDirect3DDevice9* d3d9Device)
+	void D3D9TextureCore::createVolumeTex(IDirect3DDevice9* d3d9Device)
 	{
-		assert(mWidth > 0 && mHeight > 0 && mDepth>0);
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		UINT32 depth = mProperties.getDepth();
+		int texUsage = mProperties.getUsage();
+		UINT32 origNumMips = mProperties.getNumMipmaps();
+		PixelFormat format = mProperties.getFormat();
+		bool hwGamma = mProperties.isHardwareGammaEnabled();
+
+		assert(width > 0 && height > 0 && depth > 0);
 
-		if (mUsage & TU_RENDERTARGET)
+		if (texUsage & TU_RENDERTARGET)
 			BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as render target !!");
 
-		if (mUsage & TU_DEPTHSTENCIL)
+		if (texUsage & TU_DEPTHSTENCIL)
 			BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as a depth stencil target !!");
 
 		D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
-		if(mFormat != D3D9Mappings::_getPF(d3dPF))
+		if(format != D3D9Mappings::_getPF(d3dPF))
 		{
-			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
+			BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
 		}
 
 		// Use D3DX to help us create the texture, this way it can adjust any relevant sizes
-		DWORD usage = (mUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
-		UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ? D3DX_DEFAULT : mNumMipmaps + 1;
+		DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
+		UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
 
 		// Check dynamic textures
-		if (mUsage & TU_DYNAMIC)
+		if (texUsage & TU_DYNAMIC)
 		{
 			if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF))
 			{
@@ -634,10 +652,10 @@ namespace BansheeEngine
 		}
 
 		// Check sRGB support
-		if (mHwGamma)
+		if (hwGamma)
 		{
 			mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, false);
-			if (mUsage & TU_RENDERTARGET)
+			if (texUsage & TU_RENDERTARGET)
 				mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, true);
 		}
 
@@ -661,19 +679,17 @@ namespace BansheeEngine
 			textureResources = allocateTextureResources(d3d9Device);
 
 		// Create the texture
-		HRESULT hr = D3DXCreateVolumeTexture(d3d9Device, (UINT)mWidth, (UINT)mHeight, (UINT)mDepth,
+		HRESULT hr = D3DXCreateVolumeTexture(d3d9Device, (UINT)width, (UINT)height, (UINT)depth,
 				numMips, usage, d3dPF, mD3DPool, &textureResources->pVolumeTex);
 
 		if (FAILED(hr))
 		{
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
 		}
 
 		hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void**)&textureResources->pBaseTex);
 		if (FAILED(hr))
 		{
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
 		}
 		
@@ -682,40 +698,40 @@ namespace BansheeEngine
 		hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
 		if (FAILED(hr))
 		{
-			destroy_internal();
 			BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 		}
 
 		setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, desc.Depth, D3D9Mappings::_getPF(desc.Format));
 	}
 
-	void D3D9Texture::setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources,
+	void D3D9TextureCore::setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources,
 		UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
 	{ 
-		if(width != mWidth || height != mHeight || depth != mDepth)
+		if(width != mProperties.getWidth() || height != mProperties.getHeight() || depth != mProperties.getDepth())
 		{
 			BS_EXCEPT(InternalErrorException, "Wanted and created textures sizes don't match!" \
-				"Width: " + toString(width) + "/" + toString(mWidth) +
-				"Height: " + toString(height) + "/" + toString(mHeight) +
-				"Depth: " + toString(depth) + "/" + toString(mDepth));
+				"Width: " + toString(width) + "/" + toString(mProperties.getWidth()) +
+				"Height: " + toString(height) + "/" + toString(mProperties.getHeight()) +
+				"Depth: " + toString(depth) + "/" + toString(mProperties.getDepth()));
 		}
 
-		if(format != mFormat)
+		if(format != mProperties.getFormat())
 		{
-			BS_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " + toString(format) + "/" + toString(mFormat));
+			BS_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " + 
+				toString(format) + "/" + toString(mProperties.getFormat()));
 		}
 		
 		createSurfaceList(d3d9Device, textureResources);
 	}
 	
-	D3DTEXTUREFILTERTYPE D3D9Texture::getBestFilterMethod(IDirect3DDevice9* d3d9Device)
+	D3DTEXTUREFILTERTYPE D3D9TextureCore::getBestFilterMethod(IDirect3DDevice9* d3d9Device)
 	{
 		D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
 		const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();			
 		
 		DWORD filterCaps = 0;
 
-		switch (getTextureType())
+		switch (mProperties.getTextureType())
 		{
 		case TEX_TYPE_1D:		
 			// Same as 2D
@@ -748,7 +764,7 @@ namespace BansheeEngine
 		return D3DTEXF_POINT;
 	}
 	
-	bool D3D9Texture::canUseDynamicTextures(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, 
+	bool D3D9TextureCore::canUseDynamicTextures(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, 
 		D3DFORMAT srcFormat)
 	{		
 		IDirect3D9* pD3D = nullptr;
@@ -770,7 +786,7 @@ namespace BansheeEngine
 		return hr == D3D_OK;
 	}
 	
-	bool D3D9Texture::canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device, DWORD srcUsage, 
+	bool D3D9TextureCore::canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device, DWORD srcUsage, 
 		D3DRESOURCETYPE srcType, D3DFORMAT srcFormat, bool forwriting)
 	{
 		IDirect3D9* pD3D = nullptr;
@@ -799,7 +815,7 @@ namespace BansheeEngine
 		return hr == D3D_OK;
 	}
 	
-	bool D3D9Texture::canAutoGenMipmaps(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
+	bool D3D9TextureCore::canAutoGenMipmaps(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
 	{
 		IDirect3D9* pD3D = nullptr;
 
@@ -827,30 +843,34 @@ namespace BansheeEngine
 			return false;
 	}
 	
-	D3DFORMAT D3D9Texture::chooseD3DFormat(IDirect3DDevice9* d3d9Device)
+	D3DFORMAT D3D9TextureCore::chooseD3DFormat(IDirect3DDevice9* d3d9Device)
 	{		
 		// Choose frame buffer pixel format in case PF_UNKNOWN was requested
-		if(mFormat == PF_UNKNOWN)
+		if(mProperties.getFormat() == PF_UNKNOWN)
 		{	
 			D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
 			
-			if((mUsage & TU_DEPTHSTENCIL) != 0)
+			if((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
 				return device->getDepthStencilFormat();
 			else
 				return device->getBackBufferFormat();		
 		}
 
 		// Choose closest supported D3D format as a D3D format
-		return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mFormat));
+		return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mProperties.getFormat()));
 	}
 	
-	void D3D9Texture::createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
+	void D3D9TextureCore::createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
 	{
+		int texUsage = mProperties.getUsage();
+		TextureType texType = mProperties.getTextureType();
+		UINT32 numMips = mProperties.getNumMipmaps();
+
 		assert(textureResources != nullptr);
 
 		// Need to know static / dynamic
 		UINT32 usage;
-		if ((mUsage & TU_DYNAMIC) && mDynamicTextures)
+		if ((texUsage & TU_DYNAMIC) && mDynamicTextures)
 		{
 			usage = GBU_DYNAMIC;
 		}
@@ -859,23 +879,23 @@ namespace BansheeEngine
 			usage = GBU_STATIC;
 		}
 
-		if (mUsage & TU_RENDERTARGET)
+		if (texUsage & TU_RENDERTARGET)
 		{
 			usage |= TU_RENDERTARGET;
 		}
-		else if(mUsage & TU_DEPTHSTENCIL)
+		else if (texUsage & TU_DEPTHSTENCIL)
 		{
 			usage |= TU_RENDERTARGET;
 		}
 		
-		UINT32 surfaceCount  = static_cast<UINT32>((getNumFaces() * (mNumMipmaps + 1)));
+		UINT32 surfaceCount = static_cast<UINT32>((mProperties.getNumFaces() * (numMips + 1)));
 		bool updateOldList = mSurfaceList.size() == surfaceCount;
 		if(!updateOldList)
 		{			
 			mSurfaceList.clear();
-			for(UINT32 face = 0; face < getNumFaces(); face++)
+			for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
 			{
-				for(UINT32 mip = 0; mip <= mNumMipmaps; mip++)
+				for (UINT32 mip = 0; mip <= numMips; mip++)
 				{
 					mSurfaceList.push_back(bs_shared_ptr<D3D9PixelBuffer>((GpuBufferUsage)usage, this));
 				}
@@ -885,19 +905,19 @@ namespace BansheeEngine
 		IDirect3DSurface9* surface = nullptr;
 		IDirect3DVolume9* volume = nullptr;
 
-		if((mUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
+		if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
 		{
 			assert(textureResources->pMultisampleSurface);
-			assert(getTextureType() == TEX_TYPE_2D);
+			assert(texUsage == TEX_TYPE_2D);
 
 			D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
 
 			currPixelBuffer->bind(d3d9Device, textureResources->pMultisampleSurface, textureResources->pBaseTex);
 		}
-		else if((mUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
+		else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
 		{
 			assert(textureResources->pDepthStencilSurface);
-			assert(getTextureType() == TEX_TYPE_2D);
+			assert(texUsage == TEX_TYPE_2D);
 
 			D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
 
@@ -908,19 +928,19 @@ namespace BansheeEngine
 			assert(textureResources->pBaseTex);
 
 			UINT32 numCreatedMips = textureResources->pBaseTex->GetLevelCount() - 1;
-			if(numCreatedMips != mNumMipmaps)
+			if (numCreatedMips != numMips)
 			{
 				BS_EXCEPT(InternalErrorException, "Number of created and wanted mip map levels doesn't match: " + 
-					toString(numCreatedMips) + "/" + toString(mNumMipmaps));
+					toString(numCreatedMips) + "/" + toString(numMips));
 			}
 
-			switch(getTextureType()) 
+			switch(texType) 
 			{
 			case TEX_TYPE_2D:
 			case TEX_TYPE_1D:
 				assert(textureResources->pNormTex);
 
-				for(UINT32 mip = 0; mip <= mNumMipmaps; mip++)
+				for (UINT32 mip = 0; mip <= numMips; mip++)
 				{
 					if(textureResources->pNormTex->GetSurfaceLevel(static_cast<UINT>(mip), &surface) != D3D_OK)
 						BS_EXCEPT(RenderingAPIException, "Get surface level failed");
@@ -938,12 +958,12 @@ namespace BansheeEngine
 
 				for(UINT32 face = 0; face < 6; face++)
 				{
-					for(UINT32 mip = 0; mip <= mNumMipmaps; mip++)
+					for (UINT32 mip = 0; mip <= numMips; mip++)
 					{
 						if(textureResources->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, static_cast<UINT>(mip), &surface) != D3D_OK)
 							BS_EXCEPT(RenderingAPIException, "Get cubemap surface failed");
 
-						UINT32 idx = face*(mNumMipmaps + 1) + mip;
+						UINT32 idx = face*(numMips + 1) + mip;
 						D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[idx].get());
 
 						currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
@@ -955,7 +975,7 @@ namespace BansheeEngine
 			case TEX_TYPE_3D:
 				assert(textureResources->pVolumeTex);
 
-				for(UINT32 mip = 0; mip <= mNumMipmaps; mip++)
+				for (UINT32 mip = 0; mip <= numMips; mip++)
 				{
 					if(textureResources->pVolumeTex->GetVolumeLevel(static_cast<UINT>(mip), &volume) != D3D_OK)
 						BS_EXCEPT(RenderingAPIException, "Get volume level failed");	
@@ -970,16 +990,16 @@ namespace BansheeEngine
 		}		
 	}
 
-	PixelBufferPtr D3D9Texture::getBuffer(UINT32 face, UINT32 mipmap) 
+	PixelBufferPtr D3D9TextureCore::getBuffer(UINT32 face, UINT32 mipmap) 
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(face >= getNumFaces())
+		if(face >= mProperties.getNumFaces())
 			BS_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
-		if(mipmap > mNumMipmaps)
+		if (mipmap > mProperties.getNumMipmaps())
 			BS_EXCEPT(InvalidParametersException, "Mipmap index out of range");
 
-		UINT32 idx = face*(mNumMipmaps+1) + mipmap;
+		UINT32 idx = face*(mProperties.getNumMipmaps() + 1) + mipmap;
 
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 		TextureResources* textureResources = getTextureResources(d3d9Device);
@@ -994,12 +1014,13 @@ namespace BansheeEngine
 		return mSurfaceList[idx];
 	}
 
-	bool D3D9Texture::useDefaultPool()
+	bool D3D9TextureCore::useDefaultPool()
 	{
-		return (mUsage & TU_RENDERTARGET) || (mUsage & TU_DEPTHSTENCIL) || ((mUsage & TU_DYNAMIC) && mDynamicTextures);
+		int usage = mProperties.getUsage();
+		return (usage & TU_RENDERTARGET) || (usage & TU_DEPTHSTENCIL) || ((usage & TU_DYNAMIC) && mDynamicTextures);
 	}
 	
-	void D3D9Texture::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) 
+	void D3D9TextureCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) 
 	{		
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -1007,7 +1028,7 @@ namespace BansheeEngine
 			createInternalResources(d3d9Device);
 	}
 
-	void D3D9Texture::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) 
+	void D3D9TextureCore::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) 
 	{				
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -1033,7 +1054,7 @@ namespace BansheeEngine
 		}	
 	}
 
-	void D3D9Texture::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device) 
+	void D3D9TextureCore::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device) 
 	{		
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -1049,7 +1070,7 @@ namespace BansheeEngine
 		}		
 	}
 
-	void D3D9Texture::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device) 
+	void D3D9TextureCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device) 
 	{		
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -1059,7 +1080,7 @@ namespace BansheeEngine
 		}
 	}
 
-	IDirect3DBaseTexture9* D3D9Texture::getTexture_internal()
+	IDirect3DBaseTexture9* D3D9TextureCore::getTexture_internal()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -1079,7 +1100,7 @@ namespace BansheeEngine
 		return textureResources->pBaseTex;
 	}
 
-	IDirect3DTexture9* D3D9Texture::getNormTexture_internal()
+	IDirect3DTexture9* D3D9TextureCore::getNormTexture_internal()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -1098,7 +1119,7 @@ namespace BansheeEngine
 		return textureResources->pNormTex;
 	}
 
-	IDirect3DCubeTexture9* D3D9Texture::getCubeTexture_internal()
+	IDirect3DCubeTexture9* D3D9TextureCore::getCubeTexture_internal()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 

+ 9 - 7
BansheeD3D9RenderSystem/Source/BsD3D9TextureManager.cpp

@@ -15,13 +15,6 @@ namespace BansheeEngine
 	D3D9TextureManager::~D3D9TextureManager()
 	{ }
 
-    TexturePtr D3D9TextureManager::createTextureImpl()
-    {
-		D3D9Texture* tex = new (bs_alloc<D3D9Texture, PoolAlloc>()) D3D9Texture();
-
-		return bs_core_ptr<D3D9Texture, PoolAlloc>(tex);
-    }
-
 	RenderTexturePtr D3D9TextureManager::createRenderTextureImpl(const RENDER_TEXTURE_DESC& desc)
 	{
 		D3D9RenderTexture* tex = new (bs_alloc<D3D9RenderTexture, PoolAlloc>()) D3D9RenderTexture(desc);
@@ -53,6 +46,15 @@ namespace BansheeEngine
 		}
 	}
 
+	SPtr<TextureCore> D3D9TextureCoreManager::createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+	{
+		D3D9TextureCore* tex = new (bs_alloc<D3D9TextureCore>()) D3D9TextureCore(texType,
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
+
+		return bs_shared_ptr<D3D9TextureCore, GenAlloc>(tex);
+	}
+
 	SPtr<RenderTextureCore> D3D9TextureCoreManager::createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc)
 	{
 		return bs_shared_ptr<D3D9RenderTextureCore>(desc);

+ 3 - 4
BansheeEditor/Source/BsScenePicking.cpp

@@ -286,21 +286,20 @@ namespace BansheeEngine
 		SPtr<RenderTextureCore> rtt = std::static_pointer_cast<RenderTextureCore>(target);
 		TexturePtr outputTexture = rtt->getBindableColorTexture();
 
-		if (position.x < 0 || position.x >= (INT32)outputTexture->getWidth() ||
-			position.y < 0 || position.y >= (INT32)outputTexture->getHeight())
+		if (position.x < 0 || position.x >= (INT32)outputTexture->getProperties().getWidth() ||
+			position.y < 0 || position.y >= (INT32)outputTexture->getProperties().getHeight())
 		{
 			asyncOp._completeOperation(Vector<UINT32>());
 			return;
 		}
 
 		PixelDataPtr outputPixelData = outputTexture->allocateSubresourceBuffer(0);
-		GpuResourceDataPtr outputData = outputPixelData;
 		AsyncOp unused;
 
 		RenderSystem& rs = RenderSystem::instance();
 
 		rs.endFrame();
-		rs.readSubresource(outputTexture, 0, outputData, unused);
+		outputTexture->getCore()->readSubresource(0, *outputPixelData);
 
 		Map<UINT32, UINT32> selectionScores;
 		UINT32 numPixels = outputPixelData->getWidth() * outputPixelData->getHeight();

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

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

+ 10 - 10
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -218,34 +218,34 @@ namespace BansheeEngine
 		HTexture cursorSizeWETex = getCursorTexture(CursorSizeWETex);
 
 		mCursorArrow = cursorArrowTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorArrowTex.getInternalPtr(), 0, mCursorArrow);
+		cursorArrowTex->readSubresource(gCoreAccessor(), 0, mCursorArrow);
 
 		mCursorArrowDrag = cursorArrowDragTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorArrowDragTex.getInternalPtr(), 0, mCursorArrowDrag);
+		cursorArrowDragTex->readSubresource(gCoreAccessor(), 0, mCursorArrowDrag);
 
 		mCursorArrowLeftRight = cursorArrowLeftRightTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorArrowLeftRightTex.getInternalPtr(), 0, mCursorArrowLeftRight);
+		cursorArrowLeftRightTex->readSubresource(gCoreAccessor(), 0, mCursorArrowLeftRight);
 
 		mCursorIBeam = cursorIBeamTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorIBeamTex.getInternalPtr(), 0, mCursorIBeam);
+		cursorIBeamTex->readSubresource(gCoreAccessor(), 0, mCursorIBeam);
 
 		mCursorDeny = cursorDenyTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorDenyTex.getInternalPtr(), 0, mCursorDeny);
+		cursorDenyTex->readSubresource(gCoreAccessor(), 0, mCursorDeny);
 
 		mCursorWait = cursorWaitTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorWaitTex.getInternalPtr(), 0, mCursorWait);
+		cursorWaitTex->readSubresource(gCoreAccessor(), 0, mCursorWait);
 
 		mCursorSizeNESW = cursorSizeNESWTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorSizeNESWTex.getInternalPtr(), 0, mCursorSizeNESW);
+		cursorSizeNESWTex->readSubresource(gCoreAccessor(), 0, mCursorSizeNESW);
 
 		mCursorSizeNS = cursorSizeNSTex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorSizeNSTex.getInternalPtr(), 0, mCursorSizeNS);
+		cursorSizeNSTex->readSubresource(gCoreAccessor(), 0, mCursorSizeNS);
 
 		mCursorSizeNWSE = cursorSizeNWSETex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorSizeNWSETex.getInternalPtr(), 0, mCursorSizeNWSE);
+		cursorSizeNWSETex->readSubresource(gCoreAccessor(), 0, mCursorSizeNWSE);
 
 		mCursorSizeWE = cursorSizeWETex->allocateSubresourceBuffer(0);
-		gCoreAccessor().readSubresource(cursorSizeWETex.getInternalPtr(), 0, mCursorSizeWE);
+		cursorSizeWETex->readSubresource(gCoreAccessor(), 0, mCursorSizeWE);
 
 		gCoreAccessor().submitToCoreThread(true);
 

+ 4 - 4
BansheeEngine/Source/BsGUIButtonBase.cpp

@@ -122,8 +122,8 @@ namespace BansheeEngine
 		{
 			IMAGE_SPRITE_DESC contentImgDesc;
 			contentImgDesc.texture = mContent.getImage().getInternalPtr();
-			contentImgDesc.width = mContent.getImage()->getTexture()->getWidth();
-			contentImgDesc.height = mContent.getImage()->getTexture()->getHeight();
+			contentImgDesc.width = mContent.getImage()->getWidth();
+			contentImgDesc.height = mContent.getImage()->getHeight();
 
 			mContentImageSprite->update(contentImgDesc);
 		}
@@ -144,8 +144,8 @@ namespace BansheeEngine
 		const HSpriteTexture& activeTex = getActiveTexture();
 		if(SpriteTexture::checkIsLoaded(activeTex))
 		{
-			imageWidth = activeTex->getTexture()->getWidth();
-			imageHeight = activeTex->getTexture()->getHeight();
+			imageWidth = activeTex->getWidth();
+			imageHeight = activeTex->getHeight();
 		}
 
 		Vector2I contentSize = GUIHelper::calcOptimalContentsSize(mContent, *_getStyle(), _getLayoutOptions());

+ 2 - 2
BansheeEngine/Source/BsGUIHelper.cpp

@@ -22,8 +22,8 @@ namespace BansheeEngine
 		UINT32 contentHeight = style.margins.top + style.margins.bottom + style.contentOffset.top + style.contentOffset.bottom;
 		if(content.getImage() != nullptr)
 		{
-			contentWidth += content.getImage()->getTexture()->getWidth();
-			contentHeight += content.getImage()->getTexture()->getHeight();
+			contentWidth += content.getImage()->getWidth();
+			contentHeight += content.getImage()->getHeight();
 		}
 
 		return Vector2I(std::max((UINT32)textContentBounds.x, contentWidth), std::max((UINT32)textContentBounds.y, contentHeight));

+ 2 - 2
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -315,8 +315,8 @@ namespace BansheeEngine
 		const HSpriteTexture& activeTex = getActiveTexture();
 		if(SpriteTexture::checkIsLoaded(activeTex))
 		{
-			imageWidth = activeTex->getTexture()->getWidth();
-			imageHeight = activeTex->getTexture()->getHeight();
+			imageWidth = activeTex->getWidth();
+			imageHeight = activeTex->getHeight();
 		}
 
 		Vector2I contentSize = GUIHelper::calcOptimalContentsSize(mText, *_getStyle(), _getLayoutOptions());

+ 4 - 5
BansheeEngine/Source/BsGUIManager.cpp

@@ -603,12 +603,11 @@ namespace BansheeEngine
 		}
 
 		const HTexture& tex = mCaretTexture->getTexture();
-		UINT32 subresourceIdx = tex->mapToSubresourceIdx(0, 0);
+		UINT32 subresourceIdx = tex->getProperties().mapToSubresourceIdx(0, 0);
 		PixelDataPtr data = tex->allocateSubresourceBuffer(subresourceIdx);
 
 		data->setColorAt(mCaretColor, 0, 0);
-
-		gCoreAccessor().writeSubresource(tex.getInternalPtr(), tex->mapToSubresourceIdx(0, 0), data);
+		tex->writeSubresource(gCoreAccessor(), subresourceIdx, data, false);
 	}
 
 	void GUIManager::updateTextSelectionTexture()
@@ -621,12 +620,12 @@ namespace BansheeEngine
 		}
 
 		const HTexture& tex = mTextSelectionTexture->getTexture();
-		UINT32 subresourceIdx = tex->mapToSubresourceIdx(0, 0);
+		UINT32 subresourceIdx = tex->getProperties().mapToSubresourceIdx(0, 0);
 		PixelDataPtr data = tex->allocateSubresourceBuffer(subresourceIdx);
 
 		data->setColorAt(mTextSelectionColor, 0, 0);
 
-		gCoreAccessor().writeSubresource(tex.getInternalPtr(), tex->mapToSubresourceIdx(0, 0), data);
+		tex->writeSubresource(gCoreAccessor(), subresourceIdx, data, false);
 	}
 
 	void GUIManager::onMouseDragEnded(const PointerEvent& event, DragCallbackInfo& dragInfo)

+ 1 - 1
BansheeEngine/Source/BsGUIScrollBarHandle.cpp

@@ -122,7 +122,7 @@ namespace BansheeEngine
 		HSpriteTexture activeTex = getActiveTexture();
 
 		if(SpriteTexture::checkIsLoaded(activeTex))
-			return Vector2I(activeTex->getTexture()->getWidth(), activeTex->getTexture()->getHeight());
+			return Vector2I(activeTex->getWidth(), activeTex->getHeight());
 
 		return Vector2I();
 	}

+ 4 - 4
BansheeEngine/Source/BsGUITexture.cpp

@@ -142,8 +142,8 @@ namespace BansheeEngine
 		if (SpriteTexture::checkIsLoaded(mActiveTexture))
 		{
 			mDesc.texture = mActiveTexture.getInternalPtr();
-			optimalWidth = (float)mDesc.texture->getTexture()->getWidth();
-			optimalHeight = (float)mDesc.texture->getTexture()->getHeight();
+			optimalWidth = (float)mDesc.texture->getWidth();
+			optimalHeight = (float)mDesc.texture->getHeight();
 		}
 
 		switch (mScaleMode)
@@ -210,7 +210,7 @@ namespace BansheeEngine
 		else
 		{
 			if (SpriteTexture::checkIsLoaded(mActiveTexture))
-				optimalSize.x = mActiveTexture->getTexture()->getWidth();
+				optimalSize.x = mActiveTexture->getWidth();
 			else
 				optimalSize.x = _getLayoutOptions().maxWidth;
 		}
@@ -220,7 +220,7 @@ namespace BansheeEngine
 		else
 		{
 			if (SpriteTexture::checkIsLoaded(mActiveTexture))
-				optimalSize.y = mActiveTexture->getTexture()->getHeight();
+				optimalSize.y = mActiveTexture->getHeight();
 			else
 				optimalSize.y = _getLayoutOptions().maxHeight;
 		}

+ 2 - 2
BansheeEngine/Source/BsImageSprite.cpp

@@ -177,8 +177,8 @@ namespace BansheeEngine
 			renderElem.vertices[34] = Vector2(topRightStart, bottomStart + bottomBorder);
 			renderElem.vertices[35] = Vector2(topRightStart + rightBorder, bottomStart + bottomBorder);
 
-			float invWidth = 1.0f / (float)desc.texture->getTexture()->getWidth();
-			float invHeight = 1.0f / (float)desc.texture->getTexture()->getHeight();
+			float invWidth = 1.0f / (float)desc.texture->getTexture()->getProperties().getWidth();
+			float invHeight = 1.0f / (float)desc.texture->getTexture()->getProperties().getHeight();
 
 			float uvLeftBorder = desc.borderLeft * invWidth;
 			float uvRightBorder = desc.borderRight * invWidth;

+ 2 - 2
BansheeEngine/Source/BsSpriteTexture.cpp

@@ -35,12 +35,12 @@ namespace BansheeEngine
 
 	UINT32 SpriteTexture::getWidth() const
 	{
-		return Math::roundToInt(mAtlasTexture->getWidth() * mUVScale.x);
+		return Math::roundToInt(mAtlasTexture->getProperties().getWidth() * mUVScale.x);
 	}
 
 	UINT32 SpriteTexture::getHeight() const
 	{
-		return Math::roundToInt(mAtlasTexture->getHeight() * mUVScale.y);
+		return Math::roundToInt(mAtlasTexture->getProperties().getHeight() * mUVScale.y);
 	}
 
 	HSpriteTexture SpriteTexture::create(const HTexture& texture)

+ 4 - 8
BansheeFontImporter/Source/BsFontImporter.cpp

@@ -275,23 +275,19 @@ namespace BansheeEngine
 				HTexture newTex = Texture::create(TEX_TYPE_2D, pageIter->width, pageIter->height, 0, PF_R8G8);
 				newTex.synchronize(); // TODO - Required due to a bug in allocateSubresourceBuffer
 
-				UINT32 subresourceIdx = newTex->mapToSubresourceIdx(0, 0);
+				UINT32 subresourceIdx = newTex->getProperties().mapToSubresourceIdx(0, 0);
 
 				// It's possible the formats no longer match
-				if(newTex->getFormat() != pixelData->getFormat())
+				if (newTex->getProperties().getFormat() != pixelData->getFormat())
 				{
 					PixelDataPtr temp = newTex->allocateSubresourceBuffer(subresourceIdx);
 					PixelUtil::bulkPixelConversion(*pixelData, *temp);
 
-					temp->_lock();
-					gCoreThread().queueReturnCommand(std::bind(&RenderSystem::writeSubresource, 
-						RenderSystem::instancePtr(), newTex.getInternalPtr(), subresourceIdx, temp, false, _1));
+					newTex->writeSubresource(gCoreAccessor(), subresourceIdx, temp, false);
 				}
 				else
 				{
-					pixelData->_lock();
-					gCoreThread().queueReturnCommand(std::bind(&RenderSystem::writeSubresource, 
-						RenderSystem::instancePtr(), newTex.getInternalPtr(), subresourceIdx, pixelData, false, _1));
+					newTex->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData, false);
 				}
 
 				newTex->setName(L"FontPage" + toWString((UINT32)fontData.texturePages.size()));

+ 2 - 3
BansheeFreeImgImporter/Source/BsFreeImgImporter.cpp

@@ -161,13 +161,12 @@ namespace BansheeEngine
 		newTexture->synchronize(); // TODO - Required due to a bug in allocateSubresourceBuffer
 		for (UINT32 mip = 0; mip < (UINT32)mipLevels.size(); ++mip)
 		{
-			UINT32 subresourceIdx = newTexture->mapToSubresourceIdx(0, mip);
+			UINT32 subresourceIdx = newTexture->getProperties().mapToSubresourceIdx(0, mip);
 			PixelDataPtr dst = newTexture->allocateSubresourceBuffer(subresourceIdx);
 
 			PixelUtil::bulkPixelConversion(*mipLevels[mip], *dst);
 
-			dst->_lock();
-			gCoreThread().queueReturnCommand(std::bind(&RenderSystem::writeSubresource, RenderSystem::instancePtr(), newTexture, subresourceIdx, dst, false, _1));
+			newTexture->writeSubresource(gCoreAccessor(), subresourceIdx, dst, false);
 		}
 
 		fileData->close();

+ 1 - 1
BansheeGLRenderSystem/Include/BsGLPrerequisites.h

@@ -8,7 +8,7 @@ namespace BansheeEngine
 
     class GLSupport;
     class GLRenderSystem;
-    class GLTexture;
+    class GLTextureCore;
 	class GLVertexBuffer;
 	class GLVertexBufferCore;
     class GLTextureManager;

+ 2 - 2
BansheeGLRenderSystem/Include/BsGLRenderSystem.h

@@ -61,12 +61,12 @@ namespace BansheeEngine
 		/**
 		 * @copydoc RenderSystem::setTexture()
 		 */
-        void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &tex);
+		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& tex);
 
 		/**
 		 * @copydoc	RenderSystem::setLoadStoreTexture
 		 */
-		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
 			const TextureSurface& surface);
         
 		/**

+ 15 - 16
BansheeGLRenderSystem/Include/BsGLTexture.h

@@ -11,10 +11,10 @@ namespace BansheeEngine
 	/**
 	 * @brief	OpenGL implementation of a texture.
 	 */
-    class BS_RSGL_EXPORT GLTexture : public Texture
+    class BS_RSGL_EXPORT GLTextureCore : public TextureCore
     {
     public:
-        virtual ~GLTexture();      
+		virtual ~GLTextureCore();
 
 		/**
 		 * @brief	Returns OpenGL texture target type
@@ -43,42 +43,43 @@ namespace BansheeEngine
 		std::shared_ptr<GLPixelBuffer> getBuffer(UINT32 face, UINT32 mipmap);
 
     protected:
-		friend class GLTextureManager;
+		friend class GLTextureCoreManager;
 
-		GLTexture(GLSupport& support);
+		GLTextureCore(GLSupport& support, TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
 
 		/**
-		 * @copydoc Texture::initialize_internal
+		 * @copydoc TextureCore::initialize
 		 */
-		void initialize_internal();
+		void initialize();
 
 		/**
-		 * @copydoc Texture::destroy_internal
+		 * @copydoc TextureCore::destroy
 		 */
-		void destroy_internal();
+		void destroy();
 
 		/**
-		 * @copydoc Texture::lock
+		 * @copydoc TextureCore::lock
 		 */
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 
 		/**
-		 * @copydoc Texture::unlock
+		 * @copydoc TextureCore::unlock
 		 */
 		void unlockImpl();
 
 		/**
-		 * @copydoc Texture::copy
+		 * @copydoc TextureCore::copy
 		 */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target);
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target);
 
 		/**
-		 * @copydoc Texture::readData
+		 * @copydoc TextureCore::readData
 		 */
 		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
 
 		/**
-		 * @copydoc Texture::writeData
+		 * @copydoc TextureCore::writeData
 		 */
 		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false);
 
@@ -96,6 +97,4 @@ namespace BansheeEngine
 		
 		Vector<std::shared_ptr<GLPixelBuffer>>mSurfaceList;
     };
-
-	typedef std::shared_ptr<GLTexture> GLTexturePtr;
 }

+ 7 - 5
BansheeGLRenderSystem/Include/BsGLTextureManager.h

@@ -23,11 +23,6 @@ namespace BansheeEngine
 		PixelFormat getNativeFormat(TextureType ttype, PixelFormat format, int usage, bool hwGamma);
 
 	protected:
-		/**
-		 * @copydoc	TextureManager::createTextureImpl
-		 */
-		TexturePtr createTextureImpl();
-
 		/**
 		 * @copydoc	TextureManager::createRenderTextureImpl
 		 */
@@ -50,6 +45,13 @@ namespace BansheeEngine
 		GLTextureCoreManager(GLSupport& support);
 
 	protected:		
+		/**
+		 * @copydoc	TextureCoreManager::createTextureInternal
+		 */
+		SPtr<TextureCore> createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false,
+			UINT32 multisampleCount = 0);
+
 		/**
 		 * @copydoc	TextureCoreManager::createRenderTextureInternal
 		 */

+ 4 - 4
BansheeGLRenderSystem/Source/BsGLMultiRenderTexture.cpp

@@ -23,11 +23,11 @@ namespace BansheeEngine
 		{
 			if (mColorSurfaces[i] != nullptr)
 			{
-				GLTexture* glColorSurface = static_cast<GLTexture*>(mColorSurfaces[i]->getTexture().get());
+				GLTextureCore* glColorSurface = static_cast<GLTextureCore*>(mColorSurfaces[i]->getTexture().get());
 				GLPixelBufferPtr colorBuffer = nullptr;
 				GLSurfaceDesc surfaceDesc;
 
-				if (glColorSurface->getTextureType() != TEX_TYPE_3D)
+				if (glColorSurface->getProperties().getTextureType() != TEX_TYPE_3D)
 				{
 					surfaceDesc.zoffset = 0;
 					colorBuffer = glColorSurface->getBuffer(mColorSurfaces[i]->getFirstArraySlice(),
@@ -52,10 +52,10 @@ namespace BansheeEngine
 
 		if (mDepthStencilSurface != nullptr)
 		{
-			GLTexture* glDepthStencilSurface = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
+			GLTextureCore* glDepthStencilSurface = static_cast<GLTextureCore*>(mDepthStencilSurface->getTexture().get());
 			GLPixelBufferPtr depthStencilBuffer = nullptr;
 
-			if (glDepthStencilSurface->getTextureType() != TEX_TYPE_3D)
+			if (glDepthStencilSurface->getProperties().getTextureType() != TEX_TYPE_3D)
 			{
 				depthStencilBuffer = glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice,
 					mDepthStencilSurface->getDesc().mostDetailMip);

+ 6 - 6
BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp

@@ -263,7 +263,7 @@ namespace BansheeEngine
 				if (!texture.isLoaded())
 					setTexture(gptype, iter->second.slot, false, nullptr);
 				else
-					setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+					setTexture(gptype, iter->second.slot, true, texture->getCore());
 			}
 			else
 			{
@@ -272,7 +272,7 @@ namespace BansheeEngine
 				if (!texture.isLoaded())
 					setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
 				else
-					setLoadStoreTexture(gptype, iter->second.slot, true, texture.getInternalPtr(), surface);
+					setLoadStoreTexture(gptype, iter->second.slot, true, texture->getCore(), surface);
 			}
 		}
 
@@ -412,13 +412,13 @@ namespace BansheeEngine
 		}
 	}
 
-	void GLRenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr)
+	void GLRenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		unit = getGLTextureUnit(gptype, unit);
 
-		GLTexturePtr tex = std::static_pointer_cast<GLTexture>(texPtr);
+		SPtr<GLTextureCore> tex = std::static_pointer_cast<GLTextureCore>(texPtr);
 
 		GLenum lastTextureType = mTextureTypes[unit];
 
@@ -470,7 +470,7 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumSamplerBinds);
 	}
 
-	void GLRenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+	void GLRenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const SPtr<TextureCore>& texPtr,
 		const TextureSurface& surface)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -478,7 +478,7 @@ namespace BansheeEngine
 		// TODO - OpenGL can't bind a certain subset of faces like DX11, only zero, one or all, so I'm ignoring numSlices parameter
 		if (texPtr != nullptr)
 		{
-			GLTexturePtr tex = std::static_pointer_cast<GLTexture>(texPtr);
+			SPtr<GLTextureCore> tex = std::static_pointer_cast<GLTextureCore>(texPtr);
 			glBindImageTexture(unit, tex->getGLID(), surface.mipLevel, surface.numArraySlices > 1, 
 				surface.arraySlice, tex->getGLFormat(), GL_READ_WRITE);
 		}

+ 4 - 4
BansheeGLRenderSystem/Source/BsGLRenderTexture.cpp

@@ -39,12 +39,12 @@ namespace BansheeEngine
 
 		mFB = bs_new<GLFrameBufferObject, PoolAlloc>();
 
-		GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
+		GLTextureCore* glTexture = static_cast<GLTextureCore*>(mColorSurface->getTexture().get());
 
 		GLSurfaceDesc surfaceDesc;
 		surfaceDesc.numSamples = getProperties().getMultisampleCount();
 
-		if (glTexture->getTextureType() != TEX_TYPE_3D)
+		if (glTexture->getProperties().getTextureType() != TEX_TYPE_3D)
 		{
 			surfaceDesc.zoffset = 0;
 			surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
@@ -57,10 +57,10 @@ namespace BansheeEngine
 
 		mFB->bindSurface(0, surfaceDesc);
 
-		GLTexture* glDepthStencilTexture = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
+		GLTextureCore* glDepthStencilTexture = static_cast<GLTextureCore*>(mDepthStencilSurface->getTexture().get());
 		GLPixelBufferPtr depthStencilBuffer = nullptr;
 
-		if (glDepthStencilTexture->getTextureType() != TEX_TYPE_3D)
+		if (glDepthStencilTexture->getProperties().getTextureType() != TEX_TYPE_3D)
 		{
 			depthStencilBuffer = glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(),
 				mDepthStencilSurface->getMostDetailedMip());

+ 70 - 61
BansheeGLRenderSystem/Source/BsGLTexture.cpp

@@ -11,33 +11,43 @@
 
 namespace BansheeEngine 
 {
-    GLTexture::GLTexture(GLSupport& support) 
-		: Texture(), mTextureID(0), mGLSupport(support), mGLFormat(0)
+	GLTextureCore::GLTextureCore(GLSupport& support, TextureType textureType, UINT32 width, UINT32 height, 
+		UINT32 depth, UINT32 numMipmaps, PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount),
+		mTextureID(0), mGLSupport(support), mGLFormat(0)
     { }
 
-    GLTexture::~GLTexture()
+	GLTextureCore::~GLTextureCore()
     { }
 
-	void GLTexture::initialize_internal()
+	void GLTextureCore::initialize()
 	{
+		UINT32 width = mProperties.getWidth();
+		UINT32 height = mProperties.getHeight();
+		UINT32 depth = mProperties.getDepth();
+		TextureType texType = mProperties.getTextureType();
+		PixelFormat pixFormat = mProperties.getFormat();
+		int usage = mProperties.getUsage();
+		UINT32 numMips = mProperties.getNumMipmaps();
+
 		// Check requested number of mipmaps
-		UINT32 maxMips = PixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);
-		if(mNumMipmaps > maxMips)
+		UINT32 maxMips = PixelUtil::getMaxMipmaps(width, height, depth, mProperties.getFormat());
+		if (numMips > maxMips)
 			BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: " + toString(maxMips));
 
-		if((mUsage & TU_RENDERTARGET) != 0)
+		if ((usage & TU_RENDERTARGET) != 0)
 		{
-			if(mTextureType != TEX_TYPE_2D)
+			if (texType != TEX_TYPE_2D)
 				BS_EXCEPT(NotImplementedException, "Only 2D render targets are supported at the moment");
 		}
 
-		if((mUsage & TU_DEPTHSTENCIL) != 0)
+		if ((usage & TU_DEPTHSTENCIL) != 0)
 		{
-			if(mTextureType != TEX_TYPE_2D)
+			if (texType != TEX_TYPE_2D)
 				BS_EXCEPT(NotImplementedException, "Only 2D depth stencil targets are supported at the moment");
 
-			if(!PixelUtil::isDepth(mFormat))
-				BS_EXCEPT(NotImplementedException, "Supplied format is not a depth stencil format. Format: " + toString(mFormat));
+			if (!PixelUtil::isDepth(pixFormat))
+				BS_EXCEPT(NotImplementedException, "Supplied format is not a depth stencil format. Format: " + toString(pixFormat));
 		}
 
 		// Generate texture handle
@@ -47,37 +57,35 @@ namespace BansheeEngine
 		glBindTexture(getGLTextureTarget(), mTextureID);
 
 		// This needs to be set otherwise the texture doesn't get rendered
-		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps);
+		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, numMips);
 
 		// Allocate internal buffer so that glTexSubImageXD can be used
-		mGLFormat = GLPixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma);
-		UINT32 width = mWidth;
-		UINT32 height = mHeight;
-		UINT32 depth = mDepth;
+		mGLFormat = GLPixelUtil::getClosestGLInternalFormat(pixFormat, mProperties.isHardwareGammaEnabled());
 
-		if(PixelUtil::isCompressed(mFormat))
+		if (PixelUtil::isCompressed(pixFormat))
 		{
-			if((mUsage & TU_RENDERTARGET) != 0)
+			if((usage & TU_RENDERTARGET) != 0)
 				BS_EXCEPT(InvalidParametersException, "Cannot use a compressed format for a render target.");
 
-			if((mUsage & TU_DEPTHSTENCIL) != 0)
+			if ((usage & TU_DEPTHSTENCIL) != 0)
 				BS_EXCEPT(InvalidParametersException, "Cannot use a compressed format for a depth stencil target.");
 		}
 
-		if((mUsage & TU_RENDERTARGET) != 0 && mTextureType == TEX_TYPE_2D && mMultisampleCount > 0)
+		UINT32 sampleCount = mProperties.getMultisampleCount();
+		if ((usage & TU_RENDERTARGET) != 0 && mProperties.getTextureType() == TEX_TYPE_2D && sampleCount > 0)
 		{
-			glTexImage2DMultisample(GL_TEXTURE_2D, mMultisampleCount, mGLFormat, width, height, GL_FALSE);
+			glTexImage2DMultisample(GL_TEXTURE_2D, sampleCount, mGLFormat, width, height, GL_FALSE);
 		}
-		else if((mUsage & TU_DEPTHSTENCIL) != 0)
+		else if ((usage & TU_DEPTHSTENCIL) != 0)
 		{
-			if(mMultisampleCount > 0)
+			if (sampleCount > 0)
 			{
-				glTexImage2DMultisample(GL_TEXTURE_2D, mMultisampleCount, mGLFormat,
+				glTexImage2DMultisample(GL_TEXTURE_2D, sampleCount, mGLFormat,
 					width, height, GL_FALSE);
 			}
 			else
 			{
-				GLenum depthStencilFormat = GLPixelUtil::getDepthStencilTypeFromFormat(mFormat);
+				GLenum depthStencilFormat = GLPixelUtil::getDepthStencilTypeFromFormat(pixFormat);
 
 				glTexImage2D(GL_TEXTURE_2D, 0, mGLFormat,
 					width, height, 0, 
@@ -86,13 +94,13 @@ namespace BansheeEngine
 		}
 		else
 		{
-			GLenum baseFormat = GLPixelUtil::getGLOriginFormat(mFormat);
-			GLenum baseDataType = GLPixelUtil::getGLOriginDataType(mFormat);
+			GLenum baseFormat = GLPixelUtil::getGLOriginFormat(pixFormat);
+			GLenum baseDataType = GLPixelUtil::getGLOriginDataType(pixFormat);
 
 			// Run through this process to pre-generate mipmap pyramid
-			for(UINT32 mip = 0; mip <= mNumMipmaps; mip++)
+			for (UINT32 mip = 0; mip <= numMips; mip++)
 			{
-				switch(mTextureType)
+				switch (texType)
 				{
 				case TEX_TYPE_1D:
 					glTexImage1D(GL_TEXTURE_1D, mip, mGLFormat, width, 0,
@@ -134,18 +142,18 @@ namespace BansheeEngine
 #if BS_DEBUG_MODE
 		if(buffer != nullptr)
 		{
-			if(mFormat != buffer->getFormat())
+			if(pixFormat != buffer->getFormat())
 			{
-				BS_EXCEPT(InternalErrorException, "Could not create a texture buffer with wanted format: " + toString(mFormat));
+				BS_EXCEPT(InternalErrorException, "Could not create a texture buffer with wanted format: " + toString(pixFormat));
 			}
 		}
 #endif
 
 		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
-		Texture::initialize_internal();
+		TextureCore::initialize();
 	}
 
-	void GLTexture::destroy_internal()
+	void GLTextureCore::destroy()
 	{
 		mSurfaceList.clear();
 		glDeleteTextures(1, &mTextureID);
@@ -153,17 +161,17 @@ namespace BansheeEngine
 		clearBufferViews();
 
 		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
-		Texture::destroy_internal();
+		TextureCore::destroy();
 	}
 
-    GLenum GLTexture::getGLTextureTarget() const
+    GLenum GLTextureCore::getGLTextureTarget() const
     {
-        switch(mTextureType)
+		switch (mProperties.getTextureType())
         {
             case TEX_TYPE_1D:
                 return GL_TEXTURE_1D;
             case TEX_TYPE_2D:
-				if(mMultisampleCount > 0)
+				if (mProperties.getMultisampleCount() > 0)
 					return GL_TEXTURE_2D_MULTISAMPLE;
 				else
 					return GL_TEXTURE_2D;
@@ -176,26 +184,26 @@ namespace BansheeEngine
         };
     }
 
-	GLuint GLTexture::getGLID() const
+	GLuint GLTextureCore::getGLID() const
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		return mTextureID;
 	}
 
-	PixelData GLTexture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
+	PixelData GLTextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 		if(mLockedBuffer != nullptr)
 			BS_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
 
-		UINT32 mipWidth = mWidth >> mipLevel;
-		UINT32 mipHeight = mHeight >> mipLevel;
-		UINT32 mipDepth = mDepth >> mipLevel;
+		UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
+		UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
+		UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
 
-		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mFormat);
+		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
 
 		mLockedBuffer = getBuffer(face, mipLevel);
 		lockedArea.setExternalBuffer((UINT8*)mLockedBuffer->lock(options));
@@ -203,7 +211,7 @@ namespace BansheeEngine
 		return lockedArea;
 	}
 
-	void GLTexture::unlockImpl()
+	void GLTextureCore::unlockImpl()
 	{
 		if(mLockedBuffer == nullptr)
 			BS_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
@@ -213,42 +221,43 @@ namespace BansheeEngine
 	}
 
 
-	void GLTexture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	void GLTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 		getBuffer(face, mipLevel)->download(dest);
 	}
 
-	void GLTexture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	void GLTextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
 	{
-		if (mMultisampleCount > 0)
+		if (mProperties.getMultisampleCount() > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 		getBuffer(face, mipLevel)->upload(src, src.getExtents());
 	}
 
-	void GLTexture::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, TexturePtr& target)
+	void GLTextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
 	{
-		size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
+		size_t numMips = std::min(mProperties.getNumMipmaps(), target->getProperties().getNumMipmaps());
 
-		GLTexture* destTex = static_cast<GLTexture*>(target.get());
+		GLTextureCore* destTex = static_cast<GLTextureCore*>(target.get());
 		GLTextureBuffer *src = static_cast<GLTextureBuffer*>(getBuffer(srcFace, srcMipLevel).get());
 
 		destTex->getBuffer(destFace, destMipLevel)->blitFromTexture(src);
 	}
 
-	void GLTexture::createSurfaceList()
+	void GLTextureCore::createSurfaceList()
 	{
 		mSurfaceList.clear();
 		
-		for(UINT32 face = 0; face < getNumFaces(); face++)
+		for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
 		{
-			for(UINT32 mip = 0; mip <= getNumMipmaps(); mip++)
+			for (UINT32 mip = 0; mip <= mProperties.getNumMipmaps(); mip++)
 			{
                 GLPixelBuffer *buf = bs_new<GLTextureBuffer, PoolAlloc>(getGLTextureTarget(), mTextureID, face, mip,
-						static_cast<GpuBufferUsage>(mUsage), mHwGamma, mMultisampleCount);
+					static_cast<GpuBufferUsage>(mProperties.getUsage()), 
+					mProperties.isHardwareGammaEnabled(), mProperties.getMultisampleCount());
 
 				mSurfaceList.push_back(bs_shared_ptr<GLPixelBuffer, PoolAlloc>(buf));
                 if(buf->getWidth() == 0 || buf->getHeight() == 0 || buf->getDepth() == 0)
@@ -263,17 +272,17 @@ namespace BansheeEngine
 		}
 	}
 	
-	std::shared_ptr<GLPixelBuffer> GLTexture::getBuffer(UINT32 face, UINT32 mipmap)
+	std::shared_ptr<GLPixelBuffer> GLTextureCore::getBuffer(UINT32 face, UINT32 mipmap)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if(face >= getNumFaces())
+		if(face >= mProperties.getNumFaces())
 			BS_EXCEPT(InvalidParametersException, "Face index out of range");
 
-		if(mipmap > mNumMipmaps)
+		if (mipmap > mProperties.getNumMipmaps())
 			BS_EXCEPT(InvalidParametersException, "Mipmap index out of range");
 
-		unsigned int idx = face*(mNumMipmaps+1) + mipmap;
+		unsigned int idx = face * (mProperties.getNumMipmaps() + 1) + mipmap;
 		assert(idx < mSurfaceList.size());
 		return mSurfaceList[idx];
 	}

+ 10 - 8
BansheeGLRenderSystem/Source/BsGLTextureManager.cpp

@@ -6,7 +6,7 @@
 
 namespace BansheeEngine
 {
-    GLTextureManager::GLTextureManager( GLSupport& support)
+    GLTextureManager::GLTextureManager(GLSupport& support)
         :TextureManager(), mGLSupport(support)
     {
 
@@ -15,13 +15,6 @@ namespace BansheeEngine
     GLTextureManager::~GLTextureManager()
     {
 
-    }
-
-    TexturePtr GLTextureManager::createTextureImpl()
-    {
-        GLTexture* tex = new (bs_alloc<GLTexture, PoolAlloc>()) GLTexture(mGLSupport);
-
-		return bs_core_ptr<GLTexture, PoolAlloc>(tex);
     }
 
 	RenderTexturePtr GLTextureManager::createRenderTextureImpl(const RENDER_TEXTURE_DESC& desc)
@@ -71,6 +64,15 @@ namespace BansheeEngine
 		:mGLSupport(support)
 	{ }
 
+	SPtr<TextureCore> GLTextureCoreManager::createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+	{
+		GLTextureCore* tex = new (bs_alloc<GLTextureCore>()) GLTextureCore(mGLSupport, texType,
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
+
+		return bs_shared_ptr<GLTextureCore, GenAlloc>(tex);
+	}
+
 	SPtr<RenderTextureCore> GLTextureCoreManager::createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc)
 	{
 		return bs_shared_ptr<GLRenderTextureCore>(desc);

+ 7 - 7
SBansheeEngine/Source/BsScriptTexture.cpp

@@ -26,42 +26,42 @@ namespace BansheeEngine
 	void ScriptTexture::internal_getPixelFormat(ScriptTexture* thisPtr, PixelFormat* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = texture->getFormat();
+		*value = texture->getProperties().getFormat();
 	}
 
 	void ScriptTexture::internal_getUsage(ScriptTexture* thisPtr, TextureUsage* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = (TextureUsage)texture->getUsage();
+		*value = (TextureUsage)texture->getProperties().getUsage();
 	}
 
 	void ScriptTexture::internal_getWidth(ScriptTexture* thisPtr, int* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = (TextureUsage)texture->getWidth();
+		*value = (TextureUsage)texture->getProperties().getWidth();
 	}
 
 	void ScriptTexture::internal_getHeight(ScriptTexture* thisPtr, int* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = (TextureUsage)texture->getHeight();
+		*value = (TextureUsage)texture->getProperties().getHeight();
 	}
 
 	void ScriptTexture::internal_getGammaCorrection(ScriptTexture* thisPtr, bool* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = (TextureUsage)texture->isHardwareGammaEnabled();
+		*value = (TextureUsage)texture->getProperties().isHardwareGammaEnabled();
 	}
 
 	void ScriptTexture::internal_getSampleCount(ScriptTexture* thisPtr, int* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = (TextureUsage)texture->getMultisampleCount();
+		*value = (TextureUsage)texture->getProperties().getMultisampleCount();
 	}
 
 	void ScriptTexture::internal_getMipmapCount(ScriptTexture* thisPtr, int* value)
 	{
 		HTexture texture = static_resource_cast<Texture>(thisPtr->getNativeHandle());
-		*value = (TextureUsage)texture->getNumMipmaps();
+		*value = (TextureUsage)texture->getProperties().getNumMipmaps();
 	}
 }

+ 6 - 6
SBansheeEngine/Source/BsScriptTexture2D.cpp

@@ -44,11 +44,11 @@ namespace BansheeEngine
 	MonoObject* ScriptTexture2D::internal_getPixels(ScriptTexture2D* thisPtr, UINT32 mipLevel)
 	{
 		HTexture texture = thisPtr->mTexture;
-		UINT32 subresourceIdx = texture->mapToSubresourceIdx(0, mipLevel);
+		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 		PixelDataPtr pixelData = thisPtr->mTexture->allocateSubresourceBuffer(subresourceIdx);
 
-		thisPtr->mTexture->readDataSim(*pixelData, mipLevel);
+		thisPtr->mTexture->readData(*pixelData, mipLevel);
 
 		return ScriptPixelData::create(pixelData);
 	}
@@ -56,11 +56,11 @@ namespace BansheeEngine
 	MonoObject* ScriptTexture2D::internal_getGPUPixels(ScriptTexture2D* thisPtr, UINT32 mipLevel)
 	{
 		HTexture texture = thisPtr->mTexture;
-		UINT32 subresourceIdx = texture->mapToSubresourceIdx(0, mipLevel);
+		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 		PixelDataPtr readData = texture->allocateSubresourceBuffer(subresourceIdx);
 
-		AsyncOp asyncOp = gCoreAccessor().readSubresource(texture.getInternalPtr(), subresourceIdx, readData);
+		AsyncOp asyncOp = texture->readSubresource(gCoreAccessor(), subresourceIdx, readData);
 
 		std::function<MonoObject*(const AsyncOp&, const PixelDataPtr&)> asyncOpToMono =
 			[&](const AsyncOp& op, const PixelDataPtr& returnValue)
@@ -78,9 +78,9 @@ namespace BansheeEngine
 		if (scriptPixelData != nullptr)
 		{
 			HTexture texture = thisPtr->mTexture;
-			UINT32 subresourceIdx = texture->mapToSubresourceIdx(0, mipLevel);
+			UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
-			gCoreAccessor().writeSubresource(texture.getInternalPtr(), subresourceIdx, scriptPixelData->getInternalValue());
+			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
 		}
 	}
 

+ 6 - 6
SBansheeEngine/Source/BsScriptTexture3D.cpp

@@ -44,11 +44,11 @@ namespace BansheeEngine
 	MonoObject* ScriptTexture3D::internal_getPixels(ScriptTexture3D* thisPtr, UINT32 mipLevel)
 	{
 		HTexture texture = thisPtr->mTexture;
-		UINT32 subresourceIdx = texture->mapToSubresourceIdx(0, mipLevel);
+		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 		PixelDataPtr pixelData = thisPtr->mTexture->allocateSubresourceBuffer(subresourceIdx);
 
-		thisPtr->mTexture->readDataSim(*pixelData, mipLevel);
+		thisPtr->mTexture->readData(*pixelData, mipLevel);
 
 		return ScriptPixelData::create(pixelData);
 	}
@@ -56,11 +56,11 @@ namespace BansheeEngine
 	MonoObject* ScriptTexture3D::internal_getGPUPixels(ScriptTexture3D* thisPtr, UINT32 mipLevel)
 	{
 		HTexture texture = thisPtr->mTexture;
-		UINT32 subresourceIdx = texture->mapToSubresourceIdx(0, mipLevel);
+		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
 		PixelDataPtr readData = texture->allocateSubresourceBuffer(subresourceIdx);
 
-		AsyncOp asyncOp = gCoreAccessor().readSubresource(texture.getInternalPtr(), subresourceIdx, readData);
+		AsyncOp asyncOp = texture->readSubresource(gCoreAccessor(), subresourceIdx, readData);
 
 		std::function<MonoObject*(const AsyncOp&, const PixelDataPtr&)> asyncOpToMono =
 			[&](const AsyncOp& op, const PixelDataPtr& returnValue)
@@ -78,9 +78,9 @@ namespace BansheeEngine
 		if (scriptPixelData != nullptr)
 		{
 			HTexture texture = thisPtr->mTexture;
-			UINT32 subresourceIdx = texture->mapToSubresourceIdx(0, mipLevel);
+			UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 
-			gCoreAccessor().writeSubresource(texture.getInternalPtr(), subresourceIdx, scriptPixelData->getInternalValue());
+			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
 		}
 	}
 

+ 6 - 7
SBansheeEngine/Source/BsScriptTextureCube.cpp

@@ -44,11 +44,11 @@ namespace BansheeEngine
 	MonoObject* ScriptTextureCube::internal_getPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel)
 	{
 		HTexture texture = thisPtr->mTexture;
-		UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipLevel);
+		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(face, mipLevel);
 
 		PixelDataPtr pixelData = thisPtr->mTexture->allocateSubresourceBuffer(subresourceIdx);
 
-		thisPtr->mTexture->readDataSim(*pixelData, mipLevel, face);
+		thisPtr->mTexture->readData(*pixelData, mipLevel, face);
 
 		return ScriptPixelData::create(pixelData);
 	}
@@ -56,11 +56,10 @@ namespace BansheeEngine
 	MonoObject* ScriptTextureCube::internal_getGPUPixels(ScriptTextureCube* thisPtr, UINT32 face, UINT32 mipLevel)
 	{
 		HTexture texture = thisPtr->mTexture;
-		UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipLevel);
+		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(face, mipLevel);
 
 		PixelDataPtr readData = texture->allocateSubresourceBuffer(subresourceIdx);
-
-		AsyncOp asyncOp = gCoreAccessor().readSubresource(texture.getInternalPtr(), subresourceIdx, readData);
+		AsyncOp asyncOp = texture->readSubresource(gCoreAccessor(), subresourceIdx, readData);
 
 		std::function<MonoObject*(const AsyncOp&, const PixelDataPtr&)> asyncOpToMono =
 			[&](const AsyncOp& op, const PixelDataPtr& returnValue)
@@ -78,9 +77,9 @@ namespace BansheeEngine
 		if (scriptPixelData != nullptr)
 		{
 			HTexture texture = thisPtr->mTexture;
-			UINT32 subresourceIdx = texture->mapToSubresourceIdx(face, mipLevel);
+			UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(face, mipLevel);
 
-			gCoreAccessor().writeSubresource(texture.getInternalPtr(), subresourceIdx, scriptPixelData->getInternalValue());
+			texture->writeSubresource(gCoreAccessor(), subresourceIdx, scriptPixelData->getInternalValue(), false);
 		}
 	}
 

+ 2 - 3
TODO.txt

@@ -24,11 +24,10 @@ Disallow CoreObject creation from core thread
  - Add asserts in CoreObject::destroy and CoreObject::initialize
  - Possibly also add asserts to CoreThread::queueCommand and CoreThread::queueReturnCommand
 
-After I refactor Texture remove write/read subresource from core accessor
- - Also get rid of GpuResource class
-
 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)
 
+There seems to be a threading issue with frame alloc freeing due to CoreObject syncing. Sometimes I get crashes in frame alloc relating to unfreed memory
+
 -----------------