ソースを参照

Added support for texture arrays
More work on 3D texture support

BearishSun 9 年 前
コミット
aa06514ff9
31 ファイル変更555 行追加285 行削除
  1. 28 4
      Source/BansheeCore/Include/BsRenderTarget.h
  2. 4 4
      Source/BansheeCore/Include/BsRenderTexture.h
  3. 24 14
      Source/BansheeCore/Include/BsTexture.h
  4. 9 8
      Source/BansheeCore/Include/BsTextureManager.h
  5. 12 4
      Source/BansheeCore/Source/BsMultiRenderTexture.cpp
  6. 12 4
      Source/BansheeCore/Source/BsRenderTexture.cpp
  7. 42 25
      Source/BansheeCore/Source/BsTexture.cpp
  8. 7 4
      Source/BansheeCore/Source/BsTextureManager.cpp
  9. 1 0
      Source/BansheeD3D11RenderAPI/Include/BsD3D11Prerequisites.h
  10. 5 5
      Source/BansheeD3D11RenderAPI/Include/BsD3D11Texture.h
  11. 1 1
      Source/BansheeD3D11RenderAPI/Include/BsD3D11TextureManager.h
  12. 45 93
      Source/BansheeD3D11RenderAPI/Source/BsD3D11Texture.cpp
  13. 2 2
      Source/BansheeD3D11RenderAPI/Source/BsD3D11TextureManager.cpp
  14. 160 31
      Source/BansheeD3D11RenderAPI/Source/BsD3D11TextureView.cpp
  15. 2 1
      Source/BansheeD3D9RenderAPI/Include/BsD3D9Texture.h
  16. 1 1
      Source/BansheeD3D9RenderAPI/Include/BsD3D9TextureManager.h
  17. 2 2
      Source/BansheeD3D9RenderAPI/Source/BsD3D9Texture.cpp
  18. 3 2
      Source/BansheeD3D9RenderAPI/Source/BsD3D9TextureManager.cpp
  19. 2 1
      Source/BansheeGLRenderAPI/Include/BsGLFrameBufferObject.h
  20. 4 3
      Source/BansheeGLRenderAPI/Include/BsGLPixelBuffer.h
  21. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLTexture.h
  22. 1 1
      Source/BansheeGLRenderAPI/Include/BsGLTextureManager.h
  23. 5 2
      Source/BansheeGLRenderAPI/Source/BsGLFrameBufferObject.cpp
  24. 36 11
      Source/BansheeGLRenderAPI/Source/BsGLMultiRenderTexture.cpp
  25. 39 26
      Source/BansheeGLRenderAPI/Source/BsGLPixelBuffer.cpp
  26. 32 6
      Source/BansheeGLRenderAPI/Source/BsGLRenderTexture.cpp
  27. 63 27
      Source/BansheeGLRenderAPI/Source/BsGLTexture.cpp
  28. 2 2
      Source/BansheeGLRenderAPI/Source/BsGLTextureManager.cpp
  29. 5 0
      Source/RenderBeast/Source/BsRenderTargets.cpp
  30. 2 0
      Source/RenderBeast/Source/BsRenderTexturePool.cpp
  31. 3 0
      Source/SBansheeEngine/Source/BsScriptRenderTexture2D.cpp

+ 28 - 4
Source/BansheeCore/Include/BsRenderTarget.h

@@ -17,9 +17,21 @@ namespace BansheeEngine
 	/** Structure that contains information about what part of the texture represents the render surface. */
 	struct BS_CORE_EXPORT RENDER_SURFACE_DESC
 	{
+		RENDER_SURFACE_DESC() { }
+
 		HTexture texture;
-		UINT32 face;
-		UINT32 mipLevel;
+
+		/** First face of the texture to bind (array index in texture arrays, or Z slice in 3D textures). */
+		UINT32 face = 0; 
+
+		/**
+		 * Number of faces to bind (entries in a texture array, or Z slices in 3D textures). When zero the entire resource
+		 * will be bound. 
+		 */
+		UINT32 numFaces = 0;
+
+		/** If the texture has multiple mips, which one to bind (only one can be bound for rendering). */
+		UINT32 mipLevel = 0; 
 	};
 
 	/**
@@ -29,9 +41,21 @@ namespace BansheeEngine
 	 */
 	struct BS_CORE_EXPORT RENDER_SURFACE_CORE_DESC
 	{
+		RENDER_SURFACE_CORE_DESC() { }
+
 		SPtr<TextureCore> texture;
-		UINT32 face;
-		UINT32 mipLevel;
+
+		/** First face of the texture to bind (array index in texture arrays, or Z slice in 3D textures). */
+		UINT32 face = 0; 
+
+		/**
+		 * Number of faces to bind (entries in a texture array, or Z slices in 3D textures). When zero the entire resource
+		 * will be bound. 
+		 */
+		UINT32 numFaces = 0;
+
+		/** If the texture has multiple mips, which one to bind (only one can be bound for rendering). */
+		UINT32 mipLevel = 0; 
 	};
 
 	/** Contains various properties that describe a render target. */

+ 4 - 4
Source/BansheeCore/Include/BsRenderTexture.h

@@ -95,10 +95,10 @@ namespace BansheeEngine
 		RenderTexture(const RENDER_TEXTURE_DESC& desc);
 
 		/** @copydoc CoreObject::createCore */
-		virtual SPtr<CoreObjectCore> createCore() const override;
+		SPtr<CoreObjectCore> createCore() const override;
 
 		/** @copydoc CoreObject::syncToCore */
-		virtual CoreSyncData syncToCore(FrameAlloc* allocator) override;
+		CoreSyncData syncToCore(FrameAlloc* allocator) override;
 
 	protected:
 		HTexture mBindableColorTex;
@@ -136,7 +136,7 @@ namespace BansheeEngine
 		virtual ~RenderTextureCore();
 
 		/** @copydoc CoreObjectCore::initialize */
-		virtual void initialize() override;
+		void initialize() override;
 
 		/** @copydoc TextureCoreManager::createRenderTexture(const RENDER_TEXTURE_CORE_DESC&) */
 		static SPtr<RenderTextureCore> create(const RENDER_TEXTURE_CORE_DESC& desc);
@@ -160,7 +160,7 @@ namespace BansheeEngine
 
 	protected:
 		/** @copydoc CoreObjectCore::syncToCore */
-		virtual void syncToCore(const CoreSyncData& data) override;
+		void syncToCore(const CoreSyncData& data) override;
 
 	private:
 		/**	Throws an exception of the color and depth/stencil buffers aren't compatible. */

+ 24 - 14
Source/BansheeCore/Include/BsTexture.h

@@ -47,7 +47,7 @@ namespace BansheeEngine
 	public:
 		TextureProperties();
 		TextureProperties(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices);
 
 		/**	Gets the type of texture. */
         TextureType getTextureType() const { return mTextureType; }
@@ -82,9 +82,12 @@ namespace BansheeEngine
         /**	Returns true if the texture has an alpha layer. */
         bool hasAlpha() const;
 
-        /**	Return the number of faces this texture has. */
+        /**	Returns the number of faces this texture has. */
         UINT32 getNumFaces() const;
 
+		/** Returns the number of array slices of the texture (if the texture is an array texture). */
+		UINT32 getNumArraySlices() const { return mNumArraySlices; }
+
 		/**
 		 * Maps a sub-resource index to an exact face and mip level. Sub-resource indexes are used when reading or writing
 		 * to the resource.
@@ -121,6 +124,7 @@ namespace BansheeEngine
 		UINT32 mHeight;
 		UINT32 mWidth;
 		UINT32 mDepth;
+		UINT32 mNumArraySlices;
 
 		UINT32 mNumMipmaps;
 		bool mHwGamma;
@@ -212,10 +216,12 @@ namespace BansheeEngine
 		 * @param[in]	hwGammaCorrection	If true the texture data is assumed to have been gamma corrected and will be
 		 *									converted back to linear space when sampled on GPU.
 		 * @param[in]	multisampleCount	If higher than 1, texture containing multiple samples per pixel is created.
+		 * @param[in]	numArraySlices		Number of texture slices to create if creating a texture array. Ignored for
+		 *									3D textures.
 		 */
 		static HTexture create(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
 			int numMips, PixelFormat format, int usage = TU_DEFAULT,
-			bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
+			bool hwGammaCorrection = false, UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 
 
 		/**
@@ -230,10 +236,12 @@ namespace BansheeEngine
 		 * @param[in]	hwGammaCorrection	If true the texture data is assumed to have been gamma corrected and will be
 		 *									converted back to linear space when sampled on GPU.
 		 * @param[in]	multisampleCount	If higher than 1, texture containing multiple samples per pixel is created.
+		 * @param[in]	numArraySlices		Number of texture slices to create if creating a texture array. Ignored for
+		 *									3D textures.
 		 */
 		static HTexture create(TextureType texType, UINT32 width, UINT32 height, int numMips,
 			PixelFormat format, int usage = TU_DEFAULT,
-			bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
+			bool hwGammaCorrection = false, UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 
 		/**
 		 * Creates a new 2D or 3D texture initialized using the provided pixel data. Texture will not have any mipmaps.
@@ -250,21 +258,22 @@ namespace BansheeEngine
 		 */
 
 		/**
-		 * @copydoc	create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32)
+		 * @copydoc	create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, UINT32)
 		 *
 		 * @note	Internal method. Creates a texture pointer without a handle. Use create() for normal usage.
 		 */
 		static SPtr<Texture> _createPtr(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
 			int numMips, PixelFormat format, int usage = TU_DEFAULT,
-			bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
+			bool hwGammaCorrection = false, UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 
 		/**
-		 * @copydoc	create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32)
+		 * @copydoc	create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, UINT32)
 		 *
 		 * @note	Internal method. Creates a texture pointer without a handle. Use create() for normal usage.
 		 */
 		static SPtr<Texture> _createPtr(TextureType texType, UINT32 width, UINT32 height, int numMips,
-			PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
+			PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, UINT32 multisampleCount = 0, 
+			UINT32 numArraySlices = 1);
 
 		/**
 		 * @copydoc	create(const SPtr<PixelData>&, int, bool)
@@ -279,7 +288,7 @@ namespace BansheeEngine
 		friend class TextureManager;
 
 		Texture(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount);
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices);
 
 		Texture(const SPtr<PixelData>& pixelData, int usage, bool hwGamma);
 
@@ -333,7 +342,8 @@ namespace BansheeEngine
 	{
 	public:
 		TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initData);
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, 
+			const SPtr<PixelData>& initData);
 		virtual ~TextureCore() {}
 
 
@@ -429,15 +439,15 @@ namespace BansheeEngine
 		/* 								STATICS		                     		*/
 		/************************************************************************/
 
-		/** @copydoc Texture::create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32) */
+		/** @copydoc Texture::create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, UINT32) */
 		static SPtr<TextureCore> create(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
 			int numMips, PixelFormat format, int usage = TU_DEFAULT,
-			bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
+			bool hwGammaCorrection = false, UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 
-		/** @copydoc Texture::create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32) */
+		/** @copydoc Texture::create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, UINT32) */
 		static SPtr<TextureCore> create(TextureType texType, UINT32 width, UINT32 height, int numMips,
 			PixelFormat format, int usage = TU_DEFAULT,
-			bool hwGammaCorrection = false, UINT32 multisampleCount = 0);
+			bool hwGammaCorrection = false, UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 
 		/** @copydoc Texture::create(const SPtr<PixelData>&, int, bool) */
 		static SPtr<TextureCore> create(const SPtr<PixelData>& pixelData, int usage = TU_DEFAULT, bool hwGammaCorrection = false);

+ 9 - 8
Source/BansheeCore/Include/BsTextureManager.h

@@ -24,17 +24,18 @@ namespace BansheeEngine
     public:
 		virtual ~TextureManager() { }
 
-		/** @copydoc Texture::create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32) */
+		/** @copydoc Texture::create(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, UINT32) */
         SPtr<Texture> createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, 
 			int numMips, PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, 
-			UINT32 multisampleCount = 0);
+			UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 			
-		/** @copydoc Texture::create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32) */
+		/** @copydoc Texture::create(TextureType, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, UINT32) */
 		SPtr<Texture> createTexture(TextureType texType, UINT32 width, UINT32 height, int numMips,
-			PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, UINT32 multisampleCount = 0)
+			PixelFormat format, int usage = TU_DEFAULT, bool hwGammaCorrection = false, UINT32 multisampleCount = 0, 
+			UINT32 numArraySlices = 1)
 		{
 			return createTexture(texType, width, height, 1, 
-				numMips, format, usage, hwGammaCorrection, multisampleCount);
+				numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 		}
 
 		/** @copydoc Texture::create(const SPtr<PixelData>&, int, bool) */
@@ -116,11 +117,11 @@ namespace BansheeEngine
 		void onShutDown() override;
 
 		/**
-		 * @copydoc	TextureManager::createTexture(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32)
+		 * @copydoc	TextureManager::createTexture(TextureType, UINT32, UINT32, UINT32, int, PixelFormat, int, bool, UINT32, 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);
+			UINT32 multisampleCount = 0, UINT32 numArraySlices = 1);
 
 		/** @copydoc	TextureManager::createRenderTexture(const RENDER_TEXTURE_DESC&) */
 		SPtr<RenderTextureCore> createRenderTexture(const RENDER_TEXTURE_CORE_DESC& desc);
@@ -140,7 +141,7 @@ namespace BansheeEngine
 		 */
 		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, const SPtr<PixelData>& initialData = nullptr) = 0;
+			UINT32 multisampleCount = 0, UINT32 numArraySlices = 1, const SPtr<PixelData>& initialData = nullptr) = 0;
 
 		/** @copydoc TextureManager::createRenderTextureImpl */
 		virtual SPtr<RenderTextureCore> createRenderTextureInternal(const RENDER_TEXTURE_CORE_DESC& desc) = 0;

+ 12 - 4
Source/BansheeCore/Source/BsMultiRenderTexture.cpp

@@ -98,7 +98,7 @@ namespace BansheeEngine
 					BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
 				mColorSurfaces[i] = TextureCore::requestView(texture, mDesc.colorSurfaces[i].mipLevel, 1,
-					mDesc.colorSurfaces[i].face, 1, GVU_RENDERTARGET);
+					mDesc.colorSurfaces[i].face, mDesc.colorSurfaces[i].numFaces, GVU_RENDERTARGET);
 			}
 		}
 
@@ -110,7 +110,7 @@ namespace BansheeEngine
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
 			mDepthStencilSurface = TextureCore::requestView(texture, mDesc.depthStencilSurface.mipLevel, 1,
-				mDesc.depthStencilSurface.face, 1, GVU_DEPTHSTENCIL);
+				mDesc.depthStencilSurface.face, 0, GVU_DEPTHSTENCIL);
 		}
 
 		throwIfBuffersDontMatch();
@@ -163,10 +163,16 @@ namespace BansheeEngine
 			if (firstTexProps.getTextureType() != TEX_TYPE_2D)
 				BS_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
 
-			if ((firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) > firstTexProps.getNumFaces())
+			UINT32 numSlices;
+			if (firstTexProps.getTextureType() == TEX_TYPE_3D)
+				numSlices = firstTexProps.getDepth();
+			else
+				numSlices = firstTexProps.getNumFaces();
+
+			if ((firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) > numSlices)
 			{
 				BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " +
-					toString(firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) + ". Max num faces: " + toString(firstTexProps.getNumFaces()));
+					toString(firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) + ". Max num faces: " + toString(numSlices));
 			}
 
 			if (firstSurfaceDesc->getMostDetailedMip() > firstTexProps.getNumMipmaps())
@@ -221,6 +227,7 @@ namespace BansheeEngine
 				surfaceDesc.texture = colorSurface.texture->getCore();
 
 			surfaceDesc.face = colorSurface.face;
+			surfaceDesc.numFaces = colorSurface.numFaces;
 			surfaceDesc.mipLevel = colorSurface.mipLevel;
 
 			coreDesc.colorSurfaces.push_back(surfaceDesc);
@@ -230,6 +237,7 @@ namespace BansheeEngine
 			coreDesc.depthStencilSurface.texture = mDesc.depthStencilSurface.texture->getCore();
 
 		coreDesc.depthStencilSurface.face = mDesc.depthStencilSurface.face;
+		coreDesc.depthStencilSurface.numFaces = mDesc.depthStencilSurface.numFaces;
 		coreDesc.depthStencilSurface.mipLevel = mDesc.depthStencilSurface.mipLevel;
 
 		return TextureCoreManager::instance().createMultiRenderTextureInternal(coreDesc);

+ 12 - 4
Source/BansheeCore/Source/BsRenderTexture.cpp

@@ -79,7 +79,7 @@ namespace BansheeEngine
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
 			mColorSurface = TextureCore::requestView(texture, colorSurface.mipLevel, 1,
-				colorSurface.face, 1, GVU_RENDERTARGET);
+				colorSurface.face, colorSurface.numFaces, GVU_RENDERTARGET);
 		}
 
 		const RENDER_SURFACE_CORE_DESC& depthStencilSurface = mDesc.depthStencilSurface;
@@ -91,7 +91,7 @@ namespace BansheeEngine
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
 			mDepthStencilSurface = TextureCore::requestView(texture, depthStencilSurface.mipLevel, 1,
-				depthStencilSurface.face, 1, GVU_DEPTHSTENCIL);
+				depthStencilSurface.face, 0, GVU_DEPTHSTENCIL);
 		}
 
 		throwIfBuffersDontMatch();
@@ -103,11 +103,17 @@ namespace BansheeEngine
 			SPtr<TextureCore> colorTexture = mColorSurface->getTexture();
 			const TextureProperties& texProps = colorTexture->getProperties();
 
-			if ((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > texProps.getNumFaces())
+			UINT32 numSlices;
+			if (texProps.getTextureType() == TEX_TYPE_3D)
+				numSlices = texProps.getDepth();
+			else
+				numSlices = texProps.getNumFaces();
+
+			if ((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > numSlices)
 			{
 				BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " +
 					toString(mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) +
-					". Max num faces: " + toString(texProps.getNumFaces()));
+					". Max num faces: " + toString(numSlices));
 			}
 
 			if (mColorSurface->getMostDetailedMip() > texProps.getNumMipmaps())
@@ -194,8 +200,10 @@ namespace BansheeEngine
 			coreDesc.depthStencilSurface.texture = mDesc.depthStencilSurface.texture->getCore();
 
 		coreDesc.colorSurface.face = mDesc.colorSurface.face;
+		coreDesc.colorSurface.numFaces = mDesc.colorSurface.numFaces;
 		coreDesc.colorSurface.mipLevel = mDesc.colorSurface.mipLevel;
 		coreDesc.depthStencilSurface.face = mDesc.depthStencilSurface.face;
+		coreDesc.depthStencilSurface.numFaces = mDesc.depthStencilSurface.numFaces;
 		coreDesc.depthStencilSurface.mipLevel = mDesc.depthStencilSurface.mipLevel;
 
 		return TextureCoreManager::instance().createRenderTextureInternal(coreDesc);

+ 42 - 25
Source/BansheeCore/Source/BsTexture.cpp

@@ -14,7 +14,7 @@
 namespace BansheeEngine 
 {
 	TextureProperties::TextureProperties()
-		:mHeight(32), mWidth(32), mDepth(1), mNumMipmaps(0),
+		:mHeight(32), mWidth(32), mDepth(1), mNumArraySlices(1), mNumMipmaps(0),
 		mHwGamma(false), mMultisampleCount(0), mTextureType(TEX_TYPE_2D),
 		mFormat(PF_UNKNOWN), mUsage(TU_DEFAULT)
 	{
@@ -22,8 +22,8 @@ namespace BansheeEngine
 	}
 
 	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),
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices)
+		:mHeight(height), mWidth(width), mDepth(depth), mNumArraySlices(numArraySlices), mNumMipmaps(numMipmaps),
 		mHwGamma(hwGamma), mMultisampleCount(multisampleCount), mTextureType(textureType),
 		mFormat(format), mUsage(usage)
 	{
@@ -37,7 +37,9 @@ namespace BansheeEngine
 
 	UINT32 TextureProperties::getNumFaces() const
 	{
-		return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
+		UINT32 facesPerSlice = getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
+
+		return facesPerSlice * mNumArraySlices;
 	}
 
 	void TextureProperties::mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const
@@ -86,8 +88,9 @@ namespace BansheeEngine
 	SPtr<TextureCore> TextureCore::NORMAL;
 
 	TextureCore::TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initData)
-		:mProperties(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount), 
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, 
+		const SPtr<PixelData>& initData)
+		:mProperties(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, numArraySlices), 
 		mInitData(initData)
 	{ }
 
@@ -244,9 +247,21 @@ namespace BansheeEngine
 		key.mostDetailMip = mostDetailMip;
 		key.numMips = numMips;
 		key.firstArraySlice = firstArraySlice;
-		key.numArraySlices = numArraySlices;
 		key.usage = usage;
 
+		const TextureProperties& texProps = texture->getProperties();
+		if(numArraySlices == 0) // Automatically determine slice count
+		{
+			if(texProps.getTextureType() == TEX_TYPE_3D)
+				key.numArraySlices = texProps.getDepth();
+			else
+				key.numArraySlices = texProps.getNumFaces();
+		}
+		else
+		{
+			key.numArraySlices = numArraySlices;
+		}
+
 		auto iterFind = texture->mTextureViews.find(key);
 		if (iterFind == texture->mTextureViews.end())
 		{
@@ -290,24 +305,24 @@ namespace BansheeEngine
 	/* 								STATICS	                      			*/
 	/************************************************************************/
 	SPtr<TextureCore> TextureCore::create(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
 		return TextureCoreManager::instance().createTexture(texType,
-			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 	}
 
 	SPtr<TextureCore> TextureCore::create(TextureType texType, UINT32 width, UINT32 height,
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
 		return TextureCoreManager::instance().createTexture(texType,
-			width, height, 1, numMips, format, usage, hwGammaCorrection, multisampleCount);
+			width, height, 1, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 	}
 
 	SPtr<TextureCore> TextureCore::create(const SPtr<PixelData>& pixelData, int usage, bool hwGammaCorrection)
 	{
 		return TextureCoreManager::instance().createTextureInternal(pixelData->getDepth() > 1 ? TEX_TYPE_3D : TEX_TYPE_2D, 
 			pixelData->getWidth(), pixelData->getHeight(),
-			pixelData->getDepth(), 0, pixelData->getFormat(), usage, hwGammaCorrection, 0, pixelData);
+			pixelData->getDepth(), 0, pixelData->getFormat(), usage, hwGammaCorrection, 0, 1, pixelData);
 	}
 
 	Texture::Texture()
@@ -316,15 +331,15 @@ namespace BansheeEngine
 	}
 
 	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)
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices)
+		:mProperties(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, numArraySlices)
     {
         
     }
 
 	Texture::Texture(const SPtr<PixelData>& pixelData, int usage, bool hwGamma)
 		: mProperties(pixelData->getDepth() > 1 ? TEX_TYPE_3D : TEX_TYPE_2D, pixelData->getWidth(), pixelData->getHeight(),
-		pixelData->getDepth(), 0, pixelData->getFormat(), usage, hwGamma, 0), mInitData(pixelData)
+		pixelData->getDepth(), 0, pixelData->getFormat(), usage, hwGamma, 0, 1), mInitData(pixelData)
 	{
 		if (mInitData != nullptr)
 			mInitData->_lock();
@@ -350,8 +365,10 @@ namespace BansheeEngine
 	{
 		const TextureProperties& props = getProperties();
 
-		SPtr<CoreObjectCore> coreObj = TextureCoreManager::instance().createTextureInternal(props.getTextureType(), props.getWidth(), props.getHeight(),
-			props.getDepth(), props.getNumMipmaps(), props.getFormat(), props.getUsage(), props.isHardwareGammaEnabled(), props.getMultisampleCount(), mInitData);
+		SPtr<CoreObjectCore> coreObj = TextureCoreManager::instance().createTextureInternal(props.getTextureType(), 
+			props.getWidth(), props.getHeight(), props.getDepth(), props.getNumMipmaps(), props.getFormat(), 
+			props.getUsage(), props.isHardwareGammaEnabled(), props.getMultisampleCount(), props.getNumArraySlices(), 
+			mInitData);
 
 		if ((mProperties.getUsage() & TU_CPUCACHED) == 0)
 			mInitData = nullptr;
@@ -527,19 +544,19 @@ namespace BansheeEngine
 	/* 								STATICS	                      			*/
 	/************************************************************************/
 	HTexture Texture::create(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, 
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
 		SPtr<Texture> texturePtr = _createPtr(texType, 
-			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 
 		return static_resource_cast<Texture>(gResources()._createResourceHandle(texturePtr));
 	}
 	
 	HTexture Texture::create(TextureType texType, UINT32 width, UINT32 height, 
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
 		SPtr<Texture> texturePtr = _createPtr(texType, 
-			width, height, numMips, format, usage, hwGammaCorrection, multisampleCount);
+			width, height, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 
 		return static_resource_cast<Texture>(gResources()._createResourceHandle(texturePtr));
 	}
@@ -552,17 +569,17 @@ namespace BansheeEngine
 	}
 
 	SPtr<Texture> Texture::_createPtr(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, 
-		int num_mips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int num_mips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
 		return TextureManager::instance().createTexture(texType, 
-			width, height, depth, num_mips, format, usage, hwGammaCorrection, multisampleCount);
+			width, height, depth, num_mips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 	}
 
 	SPtr<Texture> Texture::_createPtr(TextureType texType, UINT32 width, UINT32 height, 
-		int num_mips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int num_mips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
 		return TextureManager::instance().createTexture(texType, 
-			width, height, num_mips, format, usage, hwGammaCorrection, multisampleCount);
+			width, height, num_mips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices);
 	}
 
 	SPtr<Texture> Texture::_createPtr(const SPtr<PixelData>& pixelData, int usage, bool hwGammaCorrection)

+ 7 - 4
Source/BansheeCore/Source/BsTextureManager.cpp

@@ -9,9 +9,9 @@
 namespace BansheeEngine 
 {
     SPtr<Texture> TextureManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, int numMipmaps,
-        PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
+        PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices)
     {
-		Texture* tex = new (bs_alloc<Texture>()) Texture(texType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount);
+		Texture* tex = new (bs_alloc<Texture>()) Texture(texType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, numArraySlices);
 		SPtr<Texture> ret = bs_core_ptr<Texture>(tex);
 
 		ret->_setThisPtr(ret);
@@ -55,10 +55,12 @@ namespace BansheeEngine
 		RENDER_TEXTURE_DESC desc;
 		desc.colorSurface.texture = texture;
 		desc.colorSurface.face = 0;
+		desc.colorSurface.numFaces = 1;
 		desc.colorSurface.mipLevel = 0;
 
 		desc.depthStencilSurface.texture = depthStencil;
 		desc.depthStencilSurface.face = 0;
+		desc.depthStencilSurface.numFaces = 1;
 		desc.depthStencilSurface.mipLevel = 0;
 
 		SPtr<RenderTexture> newRT = createRenderTexture(desc);
@@ -133,9 +135,10 @@ namespace BansheeEngine
     }
 
 	SPtr<TextureCore> TextureCoreManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices)
 	{
-		SPtr<TextureCore> newRT = createTextureInternal(texType, width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
+		SPtr<TextureCore> newRT = createTextureInternal(texType, width, height, depth, numMips, format, 
+			usage, hwGammaCorrection, multisampleCount, numArraySlices);
 		newRT->initialize();
 
 		return newRT;

+ 1 - 0
Source/BansheeD3D11RenderAPI/Include/BsD3D11Prerequisites.h

@@ -61,6 +61,7 @@ namespace BansheeEngine
 	class D3D11GpuBufferCore;
 	class D3D11RenderUtility;
 	class D3D11GpuProgramCore;
+	class D3D11TextureView;
 
 	/**	DirectX 11 specific types to track resource statistics for. */
 	enum D3D11RenderStatResourceType

+ 5 - 5
Source/BansheeD3D11RenderAPI/Include/BsD3D11Texture.h

@@ -21,7 +21,7 @@ namespace BansheeEngine
 		ID3D11Resource* getDX11Resource() const { return mTex; }
 
 		/**	Returns shader resource view associated with the texture. */
-		ID3D11ShaderResourceView* getSRV() const { return mShaderResourceView; }
+		ID3D11ShaderResourceView* getSRV() const;
 
 		/** Returns DXGI pixel format that was used to create the texture. */
 		DXGI_FORMAT getDXGIFormat() const { return mDXGIFormat; }
@@ -36,7 +36,8 @@ namespace BansheeEngine
 		friend class D3D11TextureCoreManager;
 
 		D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initialData);
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, 
+			const SPtr<PixelData>& initialData);
 
 		/** @copydoc CoreObjectCore::initialize() */
 		void initialize() override;
@@ -129,9 +130,8 @@ namespace BansheeEngine
 		ID3D11Texture3D* m3DTex;
 		ID3D11Resource* mTex;
 
-		ID3D11ShaderResourceView* mShaderResourceView;
-		D3D11_SHADER_RESOURCE_VIEW_DESC mSRVDesc;
-		D3D11_SRV_DIMENSION mDimension;
+		SPtr<D3D11TextureView> mShaderResourceView;
+		
 		DXGI_FORMAT mDXGIFormat;
 		DXGI_FORMAT mDXGIColorFormat;
 		DXGI_FORMAT mDXGIDepthStencilFormat;

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11TextureManager.h

@@ -33,7 +33,7 @@ namespace BansheeEngine
 		/** @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, const SPtr<PixelData>& initialData = nullptr) override;
+			UINT32 multisampleCount = 0, UINT32 numArraySlices = 1, const SPtr<PixelData>& initialData = nullptr) override;
 
 		/** @copydoc TextureCoreManager::createRenderTextureInternal */
 		SPtr<RenderTextureCore> createRenderTextureInternal(const RENDER_TEXTURE_CORE_DESC& desc) override;

+ 45 - 93
Source/BansheeD3D11RenderAPI/Source/BsD3D11Texture.cpp

@@ -14,17 +14,16 @@
 namespace BansheeEngine
 {
 	D3D11TextureCore::D3D11TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initialData)
-		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, const SPtr<PixelData>& initialData)
+		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, numArraySlices, initialData),
 		m1DTex(nullptr), m2DTex(nullptr), m3DTex(nullptr), mDXGIFormat(DXGI_FORMAT_UNKNOWN), mDXGIColorFormat(DXGI_FORMAT_UNKNOWN),
-		mTex(nullptr), mShaderResourceView(nullptr), mStagingBuffer(nullptr), mDXGIDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
+		mTex(nullptr), mStagingBuffer(nullptr), mDXGIDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
 		mLockedSubresourceIdx(-1), mLockedForReading(false), mStaticBuffer(nullptr)
 	{ }
 
 	D3D11TextureCore::~D3D11TextureCore()
 	{ 
 		SAFE_RELEASE(mTex);
-		SAFE_RELEASE(mShaderResourceView);
 		SAFE_RELEASE(m1DTex);
 		SAFE_RELEASE(m2DTex);
 		SAFE_RELEASE(m3DTex);
@@ -179,6 +178,12 @@ namespace BansheeEngine
 		if (mProperties.getMultisampleCount() > 1)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
+		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
+		face = Math::clamp(face, (UINT32)0, mProperties.getNumFaces() - 1);
+
+		if (face > 0 && mProperties.getTextureType() == TEX_TYPE_3D)
+			BS_EXCEPT(InvalidStateException, "3D texture arrays are not supported.");
+
 		if ((mProperties.getUsage() & TU_DYNAMIC) != 0)
 		{
 			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
@@ -187,12 +192,6 @@ namespace BansheeEngine
 		}
 		else if ((mProperties.getUsage() & TU_DEPTHSTENCIL) == 0)
 		{
-			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
-			face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
-
-			if(mProperties.getTextureType() == TEX_TYPE_3D)
-				face = 0;
-
 			D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
 			D3D11Device& device = rs->getPrimaryDevice();
 
@@ -223,8 +222,8 @@ namespace BansheeEngine
 		UINT32 numMips = mProperties.getNumMipmaps();
 		PixelFormat format = mProperties.getFormat();
 		bool hwGamma = mProperties.isHardwareGammaEnabled();
-		TextureType texType = mProperties.getTextureType();
 		PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma);
+		UINT32 numFaces = mProperties.getNumFaces();
 
 		// We must have those defined here
 		assert(width > 0);
@@ -246,7 +245,7 @@ namespace BansheeEngine
 
 		D3D11_TEXTURE1D_DESC desc;
 		desc.Width = static_cast<UINT32>(width);
-		desc.ArraySize		= 1;
+		desc.ArraySize		= numFaces == 0 ? 1 : numFaces;
 		desc.Format			= d3dPF;
 		desc.MiscFlags		= 0;
 
@@ -315,22 +314,19 @@ namespace BansheeEngine
 		}
 
 		mDXGIFormat = desc.Format;
-		mDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
 
 		// Create texture view
 		if ((usage & TU_DEPTHSTENCIL) == 0 || readableDepth)
 		{
-			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
-			mSRVDesc.Format = mDXGIColorFormat;
-			mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; 
-			mSRVDesc.Texture1D.MipLevels = desc.MipLevels;
-			hr = device.getD3D11Device()->CreateShaderResourceView(m1DTex, &mSRVDesc, &mShaderResourceView);
+			TEXTURE_VIEW_DESC viewDesc;
+			viewDesc.mostDetailMip = 0;
+			viewDesc.numMips = desc.MipLevels;
+			viewDesc.firstArraySlice = 0;
+			viewDesc.numArraySlices = desc.ArraySize;
+			viewDesc.usage = GVU_DEFAULT;
 
-			if (FAILED(hr) || device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
-			}
+			SPtr<TextureCore> thisPtr = std::static_pointer_cast<TextureCore>(getThisPtr());
+			mShaderResourceView = bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(thisPtr, viewDesc));
 		}
 	}
 
@@ -345,6 +341,7 @@ namespace BansheeEngine
 		UINT32 sampleCount = mProperties.getMultisampleCount();
 		TextureType texType = mProperties.getTextureType();
 		PixelFormat closestFormat = D3D11Mappings::getClosestSupportedPF(format, hwGamma);
+		UINT32 numFaces = mProperties.getNumFaces();
 
 		// TODO - Consider making this a parameter eventually
 		bool readableDepth = true;
@@ -367,7 +364,7 @@ namespace BansheeEngine
 		D3D11_TEXTURE2D_DESC desc;
 		desc.Width			= static_cast<UINT32>(width);
 		desc.Height			= static_cast<UINT32>(height);
-		desc.ArraySize		= 1;
+		desc.ArraySize		= numFaces == 0 ? 1 : numFaces;;
 		desc.Format			= d3dPF;
 		desc.MiscFlags		= 0;
 
@@ -429,10 +426,7 @@ namespace BansheeEngine
 		}
 
 		if (texType == TEX_TYPE_CUBE_MAP)
-        {
             desc.MiscFlags      |= D3D11_RESOURCE_MISC_TEXTURECUBE;
-            desc.ArraySize       = 6;
-        }
 
 		if ((usage & TU_LOADSTORE) != 0)
 			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
@@ -470,57 +464,15 @@ namespace BansheeEngine
 		// Create shader texture view
 		if((usage & TU_DEPTHSTENCIL) == 0 || readableDepth)
 		{
-			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
-			mSRVDesc.Format = mDXGIColorFormat;
-
-			if((usage & TU_RENDERTARGET) != 0 && (usage & TU_DEPTHSTENCIL) != 0)
-			{
-				if (sampleCount > 1)
-				{
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
-					mSRVDesc.Texture2D.MostDetailedMip = 0;
-					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
-				}
-				else
-				{
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-					mSRVDesc.Texture2D.MostDetailedMip = 0;
-					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
-				}
-			}
-			else
-			{
-				switch (texType)
-				{
-				case TEX_TYPE_CUBE_MAP:
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
-					mSRVDesc.TextureCube.MipLevels = desc.MipLevels;
-					mSRVDesc.TextureCube.MostDetailedMip = 0;
-					break;
-
-				case TEX_TYPE_2D:
-					mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-					mSRVDesc.Texture2D.MostDetailedMip = 0;
-					mSRVDesc.Texture2D.MipLevels = desc.MipLevels;
-					break;
-				}
-			}
-
-			mDimension = mSRVDesc.ViewDimension;
-			hr = device.getD3D11Device()->CreateShaderResourceView(m2DTex, &mSRVDesc, &mShaderResourceView);
+			TEXTURE_VIEW_DESC viewDesc;
+			viewDesc.mostDetailMip = 0;
+			viewDesc.numMips = desc.MipLevels;
+			viewDesc.firstArraySlice = 0;
+			viewDesc.numArraySlices = desc.ArraySize;
+			viewDesc.usage = GVU_DEFAULT;
 
-			if (FAILED(hr) || device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
-			}
-		}
-		else
-		{
-			if (sampleCount > 1)
-				mDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
-			else
-				mDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+			SPtr<TextureCore> thisPtr = std::static_pointer_cast<TextureCore>(getThisPtr());
+			mShaderResourceView = bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(thisPtr, viewDesc));
 		}
 	}
 
@@ -557,8 +509,8 @@ namespace BansheeEngine
 		desc.Width = static_cast<UINT32>(width);
 		desc.Height = static_cast<UINT32>(height);
 		desc.Depth = static_cast<UINT32>(depth);
-		desc.Format			= d3dPF;
-		desc.MiscFlags		= 0;
+		desc.Format	= d3dPF;
+		desc.MiscFlags = 0;
 
 		if ((mProperties.getUsage() & TU_RENDERTARGET) != 0)
 		{
@@ -625,23 +577,18 @@ namespace BansheeEngine
 		}
 
 		mDXGIFormat = desc.Format;
-		mDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
 
 		if ((usage & TU_DEPTHSTENCIL) == 0 || readableDepth)
 		{
-			ZeroMemory(&mSRVDesc, sizeof(mSRVDesc));
-			mSRVDesc.Format = mDXGIColorFormat;
-			mSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
-			mSRVDesc.Texture3D.MostDetailedMip = 0;
-			mSRVDesc.Texture3D.MipLevels = desc.MipLevels;
-
-			hr = device.getD3D11Device()->CreateShaderResourceView(m2DTex, &mSRVDesc, &mShaderResourceView);
+			TEXTURE_VIEW_DESC viewDesc;
+			viewDesc.mostDetailMip = 0;
+			viewDesc.numMips = desc.MipLevels;
+			viewDesc.firstArraySlice = 0;
+			viewDesc.numArraySlices = 1;
+			viewDesc.usage = GVU_DEFAULT;
 
-			if (FAILED(hr) || device.hasError())
-			{
-				String errorDescription = device.getErrorDescription();
-				BS_EXCEPT(RenderingAPIException, "D3D11 device can't create shader resource view.\nError Description:" + errorDescription);
-			}
+			SPtr<TextureCore> thisPtr = std::static_pointer_cast<TextureCore>(getThisPtr());
+			mShaderResourceView = bs_shared_ptr<D3D11TextureView>(new (bs_alloc<D3D11TextureView>()) D3D11TextureView(thisPtr, viewDesc));
 		}
 	}
 
@@ -651,7 +598,7 @@ namespace BansheeEngine
 		pMappedResource.pData = nullptr;
 
 		mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, mProperties.getNumMipmaps());
-		face = Math::clamp(face, (UINT32)0, mProperties.getDepth() - 1);
+		face = Math::clamp(face, (UINT32)0, mProperties.getNumFaces() - 1);
 
 		if (mProperties.getTextureType() == TEX_TYPE_3D)
 			face = 0;
@@ -740,6 +687,11 @@ namespace BansheeEngine
 			bs_delete(mStaticBuffer);
 	}
 
+	ID3D11ShaderResourceView* D3D11TextureCore::getSRV() const
+	{
+		return mShaderResourceView->getSRV();
+	}
+
 	void D3D11TextureCore::createStagingBuffer()
 	{
 		D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11TextureManager.cpp

@@ -32,10 +32,10 @@ namespace BansheeEngine
 	}
 
 	SPtr<TextureCore> D3D11TextureCoreManager::createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, const SPtr<PixelData>& initialData)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices, const SPtr<PixelData>& initialData)
 	{
 		D3D11TextureCore* tex = new (bs_alloc<D3D11TextureCore>()) D3D11TextureCore(texType, 
-			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, initialData);
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices, initialData);
 
 		SPtr<D3D11TextureCore> texPtr = bs_shared_ptr<D3D11TextureCore>(tex);
 		texPtr->_setThisPtr(texPtr);

+ 160 - 31
Source/BansheeD3D11RenderAPI/Source/BsD3D11TextureView.cpp

@@ -44,34 +44,78 @@ namespace BansheeEngine
 		ZeroMemory(&desc, sizeof(desc));
 
 		const TextureProperties& texProps = texture->getProperties();
+		UINT32 numFaces = texProps.getNumFaces();
+
 		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
-			desc.Texture1D.MipLevels = numMips;
-			desc.Texture1D.MostDetailedMip = mostDetailMip;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+			if (numFaces <= 1)
+			{
+				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+				desc.Texture1D.MipLevels = numMips;
+				desc.Texture1D.MostDetailedMip = mostDetailMip;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+				desc.Texture1DArray.MipLevels = numMips;
+				desc.Texture1DArray.MostDetailedMip = mostDetailMip;
+				desc.Texture1DArray.FirstArraySlice = firstArraySlice;
+				desc.Texture1DArray.ArraySize = numArraySlices;
+			}
 			break;
 		case TEX_TYPE_2D:
 			if (texProps.getMultisampleCount() > 1)
 			{
-				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+				if (numFaces <= 1)
+				{
+					desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+				}
+				else
+				{
+					desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+					desc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
+					desc.Texture2DMSArray.ArraySize = numArraySlices;
+				}
 			}
 			else
 			{
-				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-				desc.Texture2D.MipLevels = numMips;
-				desc.Texture2D.MostDetailedMip = mostDetailMip;
+				if (numFaces <= 1)
+				{
+					desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+					desc.Texture2D.MipLevels = numMips;
+					desc.Texture2D.MostDetailedMip = mostDetailMip;
+				}
+				else
+				{
+					desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+					desc.Texture2DArray.MipLevels = numMips;
+					desc.Texture2DArray.MostDetailedMip = mostDetailMip;
+					desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+					desc.Texture2DArray.ArraySize = numArraySlices;
+				}
 			}
 			break;
 		case TEX_TYPE_3D:
+			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
 			desc.Texture3D.MipLevels = numMips;
 			desc.Texture3D.MostDetailedMip = mostDetailMip;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
 			break;
 		case TEX_TYPE_CUBE_MAP:
-			desc.TextureCube.MipLevels = numMips;
-			desc.TextureCube.MostDetailedMip = mostDetailMip;
-			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+			if (numFaces <= 6)
+			{
+				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+				desc.TextureCube.MipLevels = numMips;
+				desc.TextureCube.MostDetailedMip = mostDetailMip;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
+				desc.TextureCubeArray.MipLevels = numMips;
+				desc.TextureCubeArray.MostDetailedMip = mostDetailMip;
+				desc.TextureCubeArray.First2DArrayFace = firstArraySlice;
+				desc.TextureCubeArray.NumCubes = numArraySlices / 6;
+			}
 			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
@@ -100,34 +144,65 @@ namespace BansheeEngine
 		ZeroMemory(&desc, sizeof(desc));
 
 		const TextureProperties& texProps = texture->getProperties();
+		UINT32 numFaces = texProps.getNumFaces();
+
 		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
-			desc.Texture1D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+			if (numFaces <= 1)
+			{
+				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+				desc.Texture1D.MipSlice = mipSlice;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
+				desc.Texture1DArray.MipSlice = mipSlice;
+				desc.Texture1DArray.FirstArraySlice = firstArraySlice;
+				desc.Texture1DArray.ArraySize = numArraySlices;
+			}
 			break;
 		case TEX_TYPE_2D:
 			if (texProps.getMultisampleCount() > 1)
 			{
-				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+				if (numFaces <= 1)
+				{
+					desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+				}
+				else
+				{
+					desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
+					desc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
+					desc.Texture2DMSArray.ArraySize = numArraySlices;
+				}
 			}
 			else
 			{
-				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
-				desc.Texture2D.MipSlice = mipSlice;
+				if (numFaces <= 1)
+				{
+					desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+					desc.Texture2D.MipSlice = mipSlice;
+				}
+				else
+				{
+					desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+					desc.Texture2DArray.MipSlice = mipSlice;
+					desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+					desc.Texture2DArray.ArraySize = numArraySlices;
+				}
 			}
 			break;
 		case TEX_TYPE_3D:
+			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
 			desc.Texture3D.MipSlice = mipSlice;
 			desc.Texture3D.FirstWSlice = firstArraySlice;
 			desc.Texture3D.WSize = numArraySlices;
-			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
 			break;
 		case TEX_TYPE_CUBE_MAP:
+			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
 			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
 			desc.Texture2DArray.ArraySize = numArraySlices;
 			desc.Texture2DArray.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
 			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
@@ -155,27 +230,50 @@ namespace BansheeEngine
 		D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
 
-		switch(texture->getProperties().getTextureType())
+		const TextureProperties& texProps = texture->getProperties();
+		UINT32 numFaces = texProps.getNumFaces();
+
+		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
-			desc.Texture1D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
+			if (numFaces <= 1)
+			{
+				desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D;
+				desc.Texture1D.MipSlice = mipSlice;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY;
+				desc.Texture1DArray.MipSlice = mipSlice;
+				desc.Texture1DArray.FirstArraySlice = firstArraySlice;
+				desc.Texture1DArray.ArraySize = numArraySlices;
+			}
 			break;
 		case TEX_TYPE_2D:
-			desc.Texture2D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+			if (numFaces <= 1)
+			{
+				desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+				desc.Texture2D.MipSlice = mipSlice;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+				desc.Texture2DArray.MipSlice = mipSlice;
+				desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+				desc.Texture2DArray.ArraySize = numArraySlices;
+			}
 			break;
 		case TEX_TYPE_3D:
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
 			desc.Texture3D.MipSlice = mipSlice;
 			desc.Texture3D.FirstWSlice = firstArraySlice;
 			desc.Texture3D.WSize = numArraySlices;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
 			break;
 		case TEX_TYPE_CUBE_MAP:
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
 			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
 			desc.Texture2DArray.ArraySize = numArraySlices;
 			desc.Texture2DArray.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
 			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
@@ -204,29 +302,60 @@ namespace BansheeEngine
 		ZeroMemory(&desc, sizeof(desc));
 
 		const TextureProperties& texProps = texture->getProperties();
+		UINT32 numFaces = texProps.getNumFaces();
+
 		switch (texProps.getTextureType())
 		{
 		case TEX_TYPE_1D:
-			desc.Texture1D.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
+			if (numFaces <= 1)
+			{
+				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
+				desc.Texture1D.MipSlice = mipSlice;
+			}
+			else
+			{
+				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
+				desc.Texture1DArray.MipSlice = mipSlice;
+				desc.Texture1DArray.FirstArraySlice = firstArraySlice;
+				desc.Texture1DArray.ArraySize = numArraySlices;
+			}
 			break;
 		case TEX_TYPE_2D:
 			if (texProps.getMultisampleCount() > 1)
 			{
-				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+				if (numFaces <= 1)
+				{
+					desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+				}
+				else
+				{
+					desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
+					desc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
+					desc.Texture2DMSArray.ArraySize = numArraySlices;
+				}
 			}
 			else
 			{
-				desc.Texture2D.MipSlice = mipSlice;
-				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+				if (numFaces <= 1)
+				{
+					desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+					desc.Texture2D.MipSlice = mipSlice;
+				}
+				else
+				{
+					desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+					desc.Texture2DArray.MipSlice = mipSlice;
+					desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+					desc.Texture2DArray.ArraySize = numArraySlices;
+				}
 			}
 			break;
 		case TEX_TYPE_3D:
 		case TEX_TYPE_CUBE_MAP:
+			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
 			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
 			desc.Texture2DArray.ArraySize = numArraySlices;
 			desc.Texture2DArray.MipSlice = mipSlice;
-			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
 			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");

+ 2 - 1
Source/BansheeD3D9RenderAPI/Include/BsD3D9Texture.h

@@ -74,7 +74,8 @@ namespace BansheeEngine
 		friend class D3D9PixelBuffer;
 
 		D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initialData);
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, 
+			const SPtr<PixelData>& initialData);
 
 		/** @copydoc TextureCore::initialize */
 		void initialize() override;

+ 1 - 1
Source/BansheeD3D9RenderAPI/Include/BsD3D9TextureManager.h

@@ -37,7 +37,7 @@ namespace BansheeEngine
 		/** @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, const SPtr<PixelData>& initialData = nullptr) override;
+			UINT32 multisampleCount = 0, UINT32 numArraySlices = 1, const SPtr<PixelData>& initialData = nullptr) override;
 
 		/** @copydoc TextureCoreManager::createRenderTextureInternal */
 		SPtr<RenderTextureCore> createRenderTextureInternal(const RENDER_TEXTURE_CORE_DESC& desc) override;

+ 2 - 2
Source/BansheeD3D9RenderAPI/Source/BsD3D9Texture.cpp

@@ -17,8 +17,8 @@
 namespace BansheeEngine 
 {
 	D3D9TextureCore::D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initialData)
-		:TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
+		PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, const SPtr<PixelData>& initialData)
+		:TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, numArraySlices, initialData),
 		mD3DPool(D3DPOOL_MANAGED), mDynamicTextures(false), mHwGammaReadSupported(false), mHwGammaWriteSupported(false), 
 		mMultisampleType(D3DMULTISAMPLE_NONE), mMultisampleQuality(0), mIsBindableAsShaderResource(true)
 	{

+ 3 - 2
Source/BansheeD3D9RenderAPI/Source/BsD3D9TextureManager.cpp

@@ -49,10 +49,11 @@ namespace BansheeEngine
 	}
 
 	SPtr<TextureCore> D3D9TextureCoreManager::createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, const SPtr<PixelData>& initialData)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices,
+		const SPtr<PixelData>& initialData)
 	{
 		D3D9TextureCore* tex = new (bs_alloc<D3D9TextureCore>()) D3D9TextureCore(texType,
-			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, initialData);
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices, initialData);
 
 		SPtr<D3D9TextureCore> texPtr = bs_shared_ptr<D3D9TextureCore>(tex);
 		texPtr->_setThisPtr(texPtr);

+ 2 - 1
Source/BansheeGLRenderAPI/Include/BsGLFrameBufferObject.h

@@ -18,12 +18,13 @@ namespace BansheeEngine
     {
     public:
 		GLSurfaceDesc() 
-			:zoffset(0), numSamples(0) 
+			:zoffset(0), numSamples(0), allLayers(false)
 		{ }
 
 		SPtr<GLPixelBuffer> buffer;
 		UINT32 zoffset;
 		UINT32 numSamples;
+		bool allLayers;
     };
 
 	/**

+ 4 - 3
Source/BansheeGLRenderAPI/Include/BsGLPixelBuffer.h

@@ -49,8 +49,9 @@ namespace BansheeEngine
 		 *
 		 * @param[in]	attachment	Attachment point index in the range [0, BS_MAX_MULTIPLE_RENDER_TARGETS).
 		 * @param[in]	zoffset		Depth slice to bind, in the case of a 3D texture.
+		 * @param[in]	allLayers	Should all layers of the texture be bound, or just one (zoffset is ignored if true).
 		 */
-		virtual void bindToFramebuffer(GLenum attachment, UINT32 zoffset);
+		virtual void bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers);
 
 		/**	Returns internal OpenGL pixel format used by the buffer. */
 		GLenum getGLFormat() const { return mGLInternalFormat; }
@@ -106,7 +107,7 @@ namespace BansheeEngine
         ~GLTextureBuffer();
         
 		/** @copydoc GLPixelBuffer::bindToFramebuffer */
-        void bindToFramebuffer(GLenum attachment, UINT32 zoffset) override;
+        void bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers) override;
 
 		/** @copydoc GLPixelBuffer::upload */
 		void upload(const PixelData &data, const PixelVolume &dest) override;
@@ -149,7 +150,7 @@ namespace BansheeEngine
         ~GLRenderBuffer();
         
 		/** @copydoc	GLPixelBuffer::bindToFramebuffer */
-        void bindToFramebuffer(GLenum attachment, UINT32 zoffset) override;
+        void bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers) override;
     protected:
         GLuint mRenderbufferID;
     };

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLTexture.h

@@ -42,7 +42,7 @@ namespace BansheeEngine
 		friend class GLTextureCoreManager;
 
 		GLTextureCore(GLSupport& support, TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
-			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initialData);
+			PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, const SPtr<PixelData>& initialData);
 
 		/** @copydoc TextureCore::initialize */
 		void initialize() override;

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLTextureManager.h

@@ -45,7 +45,7 @@ namespace BansheeEngine
 		/** @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, const SPtr<PixelData>& initialData = nullptr) override;
+			UINT32 multisampleCount = 0, UINT32 numArraySlices = 1, const SPtr<PixelData>& initialData = nullptr) override;
 
 		/** @copydoc TextureCoreManager::createRenderTextureInternal */
 		SPtr<RenderTextureCore> createRenderTextureInternal(const RENDER_TEXTURE_CORE_DESC& desc) override;

+ 5 - 2
Source/BansheeGLRenderAPI/Source/BsGLFrameBufferObject.cpp

@@ -69,6 +69,8 @@ namespace BansheeEngine
 		// Bind simple buffer to add color attachments
 		glBindFramebuffer(GL_FRAMEBUFFER, mFB);
 
+		bool bindAllLayers = false;
+
         // Bind all attachment points to frame buffer
         for(UINT16 x = 0; x < maxSupportedMRTs; ++x)
         {
@@ -88,7 +90,8 @@ namespace BansheeEngine
 				// Note: I'm attaching textures to FBO while renderbuffers might yield better performance if I
 				// don't need to read from them
 
-	            mColor[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0 + x, mColor[x].zoffset);
+	            mColor[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0 + x, mColor[x].zoffset, mColor[x].allLayers);
+				bindAllLayers |= mColor[x].allLayers;
             }
             else
             {
@@ -98,7 +101,7 @@ namespace BansheeEngine
         }
 
 		if(mDepthStencilBuffer != nullptr)
-			mDepthStencilBuffer->bindToFramebuffer(GL_DEPTH_STENCIL_ATTACHMENT, 0);
+			mDepthStencilBuffer->bindToFramebuffer(GL_DEPTH_STENCIL_ATTACHMENT, 0, bindAllLayers);
 
 		// Do glDrawBuffer calls
 		GLenum bufs[BS_MAX_MULTIPLE_RENDER_TARGETS];

+ 36 - 11
Source/BansheeGLRenderAPI/Source/BsGLMultiRenderTexture.cpp

@@ -29,23 +29,48 @@ namespace BansheeEngine
 			if (mColorSurfaces[i] != nullptr)
 			{
 				GLTextureCore* glColorSurface = static_cast<GLTextureCore*>(mColorSurfaces[i]->getTexture().get());
-				SPtr<GLPixelBuffer> colorBuffer = nullptr;
 				GLSurfaceDesc surfaceDesc;
+				surfaceDesc.numSamples = getProperties().getMultisampleCount();
 
-				if (glColorSurface->getProperties().getTextureType() != TEX_TYPE_3D)
+				if (mColorSurfaces[i]->getNumArraySlices() == 1) // Binding a single texture layer
 				{
-					surfaceDesc.zoffset = 0;
-					colorBuffer = glColorSurface->getBuffer(mColorSurfaces[i]->getFirstArraySlice(),
-						mColorSurfaces[i]->getMostDetailedMip());
+					surfaceDesc.allLayers = false;
+
+					if (glColorSurface->getProperties().getTextureType() != TEX_TYPE_3D)
+					{
+						surfaceDesc.zoffset = 0;
+						surfaceDesc.buffer = glColorSurface->getBuffer(mColorSurfaces[i]->getFirstArraySlice(),
+							mColorSurfaces[i]->getMostDetailedMip());
+					}
+					else
+					{
+						surfaceDesc.zoffset = mColorSurfaces[i]->getFirstArraySlice();
+						surfaceDesc.buffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
+					}
 				}
-				else
+				else // Binding an array of textures or a range of 3D texture slices
 				{
-					surfaceDesc.zoffset = mColorSurfaces[i]->getFirstArraySlice();
-					colorBuffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
-				}
+					surfaceDesc.allLayers = true;
 
-				surfaceDesc.numSamples = getProperties().getMultisampleCount();
-				surfaceDesc.buffer = colorBuffer;
+					if (glColorSurface->getProperties().getTextureType() != TEX_TYPE_3D)
+					{
+						if (mColorSurfaces[i]->getNumArraySlices() != glColorSurface->getProperties().getNumFaces())
+							LOGWRN("OpenGL doesn't support binding of arbitrary ranges for array textures. The entire range will be bound instead.");
+
+						surfaceDesc.zoffset = 0;
+						surfaceDesc.buffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
+					}
+					else
+					{
+						if (mColorSurfaces[i]->getNumArraySlices() != glColorSurface->getProperties().getDepth())
+							LOGWRN("OpenGL doesn't support binding of arbitrary ranges for array textures. The entire range will be bound instead.");
+
+						surfaceDesc.zoffset = 0;
+						surfaceDesc.buffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip());
+					}
+
+					
+				}
 
 				mFB->bindSurface((UINT32)i, surfaceDesc);
 			}

+ 39 - 26
Source/BansheeGLRenderAPI/Source/BsGLPixelBuffer.cpp

@@ -91,7 +91,7 @@ namespace BansheeEngine
 		BS_EXCEPT(RenderingAPIException, "BlitFromTexture not possible for this pixel buffer type");
 	}
 
-	void GLPixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
+	void GLPixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers)
 	{
 		BS_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixel buffer type");
 	}
@@ -109,7 +109,7 @@ namespace BansheeEngine
 		// Get face identifier
 		mFaceTarget = mTarget;
 		if(mTarget == GL_TEXTURE_CUBE_MAP)
-			mFaceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+			mFaceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (face % 6);
 	
 		// Get width
 		glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_WIDTH, &value);
@@ -321,29 +321,42 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT_CAT(ResRead, RenderStatObject_Texture);
 	}
 
-	void GLTextureBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
+	void GLTextureBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers)
 	{
-		assert(zoffset < mDepth);
-
-		switch(mTarget)
+		if(allLayers)
 		{
-		case GL_TEXTURE_1D:
-			glFramebufferTexture1D(GL_FRAMEBUFFER, attachment,
-				mFaceTarget, mTextureID, mLevel);
-			break;
-		case GL_TEXTURE_2D:
-		case GL_TEXTURE_CUBE_MAP:
-			glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
-				mFaceTarget, mTextureID, mLevel);
-			break;
-		case GL_TEXTURE_2D_MULTISAMPLE:
-			glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
-				mFaceTarget, mTextureID, 0);
-			break;
-		case GL_TEXTURE_3D:
-			glFramebufferTexture3D(GL_FRAMEBUFFER, attachment,
-				mFaceTarget, mTextureID, mLevel, zoffset);
-			break;
+			switch (mTarget)
+			{
+			case GL_TEXTURE_1D:
+				glFramebufferTexture1D(GL_FRAMEBUFFER, attachment,
+					mFaceTarget, mTextureID, mLevel);
+				break;
+			case GL_TEXTURE_2D:
+				glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
+					mFaceTarget, mTextureID, mLevel);
+				break;
+			case GL_TEXTURE_2D_MULTISAMPLE:
+				glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
+					mFaceTarget, mTextureID, 0);
+				break;
+			case GL_TEXTURE_CUBE_MAP:
+			case GL_TEXTURE_3D:
+			default: // Texture arrays (binding all layers)
+				glFramebufferTexture(GL_FRAMEBUFFER, attachment, mTextureID, mLevel);
+				break;
+			}
+		}
+		else
+		{
+			switch (mTarget)
+			{
+			case GL_TEXTURE_3D:
+				glFramebufferTexture3D(GL_FRAMEBUFFER, attachment, mFaceTarget, mTextureID, mLevel, zoffset);
+				break;
+			default: // Texture arrays and cube maps
+				glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, mTextureID, mLevel, mFace);
+				break;
+			}
 		}
 	}
 
@@ -380,11 +393,11 @@ namespace BansheeEngine
 
 			// Attach source texture
 			glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
-			src->bindToFramebuffer(0, 0);
+			src->bindToFramebuffer(0, 0, true);
 
 			// Attach destination texture
 			glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
-			bindToFramebuffer(0, 0);
+			bindToFramebuffer(0, 0, true);
 
 			// Perform blit
 			glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
@@ -443,7 +456,7 @@ namespace BansheeEngine
 		glDeleteRenderbuffers(1, &mRenderbufferID);
 	}
 
-	void GLRenderBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
+	void GLRenderBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers)
 	{
 		assert(zoffset < mDepth);
 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment,

+ 32 - 6
Source/BansheeGLRenderAPI/Source/BsGLRenderTexture.cpp

@@ -44,15 +44,41 @@ namespace BansheeEngine
 		GLSurfaceDesc surfaceDesc;
 		surfaceDesc.numSamples = getProperties().getMultisampleCount();
 
-		if (glTexture->getProperties().getTextureType() != TEX_TYPE_3D)
+		if(mColorSurface->getNumArraySlices() == 1) // Binding a single texture layer
 		{
-			surfaceDesc.zoffset = 0;
-			surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
+			surfaceDesc.allLayers = false;
+
+			if (glTexture->getProperties().getTextureType() != TEX_TYPE_3D)
+			{
+				surfaceDesc.zoffset = 0;
+				surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
+			}
+			else
+			{
+				surfaceDesc.zoffset = mColorSurface->getFirstArraySlice();
+				surfaceDesc.buffer = glTexture->getBuffer(0, mColorSurface->getMostDetailedMip());
+			}
 		}
-		else
+		else // Binding an array of textures or a range of 3D texture slices
 		{
-			surfaceDesc.zoffset = mColorSurface->getFirstArraySlice();
-			surfaceDesc.buffer = glTexture->getBuffer(0, mColorSurface->getMostDetailedMip());
+			surfaceDesc.allLayers = true;
+
+			if (glTexture->getProperties().getTextureType() != TEX_TYPE_3D)
+			{
+				if (mColorSurface->getNumArraySlices() != glTexture->getProperties().getNumFaces())
+					LOGWRN("OpenGL doesn't support binding of arbitrary ranges for array textures. The entire range will be bound instead.");
+
+				surfaceDesc.zoffset = 0;
+				surfaceDesc.buffer = glTexture->getBuffer(0, mColorSurface->getMostDetailedMip());
+			}
+			else
+			{
+				if (mColorSurface->getNumArraySlices() != glTexture->getProperties().getDepth())
+					LOGWRN("OpenGL doesn't support binding of arbitrary ranges for array textures. The entire range will be bound instead.");
+
+				surfaceDesc.zoffset = 0;
+				surfaceDesc.buffer = glTexture->getBuffer(0, mColorSurface->getMostDetailedMip());
+			}
 		}
 
 		mFB->bindSurface(0, surfaceDesc);

+ 63 - 27
Source/BansheeGLRenderAPI/Source/BsGLTexture.cpp

@@ -14,8 +14,9 @@
 namespace BansheeEngine 
 {
 	GLTextureCore::GLTextureCore(GLSupport& support, TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, 
-		UINT32 numMipmaps, PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const SPtr<PixelData>& initialData)
-		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
+		UINT32 numMipmaps, PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, UINT32 numArraySlices, 
+		const SPtr<PixelData>& initialData)
+		: TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, numArraySlices, initialData),
 		mTextureID(0), mGLFormat(0), mGLSupport(support)
     { }
 
@@ -38,6 +39,7 @@ namespace BansheeEngine
 		PixelFormat pixFormat = mProperties.getFormat();
 		int usage = mProperties.getUsage();
 		UINT32 numMips = mProperties.getNumMipmaps();
+		UINT32 numFaces = mProperties.getNumFaces();
 
 		// Check requested number of mipmaps
 		UINT32 maxMips = PixelUtil::getMaxMipmaps(width, height, depth, mProperties.getFormat());
@@ -81,27 +83,29 @@ namespace BansheeEngine
 		}
 
 		UINT32 sampleCount = mProperties.getMultisampleCount();
-		if ((usage & TU_RENDERTARGET) != 0 && mProperties.getTextureType() == TEX_TYPE_2D && sampleCount > 1)
+		if((usage & (TU_RENDERTARGET | TU_DEPTHSTENCIL)) != 0 && mProperties.getTextureType() == TEX_TYPE_2D && sampleCount > 1)
 		{
-			glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, mGLFormat, width, height, GL_FALSE);
+			if (numFaces <= 1)
+				glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCount, mGLFormat, width, height, GL_FALSE);
+			else
+				glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, sampleCount, mGLFormat, width, height, numFaces, GL_FALSE);
 		}
-		else if ((usage & TU_DEPTHSTENCIL) != 0)
+		else if((usage & TU_DEPTHSTENCIL) != 0 && mProperties.getTextureType() == TEX_TYPE_2D)
 		{
-			if (sampleCount > 1)
+			GLenum depthStencilFormat = GLPixelUtil::getDepthStencilTypeFromFormat(pixFormat);
+
+			if (numFaces <= 1)
 			{
-				glTexImage2DMultisample(GL_TEXTURE_2D, sampleCount, mGLFormat,
-					width, height, GL_FALSE);
+				glTexImage2D(GL_TEXTURE_2D, 0, mGLFormat, width, height, 0,
+					GL_DEPTH_STENCIL, depthStencilFormat, nullptr);
 			}
 			else
 			{
-				GLenum depthStencilFormat = GLPixelUtil::getDepthStencilTypeFromFormat(pixFormat);
-
-				glTexImage2D(GL_TEXTURE_2D, 0, mGLFormat,
-					width, height, 0, 
+				glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, mGLFormat, width, height, numFaces, 0,
 					GL_DEPTH_STENCIL, depthStencilFormat, nullptr);
 			}
 		}
-		else
+		else // Non-render textures
 		{
 			GLenum baseFormat = GLPixelUtil::getGLOriginFormat(pixFormat);
 			GLenum baseDataType = GLPixelUtil::getGLOriginDataType(pixFormat);
@@ -112,26 +116,43 @@ namespace BansheeEngine
 				switch (texType)
 				{
 				case TEX_TYPE_1D:
-					glTexImage1D(GL_TEXTURE_1D, mip, mGLFormat, width, 0,
-						baseFormat, baseDataType, nullptr);
-
+				{
+					if (numFaces <= 1)
+						glTexImage1D(GL_TEXTURE_1D, mip, mGLFormat, width, 0, baseFormat, baseDataType, nullptr);
+					else
+						glTexImage2D(GL_TEXTURE_1D_ARRAY, mip, mGLFormat, width, numFaces, 0, baseFormat, baseDataType, nullptr);
+				}
 					break;
 				case TEX_TYPE_2D:
-					glTexImage2D(GL_TEXTURE_2D, mip, mGLFormat,
-						width, height, 0, baseFormat, baseDataType, nullptr);
+				{
+					if (numFaces <= 1)
+						glTexImage2D(GL_TEXTURE_2D, mip, mGLFormat, width, height, 0, baseFormat, baseDataType, nullptr);
+					else
+						glTexImage3D(GL_TEXTURE_2D_ARRAY, mip, mGLFormat, width, height, numFaces, 0, baseFormat, baseDataType, nullptr);
+				}
 					break;
 				case TEX_TYPE_3D:
 					glTexImage3D(GL_TEXTURE_3D, mip, mGLFormat, width, height,
 						depth, 0, baseFormat, baseDataType, nullptr);
 					break;
 				case TEX_TYPE_CUBE_MAP:
-					for(UINT32 face = 0; face < 6; face++) 
+				{
+					if (numFaces <= 6)
 					{
-						glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, mGLFormat,
-							width, height, 0, baseFormat, baseDataType, nullptr);
+						for (UINT32 face = 0; face < 6; face++)
+						{
+							glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, mGLFormat,
+								width, height, 0, baseFormat, baseDataType, nullptr);
+						}
 					}
+					else
+					{
+						glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, mGLFormat,
+							width, height, numFaces, 0, baseFormat, baseDataType, nullptr);
+					}
+				}
 					break;
-				};
+				}
 
 				if(width > 1)
 					width = width/2;
@@ -155,16 +176,32 @@ namespace BansheeEngine
 		switch (mProperties.getTextureType())
         {
             case TEX_TYPE_1D:
-                return GL_TEXTURE_1D;
+				if(mProperties.getNumFaces() <= 1)
+					return GL_TEXTURE_1D;
+				else
+					return GL_TEXTURE_1D_ARRAY;
             case TEX_TYPE_2D:
 				if (mProperties.getMultisampleCount() > 1)
-					return GL_TEXTURE_2D_MULTISAMPLE;
+				{
+					if (mProperties.getNumFaces() <= 1)
+						return GL_TEXTURE_2D_MULTISAMPLE;
+					else
+						return GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
+				}
 				else
-					return GL_TEXTURE_2D;
+				{
+					if (mProperties.getNumFaces() <= 1)
+						return GL_TEXTURE_2D;
+					else
+						return GL_TEXTURE_2D_ARRAY;
+				}
             case TEX_TYPE_3D:
                 return GL_TEXTURE_3D;
             case TEX_TYPE_CUBE_MAP:
-                return GL_TEXTURE_CUBE_MAP;
+				if (mProperties.getNumFaces() <= 6)
+					return GL_TEXTURE_CUBE_MAP;
+				else
+					return GL_TEXTURE_CUBE_MAP_ARRAY;
             default:
                 return 0;
         };
@@ -206,7 +243,6 @@ namespace BansheeEngine
 		mLockedBuffer = nullptr;
 	}
 
-
 	void GLTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
 	{
 		if (mProperties.getMultisampleCount() > 1)

+ 2 - 2
Source/BansheeGLRenderAPI/Source/BsGLTextureManager.cpp

@@ -67,10 +67,10 @@ namespace BansheeEngine
 	{ }
 
 	SPtr<TextureCore> GLTextureCoreManager::createTextureInternal(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
-		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, const SPtr<PixelData>& initialData)
+		int numMips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 multisampleCount, UINT32 numArraySlices, const SPtr<PixelData>& initialData)
 	{
 		GLTextureCore* tex = new (bs_alloc<GLTextureCore>()) GLTextureCore(mGLSupport, texType,
-			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, initialData);
+			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount, numArraySlices, initialData);
 
 		SPtr<GLTextureCore> texPtr = bs_shared_ptr<GLTextureCore>(tex);
 		texPtr->_setThisPtr(texPtr);

+ 5 - 0
Source/RenderBeast/Source/BsRenderTargets.cpp

@@ -53,14 +53,17 @@ namespace BansheeEngine
 
 			gbufferDesc.colorSurfaces[0].texture = mSceneColorTex->texture;
 			gbufferDesc.colorSurfaces[0].face = 0;
+			gbufferDesc.colorSurfaces[0].numFaces = 1;
 			gbufferDesc.colorSurfaces[0].mipLevel = 0;
 
 			gbufferDesc.colorSurfaces[1].texture = mAlbedoTex->texture;
 			gbufferDesc.colorSurfaces[1].face = 0;
+			gbufferDesc.colorSurfaces[1].numFaces = 1;
 			gbufferDesc.colorSurfaces[1].mipLevel = 0;
 
 			gbufferDesc.colorSurfaces[2].texture = mNormalTex->texture;
 			gbufferDesc.colorSurfaces[2].face = 0;
+			gbufferDesc.colorSurfaces[2].numFaces = 1;
 			gbufferDesc.colorSurfaces[2].mipLevel = 0;
 
 			gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
@@ -72,10 +75,12 @@ namespace BansheeEngine
 			RENDER_TEXTURE_CORE_DESC sceneColorDesc;
 			sceneColorDesc.colorSurface.texture = mSceneColorTex->texture;
 			sceneColorDesc.colorSurface.face = 0;
+			sceneColorDesc.colorSurface.numFaces = 1;
 			sceneColorDesc.colorSurface.mipLevel = 0;
 
 			sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
 			sceneColorDesc.depthStencilSurface.face = 0;
+			sceneColorDesc.depthStencilSurface.numFaces = 1;
 			sceneColorDesc.depthStencilSurface.mipLevel = 0;
 
 			mSceneColorRT = TextureCoreManager::instance().createRenderTexture(sceneColorDesc);

+ 2 - 0
Source/RenderBeast/Source/BsRenderTexturePool.cpp

@@ -56,6 +56,7 @@ namespace BansheeEngine
 			{
 				rtDesc.colorSurface.texture = newTextureData->texture;
 				rtDesc.colorSurface.face = 0;
+				rtDesc.colorSurface.numFaces = desc.depth;
 				rtDesc.colorSurface.mipLevel = 0;
 			}
 
@@ -63,6 +64,7 @@ namespace BansheeEngine
 			{
 				rtDesc.depthStencilSurface.texture = newTextureData->texture;
 				rtDesc.depthStencilSurface.face = 0;
+				rtDesc.depthStencilSurface.numFaces = 1;
 				rtDesc.depthStencilSurface.mipLevel = 0;
 			}
 

+ 3 - 0
Source/SBansheeEngine/Source/BsScriptRenderTexture2D.cpp

@@ -61,6 +61,7 @@ namespace BansheeEngine
 		{
 			depthStencilSurfaceDesc.face = 0;
 			depthStencilSurfaceDesc.mipLevel = 0;
+			depthStencilSurfaceDesc.numFaces = 1;
 
 			HTexture textureHandle = scriptDepthStencilSurface->getHandle();
 			if (!textureHandle.isLoaded())
@@ -84,6 +85,7 @@ namespace BansheeEngine
 				RENDER_SURFACE_DESC surfaceDesc;
 				surfaceDesc.face = 0;
 				surfaceDesc.mipLevel = 0;
+				surfaceDesc.numFaces = 1;
 
 				MonoObject* surfaceObj = colorSurfacesList.get<MonoObject*>(i);
 				ScriptTexture2D* scriptSurface = ScriptTexture2D::toNative(surfaceObj);
@@ -111,6 +113,7 @@ namespace BansheeEngine
 			RENDER_SURFACE_DESC surfaceDesc;
 			surfaceDesc.face = 0;
 			surfaceDesc.mipLevel = 0;
+			surfaceDesc.numFaces = 1;
 
 			if (colorSurfacesList.size() > 0)
 			{