Sfoglia il codice sorgente

Added ability to bind depth & stencil buffers separately as read-only

BearishSun 8 anni fa
parent
commit
5ac8e7b2e6

+ 6 - 5
Source/BansheeCore/Include/BsRenderAPI.h

@@ -108,7 +108,7 @@ namespace bs
 		 * 
 		 * @note This is an @ref asyncMethod "asynchronous method".
 		 */
-		static void setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false, 
+		static void setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags = 0, 
 			RenderSurfaceMask loadMask = RT_NONE);
 
 		/** 
@@ -451,9 +451,10 @@ namespace bs
 		 * Change the render target into which we want to draw.
 		 *
 		 * @param[in]	target					Render target to draw to.
-		 * @param[in]	readOnlyDepthStencil	If true the caller guarantees he won't write to the depth/stencil buffer 
-		 *										(if any was provided). This allows the depth buffer to be bound for depth 
-		 *										testing, as well as reading in a shader, at the same time.
+		 * @param[in]	readOnlyFlags			Combination of one or more elements of FrameBuferType denoting which buffers
+		 *										will be bound for read-only operations. This is useful for depth or stencil
+		 *										buffers which need to be bound both for depth/stencil tests, as well as
+		 *										shader reads.
 		 * @param[in]	loadMask				Determines which render target surfaces will have their current contents
 		 *										preserved. By default when a render target is bound its contents will be
 		 *										lost. You might need to preserve contents if you need to perform blending 
@@ -465,7 +466,7 @@ namespace bs
 		 *										is executed immediately. Otherwise it is executed when executeCommands() is
 		 *										called. Buffer must support graphics operations.
 		 */
-        virtual void setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false,
+		virtual void setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags = 0,
 			RenderSurfaceMask loadMask = RT_NONE, const SPtr<CommandBuffer>& commandBuffer = nullptr) = 0;
 
 		/**

+ 2 - 2
Source/BansheeCore/Source/BsRenderAPI.cpp

@@ -84,11 +84,11 @@ namespace bs
 			nullptr));
 	}
 
-	void RenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil,
+	void RenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags,
 									RenderSurfaceMask loadMask)
 	{
 		gCoreThread().queueCommand(std::bind(&ct::RenderAPI::setRenderTarget,
-											 ct::RenderAPI::instancePtr(), target->getCore(), readOnlyDepthStencil, loadMask, nullptr));
+			ct::RenderAPI::instancePtr(), target->getCore(), readOnlyFlags, loadMask, nullptr));
 	}
 
 	void RenderAPI::clearRenderTarget(UINT32 buffers, const Color& color, float depth, 

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

@@ -45,7 +45,7 @@ namespace bs { namespace ct
 			UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPI::setRenderTarget */
-		void setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false, 
+		void setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags, 
 			RenderSurfaceMask loadMask = RT_NONE, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPI::setViewport */

+ 19 - 9
Source/BansheeD3D11RenderAPI/Include/BsD3D11TextureView.h

@@ -39,10 +39,14 @@ namespace bs { namespace ct
 		 * Returns a depth stencil view. Caller must take care this texture view actually contains a depth stencil view,
 		 * otherwise it returns null.
 		 *
-		 * @param[in]	readOnly	Should the depth stencil view only support read operations (allows the bound texture to
-		 *							be also used as a shader resource view while bound as a depth stencil target).
+		 * @param[in]	readOnlyDepth	Should the view only support read operations for the depth portion of the 
+		 *								depth/stencil buffer(allows the bound texture to be also used as a shader resource
+		 *								view while bound as a depth stencil target).
+		 * @param[in]	readOnlyStencil	Should the view only support read operations for the stencil portion of the 
+		 *								depth/stencil buffer(allows the bound texture to be also used as a shader resource
+		 *								view while bound as a depth stencil target).
 		 */
-		ID3D11DepthStencilView*	getDSV(bool readOnly) const { return readOnly ? mRODSV : mDSV; }
+		ID3D11DepthStencilView*	getDSV(bool readOnlyDepth, bool readOnlyStencil) const;
 
 	protected:
 		friend class D3D11Texture;
@@ -106,17 +110,23 @@ namespace bs { namespace ct
 		 * @param[in]	numArraySlices	Number of array slices to create the view for. This will be number of array elements
 		 *								for 1D and 2D array textures, number of slices for 3D textures, and number of cubes
 		 *								for cube textures.
-		 * @param[in]	readOnly		Should the depth stencil view only support read operations (allows the bound texture
-		 *								to be also used as a shader resource view while bound as a depth stencil target).
+		 * @param[in]	readOnlyDepth	Should the view only support read operations for the depth portion of the 
+		 *								depth/stencil buffer(allows the bound texture to be also used as a shader resource
+		 *								view while bound as a depth stencil target).
+		 * @param[in]	readOnlyStencil	Should the view only support read operations for the stencil portion of the 
+		 *								depth/stencil buffer(allows the bound texture to be also used as a shader resource
+		 *								view while bound as a depth stencil target).
 		 */
-		ID3D11DepthStencilView* createDSV(const D3D11Texture* texture,
-			UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices, bool readOnly);
+		ID3D11DepthStencilView* createDSV(const D3D11Texture* texture, UINT32 mipSlice, UINT32 firstArraySlice, 
+			UINT32 numArraySlices, bool readOnlyDepth, bool readOnlyStencil);
 
 		ID3D11ShaderResourceView* mSRV;
 		ID3D11RenderTargetView* mRTV;
 		ID3D11UnorderedAccessView* mUAV;
-		ID3D11DepthStencilView*	mDSV;
-		ID3D11DepthStencilView*	mRODSV;
+		ID3D11DepthStencilView*	mWDepthWStencilView;
+		ID3D11DepthStencilView*	mRODepthWStencilView;
+		ID3D11DepthStencilView*	mRODepthROStencilView;
+		ID3D11DepthStencilView*	mWDepthROStencilView;
 	};
 
 	/** @} */

+ 9 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11DepthStencilState.cpp

@@ -24,6 +24,13 @@ namespace bs { namespace ct
 		D3D11_DEPTH_STENCIL_DESC depthStencilState;
 		ZeroMemory(&depthStencilState, sizeof(D3D11_DEPTH_STENCIL_DESC));
 
+		bool depthEnable = mProperties.getDepthWriteEnable() || mProperties.getDepthReadEnable();
+		CompareFunction compareFunc;
+		if (mProperties.getDepthReadEnable())
+			compareFunc = mProperties.getDepthComparisonFunc();
+		else
+			compareFunc = CMPF_ALWAYS_PASS;
+
 		depthStencilState.BackFace.StencilPassOp = D3D11Mappings::get(mProperties.getStencilBackPassOp());
 		depthStencilState.BackFace.StencilFailOp = D3D11Mappings::get(mProperties.getStencilBackFailOp());
 		depthStencilState.BackFace.StencilDepthFailOp = D3D11Mappings::get(mProperties.getStencilBackZFailOp());
@@ -32,9 +39,9 @@ namespace bs { namespace ct
 		depthStencilState.FrontFace.StencilFailOp = D3D11Mappings::get(mProperties.getStencilFrontFailOp());
 		depthStencilState.FrontFace.StencilDepthFailOp = D3D11Mappings::get(mProperties.getStencilFrontZFailOp());
 		depthStencilState.FrontFace.StencilFunc = D3D11Mappings::get(mProperties.getStencilFrontCompFunc());
-		depthStencilState.DepthEnable = mProperties.getDepthReadEnable();
+		depthStencilState.DepthEnable = depthEnable;
 		depthStencilState.DepthWriteMask = mProperties.getDepthWriteEnable() ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
-		depthStencilState.DepthFunc = D3D11Mappings::get(mProperties.getDepthComparisonFunc());
+		depthStencilState.DepthFunc = D3D11Mappings::get(compareFunc);
 		depthStencilState.StencilEnable = mProperties.getStencilEnable();
 		depthStencilState.StencilReadMask = mProperties.getStencilReadMask();
 		depthStencilState.StencilWriteMask = mProperties.getStencilWriteMask();

+ 17 - 7
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -1032,10 +1032,10 @@ namespace bs { namespace ct
 		BS_INC_RENDER_STAT(NumClears);
 	}
 
-	void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil, 
+	void D3D11RenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags, 
 		RenderSurfaceMask loadMask, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto executeRef = [&](const SPtr<RenderTarget>& target, bool readOnlyDepthStencil)
+		auto executeRef = [&](const SPtr<RenderTarget>& target, UINT32 readOnlyFlags)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -1051,10 +1051,20 @@ namespace bs { namespace ct
 			{
 				target->getCustomAttribute("RTV", views);
 
-				if (readOnlyDepthStencil)
-					target->getCustomAttribute("RODSV", &depthStencilView);
+				if((readOnlyFlags & FBT_DEPTH) == 0)
+				{
+					if((readOnlyFlags & FBT_STENCIL) == 0)
+						target->getCustomAttribute("DSV", &depthStencilView);
+					else
+						target->getCustomAttribute("WDROSV", &depthStencilView);
+				}
 				else
-					target->getCustomAttribute("DSV", &depthStencilView);
+				{
+					if((readOnlyFlags & FBT_STENCIL) == 0)
+						target->getCustomAttribute("RODWSV", &depthStencilView);
+					else
+						target->getCustomAttribute("RODSV", &depthStencilView);
+				}
 			}
 
 			// Bind render targets
@@ -1067,10 +1077,10 @@ namespace bs { namespace ct
 		};
 
 		if (commandBuffer == nullptr)
-			executeRef(target, readOnlyDepthStencil);
+			executeRef(target, readOnlyFlags);
 		else
 		{
-			auto execute = [=]() { executeRef(target, readOnlyDepthStencil); };
+			auto execute = [=]() { executeRef(target, readOnlyFlags); };
 
 			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
 			cb->queueCommand(execute);

+ 22 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderTexture.cpp

@@ -41,7 +41,7 @@ namespace bs
 			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView**)data;
 			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
 
-			*dsv = depthStencilView->getDSV(false);
+			*dsv = depthStencilView->getDSV(false, false);
 		}
 		else if (name == "RODSV")
 		{
@@ -51,7 +51,27 @@ namespace bs
 			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView**)data;
 			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
 
-			*dsv = depthStencilView->getDSV(true);
+			*dsv = depthStencilView->getDSV(true, true);
+		}
+		else if (name == "RODWSV")
+		{
+			if (mDepthStencilSurface == nullptr)
+				return;
+
+			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView**)data;
+			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
+
+			*dsv = depthStencilView->getDSV(true, false);
+		}
+		else if (name == "WDROSV")
+		{
+			if (mDepthStencilSurface == nullptr)
+				return;
+
+			ID3D11DepthStencilView** dsv = (ID3D11DepthStencilView**)data;
+			D3D11TextureView* depthStencilView = static_cast<D3D11TextureView*>(mDepthStencilSurface.get());
+
+			*dsv = depthStencilView->getDSV(false, true);
 		}
 	}
 }}

+ 10 - 10
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderUtility.cpp

@@ -55,26 +55,26 @@ namespace bs { namespace ct
 		{
 			if((clearBuffers & FBT_STENCIL) != 0)
 			{
-				D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateYesD_YesS.get()));
-				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
+				D3D11DepthStencilState* d3d11DepthStencilState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateYesD_YesS.get()));
+				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11DepthStencilState->getInternal(), stencil);
 			}
 			else
 			{
-				D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateYesD_NoS.get()));
-				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
+				D3D11DepthStencilState* d3d11DepthStencilState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateYesD_NoS.get()));
+				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11DepthStencilState->getInternal(), stencil);
 			}
 		}
 		else
 		{
 			if((clearBuffers & FBT_STENCIL) != 0)
 			{
-				D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateNoD_YesS.get()));
-				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
+				D3D11DepthStencilState* d3d11DepthStencilState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateNoD_YesS.get()));
+				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11DepthStencilState->getInternal(), stencil);
 			}
 			else
 			{
-				D3D11DepthStencilState* d3d11RasterizerState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateNoD_NoS.get()));
-				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11RasterizerState->getInternal(), stencil);
+				D3D11DepthStencilState* d3d11DepthStencilState = static_cast<D3D11DepthStencilState*>(const_cast<DepthStencilState*>(mClearQuadDSStateNoD_NoS.get()));
+				mDevice->getImmediateContext()->OMSetDepthStencilState(d3d11DepthStencilState->getInternal(), stencil);
 			}
 		}
 
@@ -128,8 +128,8 @@ namespace bs { namespace ct
 
 		DEPTH_STENCIL_STATE_DESC depthStateDescYesD_NoS;
 		depthStateDescYesD_NoS.depthReadEnable = false;
-		depthStateDescYesD_NoS.depthWriteEnable = false; // TODO - Set to true
-		//depthStateDescYesD_NoS.depthComparisonFunc = CMPF_ALWAYS_PASS;
+		depthStateDescYesD_NoS.depthWriteEnable = true;
+		depthStateDescYesD_NoS.depthComparisonFunc = CMPF_ALWAYS_PASS;
 		mClearQuadDSStateYesD_NoS = RenderStateManager::instance().createDepthStencilState(depthStateDescYesD_NoS);
 
 		DEPTH_STENCIL_STATE_DESC depthStateDescYesD_YesS;

+ 30 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderWindow.cpp

@@ -479,7 +479,7 @@ namespace bs
 			if (mDepthStencilView != nullptr)
 			{
 				D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
-				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(false);
+				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(false, false);
 			}
 			else
 			{
@@ -493,7 +493,35 @@ namespace bs
 			if (mDepthStencilView != nullptr)
 			{
 				D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
-				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(true);
+				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(true, true);
+			}
+			else
+			{
+				*static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
+			}
+
+			return;
+		}
+		else if (name == "RODWSV")
+		{
+			if (mDepthStencilView != nullptr)
+			{
+				D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
+				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(true, false);
+			}
+			else
+			{
+				*static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
+			}
+
+			return;
+		}
+		else if (name == "WDROSV")
+		{
+			if (mDepthStencilView != nullptr)
+			{
+				D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
+				*static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(false, true);
 			}
 			else
 			{

+ 39 - 14
Source/BansheeD3D11RenderAPI/Source/BsD3D11TextureView.cpp

@@ -11,7 +11,8 @@
 namespace bs { namespace ct
 {
 	D3D11TextureView::D3D11TextureView(const D3D11Texture* texture, const TEXTURE_VIEW_DESC& desc)
-		:TextureView(desc), mSRV(nullptr), mUAV(nullptr), mDSV(nullptr), mRTV(nullptr), mRODSV(nullptr)
+		: TextureView(desc), mSRV(nullptr), mUAV(nullptr), mRTV(nullptr), mWDepthWStencilView(nullptr)
+		, mRODepthWStencilView(nullptr), mRODepthROStencilView(nullptr), mWDepthROStencilView(nullptr)
 	{
 		if ((mDesc.usage & GVU_RANDOMWRITE) != 0)
 			mUAV = createUAV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
@@ -19,8 +20,14 @@ namespace bs { namespace ct
 			mRTV = createRTV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices);
 		else if ((mDesc.usage & GVU_DEPTHSTENCIL) != 0)
 		{
-			mDSV = createDSV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, false);
-			mRODSV = createDSV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, true);
+			mWDepthWStencilView = createDSV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, 
+				false, false);
+			mRODepthWStencilView = createDSV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, 
+				true, false);
+			mRODepthROStencilView = createDSV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, 
+				true, true);
+			mWDepthROStencilView = createDSV(texture, mDesc.mostDetailMip, mDesc.firstArraySlice, mDesc.numArraySlices, 
+				false, true);
 		}
 		else
 			mSRV = createSRV(texture, mDesc.mostDetailMip, mDesc.numMips, mDesc.firstArraySlice, mDesc.numArraySlices);
@@ -30,9 +37,29 @@ namespace bs { namespace ct
 	{
 		SAFE_RELEASE(mSRV);
 		SAFE_RELEASE(mUAV);
-		SAFE_RELEASE(mDSV);
-		SAFE_RELEASE(mRODSV);
 		SAFE_RELEASE(mRTV);
+		SAFE_RELEASE(mWDepthWStencilView);
+		SAFE_RELEASE(mWDepthROStencilView);
+		SAFE_RELEASE(mRODepthWStencilView);
+		SAFE_RELEASE(mRODepthROStencilView);
+	}
+
+	ID3D11DepthStencilView* D3D11TextureView::getDSV(bool readOnlyDepth, bool readOnlyStencil) const
+	{
+		if(readOnlyDepth)
+		{
+			if (readOnlyStencil)
+				return mRODepthROStencilView;
+			else
+				return mRODepthWStencilView;
+		}
+		else
+		{
+			if (readOnlyStencil)
+				return mWDepthROStencilView;
+			else
+				return mWDepthWStencilView;
+		}
 	}
 
 	ID3D11ShaderResourceView* D3D11TextureView::createSRV(const D3D11Texture* texture,
@@ -306,7 +333,7 @@ namespace bs { namespace ct
 	}
 
 	ID3D11DepthStencilView* D3D11TextureView::createDSV(const D3D11Texture* texture,
-		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices, bool readOnly)
+		UINT32 mipSlice, UINT32 firstArraySlice, UINT32 numArraySlices, bool readOnlyDepth, bool readOnlyStencil)
 	{
 		D3D11_DEPTH_STENCIL_VIEW_DESC desc;
 		ZeroMemory(&desc, sizeof(desc));
@@ -378,16 +405,14 @@ namespace bs { namespace ct
 
 		desc.Format = texture->getDepthStencilFormat();
 
-		if (readOnly)
-		{
-			bool hasStencil = desc.Format == DXGI_FORMAT_D32_FLOAT_S8X24_UINT ||
-				desc.Format == DXGI_FORMAT_D24_UNORM_S8_UINT;
-
+		if (readOnlyDepth)
 			desc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
 
-			if (hasStencil)
-				desc.Flags |= D3D11_DSV_READ_ONLY_STENCIL;
-		}		
+		bool hasStencil = desc.Format == DXGI_FORMAT_D32_FLOAT_S8X24_UINT ||
+			desc.Format == DXGI_FORMAT_D24_UNORM_S8_UINT;
+
+		if (readOnlyStencil && hasStencil)
+			desc.Flags |= D3D11_DSV_READ_ONLY_STENCIL;
 
 		ID3D11DepthStencilView* dsv = nullptr;
 

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

@@ -80,7 +80,7 @@ namespace bs { namespace ct
 		void swapBuffers(const SPtr<RenderTarget>& target, UINT32 syncMask = 0xFFFFFFFF) override;
 
 		/** @copydoc RenderAPI::setRenderTarget() */
-		void setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false, 
+		void setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags = 0, 
 			RenderSurfaceMask loadMask = RT_NONE, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPI::clearRenderTarget() */

+ 4 - 4
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -789,10 +789,10 @@ namespace bs { namespace ct
 		}
 	}
 
-	void GLRenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil, 
+	void GLRenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags, 
 		RenderSurfaceMask loadMask, const SPtr<CommandBuffer>& commandBuffer)
 	{
-		auto executeRef = [&](const SPtr<RenderTarget>& target, bool readOnlyDepthStencil)
+		auto executeRef = [&](const SPtr<RenderTarget>& target, UINT32 readOnlyFlags)
 		{
 			THROW_IF_NOT_CORE_THREAD;
 
@@ -832,10 +832,10 @@ namespace bs { namespace ct
 		};
 
 		if (commandBuffer == nullptr)
-			executeRef(target, readOnlyDepthStencil);
+			executeRef(target, readOnlyFlags);
 		else
 		{
-			auto execute = [=]() { executeRef(target, readOnlyDepthStencil); };
+			auto execute = [=]() { executeRef(target, readOnlyFlags); };
 
 			SPtr<GLCommandBuffer> cb = std::static_pointer_cast<GLCommandBuffer>(commandBuffer);
 			cb->queueCommand(execute);

+ 2 - 2
Source/BansheeVulkanRenderAPI/Include/BsVulkanCommandBuffer.h

@@ -252,7 +252,7 @@ namespace bs { namespace ct
 		 * Assigns a render target the the command buffer. This render target's framebuffer and render pass will be used
 		 * when beginRenderPass() is called. Command buffer must not be currently recording a render pass.
 		 */
-		void setRenderTarget(const SPtr<RenderTarget>& rt, bool readOnlyDepthStencil, RenderSurfaceMask loadMask);
+		void setRenderTarget(const SPtr<RenderTarget>& rt, UINT32 readOnlyFlags, RenderSurfaceMask loadMask);
 
 		/** Clears the entirety currently bound render target. */
 		void clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil, UINT8 targetMask);
@@ -458,7 +458,7 @@ namespace bs { namespace ct
 		VulkanFramebuffer* mFramebuffer;
 		UINT32 mRenderTargetWidth;
 		UINT32 mRenderTargetHeight;
-		bool mRenderTargetDepthReadOnly;
+		UINT32 mRenderTargetReadOnlyFlags;
 		RenderSurfaceMask mRenderTargetLoadMask;
 
 		UnorderedMap<VulkanResource*, ResourceUseHandle> mResources;

+ 11 - 9
Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuPipelineState.h

@@ -27,13 +27,13 @@ namespace bs { namespace ct
 		/** Checks is the specified color attachment read-only. Only relevant for graphics pipelines. */
 		bool isColorReadOnly(UINT32 colorIdx) const { return mReadOnlyColor[colorIdx]; }
 
-		/** Checks is the depth-stencil attachment read-only. Only relevant for graphics pipelines. */
-		bool isDepthStencilReadOnly() const { return mReadOnlyDepthStencil; }
+		/** Checks is the depth attachment read-only. Only relevant for graphics pipelines. */
+		bool isDepthReadOnly() const { return mReadOnlyDepth; }
 	private:
 		VkPipeline mPipeline;
 
 		std::array<bool, BS_MAX_MULTIPLE_RENDER_TARGETS> mReadOnlyColor;
-		bool mReadOnlyDepthStencil;
+		bool mReadOnlyDepth;
 	};
 
 	/**	Vulkan implementation of a graphics pipeline state. */
@@ -54,14 +54,15 @@ namespace bs { namespace ct
 		 * 
 		 * @param[in]	deviceIdx			Index of the device to retrieve the pipeline for.
 		 * @param[in]	framebuffer			Framebuffer object that defines the surfaces this pipeline will render to.
-		 * @param[in]	readOnlyDepth		True if the pipeline is only allowed to read the depth buffer, without writes.
+		 * @param[in]	readOnlyFlags		Flags that control which portion of the framebuffer is read-only. Accepts
+		 *									combinations of FrameBufferType enum.
 		 * @param[in]	drawOp				Type of geometry that will be drawn using the pipeline.
 		 * @param[in]	vertexInput			State describing inputs to the vertex program.
 		 * @return							Vulkan graphics pipeline object.
 		 * 
 		 * @note	Thread safe.
 		 */
-		VulkanPipeline* getPipeline(UINT32 deviceIdx, VulkanFramebuffer* framebuffer, bool readOnlyDepth, 
+		VulkanPipeline* getPipeline(UINT32 deviceIdx, VulkanFramebuffer* framebuffer, UINT32 readOnlyFlags, 
 			DrawOperationType drawOp, const SPtr<VulkanVertexInput>& vertexInput);
 
 		/** 
@@ -89,24 +90,25 @@ namespace bs { namespace ct
 		 * 
 		 * @param[in]	deviceIdx			Index of the device to create the pipeline for.
 		 * @param[in]	framebuffer			Framebuffer object that defines the surfaces this pipeline will render to.
-		 * @param[in]	readOnlyDepth		True if the pipeline is only allowed to read the depth buffer, without writes.
+		 * @param[in]	readOnlyFlags		Flags that control which portion of the framebuffer is read-only. Accepts
+		 *									combinations of FrameBufferType enum.
 		 * @param[in]	drawOp				Type of geometry that will be drawn using the pipeline.
 		 * @param[in]	vertexInput			State describing inputs to the vertex program.
 		 * @return							Vulkan graphics pipeline object.
 		 * 
 		 * @note	Thread safe.
 		 */
-		VulkanPipeline* createPipeline(UINT32 deviceIdx, VulkanFramebuffer* framebuffer, bool readOnlyDepth, 
+		VulkanPipeline* createPipeline(UINT32 deviceIdx, VulkanFramebuffer* framebuffer, UINT32 readOnlyFlags, 
 			DrawOperationType drawOp, const SPtr<VulkanVertexInput>& vertexInput);
 
 		/**	Key uniquely identifying GPU pipelines. */
 		struct GpuPipelineKey
 		{
-			GpuPipelineKey(UINT32 framebufferId, UINT32 vertexInputId, bool readOnlyDepth, DrawOperationType drawOp);
+			GpuPipelineKey(UINT32 framebufferId, UINT32 vertexInputId, UINT32 readOnlyFlags, DrawOperationType drawOp);
 
 			UINT32 framebufferId;
 			UINT32 vertexInputId;
-			bool readOnlyDepth;
+			UINT32 readOnlyFlags;
 			DrawOperationType drawOp;
 		};
 

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanRenderAPI.h

@@ -45,7 +45,7 @@ namespace bs { namespace ct
 			UINT8 targetMask = 0xFF, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPI::setRenderTarget */
-		void setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil = false,
+		void setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags = 0,
 			RenderSurfaceMask loadMask = RT_NONE, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
 
 		/** @copydoc RenderAPI::setViewport */

+ 7 - 7
Source/BansheeVulkanRenderAPI/Source/BsVulkanCommandBuffer.cpp

@@ -133,7 +133,7 @@ namespace bs { namespace ct
 		: mId(id), mQueueFamily(queueFamily), mState(State::Ready), mDevice(device), mPool(pool)
 		, mIntraQueueSemaphore(nullptr), mInterQueueSemaphores(), mNumUsedInterQueueSemaphores(0)
 		, mFramebuffer(nullptr), mRenderTargetWidth(0)
-		, mRenderTargetHeight(0), mRenderTargetDepthReadOnly(false), mRenderTargetLoadMask(RT_NONE), mGlobalQueueIdx(-1)
+		, mRenderTargetHeight(0), mRenderTargetReadOnlyFlags(0), mRenderTargetLoadMask(RT_NONE), mGlobalQueueIdx(-1)
 		, mViewport(0.0f, 0.0f, 1.0f, 1.0f), mScissor(0, 0, 0, 0), mStencilRef(0), mDrawOp(DOT_TRIANGLE_LIST)
 		, mNumBoundDescriptorSets(0), mGfxPipelineRequiresBind(true), mCmpPipelineRequiresBind(true)
 		, mViewportRequiresBind(true), mStencilRefRequiresBind(true), mScissorRequiresBind(true), mBoundParamsDirty(false)
@@ -774,7 +774,7 @@ namespace bs { namespace ct
 		mSubresourceInfos.clear();
 	}
 
-	void VulkanCmdBuffer::setRenderTarget(const SPtr<RenderTarget>& rt, bool readOnlyDepthStencil, 
+	void VulkanCmdBuffer::setRenderTarget(const SPtr<RenderTarget>& rt, UINT32 readOnlyFlags, 
 		RenderSurfaceMask loadMask)
 	{
 		assert(mState != State::Submitted);
@@ -800,7 +800,7 @@ namespace bs { namespace ct
 			newFB = nullptr;
 		}
 
-		if (mFramebuffer == newFB && mRenderTargetDepthReadOnly == readOnlyDepthStencil && mRenderTargetLoadMask == loadMask)
+		if (mFramebuffer == newFB && mRenderTargetReadOnlyFlags == readOnlyFlags && mRenderTargetLoadMask == loadMask)
 			return;
 
 		if (isInRenderPass())
@@ -817,7 +817,7 @@ namespace bs { namespace ct
 			mFramebuffer = nullptr;
 			mRenderTargetWidth = 0;
 			mRenderTargetHeight = 0;
-			mRenderTargetDepthReadOnly = false;
+			mRenderTargetReadOnlyFlags = 0;
 			mRenderTargetLoadMask = RT_NONE;
 		}
 		else
@@ -825,7 +825,7 @@ namespace bs { namespace ct
 			mFramebuffer = newFB;
 			mRenderTargetWidth = rt->getProperties().getWidth();
 			mRenderTargetHeight = rt->getProperties().getHeight();
-			mRenderTargetDepthReadOnly = readOnlyDepthStencil;
+			mRenderTargetReadOnlyFlags = readOnlyFlags;
 			mRenderTargetLoadMask = loadMask;
 		}
 
@@ -1170,7 +1170,7 @@ namespace bs { namespace ct
 		SPtr<VulkanVertexInput> vertexInput = VulkanVertexInputManager::instance().getVertexInfo(mVertexDecl, inputDecl);
 
 		VulkanPipeline* pipeline = mGraphicsPipeline->getPipeline(mDevice.getIndex(), mFramebuffer,
-																  mRenderTargetDepthReadOnly, mDrawOp, vertexInput);
+																  mRenderTargetReadOnlyFlags, mDrawOp, vertexInput);
 
 		if (pipeline == nullptr)
 			return false;
@@ -1196,7 +1196,7 @@ namespace bs { namespace ct
 			ImageSubresourceInfo& subresourceInfo = findSubresourceInfo(fbAttachment.image, fbAttachment.surface.arraySlice,
 																		fbAttachment.surface.mipLevel);
 
-			if (subresourceInfo.isShaderInput && !pipeline->isDepthStencilReadOnly())
+			if (subresourceInfo.isShaderInput && !pipeline->isDepthReadOnly())
 			{
 				LOGWRN("Framebuffer attachment also used as a shader input, but depth/stencil writes aren't disabled. "
 					"This will result in undefined behavior.");

+ 17 - 16
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuPipelineState.cpp

@@ -19,11 +19,11 @@ namespace bs { namespace ct
 	VulkanPipeline::VulkanPipeline(VulkanResourceManager* owner, VkPipeline pipeline, 
 		const std::array<bool, BS_MAX_MULTIPLE_RENDER_TARGETS>& colorReadOnly, bool depthStencilReadOnly)
 		: VulkanResource(owner, true), mPipeline(pipeline), mReadOnlyColor(colorReadOnly)
-		, mReadOnlyDepthStencil(depthStencilReadOnly)
+		, mReadOnlyDepth(depthStencilReadOnly)
 	{ }
 
 	VulkanPipeline::VulkanPipeline(VulkanResourceManager* owner, VkPipeline pipeline)
-		: VulkanResource(owner, true), mPipeline(pipeline), mReadOnlyColor(), mReadOnlyDepthStencil(false)
+		: VulkanResource(owner, true), mPipeline(pipeline), mReadOnlyColor(), mReadOnlyDepth(false)
 	{ }
 
 	VulkanPipeline::~VulkanPipeline()
@@ -32,8 +32,8 @@ namespace bs { namespace ct
 	}
 
 	VulkanGraphicsPipelineState::GpuPipelineKey::GpuPipelineKey(
-		UINT32 framebufferId, UINT32 vertexInputId, bool readOnlyDepth, DrawOperationType drawOp)
-		: framebufferId(framebufferId), vertexInputId(vertexInputId), readOnlyDepth(readOnlyDepth)
+		UINT32 framebufferId, UINT32 vertexInputId, UINT32 readOnlyFlags, DrawOperationType drawOp)
+		: framebufferId(framebufferId), vertexInputId(vertexInputId), readOnlyFlags(readOnlyFlags)
 		, drawOp(drawOp)
 	{
 		
@@ -44,7 +44,7 @@ namespace bs { namespace ct
 		size_t hash = 0;
 		hash_combine(hash, key.framebufferId);
 		hash_combine(hash, key.vertexInputId);
-		hash_combine(hash, key.readOnlyDepth);
+		hash_combine(hash, key.readOnlyFlags);
 		hash_combine(hash, key.drawOp);
 
 		return hash;
@@ -58,7 +58,7 @@ namespace bs { namespace ct
 		if (a.vertexInputId != b.vertexInputId)
 			return false;
 
-		if (a.readOnlyDepth != b.readOnlyDepth)
+		if (a.readOnlyFlags != b.readOnlyFlags)
 			return false;
 
 		if (a.drawOp != b.drawOp)
@@ -318,7 +318,7 @@ namespace bs { namespace ct
 	}
 
 	VulkanPipeline* VulkanGraphicsPipelineState::getPipeline(
-		UINT32 deviceIdx, VulkanFramebuffer* framebuffer, bool readOnlyDepth, DrawOperationType drawOp, 
+		UINT32 deviceIdx, VulkanFramebuffer* framebuffer, UINT32 readOnlyFlags, DrawOperationType drawOp, 
 			const SPtr<VulkanVertexInput>& vertexInput)
 	{
 		Lock(mMutex);
@@ -326,14 +326,15 @@ namespace bs { namespace ct
 		if (mPerDeviceData[deviceIdx].device == nullptr)
 			return nullptr;
 
-		GpuPipelineKey key(framebuffer->getId(), vertexInput->getId(), readOnlyDepth, drawOp);
+		readOnlyFlags &= ~FBT_COLOR; // Ignore the color
+		GpuPipelineKey key(framebuffer->getId(), vertexInput->getId(), readOnlyFlags, drawOp);
 
 		PerDeviceData& perDeviceData = mPerDeviceData[deviceIdx];
 		auto iterFind = perDeviceData.pipelines.find(key);
 		if (iterFind != perDeviceData.pipelines.end())
 			return iterFind->second;
 
-		VulkanPipeline* newPipeline = createPipeline(deviceIdx, framebuffer, readOnlyDepth, drawOp, vertexInput);
+		VulkanPipeline* newPipeline = createPipeline(deviceIdx, framebuffer, readOnlyFlags, drawOp, vertexInput);
 		perDeviceData.pipelines[key] = newPipeline;
 
 		return newPipeline;
@@ -369,7 +370,7 @@ namespace bs { namespace ct
 	}
 
 	VulkanPipeline* VulkanGraphicsPipelineState::createPipeline(UINT32 deviceIdx, VulkanFramebuffer* framebuffer,
-		bool readOnlyDepth, DrawOperationType drawOp, const SPtr<VulkanVertexInput>& vertexInput)
+		UINT32 readOnlyFlags, DrawOperationType drawOp, const SPtr<VulkanVertexInput>& vertexInput)
 	{
 		mInputAssemblyInfo.topology = VulkanUtility::getDrawOp(drawOp);
 		mTesselationInfo.patchControlPoints = 3; // Not provided by our shaders for now
@@ -381,7 +382,7 @@ namespace bs { namespace ct
 			dsState = DepthStencilState::getDefault().get();
 
 		const DepthStencilProperties dsProps = dsState->getProperties();
-		bool enableDepthWrites = dsProps.getDepthWriteEnable() && !readOnlyDepth;
+		bool enableDepthWrites = dsProps.getDepthWriteEnable() && (readOnlyFlags & FBT_DEPTH) == 0;
 
 		mDepthStencilInfo.depthWriteEnable = enableDepthWrites; // If depth stencil attachment is read only, depthWriteEnable must be VK_FALSE
 
@@ -394,7 +395,7 @@ namespace bs { namespace ct
 		VkStencilOp oldBackFailOp = mDepthStencilInfo.back.failOp;
 		VkStencilOp oldBackZFailOp = mDepthStencilInfo.back.depthFailOp;
 
-		if(readOnlyDepth)
+		if((readOnlyFlags & FBT_STENCIL) == 1)
 		{
 			// Disable any stencil writes
 			mDepthStencilInfo.front.passOp = VK_STENCIL_OP_KEEP;
@@ -413,16 +414,16 @@ namespace bs { namespace ct
 		mPipelineInfo.layout = mPerDeviceData[deviceIdx].pipelineLayout;
 		mPipelineInfo.pVertexInputState = vertexInput->getCreateInfo();
 
-		bool depthStencilReadOnly;
+		bool depthReadOnly;
 		if (framebuffer->hasDepthAttachment())
 		{
 			mPipelineInfo.pDepthStencilState = &mDepthStencilInfo;
-			depthStencilReadOnly = readOnlyDepth;
+			depthReadOnly = (readOnlyFlags & FBT_DEPTH) == 1;
 		}
 		else
 		{
 			mPipelineInfo.pDepthStencilState = nullptr;
-			depthStencilReadOnly = true;
+			depthReadOnly = true;
 		}
 
 		std::array<bool, BS_MAX_MULTIPLE_RENDER_TARGETS> colorReadOnly;
@@ -492,7 +493,7 @@ namespace bs { namespace ct
 		mDepthStencilInfo.back.failOp = oldBackFailOp;
 		mDepthStencilInfo.back.depthFailOp = oldBackZFailOp;
 
-		return device->getResourceManager().create<VulkanPipeline>(pipeline, colorReadOnly, depthStencilReadOnly);
+		return device->getResourceManager().create<VulkanPipeline>(pipeline, colorReadOnly, depthReadOnly);
 	}
 
 	VulkanComputePipelineState::VulkanComputePipelineState(const SPtr<GpuProgram>& program, 

+ 2 - 2
Source/BansheeVulkanRenderAPI/Source/BsVulkanRenderAPI.cpp

@@ -491,13 +491,13 @@ namespace bs { namespace ct
 		BS_INC_RENDER_STAT(NumClears);
 	}
 
-	void VulkanRenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, bool readOnlyDepthStencil,
+	void VulkanRenderAPI::setRenderTarget(const SPtr<RenderTarget>& target, UINT32 readOnlyFlags,
 		RenderSurfaceMask loadMask, const SPtr<CommandBuffer>& commandBuffer)
 	{
 		VulkanCommandBuffer* cb = getCB(commandBuffer);
 		VulkanCmdBuffer* vkCB = cb->getInternal();
 
-		vkCB->setRenderTarget(target, readOnlyDepthStencil, loadMask);
+		vkCB->setRenderTarget(target, readOnlyFlags, loadMask);
 		
 		BS_INC_RENDER_STAT(NumRenderTargetChanges);
 	}

+ 1 - 1
Source/Examples/ExampleLowLevelRendering/Source/Main.cpp

@@ -319,7 +319,7 @@ namespace bs { namespace ct
 		RenderAPI& rapi = RenderAPI::instance();
 
 		// Bind render surface & clear it
-		rapi.setRenderTarget(gRenderTarget, false, RT_NONE, cmds);
+		rapi.setRenderTarget(gRenderTarget, 0, RT_NONE, cmds);
 		rapi.clearRenderTarget(FBT_COLOR | FBT_DEPTH, Color::Blue, 1, 0, 0xFF, cmds);
 
 		// Bind the pipeline state

+ 3 - 3
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -46,7 +46,7 @@ namespace bs { namespace ct
 		ppInfo.downsampledSceneTex = GpuResourcePool::instance().get(mOutputDesc);
 
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(ppInfo.downsampledSceneTex->renderTexture, true);
+		rapi.setRenderTarget(ppInfo.downsampledSceneTex->renderTexture, FBT_DEPTH | FBT_STENCIL);
 
 		gRendererUtility().setPass(mMaterial);
 		gRendererUtility().setPassParams(mParamsSet);
@@ -193,7 +193,7 @@ namespace bs { namespace ct
 		ppInfo.histogramReduceTex = GpuResourcePool::instance().get(mOutputDesc);
 
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(ppInfo.histogramReduceTex->renderTexture, true);
+		rapi.setRenderTarget(ppInfo.histogramReduceTex->renderTexture, FBT_DEPTH | FBT_STENCIL);
 
 		gRendererUtility().setPass(mMaterial);
 		gRendererUtility().setPassParams(mParamsSet);
@@ -275,7 +275,7 @@ namespace bs { namespace ct
 		SPtr<PooledRenderTexture> eyeAdaptationRT = ppInfo.eyeAdaptationTex[ppInfo.lastEyeAdaptationTex];
 
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(eyeAdaptationRT->renderTexture, true);
+		rapi.setRenderTarget(eyeAdaptationRT->renderTexture, FBT_DEPTH | FBT_STENCIL);
 
 		gRendererUtility().setPass(mMaterial);
 		gRendererUtility().setPassParams(mParamsSet);

+ 1 - 1
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -753,7 +753,7 @@ namespace bs { namespace ct
 				viewport->getClearDepthValue(), viewport->getClearStencilValue());
 		}
 		else
-			RenderAPI::instance().setRenderTarget(target, false, RT_COLOR0);
+			RenderAPI::instance().setRenderTarget(target, 0, RT_COLOR0);
 
 		RenderAPI::instance().setViewport(viewport->getNormArea());
 

+ 7 - 3
Source/RenderBeast/Source/BsRenderTargets.cpp

@@ -274,8 +274,12 @@ namespace bs { namespace ct
 
 	void RenderTargets::bindSceneColor(bool readOnlyDepthStencil)
 	{
+		int readOnlyFlags = 0;
+		if (readOnlyDepthStencil)
+			readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
+
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mSceneColorRT, readOnlyDepthStencil, RT_COLOR0 | RT_DEPTH);
+		rapi.setRenderTarget(mSceneColorRT, readOnlyFlags, RT_COLOR0 | RT_DEPTH);
 
 		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
 		rapi.setViewport(area);
@@ -284,13 +288,13 @@ namespace bs { namespace ct
 	void RenderTargets::bindLightAccumulation()
 	{
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mLightAccumulationRT, true, RT_COLOR0 | RT_DEPTH);
+		rapi.setRenderTarget(mLightAccumulationRT, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH);
 	}
 
 	void RenderTargets::bindLightOcclusion()
 	{
 		RenderAPI& rapi = RenderAPI::instance();
-		rapi.setRenderTarget(mLightOcclusionRT, true, RT_DEPTH);
+		rapi.setRenderTarget(mLightOcclusionRT, FBT_DEPTH, RT_DEPTH);
 
 		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
 		rapi.setViewport(area);