2
0

BsRenderTargets.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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::allocate()
  24. {
  25. GpuResourcePool& texPool = GpuResourcePool::instance();
  26. UINT32 width = mViewTarget.viewRect.width;
  27. UINT32 height = mViewTarget.viewRect.height;
  28. // Note: This class is keeping all these textures alive for too long (even after they are done for a frame). We
  29. // could save on memory by deallocating and reallocating them every frame, but it remains to be seen how much of
  30. // a performance impact would that have.
  31. // Note: Albedo is allocated as SRGB, meaning when reading from textures during depth pass we decode from sRGB into linear,
  32. // then back into sRGB when writing to albedo, and back to linear when reading from albedo during light pass. This /might/ have
  33. // a performance impact. In which case we could just use a higher precision albedo buffer, which can then store linear color
  34. // directly (storing linear in 8bit buffer causes too much detail to be lost in the blacks).
  35. SPtr<PooledRenderTexture> newColorRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
  36. height, TU_RENDERTARGET | TU_LOADSTORE, mViewTarget.numSamples, false));
  37. SPtr<PooledRenderTexture> newAlbedoRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mAlbedoFormat, width,
  38. height, TU_RENDERTARGET, mViewTarget.numSamples, true));
  39. SPtr<PooledRenderTexture> newNormalRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mNormalFormat, width,
  40. height, TU_RENDERTARGET, mViewTarget.numSamples, false));
  41. SPtr<PooledRenderTexture> newRoughMetalRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_FLOAT16_RG, width,
  42. height, TU_RENDERTARGET, mViewTarget.numSamples, false));
  43. SPtr<PooledRenderTexture> newDepthRT = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32_S8X24, width, height,
  44. TU_DEPTHSTENCIL, mViewTarget.numSamples, false));
  45. if(mViewTarget.numSamples > 1)
  46. {
  47. const RenderAPIInfo& rapiInfo = RenderAPI::instance().getAPIInfo();
  48. // DX11/HLSL is unable to have an UAV for a multisampled texture, so we need to use a buffer instead and then
  49. // perform a blit to the actual scene color
  50. if (!rapiInfo.isFlagSet(RenderAPIFeatureFlag::MSAAImageStores))
  51. {
  52. UINT32 bufferNumElements = width * height * mViewTarget.numSamples;
  53. mFlattenedSceneColorBuffer = texPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  54. }
  55. // Need a texture we'll resolve MSAA to before post-processing
  56. mSceneColorNonMSAATex = texPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(mSceneColorFormat, width,
  57. height, TU_RENDERTARGET, 1, false));
  58. }
  59. bool rebuildTargets = newColorRT != mSceneColorTex || newAlbedoRT != mAlbedoTex || newNormalRT != mNormalTex
  60. || newRoughMetalRT != mRoughMetalTex || newDepthRT != mDepthTex;
  61. mSceneColorTex = newColorRT;
  62. mAlbedoTex = newAlbedoRT;
  63. mNormalTex = newNormalRT;
  64. mRoughMetalTex = newRoughMetalRT;
  65. mDepthTex = newDepthRT;
  66. if (mGBufferRT == nullptr || mSceneColorRT == nullptr || rebuildTargets)
  67. {
  68. RENDER_TEXTURE_DESC gbufferDesc;
  69. gbufferDesc.colorSurfaces[0].texture = mAlbedoTex->texture;
  70. gbufferDesc.colorSurfaces[0].face = 0;
  71. gbufferDesc.colorSurfaces[0].numFaces = 1;
  72. gbufferDesc.colorSurfaces[0].mipLevel = 0;
  73. gbufferDesc.colorSurfaces[1].texture = mNormalTex->texture;
  74. gbufferDesc.colorSurfaces[1].face = 0;
  75. gbufferDesc.colorSurfaces[1].numFaces = 1;
  76. gbufferDesc.colorSurfaces[1].mipLevel = 0;
  77. gbufferDesc.colorSurfaces[2].texture = mRoughMetalTex->texture;
  78. gbufferDesc.colorSurfaces[2].face = 0;
  79. gbufferDesc.colorSurfaces[2].numFaces = 1;
  80. gbufferDesc.colorSurfaces[2].mipLevel = 0;
  81. gbufferDesc.depthStencilSurface.texture = mDepthTex->texture;
  82. gbufferDesc.depthStencilSurface.face = 0;
  83. gbufferDesc.depthStencilSurface.mipLevel = 0;
  84. mGBufferRT = RenderTexture::create(gbufferDesc);
  85. RENDER_TEXTURE_DESC sceneColorDesc;
  86. sceneColorDesc.colorSurfaces[0].texture = mSceneColorTex->texture;
  87. sceneColorDesc.colorSurfaces[0].face = 0;
  88. sceneColorDesc.colorSurfaces[0].numFaces = 1;
  89. sceneColorDesc.colorSurfaces[0].mipLevel = 0;
  90. sceneColorDesc.depthStencilSurface.texture = mDepthTex->texture;
  91. sceneColorDesc.depthStencilSurface.face = 0;
  92. sceneColorDesc.depthStencilSurface.numFaces = 1;
  93. sceneColorDesc.depthStencilSurface.mipLevel = 0;
  94. mSceneColorRT = TextureManager::instance().createRenderTexture(sceneColorDesc);
  95. }
  96. }
  97. void RenderTargets::release()
  98. {
  99. RenderAPI& rapi = RenderAPI::instance();
  100. rapi.setRenderTarget(nullptr);
  101. GpuResourcePool& texPool = GpuResourcePool::instance();
  102. texPool.release(mSceneColorTex);
  103. texPool.release(mAlbedoTex);
  104. texPool.release(mNormalTex);
  105. texPool.release(mDepthTex);
  106. if(mSceneColorNonMSAATex != nullptr)
  107. texPool.release(mSceneColorNonMSAATex);
  108. if (mFlattenedSceneColorBuffer != nullptr)
  109. texPool.release(mFlattenedSceneColorBuffer);
  110. }
  111. void RenderTargets::bindGBuffer()
  112. {
  113. RenderAPI& rapi = RenderAPI::instance();
  114. rapi.setRenderTarget(mGBufferRT);
  115. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  116. rapi.setViewport(area);
  117. // Clear depth & stencil according to user defined values, don't clear color as all values will get written to
  118. UINT32 clearFlags = mViewTarget.clearFlags & ~FBT_COLOR;
  119. if (clearFlags != 0)
  120. {
  121. RenderAPI::instance().clearViewport(clearFlags, mViewTarget.clearColor,
  122. mViewTarget.clearDepthValue, mViewTarget.clearStencilValue, 0x01);
  123. }
  124. // Clear all non primary targets (Note: I could perhaps clear all but albedo, since it stores a per-pixel write mask)
  125. RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
  126. }
  127. void RenderTargets::bindSceneColor(bool readOnlyDepthStencil)
  128. {
  129. RenderAPI& rapi = RenderAPI::instance();
  130. rapi.setRenderTarget(mSceneColorRT, readOnlyDepthStencil, RT_COLOR0 | RT_DEPTH);
  131. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  132. rapi.setViewport(area);
  133. }
  134. SPtr<Texture> RenderTargets::getSceneColor() const
  135. {
  136. return mSceneColorTex->texture;
  137. }
  138. SPtr<Texture> RenderTargets::getTextureA() const
  139. {
  140. return mAlbedoTex->texture;
  141. }
  142. SPtr<Texture> RenderTargets::getTextureB() const
  143. {
  144. return mNormalTex->texture;
  145. }
  146. SPtr<Texture> RenderTargets::getTextureC() const
  147. {
  148. return mRoughMetalTex->texture;
  149. }
  150. SPtr<Texture> RenderTargets::getTextureDepth() const
  151. {
  152. return mDepthTex->texture;
  153. }
  154. SPtr<Texture> RenderTargets::getSceneColorNonMSAA() const
  155. {
  156. if (mSceneColorNonMSAATex != nullptr)
  157. return mSceneColorNonMSAATex->texture;
  158. return getSceneColor();
  159. }
  160. SPtr<RenderTexture> RenderTargets::getSceneColorNonMSAART() const
  161. {
  162. if (mSceneColorNonMSAATex != nullptr)
  163. return mSceneColorNonMSAATex->renderTexture;
  164. return mSceneColorTex->renderTexture;
  165. }
  166. SPtr<GpuBuffer> RenderTargets::getFlattenedSceneColorBuffer() const
  167. {
  168. return mFlattenedSceneColorBuffer->buffer;
  169. }
  170. }}