renderTexTargetBinManager.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "renderInstance/renderTexTargetBinManager.h"
  24. #include "shaderGen/conditionerFeature.h"
  25. #include "core/util/safeDelete.h"
  26. #include "gfx/gfxTextureManager.h"
  27. #include "gfx/gfxStringEnumTranslate.h"
  28. #include "scene/sceneRenderState.h"
  29. #include "scene/sceneManager.h"
  30. IMPLEMENT_CONOBJECT(RenderTexTargetBinManager);
  31. ConsoleDocClass( RenderTexTargetBinManager,
  32. "@brief An abstract base class for render bin managers that render to a named textue target.\n\n"
  33. "This bin itself doesn't do any rendering work. It offers functionality to manage "
  34. "a texture render target which derived render bin classes can render into.\n\n"
  35. "@see RenderDeferredMgr\n"
  36. "@ingroup RenderBin\n" );
  37. RenderTexTargetBinManager::RenderTexTargetBinManager( const RenderInstType& ritype,
  38. F32 renderOrder,
  39. F32 processAddOrder,
  40. const GFXFormat targetFormat,
  41. const Point2I &targetSize,
  42. const U32 targetChainLength )
  43. : Parent( ritype, renderOrder, processAddOrder ),
  44. mTargetFormat(targetFormat),
  45. mTargetSize(targetSize),
  46. mTargetScale(1.0f, 1.0f),
  47. mTargetSizeType(FixedSize),
  48. mTargetChainLength(targetChainLength),
  49. mTargetChainIdx(0),
  50. mNumRenderTargets(1),
  51. mTargetChain(NULL),
  52. mTargetChainTextures(NULL)
  53. #ifndef TORQUE_SHIPPING
  54. ,m_NeedsOnPostRender(false)
  55. #endif
  56. {
  57. GFXDevice::getDeviceEventSignal().notify(this, &RenderTexTargetBinManager::_handleGFXEvent);
  58. GFXTextureManager::addEventDelegate( this, &RenderTexTargetBinManager::_onTextureEvent );
  59. mNamedTarget.setSamplerState( GFXSamplerStateDesc::getClampPoint() );
  60. }
  61. RenderTexTargetBinManager::~RenderTexTargetBinManager()
  62. {
  63. _teardownTargets();
  64. GFXTextureManager::removeEventDelegate( this, &RenderTexTargetBinManager::_onTextureEvent );
  65. GFXDevice::getDeviceEventSignal().remove(this, &RenderTexTargetBinManager::_handleGFXEvent);
  66. }
  67. bool RenderTexTargetBinManager::onAdd()
  68. {
  69. if(!Parent::onAdd())
  70. return false;
  71. _setupTargets();
  72. return true;
  73. }
  74. ImplementEnumType( RenderTexTargetSize,
  75. "What size to render the target texture. Sizes are based on the Window the render is occuring in.\n"
  76. "@ingroup RenderBin\n\n")
  77. { RenderTexTargetBinManager::WindowSize, "windowsize", "Render to the size of the window.\n" },
  78. { RenderTexTargetBinManager::WindowSizeScaled, "windowsizescaled", "Render to the size of the window, scaled to the render target's size.\n" },
  79. { RenderTexTargetBinManager::FixedSize, "fixedsize", "Don't scale the target texture, and render to its default size.\n" },
  80. EndImplementEnumType;
  81. void RenderTexTargetBinManager::initPersistFields()
  82. {
  83. docsURL;
  84. // TOM_TODO:
  85. //addField( "targetScale", mTargetScale );
  86. //addPropertyNOPS( "targetSizeType", mTargetSizeType)->setEnumTable(gSizeTypeEnumTable);
  87. //addPropertyNOPS<S32>( "targetFormat")->setEnumTable(gTextureFormatEnumTable)->addGet(this, &RenderTexTargetBinManager::getTargetFormatConsole)->addSet(this, &RenderTexTargetBinManager::setTargetFormatConsole);
  88. //addProperty<bool>( "blur" )->addSet(this, &RenderTexTargetBinManager::setBlur)->addGet(this, &RenderTexTargetBinManager::getBlur);
  89. Parent::initPersistFields();
  90. }
  91. bool RenderTexTargetBinManager::setTargetSize(const Point2I &newTargetSize)
  92. {
  93. if( mTargetSize.x >= newTargetSize.x &&
  94. mTargetSize.y >= newTargetSize.y )
  95. return true;
  96. mTargetSize = newTargetSize;
  97. mNamedTarget.setViewport( RectI( Point2I::Zero, mTargetSize ) );
  98. return _updateTargets();
  99. }
  100. bool RenderTexTargetBinManager::setTargetFormat(const GFXFormat &newTargetFormat)
  101. {
  102. if(mTargetFormat == newTargetFormat)
  103. return true;
  104. mTargetFormat = newTargetFormat;
  105. ConditionerFeature *conditioner = mNamedTarget.getConditioner();
  106. if(conditioner)
  107. conditioner->setBufferFormat(mTargetFormat);
  108. return _updateTargets();
  109. }
  110. void RenderTexTargetBinManager::setTargetChainLength(const U32 chainLength)
  111. {
  112. if(mTargetChainLength != chainLength)
  113. {
  114. mTargetChainLength = chainLength;
  115. _setupTargets();
  116. }
  117. }
  118. GFXTextureObject* RenderTexTargetBinManager::getTargetTexture( U32 mrtIndex, S32 chainIndex ) const
  119. {
  120. const U32 chainIdx = ( chainIndex > -1 ) ? chainIndex : mTargetChainIdx;
  121. if(chainIdx < mTargetChainLength)
  122. return mTargetChainTextures[chainIdx][mrtIndex];
  123. return NULL;
  124. }
  125. bool RenderTexTargetBinManager::_updateTargets()
  126. {
  127. PROFILE_SCOPE(RenderTexTargetBinManager_updateTargets);
  128. bool ret = true;
  129. mNamedTarget.release();
  130. // Update the target size
  131. for( U32 i = 0; i < mTargetChainLength; i++ )
  132. {
  133. AssertFatal( mTargetChain != NULL, "RenderTexTargetBinManager - target chain not set up" );
  134. if( !mTargetChain[i] )
  135. mTargetChain[i] = GFX->allocRenderToTextureTarget();
  136. for( U32 j = 0; j < mNumRenderTargets; j++ )
  137. {
  138. // try reuse of old color texture
  139. if( mTargetChainTextures[i][j].getWidthHeight() != mTargetSize
  140. || mTargetChainTextures[i][j].getFormat() != mTargetFormat)
  141. {
  142. ret &= mTargetChainTextures[i][j].set( mTargetSize.x, mTargetSize.y, mTargetFormat,
  143. &GFXRenderTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ),
  144. 1, GFXTextureManager::AA_MATCH_BACKBUFFER );
  145. mTargetChain[i]->attachTexture( GFXTextureTarget::RenderSlot(GFXTextureTarget::Color0 + j), mTargetChainTextures[i][j] );
  146. }
  147. }
  148. }
  149. return ret;
  150. }
  151. bool RenderTexTargetBinManager::_handleGFXEvent( GFXDevice::GFXDeviceEventType event_ )
  152. {
  153. if ( event_ == GFXDevice::deStartOfFrame )
  154. {
  155. mTargetChainIdx++;
  156. if ( mTargetChainIdx >= mTargetChainLength )
  157. mTargetChainIdx = 0;
  158. }
  159. return true;
  160. }
  161. void RenderTexTargetBinManager::_onTextureEvent( GFXTexCallbackCode code )
  162. {
  163. switch(code)
  164. {
  165. case GFXZombify:
  166. _teardownTargets();
  167. break;
  168. case GFXResurrect:
  169. _setupTargets();
  170. break;
  171. }
  172. }
  173. bool RenderTexTargetBinManager::_setupTargets()
  174. {
  175. _teardownTargets();
  176. mTargetChain = new GFXTextureTargetRef[mTargetChainLength];
  177. mTargetChainTextures = new GFXTexHandle*[mTargetChainLength];
  178. for( U32 i = 0; i < mTargetChainLength; i++ )
  179. mTargetChainTextures[i] = new GFXTexHandle[mNumRenderTargets];
  180. mTargetChainIdx = 0;
  181. mTargetSize = Point2I::Zero;
  182. return true;
  183. }
  184. void RenderTexTargetBinManager::_teardownTargets()
  185. {
  186. mNamedTarget.release();
  187. SAFE_DELETE_ARRAY(mTargetChain);
  188. if(mTargetChainTextures != NULL)
  189. {
  190. for( U32 i = 0; i < mTargetChainLength; i++ )
  191. SAFE_DELETE_ARRAY(mTargetChainTextures[i]);
  192. }
  193. SAFE_DELETE_ARRAY(mTargetChainTextures);
  194. }
  195. GFXTextureTargetRef RenderTexTargetBinManager::_getTextureTarget(const U32 idx /* = 0 */)
  196. {
  197. return mTargetChain[idx];
  198. }
  199. bool RenderTexTargetBinManager::_onPreRender(SceneRenderState * state, bool preserve /* = false */)
  200. {
  201. PROFILE_SCOPE(RenderTexTargetBinManager_onPreRender);
  202. #ifndef TORQUE_SHIPPING
  203. AssertFatal( m_NeedsOnPostRender == false, "_onPostRender not called on RenderTexTargetBinManager, or sub-class." );
  204. m_NeedsOnPostRender = false;
  205. #endif
  206. // Update the render target size
  207. const Point2I &rtSize = GFX->getActiveRenderTarget()->getSize();
  208. switch(mTargetSizeType)
  209. {
  210. case WindowSize:
  211. setTargetSize(rtSize);
  212. break;
  213. case WindowSizeScaled:
  214. {
  215. Point2I scaledTargetSize(mFloor(rtSize.x * mTargetScale.x), mFloor(rtSize.y * mTargetScale.y));
  216. setTargetSize(scaledTargetSize);
  217. break;
  218. }
  219. case FixedSize:
  220. // No adjustment necessary
  221. break;
  222. }
  223. if( mTargetChainLength == 0 )
  224. return false;
  225. GFXTextureTargetRef binTarget = _getTextureTarget(mTargetChainIdx);
  226. if( binTarget.isNull() )
  227. return false;
  228. // Attach active depth target texture
  229. binTarget->attachTexture(GFXTextureTarget::DepthStencil, getRenderPass()->getDepthTargetTexture());
  230. // Preserve contents
  231. if(preserve)
  232. GFX->getActiveRenderTarget()->preserve();
  233. GFX->pushActiveRenderTarget();
  234. GFX->setActiveRenderTarget(binTarget);
  235. GFX->setViewport( mNamedTarget.getViewport() );
  236. #ifndef TORQUE_SHIPPING
  237. m_NeedsOnPostRender = true;
  238. #endif
  239. return true;
  240. }
  241. void RenderTexTargetBinManager::_onPostRender()
  242. {
  243. PROFILE_SCOPE(RenderTexTargetBinManager_onPostRender);
  244. #ifndef TORQUE_SHIPPING
  245. m_NeedsOnPostRender = false;
  246. #endif
  247. GFXTextureTargetRef binTarget = _getTextureTarget(mTargetChainIdx);
  248. binTarget->resolve();
  249. GFX->popActiveRenderTarget();
  250. for ( U32 i=0; i < mNumRenderTargets; i++ )
  251. mNamedTarget.setTexture( i, mTargetChainTextures[mTargetChainIdx][i] );
  252. }