Renderer.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/renderer/Renderer.h>
  6. #include <anki/renderer/RenderQueue.h>
  7. #include <anki/core/Trace.h>
  8. #include <anki/misc/ConfigSet.h>
  9. #include <anki/renderer/Indirect.h>
  10. #include <anki/renderer/GBuffer.h>
  11. #include <anki/renderer/LightShading.h>
  12. #include <anki/renderer/ShadowMapping.h>
  13. #include <anki/renderer/FinalComposite.h>
  14. #include <anki/renderer/Ssao.h>
  15. #include <anki/renderer/Bloom.h>
  16. #include <anki/renderer/Tonemapping.h>
  17. #include <anki/renderer/ForwardShading.h>
  18. #include <anki/renderer/LensFlare.h>
  19. #include <anki/renderer/Dbg.h>
  20. #include <anki/renderer/DownscaleBlur.h>
  21. #include <anki/renderer/Volumetric.h>
  22. #include <anki/renderer/DepthDownscale.h>
  23. #include <anki/renderer/TemporalAA.h>
  24. namespace anki
  25. {
  26. static Bool threadWillDoWork(PtrSize problemSize, U32 threadId, PtrSize threadCount)
  27. {
  28. PtrSize start, end;
  29. ThreadPoolTask::choseStartEnd(threadId, threadCount, problemSize, start, end);
  30. return start != end;
  31. }
  32. Renderer::Renderer()
  33. : m_sceneDrawer(this)
  34. {
  35. }
  36. Renderer::~Renderer()
  37. {
  38. }
  39. Error Renderer::init(ThreadPool* threadpool,
  40. ResourceManager* resources,
  41. GrManager* gl,
  42. StagingGpuMemoryManager* stagingMem,
  43. HeapAllocator<U8> alloc,
  44. StackAllocator<U8> frameAlloc,
  45. const ConfigSet& config,
  46. Timestamp* globTimestamp,
  47. Bool willDrawToDefaultFbo)
  48. {
  49. ANKI_TRACE_SCOPED_EVENT(RENDERER_INIT);
  50. m_globTimestamp = globTimestamp;
  51. m_threadpool = threadpool;
  52. m_resources = resources;
  53. m_gr = gl;
  54. m_stagingMem = stagingMem;
  55. m_alloc = alloc;
  56. m_frameAlloc = frameAlloc;
  57. m_willDrawToDefaultFbo = willDrawToDefaultFbo;
  58. Error err = initInternal(config);
  59. if(err)
  60. {
  61. ANKI_R_LOGE("Failed to initialize the renderer");
  62. }
  63. return err;
  64. }
  65. Error Renderer::initInternal(const ConfigSet& config)
  66. {
  67. // Set from the config
  68. m_width = config.getNumber("width");
  69. m_height = config.getNumber("height");
  70. ANKI_R_LOGI("Initializing offscreen renderer. Size %ux%u", m_width, m_height);
  71. ANKI_ASSERT(m_lodDistances.getSize() == 2);
  72. m_lodDistances[0] = config.getNumber("r.lodDistance0");
  73. m_lodDistances[1] = config.getNumber("r.lodDistance1");
  74. m_frameCount = 0;
  75. m_tessellation = config.getNumber("tessellation");
  76. // A few sanity checks
  77. if(m_width < 10 || m_height < 10)
  78. {
  79. ANKI_R_LOGE("Incorrect sizes");
  80. return Error::USER_DATA;
  81. }
  82. {
  83. TextureInitInfo texinit;
  84. texinit.m_width = texinit.m_height = 4;
  85. texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT;
  86. texinit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
  87. texinit.m_usageWhenEncountered = TextureUsageBit::SAMPLED_FRAGMENT;
  88. texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
  89. m_dummyTex = getGrManager().newInstance<Texture>(texinit);
  90. }
  91. m_dummyBuff = getGrManager().newInstance<Buffer>(
  92. getDummyBufferSize(), BufferUsageBit::UNIFORM_ALL | BufferUsageBit::STORAGE_ALL, BufferMapAccessBit::NONE);
  93. // Init the stages. Careful with the order!!!!!!!!!!
  94. m_indirect.reset(m_alloc.newInstance<Indirect>(this));
  95. ANKI_CHECK(m_indirect->init(config));
  96. m_gbuffer.reset(m_alloc.newInstance<GBuffer>(this));
  97. ANKI_CHECK(m_gbuffer->init(config));
  98. m_shadowMapping.reset(m_alloc.newInstance<ShadowMapping>(this));
  99. ANKI_CHECK(m_shadowMapping->init(config));
  100. m_lightShading.reset(m_alloc.newInstance<LightShading>(this));
  101. ANKI_CHECK(m_lightShading->init(config));
  102. m_depth.reset(m_alloc.newInstance<DepthDownscale>(this));
  103. ANKI_CHECK(m_depth->init(config));
  104. m_vol.reset(m_alloc.newInstance<Volumetric>(this));
  105. ANKI_CHECK(m_vol->init(config));
  106. m_forwardShading.reset(m_alloc.newInstance<ForwardShading>(this));
  107. ANKI_CHECK(m_forwardShading->init(config));
  108. m_lensFlare.reset(m_alloc.newInstance<LensFlare>(this));
  109. ANKI_CHECK(m_lensFlare->init(config));
  110. m_ssao.reset(m_alloc.newInstance<Ssao>(this));
  111. ANKI_CHECK(m_ssao->init(config));
  112. m_downscale.reset(getAllocator().newInstance<DownscaleBlur>(this));
  113. ANKI_CHECK(m_downscale->init(config));
  114. m_tonemapping.reset(getAllocator().newInstance<Tonemapping>(this));
  115. ANKI_CHECK(m_tonemapping->init(config));
  116. m_temporalAA.reset(getAllocator().newInstance<TemporalAA>(this));
  117. ANKI_CHECK(m_temporalAA->init(config));
  118. m_bloom.reset(m_alloc.newInstance<Bloom>(this));
  119. ANKI_CHECK(m_bloom->init(config));
  120. m_finalComposite.reset(m_alloc.newInstance<FinalComposite>(this));
  121. ANKI_CHECK(m_finalComposite->init(config));
  122. m_dbg.reset(m_alloc.newInstance<Dbg>(this));
  123. ANKI_CHECK(m_dbg->init(config));
  124. SamplerInitInfo sinit;
  125. sinit.m_repeat = false;
  126. sinit.m_minMagFilter = SamplingFilter::NEAREST;
  127. m_nearestSampler = m_gr->newInstance<Sampler>(sinit);
  128. sinit.m_minMagFilter = SamplingFilter::LINEAR;
  129. m_linearSampler = m_gr->newInstance<Sampler>(sinit);
  130. initJitteredMats();
  131. m_rgraph = m_gr->newInstance<RenderGraph>();
  132. return Error::NONE;
  133. }
  134. void Renderer::initJitteredMats()
  135. {
  136. static const Array<Vec2, 16> SAMPLE_LOCS_16 = {{Vec2(-8.0, 0.0),
  137. Vec2(-6.0, -4.0),
  138. Vec2(-3.0, -2.0),
  139. Vec2(-2.0, -6.0),
  140. Vec2(1.0, -1.0),
  141. Vec2(2.0, -5.0),
  142. Vec2(6.0, -7.0),
  143. Vec2(5.0, -3.0),
  144. Vec2(4.0, 1.0),
  145. Vec2(7.0, 4.0),
  146. Vec2(3.0, 5.0),
  147. Vec2(0.0, 7.0),
  148. Vec2(-1.0, 3.0),
  149. Vec2(-4.0, 6.0),
  150. Vec2(-7.0, 8.0),
  151. Vec2(-5.0, 2.0)}};
  152. for(U i = 0; i < 16; ++i)
  153. {
  154. Vec2 texSize(1.0f / Vec2(m_width, m_height)); // Texel size
  155. texSize *= 2.0f; // Move it to NDC
  156. Vec2 S = SAMPLE_LOCS_16[i] / 8.0f; // In [-1, 1]
  157. Vec2 subSample = S * texSize; // In [-texSize, texSize]
  158. subSample *= 0.5f; // In [-texSize / 2, texSize / 2]
  159. m_jitteredMats16x[i] = Mat4::getIdentity();
  160. m_jitteredMats16x[i].setTranslationPart(Vec4(subSample, 0.0, 1.0));
  161. }
  162. static const Array<Vec2, 8> SAMPLE_LOCS_8 = {{Vec2(-7.0, 1.0),
  163. Vec2(-5.0, -5.0),
  164. Vec2(-1.0, -3.0),
  165. Vec2(3.0, -7.0),
  166. Vec2(5.0, -1.0),
  167. Vec2(7.0, 7.0),
  168. Vec2(1.0, 3.0),
  169. Vec2(-3.0, 5.0)}};
  170. for(U i = 0; i < 8; ++i)
  171. {
  172. Vec2 texSize(1.0f / Vec2(m_width, m_height)); // Texel size
  173. texSize *= 2.0f; // Move it to NDC
  174. Vec2 S = SAMPLE_LOCS_8[i] / 8.0f; // In [-1, 1]
  175. Vec2 subSample = S * texSize; // In [-texSize, texSize]
  176. subSample *= 0.5f; // In [-texSize / 2, texSize / 2]
  177. m_jitteredMats8x[i] = Mat4::getIdentity();
  178. m_jitteredMats8x[i].setTranslationPart(Vec4(subSample, 0.0, 1.0));
  179. }
  180. }
  181. Error Renderer::render(RenderingContext& ctx)
  182. {
  183. m_rgraph->reset();
  184. CommandBufferPtr& cmdb = ctx.m_commandBuffer;
  185. ctx.m_jitterMat = m_jitteredMats8x[m_frameCount & (8 - 1)];
  186. ctx.m_projMatJitter = ctx.m_jitterMat * ctx.m_renderQueue->m_projectionMatrix;
  187. ctx.m_viewProjMatJitter = ctx.m_projMatJitter * ctx.m_renderQueue->m_viewMatrix;
  188. ctx.m_prevViewProjMat = m_prevViewProjMat;
  189. ctx.m_prevCamTransform = m_prevCamTransform;
  190. // Check if resources got loaded
  191. if(m_prevLoadRequestCount != m_resources->getLoadingRequestCount()
  192. || m_prevAsyncTasksCompleted != m_resources->getAsyncTaskCompletedCount())
  193. {
  194. m_prevLoadRequestCount = m_resources->getLoadingRequestCount();
  195. m_prevAsyncTasksCompleted = m_resources->getAsyncTaskCompletedCount();
  196. m_resourcesDirty = true;
  197. }
  198. else
  199. {
  200. m_resourcesDirty = false;
  201. }
  202. ANKI_ASSERT(!"TODO");
  203. #if 0
  204. // Prepare SM. Do that first because it touches the render queue elements
  205. m_shadowMapping->prepareBuildCommandBuffers(ctx);
  206. // Run stages
  207. m_indirect->run(ctx);
  208. ANKI_CHECK(m_lightShading->binLights(ctx));
  209. m_lensFlare->resetOcclusionQueries(ctx, cmdb);
  210. ANKI_CHECK(buildCommandBuffers(ctx));
  211. // Barriers
  212. m_shadowMapping->setPreRunBarriers(ctx);
  213. m_gbuffer->setPreRunBarriers(ctx);
  214. // Passes & more
  215. m_shadowMapping->run(ctx);
  216. m_gbuffer->run(ctx);
  217. // Barriers
  218. m_gbuffer->setPostRunBarriers(ctx);
  219. m_shadowMapping->setPostRunBarriers(ctx);
  220. m_depth->m_hd.setPreRunBarriers(ctx);
  221. // Passes
  222. m_depth->m_hd.run(ctx);
  223. m_lensFlare->updateIndirectInfo(ctx, cmdb);
  224. // Barriers
  225. m_depth->m_hd.setPostRunBarriers(ctx);
  226. m_depth->m_qd.setPreRunBarriers(ctx);
  227. // Passes
  228. m_depth->m_qd.run(ctx);
  229. // Barriers
  230. m_depth->m_qd.setPostRunBarriers(ctx);
  231. m_vol->m_main.setPreRunBarriers(ctx);
  232. m_ssao->m_main.setPreRunBarriers(ctx);
  233. // Passes
  234. m_vol->m_main.run(ctx);
  235. m_ssao->m_main.run(ctx);
  236. // Barriers
  237. m_vol->m_main.setPostRunBarriers(ctx);
  238. m_vol->m_hblur.setPreRunBarriers(ctx);
  239. m_ssao->m_main.setPostRunBarriers(ctx);
  240. m_ssao->m_hblur.setPreRunBarriers(ctx);
  241. // Passes
  242. m_vol->m_hblur.run(ctx);
  243. m_ssao->m_hblur.run(ctx);
  244. // Barriers
  245. m_vol->m_hblur.setPostRunBarriers(ctx);
  246. m_vol->m_vblur.setPreRunBarriers(ctx);
  247. m_ssao->m_hblur.setPostRunBarriers(ctx);
  248. m_ssao->m_vblur.setPreRunBarriers(ctx);
  249. // Passes
  250. m_vol->m_vblur.run(ctx);
  251. m_ssao->m_vblur.run(ctx);
  252. // Barriers
  253. m_vol->m_vblur.setPostRunBarriers(ctx);
  254. m_ssao->m_vblur.setPostRunBarriers(ctx);
  255. m_forwardShading->setPreRunBarriers(ctx);
  256. // Passes
  257. m_forwardShading->run(ctx);
  258. // Barriers
  259. m_forwardShading->setPostRunBarriers(ctx);
  260. m_lightShading->setPreRunBarriers(ctx);
  261. // Passes
  262. m_lightShading->run(ctx);
  263. // Barriers
  264. m_lightShading->setPostRunBarriers(ctx);
  265. m_temporalAA->setPreRunBarriers(ctx);
  266. // Passes
  267. m_temporalAA->run(ctx);
  268. // Barriers
  269. m_temporalAA->setPostRunBarriers(ctx);
  270. m_downscale->setPreRunBarriers(ctx);
  271. // Passes
  272. m_downscale->run(ctx);
  273. // Barriers
  274. m_downscale->setPostRunBarriers(ctx);
  275. // Passes
  276. m_tonemapping->run(ctx);
  277. // Barriers
  278. m_bloom->m_extractExposure.setPreRunBarriers(ctx);
  279. // Passes
  280. m_bloom->m_extractExposure.run(ctx);
  281. // Barriers
  282. m_bloom->m_extractExposure.setPostRunBarriers(ctx);
  283. m_bloom->m_upscale.setPreRunBarriers(ctx);
  284. // Passes
  285. m_bloom->m_upscale.run(ctx);
  286. // Barriers
  287. m_bloom->m_upscale.setPostRunBarriers(ctx);
  288. if(m_dbg->getEnabled())
  289. {
  290. ANKI_CHECK(m_dbg->run(ctx));
  291. }
  292. // Passes
  293. ANKI_CHECK(m_finalComposite->run(ctx));
  294. #endif
  295. ++m_frameCount;
  296. m_prevViewProjMat = ctx.m_renderQueue->m_viewProjectionMatrix;
  297. m_prevCamTransform = ctx.m_renderQueue->m_cameraTransform;
  298. return Error::NONE;
  299. }
  300. Vec3 Renderer::unproject(
  301. const Vec3& windowCoords, const Mat4& modelViewMat, const Mat4& projectionMat, const int view[4])
  302. {
  303. Mat4 invPm = projectionMat * modelViewMat;
  304. invPm.invert();
  305. // the vec is in NDC space meaning: -1<=vec.x<=1 -1<=vec.y<=1 -1<=vec.z<=1
  306. Vec4 vec;
  307. vec.x() = (2.0 * (windowCoords.x() - view[0])) / view[2] - 1.0;
  308. vec.y() = (2.0 * (windowCoords.y() - view[1])) / view[3] - 1.0;
  309. vec.z() = 2.0 * windowCoords.z() - 1.0;
  310. vec.w() = 1.0;
  311. Vec4 out = invPm * vec;
  312. out /= out.w();
  313. return out.xyz();
  314. }
  315. TextureInitInfo Renderer::create2DRenderTargetInitInfo(
  316. U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, SamplingFilter filter, U mipsCount, CString name)
  317. {
  318. ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
  319. TextureInitInfo init(name);
  320. init.m_width = w;
  321. init.m_height = h;
  322. init.m_depth = 1;
  323. init.m_layerCount = 1;
  324. init.m_type = TextureType::_2D;
  325. init.m_format = format;
  326. init.m_mipmapsCount = mipsCount;
  327. init.m_samples = 1;
  328. init.m_usage = usage;
  329. init.m_sampling.m_minMagFilter = filter;
  330. if(mipsCount > 1)
  331. {
  332. init.m_sampling.m_mipmapFilter = filter;
  333. }
  334. else
  335. {
  336. init.m_sampling.m_mipmapFilter = SamplingFilter::BASE;
  337. }
  338. init.m_sampling.m_repeat = false;
  339. init.m_sampling.m_anisotropyLevel = 0;
  340. return init;
  341. }
  342. RenderTargetDescription Renderer::create2DRenderTargetDescription(
  343. U32 w, U32 h, const PixelFormat& format, TextureUsageBit usage, SamplingFilter filter, CString name)
  344. {
  345. ANKI_ASSERT(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
  346. RenderTargetDescription init(name);
  347. init.m_width = w;
  348. init.m_height = h;
  349. init.m_depth = 1;
  350. init.m_layerCount = 1;
  351. init.m_type = TextureType::_2D;
  352. init.m_format = format;
  353. init.m_mipmapsCount = 1;
  354. init.m_samples = 1;
  355. init.m_usage = usage;
  356. init.m_sampling.m_minMagFilter = filter;
  357. init.m_sampling.m_mipmapFilter = filter;
  358. init.m_sampling.m_repeat = false;
  359. init.m_sampling.m_anisotropyLevel = 0;
  360. return init;
  361. }
  362. TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, const ClearValue& clearVal)
  363. {
  364. ANKI_ASSERT(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
  365. const U faceCount = (inf.m_type == TextureType::CUBE || inf.m_type == TextureType::CUBE_ARRAY) ? 6 : 1;
  366. // Create tex
  367. TexturePtr tex = m_gr->newInstance<Texture>(inf);
  368. // Clear all surfaces
  369. CommandBufferInitInfo cmdbinit;
  370. cmdbinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
  371. if((inf.m_mipmapsCount * faceCount * inf.m_layerCount * 4) < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
  372. {
  373. cmdbinit.m_flags |= CommandBufferFlag::SMALL_BATCH;
  374. }
  375. CommandBufferPtr cmdb = m_gr->newInstance<CommandBuffer>(cmdbinit);
  376. for(U mip = 0; mip < inf.m_mipmapsCount; ++mip)
  377. {
  378. for(U face = 0; face < faceCount; ++face)
  379. {
  380. for(U layer = 0; layer < inf.m_layerCount; ++layer)
  381. {
  382. TextureSurfaceInfo surf(mip, 0, face, layer);
  383. FramebufferInitInfo fbInit;
  384. if(inf.m_format.m_components >= ComponentFormat::FIRST_DEPTH_STENCIL
  385. && inf.m_format.m_components <= ComponentFormat::LAST_DEPTH_STENCIL)
  386. {
  387. fbInit.m_depthStencilAttachment.m_texture = tex;
  388. fbInit.m_depthStencilAttachment.m_surface = surf;
  389. fbInit.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH_STENCIL;
  390. fbInit.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
  391. }
  392. else
  393. {
  394. fbInit.m_colorAttachmentCount = 1;
  395. fbInit.m_colorAttachments[0].m_texture = tex;
  396. fbInit.m_colorAttachments[0].m_surface = surf;
  397. fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
  398. fbInit.m_colorAttachments[0].m_stencilLoadOperation = AttachmentLoadOperation::CLEAR;
  399. fbInit.m_colorAttachments[0].m_clearValue = clearVal;
  400. }
  401. FramebufferPtr fb = m_gr->newInstance<Framebuffer>(fbInit);
  402. cmdb->setTextureSurfaceBarrier(
  403. tex, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, surf);
  404. cmdb->beginRenderPass(fb);
  405. cmdb->endRenderPass();
  406. if(!!inf.m_initialUsage)
  407. {
  408. cmdb->setTextureSurfaceBarrier(
  409. tex, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, inf.m_initialUsage, surf);
  410. }
  411. }
  412. }
  413. }
  414. cmdb->flush();
  415. return tex;
  416. }
  417. void Renderer::buildCommandBuffersInternal(RenderingContext& ctx, U32 threadId, PtrSize threadCount)
  418. {
  419. // G-Buffer pass
  420. //
  421. m_gbuffer->buildCommandBuffers(ctx, threadId, threadCount);
  422. // Append to the last MS's cmdb the occlusion tests
  423. if(ctx.m_gbuffer.m_lastThreadWithWork == threadId)
  424. {
  425. m_lensFlare->runOcclusionTests(ctx, ctx.m_gbuffer.m_commandBuffers[threadId]);
  426. }
  427. if(ctx.m_gbuffer.m_commandBuffers[threadId])
  428. {
  429. ctx.m_gbuffer.m_commandBuffers[threadId]->flush();
  430. }
  431. // SM
  432. //
  433. m_shadowMapping->buildCommandBuffers(ctx, threadId, threadCount);
  434. // FS
  435. //
  436. m_forwardShading->buildCommandBuffers(ctx, threadId, threadCount);
  437. // Append to the last FB's cmdb the other passes
  438. if(ctx.m_forwardShading.m_lastThreadWithWork == threadId)
  439. {
  440. m_lensFlare->run(ctx, ctx.m_forwardShading.m_commandBuffers[threadId]);
  441. m_forwardShading->drawVolumetric(ctx, ctx.m_forwardShading.m_commandBuffers[threadId]);
  442. }
  443. else if(threadId == threadCount - 1 && ctx.m_forwardShading.m_lastThreadWithWork == MAX_U32)
  444. {
  445. // There is no FS work. Create a cmdb just for LF & VOL
  446. CommandBufferInitInfo init;
  447. init.m_flags =
  448. CommandBufferFlag::GRAPHICS_WORK | CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::SMALL_BATCH;
  449. init.m_framebuffer = m_forwardShading->getFramebuffer();
  450. CommandBufferPtr cmdb = getGrManager().newInstance<CommandBuffer>(init);
  451. // Inform on textures
  452. cmdb->informTextureSurfaceCurrentUsage(m_forwardShading->getRt(),
  453. TextureSurfaceInfo(0, 0, 0, 0),
  454. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE);
  455. cmdb->informTextureSurfaceCurrentUsage(
  456. m_depth->m_hd.m_colorRt, TextureSurfaceInfo(0, 0, 0, 0), TextureUsageBit::SAMPLED_FRAGMENT);
  457. cmdb->informTextureSurfaceCurrentUsage(m_depth->m_hd.m_depthRt,
  458. TextureSurfaceInfo(0, 0, 0, 0),
  459. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE);
  460. cmdb->setViewport(0, 0, m_forwardShading->getWidth(), m_forwardShading->getHeight());
  461. m_lensFlare->run(ctx, cmdb);
  462. m_forwardShading->drawVolumetric(ctx, cmdb);
  463. ctx.m_forwardShading.m_commandBuffers[threadId] = cmdb;
  464. }
  465. if(ctx.m_forwardShading.m_commandBuffers[threadId])
  466. {
  467. ctx.m_forwardShading.m_commandBuffers[threadId]->flush();
  468. }
  469. }
  470. Error Renderer::buildCommandBuffers(RenderingContext& ctx)
  471. {
  472. ANKI_TRACE_SCOPED_EVENT(RENDERER_COMMAND_BUFFER_BUILDING);
  473. ThreadPool& threadPool = getThreadPool();
  474. // Find the last jobs for MS and FS
  475. U32 lastMsJob = MAX_U32;
  476. U32 lastFsJob = MAX_U32;
  477. const U threadCount = threadPool.getThreadsCount();
  478. for(U i = threadCount - 1; i != 0; --i)
  479. {
  480. const U gbuffProblemSize =
  481. ctx.m_renderQueue->m_renderables.getSize() + ctx.m_renderQueue->m_earlyZRenderables.getSize();
  482. if(threadWillDoWork(gbuffProblemSize, i, threadCount) && lastMsJob == MAX_U32)
  483. {
  484. lastMsJob = i;
  485. }
  486. if(threadWillDoWork(ctx.m_renderQueue->m_forwardShadingRenderables.getSize(), i, threadCount)
  487. && lastFsJob == MAX_U32)
  488. {
  489. lastFsJob = i;
  490. }
  491. }
  492. ctx.m_gbuffer.m_lastThreadWithWork = lastMsJob;
  493. ctx.m_forwardShading.m_lastThreadWithWork = lastFsJob;
  494. // Build
  495. class Task : public ThreadPoolTask
  496. {
  497. public:
  498. Renderer* m_r ANKI_DBG_NULLIFY;
  499. RenderingContext* m_ctx ANKI_DBG_NULLIFY;
  500. Error operator()(U32 threadId, PtrSize threadCount)
  501. {
  502. m_r->buildCommandBuffersInternal(*m_ctx, threadId, threadCount);
  503. return Error::NONE;
  504. }
  505. };
  506. Task task;
  507. task.m_r = this;
  508. task.m_ctx = &ctx;
  509. for(U i = 0; i < threadPool.getThreadsCount(); i++)
  510. {
  511. threadPool.assignNewTask(i, &task);
  512. }
  513. ANKI_CHECK(threadPool.waitForAllThreadsToFinish());
  514. return Error::NONE;
  515. }
  516. } // end namespace anki