BsRenderCompositor.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRenderCompositor.h"
  4. #include "BsGpuResourcePool.h"
  5. #include "BsRendererView.h"
  6. #include "BsRendererUtility.h"
  7. #include "BsMesh.h"
  8. #include "BsGpuBuffer.h"
  9. #include "BsStandardDeferredLighting.h"
  10. #include "BsRenderBeastOptions.h"
  11. #include "BsCamera.h"
  12. #include "BsRendererScene.h"
  13. #include "BsRenderBeast.h"
  14. #include "BsBitwise.h"
  15. #include "BsRendererTextures.h"
  16. #include "BsObjectRendering.h"
  17. #include "BsGpuParamsSet.h"
  18. #include "BsRendererExtension.h"
  19. #include "BsSkybox.h"
  20. #include "BsLightProbes.h"
  21. namespace bs { namespace ct
  22. {
  23. UnorderedMap<StringID, RenderCompositor::NodeType*> RenderCompositor::mNodeTypes;
  24. RenderCompositor::~RenderCompositor()
  25. {
  26. clear();
  27. }
  28. void RenderCompositor::build(const RendererView& view, const StringID& finalNode)
  29. {
  30. clear();
  31. bs_frame_mark();
  32. {
  33. FrameUnorderedMap<StringID, UINT32> processedNodes;
  34. mIsValid = true;
  35. std::function<bool(const StringID&)> registerNode = [&](const StringID& nodeId)
  36. {
  37. // Find node type
  38. auto iterFind = mNodeTypes.find(nodeId);
  39. if (iterFind == mNodeTypes.end())
  40. {
  41. LOGERR("Cannot find render compositor node of type \"" + String(nodeId.cstr()) + "\".");
  42. return false;
  43. }
  44. NodeType* nodeType = iterFind->second;
  45. // Register current node
  46. auto iterFind2 = processedNodes.find(nodeId);
  47. // New node
  48. if (iterFind2 == processedNodes.end())
  49. {
  50. // Mark it as invalid for now
  51. processedNodes[nodeId] = -1;
  52. }
  53. // Register node dependencies
  54. SmallVector<StringID, 4> depIds = nodeType->getDependencies(view);
  55. for (auto& dep : depIds)
  56. {
  57. if (!registerNode(dep))
  58. return false;
  59. }
  60. // Register current node
  61. UINT32 curIdx;
  62. // New node, properly populate its index
  63. if (iterFind2 == processedNodes.end())
  64. {
  65. iterFind2 = processedNodes.find(nodeId);
  66. curIdx = (UINT32)mNodeInfos.size();
  67. mNodeInfos.push_back(NodeInfo());
  68. processedNodes[nodeId] = curIdx;
  69. NodeInfo& nodeInfo = mNodeInfos.back();
  70. nodeInfo.node = nodeType->create();
  71. nodeInfo.lastUseIdx = -1;
  72. for (auto& depId : depIds)
  73. {
  74. iterFind2 = processedNodes.find(depId);
  75. NodeInfo& depNodeInfo = mNodeInfos[iterFind2->second];
  76. nodeInfo.inputs.push_back(depNodeInfo.node);
  77. }
  78. }
  79. else // Existing node
  80. {
  81. curIdx = iterFind2->second;
  82. // Check if invalid
  83. if (curIdx == -1)
  84. {
  85. LOGERR("Render compositor nodes recursion detected. Node \"" + String(nodeId.cstr()) + "\" " +
  86. "depends on node \"" + String(iterFind->first.cstr()) + "\" which is not available at " +
  87. "this stage.");
  88. return false;
  89. }
  90. }
  91. // Update dependency last use counters
  92. for (auto& dep : depIds)
  93. {
  94. iterFind2 = processedNodes.find(dep);
  95. NodeInfo& depNodeInfo = mNodeInfos[iterFind2->second];
  96. if (depNodeInfo.lastUseIdx == -1)
  97. depNodeInfo.lastUseIdx = curIdx;
  98. else
  99. depNodeInfo.lastUseIdx = std::max(depNodeInfo.lastUseIdx, curIdx);
  100. }
  101. return true;
  102. };
  103. mIsValid = registerNode(finalNode);
  104. if (!mIsValid)
  105. clear();
  106. }
  107. bs_frame_clear();
  108. }
  109. void RenderCompositor::execute(RenderCompositorNodeInputs& inputs) const
  110. {
  111. if (!mIsValid)
  112. return;
  113. bs_frame_mark();
  114. {
  115. FrameVector<const NodeInfo*> activeNodes;
  116. UINT32 idx = 0;
  117. for (auto& entry : mNodeInfos)
  118. {
  119. inputs.inputNodes = entry.inputs;
  120. entry.node->render(inputs);
  121. activeNodes.push_back(&entry);
  122. for (UINT32 i = 0; i < (UINT32)activeNodes.size(); ++i)
  123. {
  124. if (activeNodes[i] == nullptr)
  125. continue;
  126. if (activeNodes[i]->lastUseIdx <= idx)
  127. {
  128. activeNodes[i]->node->clear();
  129. activeNodes[i] = nullptr;
  130. }
  131. }
  132. idx++;
  133. }
  134. }
  135. bs_frame_clear();
  136. if (!mNodeInfos.empty())
  137. mNodeInfos.back().node->clear();
  138. }
  139. void RenderCompositor::clear()
  140. {
  141. for (auto& entry : mNodeInfos)
  142. bs_delete(entry.node);
  143. mNodeInfos.clear();
  144. mIsValid = false;
  145. }
  146. void RCNodeSceneDepth::render(const RenderCompositorNodeInputs& inputs)
  147. {
  148. GpuResourcePool& resPool = GpuResourcePool::instance();
  149. const RendererViewProperties& viewProps = inputs.view.getProperties();
  150. UINT32 width = viewProps.viewRect.width;
  151. UINT32 height = viewProps.viewRect.height;
  152. UINT32 numSamples = viewProps.numSamples;
  153. depthTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32_S8X24, width, height, TU_DEPTHSTENCIL,
  154. numSamples, false));
  155. }
  156. void RCNodeSceneDepth::clear()
  157. {
  158. GpuResourcePool& resPool = GpuResourcePool::instance();
  159. resPool.release(depthTex);
  160. }
  161. SmallVector<StringID, 4> RCNodeSceneDepth::getDependencies(const RendererView& view)
  162. {
  163. return {};
  164. }
  165. void RCNodeGBuffer::render(const RenderCompositorNodeInputs& inputs)
  166. {
  167. // Allocate necessary textures & targets
  168. GpuResourcePool& resPool = GpuResourcePool::instance();
  169. const RendererViewProperties& viewProps = inputs.view.getProperties();
  170. UINT32 width = viewProps.viewRect.width;
  171. UINT32 height = viewProps.viewRect.height;
  172. UINT32 numSamples = viewProps.numSamples;
  173. // Note: Consider customizable formats. e.g. for testing if quality can be improved with higher precision normals.
  174. albedoTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA8, width, height, TU_RENDERTARGET,
  175. numSamples, true));
  176. normalTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGB10A2, width, height, TU_RENDERTARGET,
  177. numSamples, false));
  178. roughMetalTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RG16F, width, height, TU_RENDERTARGET,
  179. numSamples, false)); // Note: Metal doesn't need 16-bit float
  180. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  181. SPtr<PooledRenderTexture> sceneDepthTex = sceneDepthNode->depthTex;
  182. bool rebuildRT = false;
  183. if (renderTarget != nullptr)
  184. {
  185. rebuildRT |= renderTarget->getColorTexture(0) != albedoTex->texture;
  186. rebuildRT |= renderTarget->getColorTexture(1) != normalTex->texture;
  187. rebuildRT |= renderTarget->getColorTexture(2) != roughMetalTex->texture;
  188. rebuildRT |= renderTarget->getDepthStencilTexture() != sceneDepthTex->texture;
  189. }
  190. else
  191. rebuildRT = true;
  192. if (renderTarget == nullptr || rebuildRT)
  193. {
  194. RENDER_TEXTURE_DESC gbufferDesc;
  195. gbufferDesc.colorSurfaces[0].texture = albedoTex->texture;
  196. gbufferDesc.colorSurfaces[0].face = 0;
  197. gbufferDesc.colorSurfaces[0].numFaces = 1;
  198. gbufferDesc.colorSurfaces[0].mipLevel = 0;
  199. gbufferDesc.colorSurfaces[1].texture = normalTex->texture;
  200. gbufferDesc.colorSurfaces[1].face = 0;
  201. gbufferDesc.colorSurfaces[1].numFaces = 1;
  202. gbufferDesc.colorSurfaces[1].mipLevel = 0;
  203. gbufferDesc.colorSurfaces[2].texture = roughMetalTex->texture;
  204. gbufferDesc.colorSurfaces[2].face = 0;
  205. gbufferDesc.colorSurfaces[2].numFaces = 1;
  206. gbufferDesc.colorSurfaces[2].mipLevel = 0;
  207. gbufferDesc.depthStencilSurface.texture = sceneDepthTex->texture;
  208. gbufferDesc.depthStencilSurface.face = 0;
  209. gbufferDesc.depthStencilSurface.mipLevel = 0;
  210. renderTarget = RenderTexture::create(gbufferDesc);
  211. }
  212. // Prepare all visible objects. Note that this also prepares non-opaque objects.
  213. const VisibilityInfo& visibility = inputs.view.getVisibilityMasks();
  214. UINT32 numRenderables = (UINT32)inputs.scene.renderables.size();
  215. for (UINT32 i = 0; i < numRenderables; i++)
  216. {
  217. if (!visibility.renderables[i])
  218. continue;
  219. RendererObject* rendererObject = inputs.scene.renderables[i];
  220. rendererObject->updatePerCallBuffer(viewProps.viewProjTransform);
  221. for (auto& element : inputs.scene.renderables[i]->elements)
  222. {
  223. if (element.perCameraBindingIdx != -1)
  224. element.params->setParamBlockBuffer(element.perCameraBindingIdx, inputs.view.getPerViewBuffer(), true);
  225. }
  226. }
  227. Camera* sceneCamera = inputs.view.getSceneCamera();
  228. // Trigger pre-base-pass callbacks
  229. if (sceneCamera != nullptr)
  230. {
  231. for(auto& extension : inputs.extPreBasePass)
  232. {
  233. if (extension->check(*sceneCamera))
  234. extension->render(*sceneCamera);
  235. }
  236. }
  237. // Render base pass
  238. RenderAPI& rapi = RenderAPI::instance();
  239. rapi.setRenderTarget(renderTarget);
  240. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  241. rapi.setViewport(area);
  242. // Clear depth & stencil according to user defined values, don't clear color as all values will get written to
  243. UINT32 clearFlags = viewProps.clearFlags & ~FBT_COLOR;
  244. if (clearFlags != 0)
  245. {
  246. rapi.clearViewport(clearFlags, viewProps.clearColor, viewProps.clearDepthValue,
  247. viewProps.clearStencilValue, 0x01);
  248. }
  249. // Clear all non primary targets (Note: I could perhaps clear all but albedo, since it stores a per-pixel write mask)
  250. rapi.clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
  251. // Render all visible opaque elements
  252. const Vector<RenderQueueElement>& opaqueElements = inputs.view.getOpaqueQueue()->getSortedElements();
  253. for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
  254. {
  255. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  256. SPtr<Material> material = renderElem->material;
  257. if (iter->applyPass)
  258. gRendererUtility().setPass(material, iter->passIdx, renderElem->techniqueIdx);
  259. gRendererUtility().setPassParams(renderElem->params, iter->passIdx);
  260. if(renderElem->morphVertexDeclaration == nullptr)
  261. gRendererUtility().draw(renderElem->mesh, renderElem->subMesh);
  262. else
  263. gRendererUtility().drawMorph(renderElem->mesh, renderElem->subMesh, renderElem->morphShapeBuffer,
  264. renderElem->morphVertexDeclaration);
  265. }
  266. // Trigger post-base-pass callbacks
  267. if (sceneCamera != nullptr)
  268. {
  269. for(auto& extension : inputs.extPostBasePass)
  270. {
  271. if (extension->check(*sceneCamera))
  272. extension->render(*sceneCamera);
  273. }
  274. }
  275. }
  276. void RCNodeGBuffer::clear()
  277. {
  278. GpuResourcePool& resPool = GpuResourcePool::instance();
  279. resPool.release(albedoTex);
  280. resPool.release(normalTex);
  281. resPool.release(roughMetalTex);
  282. }
  283. SmallVector<StringID, 4> RCNodeGBuffer::getDependencies(const RendererView& view)
  284. {
  285. return { RCNodeSceneDepth::getNodeId() };
  286. }
  287. void RCNodeSceneColor::render(const RenderCompositorNodeInputs& inputs)
  288. {
  289. GpuResourcePool& resPool = GpuResourcePool::instance();
  290. const RendererViewProperties& viewProps = inputs.view.getProperties();
  291. UINT32 width = viewProps.viewRect.width;
  292. UINT32 height = viewProps.viewRect.height;
  293. UINT32 numSamples = viewProps.numSamples;
  294. // Note: Consider customizable HDR format via options? e.g. smaller PF_FLOAT_R11G11B10 or larger 32-bit format
  295. sceneColorTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width, height, TU_RENDERTARGET |
  296. TU_LOADSTORE, numSamples, false));
  297. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  298. SPtr<PooledRenderTexture> sceneDepthTex = sceneDepthNode->depthTex;
  299. if (viewProps.numSamples > 1)
  300. {
  301. UINT32 bufferNumElements = width * height * viewProps.numSamples;
  302. flattenedSceneColorBuffer = resPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  303. }
  304. else
  305. flattenedSceneColorBuffer = nullptr;
  306. bool rebuildRT = false;
  307. if (renderTarget != nullptr)
  308. {
  309. rebuildRT |= renderTarget->getColorTexture(0) != sceneColorTex->texture;
  310. rebuildRT |= renderTarget->getDepthStencilTexture() != sceneDepthTex->texture;
  311. }
  312. else
  313. rebuildRT = true;
  314. if (rebuildRT)
  315. {
  316. RENDER_TEXTURE_DESC sceneColorDesc;
  317. sceneColorDesc.colorSurfaces[0].texture = sceneColorTex->texture;
  318. sceneColorDesc.colorSurfaces[0].face = 0;
  319. sceneColorDesc.colorSurfaces[0].numFaces = 1;
  320. sceneColorDesc.colorSurfaces[0].mipLevel = 0;
  321. sceneColorDesc.depthStencilSurface.texture = sceneDepthTex->texture;
  322. sceneColorDesc.depthStencilSurface.face = 0;
  323. sceneColorDesc.depthStencilSurface.numFaces = 1;
  324. sceneColorDesc.depthStencilSurface.mipLevel = 0;
  325. renderTarget = RenderTexture::create(sceneColorDesc);
  326. }
  327. }
  328. void RCNodeSceneColor::clear()
  329. {
  330. GpuResourcePool& resPool = GpuResourcePool::instance();
  331. resPool.release(sceneColorTex);
  332. if (flattenedSceneColorBuffer != nullptr)
  333. resPool.release(flattenedSceneColorBuffer);
  334. }
  335. SmallVector<StringID, 4> RCNodeSceneColor::getDependencies(const RendererView& view)
  336. {
  337. return { RCNodeSceneDepth::getNodeId() };
  338. }
  339. void RCNodeLightAccumulation::render(const RenderCompositorNodeInputs& inputs)
  340. {
  341. GpuResourcePool& resPool = GpuResourcePool::instance();
  342. const RendererViewProperties& viewProps = inputs.view.getProperties();
  343. UINT32 width = viewProps.viewRect.width;
  344. UINT32 height = viewProps.viewRect.height;
  345. UINT32 numSamples = viewProps.numSamples;
  346. if (numSamples > 1)
  347. {
  348. UINT32 bufferNumElements = width * height * numSamples;
  349. flattenedLightAccumBuffer =
  350. resPool.get(POOLED_STORAGE_BUFFER_DESC::createStandard(BF_16X4F, bufferNumElements));
  351. SPtr<GpuBuffer> buffer = flattenedLightAccumBuffer->buffer;
  352. auto& bufferProps = buffer->getProperties();
  353. UINT32 bufferSize = bufferProps.getElementSize() * bufferProps.getElementCount();
  354. UINT16* data = (UINT16*)buffer->lock(0, bufferSize, GBL_WRITE_ONLY_DISCARD);
  355. {
  356. memset(data, 0, bufferSize);
  357. }
  358. buffer->unlock();
  359. }
  360. else
  361. flattenedLightAccumBuffer = nullptr;
  362. lightAccumulationTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, width,
  363. height, TU_LOADSTORE | TU_RENDERTARGET, numSamples, false));
  364. bool rebuildRT;
  365. if (renderTarget != nullptr)
  366. rebuildRT = renderTarget->getColorTexture(0) != lightAccumulationTex->texture;
  367. else
  368. rebuildRT = true;
  369. if (rebuildRT)
  370. {
  371. RENDER_TEXTURE_DESC lightAccumulationRTDesc;
  372. lightAccumulationRTDesc.colorSurfaces[0].texture = lightAccumulationTex->texture;
  373. lightAccumulationRTDesc.colorSurfaces[0].face = 0;
  374. lightAccumulationRTDesc.colorSurfaces[0].numFaces = 1;
  375. lightAccumulationRTDesc.colorSurfaces[0].mipLevel = 0;
  376. renderTarget = RenderTexture::create(lightAccumulationRTDesc);
  377. }
  378. }
  379. void RCNodeLightAccumulation::clear()
  380. {
  381. GpuResourcePool& resPool = GpuResourcePool::instance();
  382. resPool.release(lightAccumulationTex);
  383. if (flattenedLightAccumBuffer)
  384. resPool.release(flattenedLightAccumBuffer);
  385. }
  386. SmallVector<StringID, 4> RCNodeLightAccumulation::getDependencies(const RendererView& view)
  387. {
  388. return {};
  389. }
  390. void RCNodeTiledDeferredLighting::render(const RenderCompositorNodeInputs& inputs)
  391. {
  392. output = static_cast<RCNodeLightAccumulation*>(inputs.inputNodes[0]);
  393. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  394. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[2]);
  395. const RendererViewProperties& viewProps = inputs.view.getProperties();
  396. TiledDeferredLightingMat* tiledDeferredMat = TiledDeferredLightingMat::getVariation(viewProps.numSamples);
  397. GBufferTextures gbuffer;
  398. gbuffer.albedo = gbufferNode->albedoTex->texture;
  399. gbuffer.normals = gbufferNode->normalTex->texture;
  400. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  401. gbuffer.depth = sceneDepthNode->depthTex->texture;
  402. RenderAPI& rapi = RenderAPI::instance();
  403. rapi.setRenderTarget(output->renderTarget, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
  404. const VisibleLightData& lightData = inputs.viewGroup.getVisibleLightData();
  405. SPtr<GpuBuffer> flattenedLightAccumBuffer;
  406. if (output->flattenedLightAccumBuffer)
  407. flattenedLightAccumBuffer = output->flattenedLightAccumBuffer->buffer;
  408. tiledDeferredMat->execute(inputs.view, lightData, gbuffer, output->lightAccumulationTex->texture,
  409. flattenedLightAccumBuffer);
  410. }
  411. void RCNodeTiledDeferredLighting::clear()
  412. {
  413. output = nullptr;
  414. }
  415. SmallVector<StringID, 4> RCNodeTiledDeferredLighting::getDependencies(const RendererView& view)
  416. {
  417. return { RCNodeLightAccumulation::getNodeId(), RCNodeGBuffer::getNodeId(), RCNodeSceneDepth::getNodeId() };
  418. }
  419. void RCNodeStandardDeferredLighting::render(const RenderCompositorNodeInputs& inputs)
  420. {
  421. GpuResourcePool& resPool = GpuResourcePool::instance();
  422. const RendererViewProperties& viewProps = inputs.view.getProperties();
  423. UINT32 width = viewProps.viewRect.width;
  424. UINT32 height = viewProps.viewRect.height;
  425. UINT32 numSamples = viewProps.numSamples;
  426. RCNodeTiledDeferredLighting* tileDeferredNode = static_cast<RCNodeTiledDeferredLighting*>(inputs.inputNodes[0]);
  427. output = tileDeferredNode->output;
  428. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  429. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[2]);
  430. // Allocate light occlusion
  431. mLightOcclusionTex = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, width,
  432. height, TU_RENDERTARGET, numSamples, false));
  433. bool rebuildRT = false;
  434. if (mRenderTarget != nullptr)
  435. {
  436. rebuildRT |= mRenderTarget->getColorTexture(0) != mLightOcclusionTex->texture;
  437. rebuildRT |= mRenderTarget->getDepthStencilTexture() != sceneDepthNode->depthTex->texture;
  438. }
  439. else
  440. rebuildRT = true;
  441. if (rebuildRT)
  442. {
  443. RENDER_TEXTURE_DESC lightOcclusionRTDesc;
  444. lightOcclusionRTDesc.colorSurfaces[0].texture = mLightOcclusionTex->texture;
  445. lightOcclusionRTDesc.colorSurfaces[0].face = 0;
  446. lightOcclusionRTDesc.colorSurfaces[0].numFaces = 1;
  447. lightOcclusionRTDesc.colorSurfaces[0].mipLevel = 0;
  448. lightOcclusionRTDesc.depthStencilSurface.texture = sceneDepthNode->depthTex->texture;
  449. lightOcclusionRTDesc.depthStencilSurface.face = 0;
  450. lightOcclusionRTDesc.depthStencilSurface.numFaces = 1;
  451. lightOcclusionRTDesc.depthStencilSurface.mipLevel = 0;
  452. mRenderTarget = RenderTexture::create(lightOcclusionRTDesc);
  453. }
  454. GBufferTextures gbuffer;
  455. gbuffer.albedo = gbufferNode->albedoTex->texture;
  456. gbuffer.normals = gbufferNode->normalTex->texture;
  457. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  458. gbuffer.depth = sceneDepthNode->depthTex->texture;
  459. const VisibleLightData& lightData = inputs.viewGroup.getVisibleLightData();
  460. const ShadowRendering& shadowRenderer = inputs.viewGroup.getShadowRenderer();
  461. Camera* sceneCamera = inputs.view.getSceneCamera();
  462. // Note: Currently skipping shadow rendering for any views that aren't part of the scene (like temporary ones)
  463. if (sceneCamera != nullptr)
  464. {
  465. RenderAPI& rapi = RenderAPI::instance();
  466. UINT32 viewIdx = sceneCamera->getRendererId();
  467. for (UINT32 i = 0; i < (UINT32)LightType::Count; i++)
  468. {
  469. LightType lightType = (LightType)i;
  470. auto& lights = lightData.getLights(lightType);
  471. UINT32 count = lightData.getNumShadowedLights(lightType);
  472. UINT32 offset = lightData.getNumUnshadowedLights(lightType);
  473. for (UINT32 j = 0; j < count; j++)
  474. {
  475. rapi.setRenderTarget(mRenderTarget, FBT_DEPTH, RT_DEPTH_STENCIL);
  476. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  477. rapi.setViewport(area);
  478. rapi.clearViewport(FBT_COLOR, Color::ZERO);
  479. UINT32 lightIdx = offset + j;
  480. const RendererLight& light = *lights[lightIdx];
  481. shadowRenderer.renderShadowOcclusion(inputs.scene, inputs.options.shadowFilteringQuality,
  482. light, viewIdx, gbuffer);
  483. rapi.setRenderTarget(output->renderTarget, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
  484. StandardDeferred::instance().renderLight(lightType, light, inputs.view, gbuffer,
  485. mLightOcclusionTex->texture);
  486. }
  487. }
  488. // Makes sure light accumulation can be read by following passes
  489. rapi.setRenderTarget(nullptr);
  490. }
  491. resPool.release(mLightOcclusionTex);
  492. }
  493. void RCNodeStandardDeferredLighting::clear()
  494. {
  495. output = nullptr;
  496. }
  497. SmallVector<StringID, 4> RCNodeStandardDeferredLighting::getDependencies(const RendererView& view)
  498. {
  499. SmallVector<StringID, 4> deps;
  500. deps.push_back(RCNodeTiledDeferredLighting::getNodeId());
  501. deps.push_back(RCNodeGBuffer::getNodeId());
  502. deps.push_back(RCNodeSceneDepth::getNodeId());
  503. if (view.getProperties().numSamples > 1)
  504. deps.push_back(RCNodeUnflattenLightAccum::getNodeId());
  505. return deps;
  506. }
  507. void RCNodeUnflattenLightAccum::render(const RenderCompositorNodeInputs& inputs)
  508. {
  509. RCNodeLightAccumulation* lightAccumNode = static_cast<RCNodeLightAccumulation*>(inputs.inputNodes[0]);
  510. FlatFramebufferToTextureMat* material = FlatFramebufferToTextureMat::get();
  511. RenderAPI& rapi = RenderAPI::instance();
  512. rapi.setRenderTarget(lightAccumNode->renderTarget, FBT_DEPTH | FBT_STENCIL, RT_COLOR0 | RT_DEPTH_STENCIL);
  513. material->execute(lightAccumNode->flattenedLightAccumBuffer->buffer, lightAccumNode->lightAccumulationTex->texture);
  514. }
  515. void RCNodeUnflattenLightAccum::clear()
  516. {
  517. output = nullptr;
  518. }
  519. SmallVector<StringID, 4> RCNodeUnflattenLightAccum::getDependencies(const RendererView& view)
  520. {
  521. return { RCNodeLightAccumulation::getNodeId() };
  522. }
  523. void RCNodeIndirectLighting::render(const RenderCompositorNodeInputs& inputs)
  524. {
  525. if (!inputs.view.getRenderSettings().enableIndirectLighting)
  526. return;
  527. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[0]);
  528. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[1]);
  529. RCNodeLightAccumulation* lightAccumNode = static_cast <RCNodeLightAccumulation*>(inputs.inputNodes[2]);
  530. GpuResourcePool& resPool = GpuResourcePool::instance();
  531. const RendererViewProperties& viewProps = inputs.view.getProperties();
  532. const LightProbes& lightProbes = inputs.scene.lightProbes;
  533. SPtr<GpuBuffer> shCoeffs = lightProbes.getSHCoefficientsBuffer();
  534. SPtr<GpuBuffer> volumeInfos = lightProbes.getTetrahedonInfosBuffer();
  535. SPtr<Mesh> volumeMesh = lightProbes.getTetrahedraVolumeMesh();
  536. IrradianceEvaluateMat* evaluateMat;
  537. SPtr<PooledRenderTexture> volumeIndices;
  538. if(lightProbes.hasAnyProbes())
  539. {
  540. POOLED_RENDER_TEXTURE_DESC volumeIndicesDesc;
  541. POOLED_RENDER_TEXTURE_DESC depthDesc;
  542. TetrahedraRenderMat::getOutputDesc(inputs.view, volumeIndicesDesc, depthDesc);
  543. volumeIndices = resPool.get(volumeIndicesDesc);
  544. SPtr<PooledRenderTexture> depthTex = resPool.get(depthDesc);
  545. RENDER_TEXTURE_DESC rtDesc;
  546. rtDesc.colorSurfaces[0].texture = volumeIndices->texture;
  547. rtDesc.depthStencilSurface.texture = depthTex->texture;
  548. SPtr<RenderTexture> rt = RenderTexture::create(rtDesc);
  549. RenderAPI& rapi = RenderAPI::instance();
  550. rapi.setRenderTarget(rt);
  551. rapi.clearRenderTarget(FBT_COLOR | FBT_DEPTH);
  552. TetrahedraRenderMat* renderTetrahedra = TetrahedraRenderMat::getVariation(viewProps.numSamples > 1);
  553. renderTetrahedra->execute(inputs.view, sceneDepthNode->depthTex->texture, volumeMesh, rt);
  554. rt = nullptr;
  555. resPool.release(depthTex);
  556. evaluateMat = IrradianceEvaluateMat::getVariation(viewProps.numSamples, false);
  557. }
  558. else // Sky only
  559. {
  560. evaluateMat = IrradianceEvaluateMat::getVariation(viewProps.numSamples, true);
  561. }
  562. GBufferTextures gbuffer;
  563. gbuffer.albedo = gbufferNode->albedoTex->texture;
  564. gbuffer.normals = gbufferNode->normalTex->texture;
  565. gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  566. gbuffer.depth = sceneDepthNode->depthTex->texture;
  567. SPtr<Texture> volumeIndicesTex;
  568. if (volumeIndices)
  569. volumeIndicesTex = volumeIndices->texture;
  570. evaluateMat->execute(inputs.view, gbuffer, volumeIndicesTex, shCoeffs, volumeInfos, inputs.scene.skybox,
  571. lightAccumNode->renderTarget);
  572. if(volumeIndices)
  573. resPool.release(volumeIndices);
  574. }
  575. void RCNodeIndirectLighting::clear()
  576. {
  577. // Do nothing
  578. }
  579. SmallVector<StringID, 4> RCNodeIndirectLighting::getDependencies(const RendererView& view)
  580. {
  581. SmallVector<StringID, 4> deps;
  582. deps.push_back(RCNodeGBuffer::getNodeId());
  583. deps.push_back(RCNodeSceneDepth::getNodeId());
  584. deps.push_back(RCNodeLightAccumulation::getNodeId());
  585. deps.push_back(RCNodeStandardDeferredLighting::getNodeId());
  586. if (view.getProperties().numSamples > 1)
  587. deps.push_back(RCNodeUnflattenLightAccum::getNodeId());
  588. return deps;
  589. }
  590. void RCNodeTiledDeferredIBL::render(const RenderCompositorNodeInputs& inputs)
  591. {
  592. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  593. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  594. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[2]);
  595. RCNodeLightAccumulation* lightAccumNode = static_cast <RCNodeLightAccumulation*>(inputs.inputNodes[3]);
  596. const RendererViewProperties& viewProps = inputs.view.getProperties();
  597. TiledDeferredImageBasedLightingMat* material = TiledDeferredImageBasedLightingMat::getVariation(viewProps.numSamples);
  598. TiledDeferredImageBasedLightingMat::Inputs iblInputs;
  599. iblInputs.gbuffer.albedo = gbufferNode->albedoTex->texture;
  600. iblInputs.gbuffer.normals = gbufferNode->normalTex->texture;
  601. iblInputs.gbuffer.roughMetal = gbufferNode->roughMetalTex->texture;
  602. iblInputs.gbuffer.depth = sceneDepthNode->depthTex->texture;
  603. iblInputs.sceneColorTex = sceneColorNode->sceneColorTex->texture;
  604. iblInputs.lightAccumulation = lightAccumNode->lightAccumulationTex->texture;
  605. iblInputs.preIntegratedGF = RendererTextures::preintegratedEnvGF;
  606. if(sceneColorNode->flattenedSceneColorBuffer)
  607. iblInputs.sceneColorBuffer = sceneColorNode->flattenedSceneColorBuffer->buffer;
  608. material->execute(inputs.view, inputs.scene, inputs.viewGroup.getVisibleReflProbeData(), iblInputs);
  609. }
  610. void RCNodeTiledDeferredIBL::clear()
  611. {
  612. output = nullptr;
  613. }
  614. SmallVector<StringID, 4> RCNodeTiledDeferredIBL::getDependencies(const RendererView& view)
  615. {
  616. SmallVector<StringID, 4> deps;
  617. deps.push_back(RCNodeSceneColor::getNodeId());
  618. deps.push_back(RCNodeGBuffer::getNodeId());
  619. deps.push_back(RCNodeSceneDepth::getNodeId());
  620. deps.push_back(RCNodeLightAccumulation::getNodeId());
  621. deps.push_back(RCNodeIndirectLighting::getNodeId());
  622. return deps;
  623. }
  624. void RCNodeUnflattenSceneColor::render(const RenderCompositorNodeInputs& inputs)
  625. {
  626. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  627. FlatFramebufferToTextureMat* material = FlatFramebufferToTextureMat::get();
  628. int readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
  629. RenderAPI& rapi = RenderAPI::instance();
  630. rapi.setRenderTarget(sceneColorNode->renderTarget, readOnlyFlags, RT_COLOR0 | RT_DEPTH_STENCIL);
  631. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  632. rapi.setViewport(area);
  633. material->execute(sceneColorNode->flattenedSceneColorBuffer->buffer, sceneColorNode->sceneColorTex->texture);
  634. }
  635. void RCNodeUnflattenSceneColor::clear()
  636. {
  637. output = nullptr;
  638. }
  639. void RCNodeClusteredForward::render(const RenderCompositorNodeInputs& inputs)
  640. {
  641. const SceneInfo& sceneInfo = inputs.scene;
  642. const RendererViewProperties& viewProps = inputs.view.getProperties();
  643. const VisibleLightData& visibleLightData = inputs.viewGroup.getVisibleLightData();
  644. const VisibleReflProbeData& visibleReflProbeData = inputs.viewGroup.getVisibleReflProbeData();
  645. const LightGrid& lightGrid = inputs.view.getLightGrid();
  646. SPtr<GpuParamBlockBuffer> gridParams;
  647. SPtr<GpuBuffer> gridLightOffsetsAndSize, gridLightIndices;
  648. SPtr<GpuBuffer> gridProbeOffsetsAndSize, gridProbeIndices;
  649. lightGrid.getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices,
  650. gridParams);
  651. // Prepare refl. probe param buffer
  652. ReflProbeParamBuffer reflProbeParamBuffer;
  653. reflProbeParamBuffer.populate(sceneInfo.skybox, visibleReflProbeData, sceneInfo.reflProbeCubemapsTex,
  654. viewProps.renderingReflections);
  655. SPtr<Texture> skyFilteredRadiance;
  656. if(sceneInfo.skybox)
  657. skyFilteredRadiance = sceneInfo.skybox->getFilteredRadiance();
  658. // Prepare objects for rendering
  659. const VisibilityInfo& visibility = inputs.view.getVisibilityMasks();
  660. UINT32 numRenderables = (UINT32)sceneInfo.renderables.size();
  661. for (UINT32 i = 0; i < numRenderables; i++)
  662. {
  663. if (!visibility.renderables[i])
  664. continue;
  665. for (auto& element : sceneInfo.renderables[i]->elements)
  666. {
  667. bool isTransparent = (element.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
  668. if (!isTransparent)
  669. continue;
  670. // Note: It would be nice to be able to set this once and keep it, only updating if the buffers actually
  671. // change (e.g. when growing). Although technically the internal systems should be smart enough to
  672. // avoid updates unless objects actually changed.
  673. if (element.gridParamsBindingIdx != -1)
  674. element.params->setParamBlockBuffer(element.gridParamsBindingIdx, gridParams, true);
  675. element.gridLightOffsetsAndSizeParam.set(gridLightOffsetsAndSize);
  676. element.gridLightIndicesParam.set(gridLightIndices);
  677. element.lightsBufferParam.set(visibleLightData.getLightBuffer());
  678. // Image based lighting params
  679. ImageBasedLightingParams& iblParams = element.imageBasedParams;
  680. if (iblParams.reflProbeParamsBindingIdx != -1)
  681. element.params->setParamBlockBuffer(iblParams.reflProbeParamsBindingIdx, reflProbeParamBuffer.buffer);
  682. element.gridProbeOffsetsAndSizeParam.set(gridProbeOffsetsAndSize);
  683. iblParams.reflectionProbeIndicesParam.set(gridProbeIndices);
  684. iblParams.reflectionProbesParam.set(visibleReflProbeData.getProbeBuffer());
  685. iblParams.skyReflectionsTexParam.set(skyFilteredRadiance);
  686. iblParams.reflectionProbeCubemapsTexParam.set(sceneInfo.reflProbeCubemapsTex);
  687. iblParams.preintegratedEnvBRDFParam.set(RendererTextures::preintegratedEnvGF);
  688. }
  689. }
  690. // TODO: Transparent objects cannot receive shadows. In order to support this I'd have to render the light occlusion
  691. // for all lights affecting this object into a single (or a few) textures. I can likely use texture arrays for this,
  692. // or to avoid sampling many textures, perhaps just jam it all in one or few texture channels.
  693. const Vector<RenderQueueElement>& transparentElements = inputs.view.getTransparentQueue()->getSortedElements();
  694. for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
  695. {
  696. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  697. SPtr<Material> material = renderElem->material;
  698. if (iter->applyPass)
  699. gRendererUtility().setPass(material, iter->passIdx, renderElem->techniqueIdx);
  700. gRendererUtility().setPassParams(renderElem->params, iter->passIdx);
  701. if(renderElem->morphVertexDeclaration == nullptr)
  702. gRendererUtility().draw(renderElem->mesh, renderElem->subMesh);
  703. else
  704. gRendererUtility().drawMorph(renderElem->mesh, renderElem->subMesh, renderElem->morphShapeBuffer,
  705. renderElem->morphVertexDeclaration);
  706. }
  707. // Trigger post-lighting callbacks
  708. Camera* sceneCamera = inputs.view.getSceneCamera();
  709. if (sceneCamera != nullptr)
  710. {
  711. for(auto& extension : inputs.extPostLighting)
  712. {
  713. if (extension->check(*sceneCamera))
  714. extension->render(*sceneCamera);
  715. }
  716. }
  717. }
  718. void RCNodeClusteredForward::clear()
  719. {
  720. // Do nothing
  721. }
  722. SmallVector<StringID, 4> RCNodeClusteredForward::getDependencies(const RendererView& view)
  723. {
  724. return { RCNodeSceneColor::getNodeId(), RCNodeSkybox::getNodeId() };
  725. }
  726. SmallVector<StringID, 4> RCNodeUnflattenSceneColor::getDependencies(const RendererView& view)
  727. {
  728. return { RCNodeSceneColor::getNodeId() };
  729. }
  730. void RCNodeSkybox::render(const RenderCompositorNodeInputs& inputs)
  731. {
  732. Skybox* skybox = inputs.scene.skybox;
  733. SPtr<Texture> radiance = skybox ? skybox->getTexture() : nullptr;
  734. if (radiance != nullptr)
  735. {
  736. SkyboxMat* material = SkyboxMat::getVariation(false);
  737. material->bind(inputs.view.getPerViewBuffer());
  738. material->setParams(radiance, Color::White);
  739. }
  740. else
  741. {
  742. Color clearColor = inputs.view.getProperties().clearColor;
  743. SkyboxMat* material = SkyboxMat::getVariation(true);
  744. material->bind(inputs.view.getPerViewBuffer());
  745. material->setParams(nullptr, clearColor);
  746. }
  747. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[1]);
  748. int readOnlyFlags = FBT_DEPTH | FBT_STENCIL;
  749. RenderAPI& rapi = RenderAPI::instance();
  750. rapi.setRenderTarget(sceneColorNode->renderTarget, readOnlyFlags, RT_COLOR0 | RT_DEPTH_STENCIL);
  751. Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
  752. rapi.setViewport(area);
  753. SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
  754. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  755. }
  756. void RCNodeSkybox::clear()
  757. { }
  758. SmallVector<StringID, 4> RCNodeSkybox::getDependencies(const RendererView& view)
  759. {
  760. SmallVector<StringID, 4> deps;
  761. deps.push_back(RCNodeTiledDeferredIBL::getNodeId());
  762. deps.push_back(RCNodeSceneColor::getNodeId());
  763. if (view.getProperties().numSamples > 1)
  764. deps.push_back(RCNodeUnflattenSceneColor::getNodeId());
  765. return deps;
  766. }
  767. void RCNodeFinalResolve::render(const RenderCompositorNodeInputs& inputs)
  768. {
  769. const RendererViewProperties& viewProps = inputs.view.getProperties();
  770. SPtr<Texture> input;
  771. if(viewProps.runPostProcessing)
  772. {
  773. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[0]);
  774. // Note: Ideally the last PP effect could write directly to the final target and we could avoid this copy
  775. input = postProcessNode->getLastOutput();
  776. }
  777. else
  778. {
  779. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  780. input = sceneColorNode->sceneColorTex->texture;
  781. }
  782. SPtr<RenderTarget> target = viewProps.target;
  783. RenderAPI& rapi = RenderAPI::instance();
  784. rapi.setRenderTarget(target);
  785. rapi.setViewport(viewProps.nrmViewRect);
  786. gRendererUtility().blit(input, Rect2I::EMPTY, viewProps.flipView);
  787. // Trigger overlay callbacks
  788. Camera* sceneCamera = inputs.view.getSceneCamera();
  789. if (sceneCamera != nullptr)
  790. {
  791. for(auto& extension : inputs.extOverlay)
  792. {
  793. if (extension->check(*sceneCamera))
  794. extension->render(*sceneCamera);
  795. }
  796. }
  797. }
  798. void RCNodeFinalResolve::clear()
  799. { }
  800. SmallVector<StringID, 4> RCNodeFinalResolve::getDependencies(const RendererView& view)
  801. {
  802. const RendererViewProperties& viewProps = view.getProperties();
  803. SmallVector<StringID, 4> deps;
  804. if(viewProps.runPostProcessing)
  805. {
  806. deps.push_back(RCNodePostProcess::getNodeId());
  807. deps.push_back(RCNodeFXAA::getNodeId());
  808. }
  809. else
  810. {
  811. deps.push_back(RCNodeSceneColor::getNodeId());
  812. deps.push_back(RCNodeClusteredForward::getNodeId());
  813. }
  814. return deps;
  815. }
  816. RCNodePostProcess::RCNodePostProcess()
  817. :mOutput(), mAllocated()
  818. { }
  819. void RCNodePostProcess::getAndSwitch(const RendererView& view, SPtr<RenderTexture>& output, SPtr<Texture>& lastFrame) const
  820. {
  821. GpuResourcePool& resPool = GpuResourcePool::instance();
  822. const RendererViewProperties& viewProps = view.getProperties();
  823. UINT32 width = viewProps.viewRect.width;
  824. UINT32 height = viewProps.viewRect.height;
  825. if(!mAllocated[mCurrentIdx])
  826. {
  827. mOutput[mCurrentIdx] = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA8, width, height,
  828. TU_RENDERTARGET, 1, false));
  829. mAllocated[mCurrentIdx] = true;
  830. }
  831. output = mOutput[mCurrentIdx]->renderTexture;
  832. UINT32 otherIdx = (mCurrentIdx + 1) % 2;
  833. if (mAllocated[otherIdx])
  834. lastFrame = mOutput[otherIdx]->texture;
  835. mCurrentIdx = otherIdx;
  836. }
  837. SPtr<Texture> RCNodePostProcess::getLastOutput() const
  838. {
  839. UINT32 otherIdx = (mCurrentIdx + 1) % 2;
  840. if (mAllocated[otherIdx])
  841. return mOutput[otherIdx]->texture;
  842. return nullptr;
  843. }
  844. void RCNodePostProcess::render(const RenderCompositorNodeInputs& inputs)
  845. {
  846. // Do nothing, this is just a helper node
  847. }
  848. void RCNodePostProcess::clear()
  849. {
  850. GpuResourcePool& resPool = GpuResourcePool::instance();
  851. if (mAllocated[0])
  852. resPool.release(mOutput[0]);
  853. if (mAllocated[1])
  854. resPool.release(mOutput[1]);
  855. mAllocated[0] = false;
  856. mAllocated[1] = false;
  857. mCurrentIdx = 0;
  858. }
  859. SmallVector<StringID, 4> RCNodePostProcess::getDependencies(const RendererView& view)
  860. {
  861. return {};
  862. }
  863. RCNodeTonemapping::~RCNodeTonemapping()
  864. {
  865. GpuResourcePool& resPool = GpuResourcePool::instance();
  866. if (mTonemapLUT)
  867. resPool.release(mTonemapLUT);
  868. if (prevEyeAdaptation)
  869. resPool.release(prevEyeAdaptation);
  870. }
  871. void RCNodeTonemapping::render(const RenderCompositorNodeInputs& inputs)
  872. {
  873. GpuResourcePool& resPool = GpuResourcePool::instance();
  874. const RendererViewProperties& viewProps = inputs.view.getProperties();
  875. const RenderSettings& settings = inputs.view.getRenderSettings();
  876. RCNodeSceneColor* sceneColorNode = static_cast<RCNodeSceneColor*>(inputs.inputNodes[0]);
  877. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[2]);
  878. SPtr<Texture> sceneColor = sceneColorNode->sceneColorTex->texture;
  879. bool hdr = settings.enableHDR;
  880. bool msaa = viewProps.numSamples > 1;
  881. if(hdr && settings.enableAutoExposure)
  882. {
  883. // Downsample scene
  884. DownsampleMat* downsampleMat = DownsampleMat::getVariation(1, msaa);
  885. SPtr<PooledRenderTexture> downsampledScene = resPool.get(DownsampleMat::getOutputDesc(sceneColor));
  886. downsampleMat->execute(sceneColor, downsampledScene->renderTexture);
  887. // Generate histogram
  888. SPtr<PooledRenderTexture> eyeAdaptHistogram = resPool.get(
  889. EyeAdaptHistogramMat::getOutputDesc(downsampledScene->texture));
  890. EyeAdaptHistogramMat* eyeAdaptHistogramMat = EyeAdaptHistogramMat::get();
  891. eyeAdaptHistogramMat->execute(downsampledScene->texture, eyeAdaptHistogram->texture, settings.autoExposure);
  892. // Reduce histogram
  893. SPtr<PooledRenderTexture> reducedHistogram = resPool.get(EyeAdaptHistogramReduceMat::getOutputDesc());
  894. SPtr<Texture> prevFrameEyeAdaptation;
  895. if (prevEyeAdaptation != nullptr)
  896. prevFrameEyeAdaptation = prevEyeAdaptation->texture;
  897. EyeAdaptHistogramReduceMat* eyeAdaptHistogramReduce = EyeAdaptHistogramReduceMat::get();
  898. eyeAdaptHistogramReduce->execute(downsampledScene->texture, eyeAdaptHistogram->texture,
  899. prevFrameEyeAdaptation, reducedHistogram->renderTexture);
  900. resPool.release(downsampledScene);
  901. downsampledScene = nullptr;
  902. resPool.release(eyeAdaptHistogram);
  903. eyeAdaptHistogram = nullptr;
  904. // Generate eye adaptation value
  905. eyeAdaptation = resPool.get(EyeAdaptationMat::getOutputDesc());
  906. EyeAdaptationMat* eyeAdaptationMat = EyeAdaptationMat::get();
  907. eyeAdaptationMat->execute(reducedHistogram->texture, eyeAdaptation->renderTexture, inputs.frameInfo.timeDelta,
  908. settings.autoExposure, settings.exposureScale);
  909. resPool.release(reducedHistogram);
  910. reducedHistogram = nullptr;
  911. }
  912. else
  913. {
  914. if(prevEyeAdaptation)
  915. resPool.release(prevEyeAdaptation);
  916. prevEyeAdaptation = nullptr;
  917. eyeAdaptation = nullptr;
  918. }
  919. bool gammaOnly;
  920. bool autoExposure;
  921. if (hdr)
  922. {
  923. if (settings.enableTonemapping)
  924. {
  925. UINT64 latestHash = inputs.view.getRenderSettingsHash();
  926. bool tonemapLUTDirty = mTonemapLastUpdateHash != latestHash;
  927. if (tonemapLUTDirty) // Rebuild LUT if PP settings changed
  928. {
  929. if(mTonemapLUT == nullptr)
  930. mTonemapLUT = resPool.get(CreateTonemapLUTMat::getOutputDesc());
  931. CreateTonemapLUTMat* createLUT = CreateTonemapLUTMat::get();
  932. createLUT->execute(mTonemapLUT->texture, settings);
  933. mTonemapLastUpdateHash = latestHash;
  934. }
  935. gammaOnly = false;
  936. }
  937. else
  938. gammaOnly = true;
  939. autoExposure = settings.enableAutoExposure;
  940. }
  941. else
  942. {
  943. gammaOnly = true;
  944. autoExposure = false;
  945. }
  946. if(gammaOnly)
  947. {
  948. if(mTonemapLUT)
  949. {
  950. resPool.release(mTonemapLUT);
  951. mTonemapLUT = nullptr;
  952. }
  953. }
  954. TonemappingMat* tonemapping = TonemappingMat::getVariation(gammaOnly, autoExposure, msaa);
  955. SPtr<RenderTexture> ppOutput;
  956. SPtr<Texture> ppLastFrame;
  957. postProcessNode->getAndSwitch(inputs.view, ppOutput, ppLastFrame);
  958. SPtr<Texture> eyeAdaptationTex;
  959. if (eyeAdaptation)
  960. eyeAdaptationTex = eyeAdaptation->texture;
  961. SPtr<Texture> tonemapLUTTex;
  962. if (mTonemapLUT)
  963. tonemapLUTTex = mTonemapLUT->texture;
  964. tonemapping->execute(sceneColor, eyeAdaptationTex, tonemapLUTTex, ppOutput, settings);
  965. }
  966. void RCNodeTonemapping::clear()
  967. {
  968. GpuResourcePool& resPool = GpuResourcePool::instance();
  969. // Save eye adaptation for next frame
  970. if(prevEyeAdaptation)
  971. resPool.release(prevEyeAdaptation);
  972. std::swap(eyeAdaptation, prevEyeAdaptation);
  973. }
  974. SmallVector<StringID, 4> RCNodeTonemapping::getDependencies(const RendererView& view)
  975. {
  976. return{ RCNodeSceneColor::getNodeId(), RCNodeClusteredForward::getNodeId(), RCNodePostProcess::getNodeId() };
  977. }
  978. void RCNodeGaussianDOF::render(const RenderCompositorNodeInputs& inputs)
  979. {
  980. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[1]);
  981. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[2]);
  982. const DepthOfFieldSettings& settings = inputs.view.getRenderSettings().depthOfField;
  983. bool near = settings.nearBlurAmount > 0.0f;
  984. bool far = settings.farBlurAmount > 0.0f;
  985. bool enabled = settings.enabled && (near || far);
  986. if(!enabled)
  987. return;
  988. GaussianDOFSeparateMat* separateMat = GaussianDOFSeparateMat::getVariation(near, far);
  989. GaussianDOFCombineMat* combineMat = GaussianDOFCombineMat::getVariation(near, far);
  990. GaussianBlurMat* blurMat = GaussianBlurMat::get();
  991. SPtr<RenderTexture> ppOutput;
  992. SPtr<Texture> ppLastFrame;
  993. postProcessNode->getAndSwitch(inputs.view, ppOutput, ppLastFrame);
  994. separateMat->execute(ppLastFrame, sceneDepthNode->depthTex->texture, inputs.view, settings);
  995. SPtr<PooledRenderTexture> nearTex, farTex;
  996. if(near && far)
  997. {
  998. nearTex = separateMat->getOutput(0);
  999. farTex = separateMat->getOutput(1);
  1000. }
  1001. else
  1002. {
  1003. if (near)
  1004. nearTex = separateMat->getOutput(0);
  1005. else
  1006. farTex = separateMat->getOutput(0);
  1007. }
  1008. // Blur the out of focus pixels
  1009. // Note: Perhaps set up stencil so I can avoid performing blur on unused parts of the textures?
  1010. const TextureProperties& texProps = nearTex ? nearTex->texture->getProperties() : farTex->texture->getProperties();
  1011. POOLED_RENDER_TEXTURE_DESC tempTexDesc = POOLED_RENDER_TEXTURE_DESC::create2D(texProps.getFormat(),
  1012. texProps.getWidth(), texProps.getHeight(), TU_RENDERTARGET);
  1013. SPtr<PooledRenderTexture> tempTexture = GpuResourcePool::instance().get(tempTexDesc);
  1014. SPtr<Texture> blurredNearTex;
  1015. if(nearTex)
  1016. {
  1017. blurMat->execute(nearTex->texture, settings.nearBlurAmount, tempTexture->renderTexture);
  1018. blurredNearTex = tempTexture->texture;
  1019. }
  1020. SPtr<Texture> blurredFarTex;
  1021. if(farTex)
  1022. {
  1023. // If temporary texture is used up, re-use the original near texture for the blurred result
  1024. if(blurredNearTex)
  1025. {
  1026. blurMat->execute(farTex->texture, settings.farBlurAmount, nearTex->renderTexture);
  1027. blurredFarTex = nearTex->texture;
  1028. }
  1029. else // Otherwise just use the temporary
  1030. {
  1031. blurMat->execute(farTex->texture, settings.farBlurAmount, tempTexture->renderTexture);
  1032. blurredFarTex = tempTexture->texture;
  1033. }
  1034. }
  1035. combineMat->execute(ppLastFrame, blurredNearTex, blurredFarTex,
  1036. sceneDepthNode->depthTex->texture, ppOutput, inputs.view, settings);
  1037. separateMat->release();
  1038. GpuResourcePool::instance().release(tempTexture);
  1039. }
  1040. void RCNodeGaussianDOF::clear()
  1041. {
  1042. // Do nothing
  1043. }
  1044. SmallVector<StringID, 4> RCNodeGaussianDOF::getDependencies(const RendererView& view)
  1045. {
  1046. return { RCNodeTonemapping::getNodeId(), RCNodeSceneDepth::getNodeId(), RCNodePostProcess::getNodeId() };
  1047. }
  1048. void RCNodeFXAA::render(const RenderCompositorNodeInputs& inputs)
  1049. {
  1050. const RenderSettings& settings = inputs.view.getRenderSettings();
  1051. if (!settings.enableFXAA)
  1052. return;
  1053. RCNodePostProcess* postProcessNode = static_cast<RCNodePostProcess*>(inputs.inputNodes[1]);
  1054. SPtr<RenderTexture> ppOutput;
  1055. SPtr<Texture> ppLastFrame;
  1056. postProcessNode->getAndSwitch(inputs.view, ppOutput, ppLastFrame);
  1057. // Note: I could skip executing FXAA over DOF and motion blurred pixels
  1058. FXAAMat* fxaa = FXAAMat::get();
  1059. fxaa->execute(ppLastFrame, ppOutput);
  1060. }
  1061. void RCNodeFXAA::clear()
  1062. {
  1063. // Do nothing
  1064. }
  1065. SmallVector<StringID, 4> RCNodeFXAA::getDependencies(const RendererView& view)
  1066. {
  1067. return { RCNodeGaussianDOF::getNodeId(), RCNodePostProcess::getNodeId() };
  1068. }
  1069. void RCNodeResolvedSceneDepth::render(const RenderCompositorNodeInputs& inputs)
  1070. {
  1071. GpuResourcePool& resPool = GpuResourcePool::instance();
  1072. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1073. RCNodeSceneDepth* sceneDepthNode = static_cast<RCNodeSceneDepth*>(inputs.inputNodes[0]);
  1074. if (viewProps.numSamples > 1)
  1075. {
  1076. UINT32 width = viewProps.viewRect.width;
  1077. UINT32 height = viewProps.viewRect.height;
  1078. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_D32, width, height, TU_RENDERTARGET, 1, false));
  1079. RenderAPI& rapi = RenderAPI::instance();
  1080. rapi.setRenderTarget(output->renderTexture);
  1081. gRendererUtility().blit(sceneDepthNode->depthTex->texture, Rect2I::EMPTY, false, true);
  1082. mPassThrough = false;
  1083. }
  1084. else
  1085. {
  1086. output = sceneDepthNode->depthTex;
  1087. mPassThrough = true;
  1088. }
  1089. }
  1090. void RCNodeResolvedSceneDepth::clear()
  1091. {
  1092. GpuResourcePool& resPool = GpuResourcePool::instance();
  1093. if (!mPassThrough)
  1094. resPool.release(output);
  1095. else
  1096. output = nullptr;
  1097. mPassThrough = false;
  1098. }
  1099. SmallVector<StringID, 4> RCNodeResolvedSceneDepth::getDependencies(const RendererView& view)
  1100. {
  1101. // GBuffer require because it renders the base pass (populates the depth buffer)
  1102. return { RCNodeSceneDepth::getNodeId(), RCNodeGBuffer::getNodeId() };
  1103. }
  1104. void RCNodeHiZ::render(const RenderCompositorNodeInputs& inputs)
  1105. {
  1106. GpuResourcePool& resPool = GpuResourcePool::instance();
  1107. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1108. RCNodeResolvedSceneDepth* resolvedSceneDepth = static_cast<RCNodeResolvedSceneDepth*>(inputs.inputNodes[0]);
  1109. UINT32 width = viewProps.viewRect.width;
  1110. UINT32 height = viewProps.viewRect.height;
  1111. UINT32 size = Bitwise::nextPow2(std::max(width, height));
  1112. UINT32 numMips = PixelUtil::getMaxMipmaps(size, size, 1, PF_R32F);
  1113. size = 1 << numMips;
  1114. // Note: Use the 32-bit buffer here as 16-bit causes too much banding (most of the scene gets assigned 4-5 different
  1115. // depth values).
  1116. // - When I add UNORM 16-bit format I should be able to switch to that
  1117. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R32F, size, size, TU_RENDERTARGET, 1, false, 1,
  1118. numMips));
  1119. Rect2 srcRect = viewProps.nrmViewRect;
  1120. // If viewport size is odd, adjust UV
  1121. srcRect.width += (viewProps.viewRect.width % 2) * (1.0f / viewProps.viewRect.width);
  1122. srcRect.height += (viewProps.viewRect.height % 2) * (1.0f / viewProps.viewRect.height);
  1123. // Generate first mip
  1124. RENDER_TEXTURE_DESC rtDesc;
  1125. rtDesc.colorSurfaces[0].texture = output->texture;
  1126. rtDesc.colorSurfaces[0].mipLevel = 0;
  1127. SPtr<RenderTexture> rt = RenderTexture::create(rtDesc);
  1128. Rect2 destRect;
  1129. bool downsampledFirstMip = false; // Not used currently
  1130. if (downsampledFirstMip)
  1131. {
  1132. // Make sure that 1 pixel in HiZ maps to a 2x2 block in source
  1133. destRect = Rect2(0, 0,
  1134. Math::ceilToInt(viewProps.viewRect.width / 2.0f) / (float)size,
  1135. Math::ceilToInt(viewProps.viewRect.height / 2.0f) / (float)size);
  1136. BuildHiZMat* material = BuildHiZMat::get();
  1137. material->execute(resolvedSceneDepth->output->texture, 0, srcRect, destRect, rt);
  1138. }
  1139. else // First level is just a copy of the depth buffer
  1140. {
  1141. destRect = Rect2(0, 0,
  1142. viewProps.viewRect.width / (float)size,
  1143. viewProps.viewRect.height / (float)size);
  1144. RenderAPI& rapi = RenderAPI::instance();
  1145. rapi.setRenderTarget(rt);
  1146. rapi.setViewport(destRect);
  1147. Rect2I srcAreaInt;
  1148. srcAreaInt.x = (INT32)(srcRect.x * viewProps.viewRect.width);
  1149. srcAreaInt.y = (INT32)(srcRect.y * viewProps.viewRect.height);
  1150. srcAreaInt.width = (UINT32)(srcRect.width * viewProps.viewRect.width);
  1151. srcAreaInt.height = (UINT32)(srcRect.height * viewProps.viewRect.height);
  1152. gRendererUtility().blit(resolvedSceneDepth->output->texture, srcAreaInt);
  1153. rapi.setViewport(Rect2(0, 0, 1, 1));
  1154. }
  1155. // Generate remaining mip levels
  1156. for(UINT32 i = 1; i <= numMips; i++)
  1157. {
  1158. rtDesc.colorSurfaces[0].mipLevel = i;
  1159. rt = RenderTexture::create(rtDesc);
  1160. BuildHiZMat* material = BuildHiZMat::get();
  1161. material->execute(output->texture, i - 1, destRect, destRect, rt);
  1162. }
  1163. }
  1164. void RCNodeHiZ::clear()
  1165. {
  1166. GpuResourcePool& resPool = GpuResourcePool::instance();
  1167. resPool.release(output);
  1168. }
  1169. SmallVector<StringID, 4> RCNodeHiZ::getDependencies(const RendererView& view)
  1170. {
  1171. // Note: This doesn't actually use any gbuffer textures, but node is a dependency because it renders to the depth
  1172. // buffer. In order to avoid keeping gbuffer textures alive I could separate out the base pass into its own node
  1173. // perhaps. But at the moment it doesn't matter, as anything using HiZ also needs gbuffer.
  1174. return { RCNodeResolvedSceneDepth::getNodeId(), RCNodeGBuffer::getNodeId() };
  1175. }
  1176. void RCNodeSSAO::render(const RenderCompositorNodeInputs& inputs)
  1177. {
  1178. /** Maximum valid depth range within samples in a sample set. In meters. */
  1179. static const float DEPTH_RANGE = 1.0f;
  1180. GpuResourcePool& resPool = GpuResourcePool::instance();
  1181. const RendererViewProperties& viewProps = inputs.view.getProperties();
  1182. const AmbientOcclusionSettings& settings = inputs.view.getRenderSettings().ambientOcclusion;
  1183. RCNodeResolvedSceneDepth* resolvedDepthNode = static_cast<RCNodeResolvedSceneDepth*>(inputs.inputNodes[0]);
  1184. RCNodeGBuffer* gbufferNode = static_cast<RCNodeGBuffer*>(inputs.inputNodes[1]);
  1185. SPtr<Texture> sceneDepth = resolvedDepthNode->output->texture;
  1186. SPtr<Texture> sceneNormals = gbufferNode->normalTex->texture;
  1187. const TextureProperties& normalsProps = sceneNormals->getProperties();
  1188. SPtr<PooledRenderTexture> resolvedNormals;
  1189. RenderAPI& rapi = RenderAPI::instance();
  1190. if(sceneNormals->getProperties().getNumSamples() > 1)
  1191. {
  1192. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(normalsProps.getFormat(),
  1193. normalsProps.getWidth(), normalsProps.getHeight(), TU_RENDERTARGET);
  1194. resolvedNormals = resPool.get(desc);
  1195. rapi.setRenderTarget(resolvedNormals->renderTexture);
  1196. gRendererUtility().blit(sceneNormals);
  1197. sceneNormals = resolvedNormals->texture;
  1198. }
  1199. // Multiple downsampled AO levels are used to minimize cache trashing. Downsampled AO targets use larger radius,
  1200. // whose contents are then blended with the higher level.
  1201. UINT32 quality = settings.quality;
  1202. UINT32 numDownsampleLevels = 0;
  1203. if (quality > 1)
  1204. numDownsampleLevels = 1;
  1205. else if (quality > 2)
  1206. numDownsampleLevels = 2;
  1207. SSAODownsampleMat* downsample = SSAODownsampleMat::get();
  1208. SPtr<PooledRenderTexture> setupTex0;
  1209. if(numDownsampleLevels > 0)
  1210. {
  1211. Vector2I downsampledSize(
  1212. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 2)),
  1213. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 2))
  1214. );
  1215. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, downsampledSize.x,
  1216. downsampledSize.y, TU_RENDERTARGET);
  1217. setupTex0 = GpuResourcePool::instance().get(desc);
  1218. downsample->execute(inputs.view, sceneDepth, sceneNormals, setupTex0->renderTexture, DEPTH_RANGE);
  1219. }
  1220. SPtr<PooledRenderTexture> setupTex1;
  1221. if(numDownsampleLevels > 1)
  1222. {
  1223. Vector2I downsampledSize(
  1224. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 4)),
  1225. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 4))
  1226. );
  1227. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_RGBA16F, downsampledSize.x,
  1228. downsampledSize.y, TU_RENDERTARGET);
  1229. setupTex1 = GpuResourcePool::instance().get(desc);
  1230. downsample->execute(inputs.view, sceneDepth, sceneNormals, setupTex1->renderTexture, DEPTH_RANGE);
  1231. }
  1232. SSAOTextureInputs textures;
  1233. textures.sceneDepth = sceneDepth;
  1234. textures.sceneNormals = sceneNormals;
  1235. textures.randomRotations = RendererTextures::ssaoRandomization4x4;
  1236. SPtr<PooledRenderTexture> downAOTex1;
  1237. if(numDownsampleLevels > 1)
  1238. {
  1239. textures.aoSetup = setupTex1->texture;
  1240. Vector2I downsampledSize(
  1241. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 4)),
  1242. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 4))
  1243. );
  1244. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, downsampledSize.x,
  1245. downsampledSize.y, TU_RENDERTARGET);
  1246. downAOTex1 = GpuResourcePool::instance().get(desc);
  1247. SSAOMat* ssaoMat = SSAOMat::getVariation(false, false, quality);
  1248. ssaoMat->execute(inputs.view, textures, downAOTex1->renderTexture, settings);
  1249. GpuResourcePool::instance().release(setupTex1);
  1250. setupTex1 = nullptr;
  1251. }
  1252. SPtr<PooledRenderTexture> downAOTex0;
  1253. if(numDownsampleLevels > 0)
  1254. {
  1255. textures.aoSetup = setupTex0->texture;
  1256. if(downAOTex1)
  1257. textures.aoDownsampled = downAOTex1->texture;
  1258. Vector2I downsampledSize(
  1259. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.width, 2)),
  1260. std::max(1, Math::divideAndRoundUp((INT32)viewProps.viewRect.height, 2))
  1261. );
  1262. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, downsampledSize.x,
  1263. downsampledSize.y, TU_RENDERTARGET);
  1264. downAOTex0 = GpuResourcePool::instance().get(desc);
  1265. bool upsample = numDownsampleLevels > 1;
  1266. SSAOMat* ssaoMat = SSAOMat::getVariation(upsample, false, quality);
  1267. ssaoMat->execute(inputs.view, textures, downAOTex0->renderTexture, settings);
  1268. if(upsample)
  1269. {
  1270. GpuResourcePool::instance().release(downAOTex1);
  1271. downAOTex1 = nullptr;
  1272. }
  1273. }
  1274. UINT32 width = viewProps.viewRect.width;
  1275. UINT32 height = viewProps.viewRect.height;
  1276. output = resPool.get(POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, width, height, TU_RENDERTARGET));
  1277. {
  1278. if(setupTex0)
  1279. textures.aoSetup = setupTex0->texture;
  1280. if(downAOTex0)
  1281. textures.aoDownsampled = downAOTex0->texture;
  1282. bool upsample = numDownsampleLevels > 0;
  1283. SSAOMat* ssaoMat = SSAOMat::getVariation(upsample, true, quality);
  1284. ssaoMat->execute(inputs.view, textures, output->renderTexture, settings);
  1285. }
  1286. if(resolvedNormals)
  1287. {
  1288. GpuResourcePool::instance().release(resolvedNormals);
  1289. resolvedNormals = nullptr;
  1290. }
  1291. if(numDownsampleLevels > 0)
  1292. {
  1293. GpuResourcePool::instance().release(setupTex0);
  1294. GpuResourcePool::instance().release(downAOTex0);
  1295. }
  1296. // Blur the output
  1297. // Note: If I implement temporal AA then this can probably be avoided. I can instead jitter the sample offsets
  1298. // each frame, and averaging them out should yield blurred AO.
  1299. if(quality > 1) // On level 0 we don't blur at all, on level 1 we use the ad-hoc blur in shader
  1300. {
  1301. const RenderTargetProperties& rtProps = output->renderTexture->getProperties();
  1302. POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8, rtProps.getWidth(),
  1303. rtProps.getHeight(), TU_RENDERTARGET);
  1304. SPtr<PooledRenderTexture> blurIntermediateTex = GpuResourcePool::instance().get(desc);
  1305. SSAOBlurMat* blurHorz = SSAOBlurMat::getVariation(true);
  1306. SSAOBlurMat* blurVert = SSAOBlurMat::getVariation(false);
  1307. blurHorz->execute(inputs.view, output->texture, sceneDepth, blurIntermediateTex->renderTexture, DEPTH_RANGE);
  1308. blurVert->execute(inputs.view, blurIntermediateTex->texture, sceneDepth, output->renderTexture, DEPTH_RANGE);
  1309. GpuResourcePool::instance().release(blurIntermediateTex);
  1310. }
  1311. }
  1312. void RCNodeSSAO::clear()
  1313. {
  1314. GpuResourcePool& resPool = GpuResourcePool::instance();
  1315. resPool.release(output);
  1316. }
  1317. SmallVector<StringID, 4> RCNodeSSAO::getDependencies(const RendererView& view)
  1318. {
  1319. return { RCNodeResolvedSceneDepth::getNodeId(), RCNodeGBuffer::getNodeId() };
  1320. }
  1321. }}