BsRenderTargets.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRenderTargets.h"
  4. #include "BsGpuResourcePool.h"
  5. #include "BsViewport.h"
  6. #include "BsRenderAPI.h"
  7. #include "BsTextureManager.h"
  8. #include "BsRendererUtility.h"
  9. namespace bs { namespace ct
  10. {
  11. RenderTargets::RenderTargets(const RENDERER_VIEW_TARGET_DESC& view, bool hdr)
  12. :mViewTarget(view), mHDR(hdr), mWidth(view.targetWidth), mHeight(view.targetHeight)
  13. {
  14. // Note: Consider customizable HDR format via options? e.g. smaller PF_FLOAT_R11G11B10 or larger 32-bit format
  15. mSceneColorFormat = PF_FLOAT16_RGBA;
  16. mAlbedoFormat = PF_R8G8B8A8; // Note: Also consider customizable format (e.g. 16-bit float?)
  17. mNormalFormat = PF_UNORM_R10G10B10A2; // Note: Also consider customizable format (e.g. 16-bit float?)
  18. }
  19. SPtr<RenderTargets> RenderTargets::create(const RENDERER_VIEW_TARGET_DESC& view, bool hdr)
  20. {
  21. return bs_shared_ptr<RenderTargets>(new (bs_alloc<RenderTargets>()) RenderTargets(view, hdr));
  22. }
  23. void RenderTargets::prepare()
  24. {
  25. GpuResourcePool& texPool = GpuResourcePool::instance();
  26. UINT32 width = mViewTarget.viewRect.width;
  27. UINT32 height = mViewTarget.viewRect.height;
  28. mDepthTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32_S8X24, width, height, TU_DEPTHSTENCIL,
  29. mViewTarget.numSamples, false));
  30. }
  31. void RenderTargets::cleanup()
  32. {
  33. RenderAPI& rapi = RenderAPI::instance();
  34. rapi.setRenderTarget(nullptr);
  35. GpuResourcePool& texPool = GpuResourcePool::instance();
  36. texPool.release(mDepthTex);
  37. }
  38. void RenderTargets::allocate(RenderTargetType type)
  39. {
  40. GpuResourcePool& texPool = GpuResourcePool::instance();
  41. UINT32 width = mViewTarget.viewRect.width;
  42. UINT32 height = mViewTarget.viewRect.height;
  43. // Note: This class is keeping all these textures alive for too long (even after they are done for a frame). We
  44. // could save on memory by deallocating and reallocating them every frame, but it remains to be seen how much of
  45. // a performance impact would that have.
  46. if (type == RTT_GBuffer)
  47. {
  48. // Note: Albedo is allocated as SRGB, meaning when reading from textures during depth pass we decode from sRGB
  49. // into linear, then back into sRGB when writing to albedo, and back to linear when reading from albedo during
  50. // light pass. This /might/ have a performance impact. In which case we could just use a higher precision albedo
  51. // buffer, which can then store linear color directly (storing linear in 8bit buffer causes too much detail to
  52. // be lost in the blacks).
  53. mAlbedoTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mAlbedoFormat, width, height, TU_RENDERTARGET,
  54. mViewTarget.numSamples, true));
  55. mNormalTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mNormalFormat, width, height, TU_RENDERTARGET,
  56. mViewTarget.numSamples, false));
  57. mRoughMetalTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_FLOAT16_RG, width, height, TU_RENDERTARGET,
  58. mViewTarget.numSamples, false)); // Note: Metal doesn't need 16-bit float
  59. bool rebuildRT = false;
  60. if (mGBufferRT != nullptr)
  61. {
  62. rebuildRT |= mGBufferRT->getColorTexture(0) != mAlbedoTex->texture;
  63. rebuildRT |= mGBufferRT->getColorTexture(1) != mNormalTex->texture;
  64. rebuildRT |= mGBufferRT->getColorTexture(2) != mRoughMetalTex->texture;
  65. rebuildRT |= mGBufferRT->getDepthStencilTexture() != mDepthTex->texture;
  66. }
  67. else
  68. rebuildRT = true;
  69. if (mGBufferRT == nullptr || rebuildRT)
  70. {
  71. RENDER_TEXTURE_DESC gbufferDesc;
  72. gbufferDesc.colorSurfaces[0].texture = mAlbedoTex->texture;
  73. gbufferDesc.colorSurfaces[0].face = 0;
  74. gbufferDesc.colorSurfaces[0].numFaces = 1;
  75. gbufferDesc.colorSurfaces[0].mipLevel = 0;
  76. gbufferDesc.colorSurfaces[1].texture = mNormalTex->texture;
  77. gbufferDesc.colorSurfaces[1].face = 0;
  78. gbufferDesc.colorSurfaces[1].numFaces = 1;
  79. gbufferDesc.colorSurfaces[1].mipLevel = 0;
  80. gbufferDesc.colorSurfaces[2].texture = mRoughMetalTex->texture;
  81. gbufferDesc.colorSurfaces[2].face = 0;
  82. gbufferDesc.colorSurfaces[2].numFaces = 1;
  83. gbufferDesc.colorSurfaces[2].mipLevel = 0;
  84. gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
  85. gbufferDesc.depthStencilSurface.face = 0;
  86. gbufferDesc.depthStencilSurface.mipLevel = 0;
  87. mGBufferRT = RenderTexture::create(gbufferDesc);
  88. }
  89. }
  90. else if(type == RTT_SceneColor)
  91. {
  92. mSceneColorTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
  93. height, TU_RENDERTARGET | TU_LOADSTORE, mViewTarget.numSamples, false));
  94. if (mViewTarget.numSamples > 1)
  95. {
  96. UINT32 bufferNumElements = width * height * mViewTarget.numSamples;
  97. mFlattenedSceneColorBuffer = texPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  98. // Need a texture we'll resolve MSAA to before post-processing
  99. mSceneColorNonMSAATex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
  100. height, TU_RENDERTARGET, 1, false));
  101. }
  102. bool rebuildRT = false;
  103. if (mSceneColorRT != nullptr)
  104. {
  105. rebuildRT |= mSceneColorRT->getColorTexture(0) != mSceneColorTex->texture;
  106. rebuildRT |= mSceneColorRT->getDepthStencilTexture() != mDepthTex->texture;
  107. }
  108. else
  109. rebuildRT = true;
  110. if (rebuildRT)
  111. {
  112. RENDER_TEXTURE_DESC sceneColorDesc;
  113. sceneColorDesc.colorSurfaces[0].texture = mSceneColorTex->texture;
  114. sceneColorDesc.colorSurfaces[0].face = 0;
  115. sceneColorDesc.colorSurfaces[0].numFaces = 1;
  116. sceneColorDesc.colorSurfaces[0].mipLevel = 0;
  117. sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
  118. sceneColorDesc.depthStencilSurface.face = 0;
  119. sceneColorDesc.depthStencilSurface.numFaces = 1;
  120. sceneColorDesc.depthStencilSurface.mipLevel = 0;
  121. mSceneColorRT = TextureManager::instance().createRenderTexture(sceneColorDesc);
  122. }
  123. }
  124. else if(type == RTT_LightAccumulation)
  125. {
  126. if (mViewTarget.numSamples > 1)
  127. {
  128. UINT32 bufferNumElements = width * height * mViewTarget.numSamples;
  129. mFlattenedLightAccumulationBuffer =
  130. texPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  131. }
  132. else
  133. {
  134. mLightAccumulationTex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
  135. height, TU_LOADSTORE, mViewTarget.numSamples, false));
  136. }
  137. }
  138. }
  139. void RenderTargets::release(RenderTargetType type)
  140. {
  141. GpuResourcePool& texPool = GpuResourcePool::instance();
  142. if (type == RTT_GBuffer)
  143. {
  144. texPool.release(mSceneColorTex);
  145. texPool.release(mAlbedoTex);
  146. texPool.release(mNormalTex);
  147. }
  148. else if(type == RTT_SceneColor)
  149. {
  150. texPool.release(mSceneColorTex);
  151. if (mSceneColorNonMSAATex != nullptr)
  152. texPool.release(mSceneColorNonMSAATex);
  153. if (mFlattenedSceneColorBuffer != nullptr)
  154. texPool.release(mFlattenedSceneColorBuffer);
  155. }
  156. else if(type == RTT_LightAccumulation)
  157. {
  158. if (mLightAccumulationTex != nullptr)
  159. texPool.release(mLightAccumulationTex);
  160. if (mFlattenedLightAccumulationBuffer != nullptr)
  161. texPool.release(mFlattenedLightAccumulationBuffer);
  162. }
  163. }
  164. void RenderTargets::bindGBuffer()
  165. {
  166. RenderAPI& rapi = RenderAPI::instance();
  167. rapi.setRenderTarget(mGBufferRT);
  168. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  169. rapi.setViewport(area);
  170. // Clear depth & stencil according to user defined values, don't clear color as all values will get written to
  171. UINT32 clearFlags = mViewTarget.clearFlags & ~FBT_COLOR;
  172. if (clearFlags != 0)
  173. {
  174. RenderAPI::instance().clearViewport(clearFlags, mViewTarget.clearColor,
  175. mViewTarget.clearDepthValue, mViewTarget.clearStencilValue, 0x01);
  176. }
  177. // Clear all non primary targets (Note: I could perhaps clear all but albedo, since it stores a per-pixel write mask)
  178. RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
  179. }
  180. void RenderTargets::bindSceneColor(bool readOnlyDepthStencil)
  181. {
  182. RenderAPI& rapi = RenderAPI::instance();
  183. rapi.setRenderTarget(mSceneColorRT, readOnlyDepthStencil, RT_COLOR0 | RT_DEPTH);
  184. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  185. rapi.setViewport(area);
  186. }
  187. SPtr<Texture> RenderTargets::getSceneColor() const
  188. {
  189. return mSceneColorTex->texture;
  190. }
  191. SPtr<Texture> RenderTargets::getGBufferA() const
  192. {
  193. return mAlbedoTex->texture;
  194. }
  195. SPtr<Texture> RenderTargets::getGBufferB() const
  196. {
  197. return mNormalTex->texture;
  198. }
  199. SPtr<Texture> RenderTargets::getGBufferC() const
  200. {
  201. return mRoughMetalTex->texture;
  202. }
  203. SPtr<Texture> RenderTargets::getSceneDepth() const
  204. {
  205. return mDepthTex->texture;
  206. }
  207. SPtr<Texture> RenderTargets::getResolvedSceneColor() const
  208. {
  209. if (mSceneColorNonMSAATex != nullptr)
  210. return mSceneColorNonMSAATex->texture;
  211. return getSceneColor();
  212. }
  213. SPtr<RenderTexture> RenderTargets::getResolvedSceneColorRT() const
  214. {
  215. if (mSceneColorNonMSAATex != nullptr)
  216. return mSceneColorNonMSAATex->renderTexture;
  217. return mSceneColorTex->renderTexture;
  218. }
  219. SPtr<GpuBuffer> RenderTargets::getSceneColorBuffer() const
  220. {
  221. return mFlattenedSceneColorBuffer->buffer;
  222. }
  223. SPtr<Texture> RenderTargets::getLightAccumulation() const
  224. {
  225. return mLightAccumulationTex->texture;
  226. }
  227. SPtr<GpuBuffer> RenderTargets::getLightAccumulationBuffer() const
  228. {
  229. return mFlattenedLightAccumulationBuffer->buffer;
  230. }
  231. }}