Sm.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. // Copyright (C) 2009-2016, 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/Sm.h>
  6. #include <anki/renderer/Renderer.h>
  7. #include <anki/core/App.h>
  8. #include <anki/core/Trace.h>
  9. #include <anki/scene/SceneGraph.h>
  10. #include <anki/scene/Light.h>
  11. #include <anki/scene/FrustumComponent.h>
  12. #include <anki/scene/MoveComponent.h>
  13. #include <anki/misc/ConfigSet.h>
  14. #include <anki/util/ThreadPool.h>
  15. namespace anki
  16. {
  17. //==============================================================================
  18. const PixelFormat Sm::DEPTH_RT_PIXEL_FORMAT(
  19. ComponentFormat::D16, TransformFormat::FLOAT);
  20. //==============================================================================
  21. Error Sm::init(const ConfigSet& config)
  22. {
  23. m_poissonEnabled = config.getNumber("sm.poissonEnabled");
  24. m_bilinearEnabled = config.getNumber("sm.bilinearEnabled");
  25. m_resolution = config.getNumber("sm.resolution");
  26. //
  27. // Init the shadowmaps
  28. //
  29. // Create shadowmaps array
  30. TextureInitInfo sminit;
  31. sminit.m_type = TextureType::_2D_ARRAY;
  32. sminit.m_width = m_resolution;
  33. sminit.m_height = m_resolution;
  34. sminit.m_layerCount = config.getNumber("sm.maxLights");
  35. sminit.m_depth = 1;
  36. sminit.m_format = DEPTH_RT_PIXEL_FORMAT;
  37. sminit.m_mipmapsCount = 1;
  38. sminit.m_sampling.m_minMagFilter =
  39. m_bilinearEnabled ? SamplingFilter::LINEAR : SamplingFilter::NEAREST;
  40. sminit.m_sampling.m_compareOperation = CompareOperation::LESS_EQUAL;
  41. m_spotTexArray = getGrManager().newInstance<Texture>(sminit);
  42. sminit.m_type = TextureType::CUBE_ARRAY;
  43. m_omniTexArray = getGrManager().newInstance<Texture>(sminit);
  44. // Init 2D layers
  45. m_spots.create(getAllocator(), config.getNumber("sm.maxLights"));
  46. FramebufferInitInfo fbInit;
  47. fbInit.m_depthStencilAttachment.m_texture = m_spotTexArray;
  48. fbInit.m_depthStencilAttachment.m_loadOperation =
  49. AttachmentLoadOperation::CLEAR;
  50. fbInit.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0;
  51. U layer = 0;
  52. for(ShadowmapSpot& sm : m_spots)
  53. {
  54. sm.m_layerId = layer;
  55. fbInit.m_depthStencilAttachment.m_surface.m_layer = layer;
  56. sm.m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
  57. ++layer;
  58. }
  59. // Init cube layers
  60. m_omnis.create(getAllocator(), config.getNumber("sm.maxLights"));
  61. fbInit.m_depthStencilAttachment.m_texture = m_omniTexArray;
  62. layer = 0;
  63. for(ShadowmapOmni& sm : m_omnis)
  64. {
  65. sm.m_layerId = layer;
  66. for(U i = 0; i < 6; ++i)
  67. {
  68. fbInit.m_depthStencilAttachment.m_surface.m_layer = layer;
  69. fbInit.m_depthStencilAttachment.m_surface.m_face = i;
  70. sm.m_fb[i] = getGrManager().newInstance<Framebuffer>(fbInit);
  71. }
  72. ++layer;
  73. }
  74. getGrManager().finish();
  75. return ErrorCode::NONE;
  76. }
  77. //==============================================================================
  78. void Sm::run(RenderingContext& ctx)
  79. {
  80. ANKI_TRACE_START_EVENT(RENDER_SM);
  81. CommandBufferPtr& cmdb = ctx.m_commandBuffer;
  82. const U threadCount = m_r->getThreadPool().getThreadsCount();
  83. // Spot lights
  84. for(U i = 0; i < ctx.m_sm.m_spots.getSize(); ++i)
  85. {
  86. cmdb->beginRenderPass(ctx.m_sm.m_spotFramebuffers[i]);
  87. for(U j = 0; j < threadCount; ++j)
  88. {
  89. U idx = i * threadCount + j;
  90. CommandBufferPtr& cmdb2 = ctx.m_sm.m_spotCommandBuffers[idx];
  91. if(cmdb2.isCreated())
  92. {
  93. cmdb->pushSecondLevelCommandBuffer(cmdb2);
  94. }
  95. }
  96. cmdb->endRenderPass();
  97. }
  98. // Omni lights
  99. for(U i = 0; i < ctx.m_sm.m_omnis.getSize(); ++i)
  100. {
  101. for(U j = 0; j < 6; ++j)
  102. {
  103. cmdb->beginRenderPass(ctx.m_sm.m_omniFramebuffers[i][j]);
  104. for(U k = 0; k < threadCount; ++k)
  105. {
  106. U idx = i * threadCount * 6 + k * 6 + j;
  107. CommandBufferPtr& cmdb2 = ctx.m_sm.m_omniCommandBuffers[idx];
  108. if(cmdb2.isCreated())
  109. {
  110. cmdb->pushSecondLevelCommandBuffer(cmdb2);
  111. }
  112. }
  113. cmdb->endRenderPass();
  114. }
  115. }
  116. ANKI_TRACE_STOP_EVENT(RENDER_SM);
  117. }
  118. //==============================================================================
  119. template<typename TShadowmap, typename TContainer>
  120. void Sm::bestCandidate(SceneNode& light, TContainer& arr, TShadowmap*& out)
  121. {
  122. // Allready there
  123. for(TShadowmap& sm : arr)
  124. {
  125. if(&light == sm.m_light)
  126. {
  127. out = &sm;
  128. return;
  129. }
  130. }
  131. // Find a null
  132. for(TShadowmap& sm : arr)
  133. {
  134. if(sm.m_light == nullptr)
  135. {
  136. sm.m_light = &light;
  137. sm.m_timestamp = 0;
  138. out = &sm;
  139. return;
  140. }
  141. }
  142. // Find an old and replace it
  143. TShadowmap* sm = &arr[0];
  144. for(U i = 1; i < arr.getSize(); i++)
  145. {
  146. if(arr[i].m_timestamp < sm->m_timestamp)
  147. {
  148. sm = &arr[i];
  149. }
  150. }
  151. sm->m_light = &light;
  152. sm->m_timestamp = 0;
  153. out = sm;
  154. }
  155. //==============================================================================
  156. Bool Sm::skip(SceneNode& light, ShadowmapBase& sm)
  157. {
  158. MoveComponent* movc = light.tryGetComponent<MoveComponent>();
  159. Timestamp lastUpdate = movc->getTimestamp();
  160. Error err = light.iterateComponentsOfType<FrustumComponent>(
  161. [&](FrustumComponent& fr) {
  162. lastUpdate = max(lastUpdate, fr.getTimestamp());
  163. VisibilityTestResults& vi = fr.getVisibilityTestResults();
  164. lastUpdate = max(lastUpdate, vi.getShapeUpdateTimestamp());
  165. return ErrorCode::NONE;
  166. });
  167. (void)err;
  168. Bool shouldUpdate = lastUpdate >= sm.m_timestamp || m_r->resourcesLoaded();
  169. if(shouldUpdate)
  170. {
  171. sm.m_timestamp = m_r->getGlobalTimestamp();
  172. }
  173. // Update the layer ID anyway
  174. LightComponent& lcomp = light.getComponent<LightComponent>();
  175. lcomp.setShadowMapIndex(sm.m_layerId);
  176. return !shouldUpdate;
  177. }
  178. //==============================================================================
  179. Error Sm::buildCommandBuffers(
  180. RenderingContext& ctx, U threadId, U threadCount) const
  181. {
  182. ANKI_TRACE_START_EVENT(RENDER_SM);
  183. for(U i = 0; i < ctx.m_sm.m_spots.getSize(); ++i)
  184. {
  185. U idx = i * threadCount + threadId;
  186. ANKI_CHECK(doSpotLight(*ctx.m_sm.m_spots[i],
  187. ctx.m_sm.m_spotCommandBuffers[idx],
  188. ctx.m_sm.m_spotFramebuffers[i],
  189. threadId,
  190. threadCount));
  191. }
  192. for(U i = 0; i < ctx.m_sm.m_omnis.getSize(); ++i)
  193. {
  194. U idx = i * threadCount * 6 + threadId * 6 + 0;
  195. ANKI_CHECK(doOmniLight(*ctx.m_sm.m_omnis[i],
  196. &ctx.m_sm.m_omniCommandBuffers[idx],
  197. ctx.m_sm.m_omniFramebuffers[i],
  198. threadId,
  199. threadCount));
  200. }
  201. ANKI_TRACE_STOP_EVENT(RENDER_SM);
  202. return ErrorCode::NONE;
  203. }
  204. //==============================================================================
  205. Error Sm::doSpotLight(SceneNode& light,
  206. CommandBufferPtr& cmdb,
  207. FramebufferPtr& fb,
  208. U threadId,
  209. U threadCount) const
  210. {
  211. FrustumComponent& frc = light.getComponent<FrustumComponent>();
  212. VisibilityTestResults& vis = frc.getVisibilityTestResults();
  213. U problemSize = vis.getCount(VisibilityGroupType::RENDERABLES_MS);
  214. PtrSize start, end;
  215. ThreadPoolTask::choseStartEnd(
  216. threadId, threadCount, problemSize, start, end);
  217. if(start == end)
  218. {
  219. return ErrorCode::NONE;
  220. }
  221. CommandBufferInitInfo cinf;
  222. cinf.m_flags = CommandBufferFlag::SECOND_LEVEL;
  223. cinf.m_framebuffer = fb;
  224. cmdb = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
  225. cmdb->setViewport(0, 0, m_resolution, m_resolution);
  226. cmdb->setPolygonOffset(1.0, 2.0);
  227. Error err = m_r->getSceneDrawer().drawRange(Pass::SM,
  228. frc,
  229. cmdb,
  230. vis.getBegin(VisibilityGroupType::RENDERABLES_MS) + start,
  231. vis.getBegin(VisibilityGroupType::RENDERABLES_MS) + end);
  232. return err;
  233. }
  234. //==============================================================================
  235. Error Sm::doOmniLight(SceneNode& light,
  236. CommandBufferPtr cmdbs[],
  237. Array<FramebufferPtr, 6>& fbs,
  238. U threadId,
  239. U threadCount) const
  240. {
  241. U frCount = 0;
  242. Error err = light.iterateComponentsOfType<FrustumComponent>(
  243. [&](FrustumComponent& frc) -> Error {
  244. VisibilityTestResults& vis = frc.getVisibilityTestResults();
  245. U problemSize = vis.getCount(VisibilityGroupType::RENDERABLES_MS);
  246. PtrSize start, end;
  247. ThreadPoolTask::choseStartEnd(
  248. threadId, threadCount, problemSize, start, end);
  249. if(start != end)
  250. {
  251. CommandBufferInitInfo cinf;
  252. cinf.m_flags = CommandBufferFlag::SECOND_LEVEL;
  253. cinf.m_framebuffer = fbs[frCount];
  254. cmdbs[frCount] =
  255. m_r->getGrManager().newInstance<CommandBuffer>(cinf);
  256. cmdbs[frCount]->setViewport(0, 0, m_resolution, m_resolution);
  257. cmdbs[frCount]->setPolygonOffset(1.0, 2.0);
  258. ANKI_CHECK(m_r->getSceneDrawer().drawRange(Pass::SM,
  259. frc,
  260. cmdbs[frCount],
  261. vis.getBegin(VisibilityGroupType::RENDERABLES_MS) + start,
  262. vis.getBegin(VisibilityGroupType::RENDERABLES_MS) + end));
  263. }
  264. ++frCount;
  265. return ErrorCode::NONE;
  266. });
  267. return err;
  268. }
  269. //==============================================================================
  270. void Sm::prepareBuildCommandBuffers(RenderingContext& ctx)
  271. {
  272. ANKI_TRACE_START_EVENT(RENDER_SM);
  273. // Gather the lights
  274. VisibilityTestResults& vi =
  275. ctx.m_frustumComponent->getVisibilityTestResults();
  276. const U MAX = 64;
  277. Array<SceneNode*, MAX> spotCasters;
  278. Array<SceneNode*, MAX> omniCasters;
  279. U spotCastersCount = 0;
  280. U omniCastersCount = 0;
  281. auto it = vi.getBegin(VisibilityGroupType::LIGHTS_POINT);
  282. auto lend = vi.getEnd(VisibilityGroupType::LIGHTS_POINT);
  283. for(; it != lend; ++it)
  284. {
  285. SceneNode* node = (*it).m_node;
  286. LightComponent& light = node->getComponent<LightComponent>();
  287. ANKI_ASSERT(light.getLightType() == LightComponent::LightType::POINT);
  288. if(light.getShadowEnabled())
  289. {
  290. ShadowmapOmni* sm;
  291. bestCandidate(*node, m_omnis, sm);
  292. if(!skip(*node, *sm))
  293. {
  294. omniCasters[omniCastersCount++] = node;
  295. }
  296. }
  297. }
  298. it = vi.getBegin(VisibilityGroupType::LIGHTS_SPOT);
  299. lend = vi.getEnd(VisibilityGroupType::LIGHTS_SPOT);
  300. for(; it != lend; ++it)
  301. {
  302. SceneNode* node = (*it).m_node;
  303. LightComponent& light = node->getComponent<LightComponent>();
  304. ANKI_ASSERT(light.getLightType() == LightComponent::LightType::SPOT);
  305. if(light.getShadowEnabled())
  306. {
  307. ShadowmapSpot* sm;
  308. bestCandidate(*node, m_spots, sm);
  309. if(!skip(*node, *sm))
  310. {
  311. spotCasters[spotCastersCount++] = node;
  312. }
  313. }
  314. }
  315. if(omniCastersCount > m_omnis.getSize()
  316. || spotCastersCount > m_spots.getSize())
  317. {
  318. ANKI_LOGW("Too many shadow casters");
  319. omniCastersCount = min<U>(omniCastersCount, m_omnis.getSize());
  320. spotCastersCount = min<U>(spotCastersCount, m_spots.getSize());
  321. }
  322. if(spotCastersCount > 0)
  323. {
  324. ctx.m_sm.m_spots.create(spotCastersCount);
  325. memcpy(&ctx.m_sm.m_spots[0],
  326. &spotCasters[0],
  327. sizeof(SceneNode*) * spotCastersCount);
  328. ctx.m_sm.m_spotCommandBuffers.create(
  329. spotCastersCount * m_r->getThreadPool().getThreadsCount());
  330. ctx.m_sm.m_spotCacheIndices.create(spotCastersCount);
  331. #if ANKI_ASSERTIONS
  332. memset(&ctx.m_sm.m_spotCacheIndices[0],
  333. 0xFF,
  334. sizeof(ctx.m_sm.m_spotCacheIndices[0]) * spotCastersCount);
  335. #endif
  336. ctx.m_sm.m_spotFramebuffers.create(spotCastersCount);
  337. for(U i = 0; i < spotCastersCount; ++i)
  338. {
  339. const LightComponent& lightc =
  340. ctx.m_sm.m_spots[i]->getComponent<LightComponent>();
  341. U idx = lightc.getShadowMapIndex();
  342. ctx.m_sm.m_spotFramebuffers[i] = m_spots[idx].m_fb;
  343. ctx.m_sm.m_spotCacheIndices[i] = idx;
  344. }
  345. }
  346. if(omniCastersCount > 0)
  347. {
  348. ctx.m_sm.m_omnis.create(omniCastersCount);
  349. memcpy(&ctx.m_sm.m_omnis[0],
  350. &omniCasters[0],
  351. sizeof(SceneNode*) * omniCastersCount);
  352. ctx.m_sm.m_omniCommandBuffers.create(
  353. omniCastersCount * 6 * m_r->getThreadPool().getThreadsCount());
  354. ctx.m_sm.m_omniCacheIndices.create(omniCastersCount);
  355. #if ANKI_ASSERTIONS
  356. memset(&ctx.m_sm.m_omniCacheIndices[0],
  357. 0xFF,
  358. sizeof(ctx.m_sm.m_omniCacheIndices[0]) * omniCastersCount);
  359. #endif
  360. ctx.m_sm.m_omniFramebuffers.create(omniCastersCount);
  361. for(U i = 0; i < omniCastersCount; ++i)
  362. {
  363. const LightComponent& lightc =
  364. ctx.m_sm.m_omnis[i]->getComponent<LightComponent>();
  365. U idx = lightc.getShadowMapIndex();
  366. for(U j = 0; j < 6; ++j)
  367. {
  368. ctx.m_sm.m_omniFramebuffers[i][j] = m_omnis[idx].m_fb[j];
  369. }
  370. ctx.m_sm.m_omniCacheIndices[i] = idx;
  371. }
  372. }
  373. ANKI_TRACE_STOP_EVENT(RENDER_SM);
  374. }
  375. //==============================================================================
  376. void Sm::setPreRunBarriers(RenderingContext& ctx)
  377. {
  378. ANKI_TRACE_START_EVENT(RENDER_SM);
  379. CommandBufferPtr& cmdb = ctx.m_commandBuffer;
  380. // Spot lights
  381. for(U i = 0; i < ctx.m_sm.m_spotCacheIndices.getSize(); ++i)
  382. {
  383. U layer = ctx.m_sm.m_spotCacheIndices[i];
  384. cmdb->setTextureBarrier(m_spotTexArray,
  385. TextureUsageBit::NONE,
  386. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  387. TextureSurfaceInfo(0, 0, 0, layer));
  388. }
  389. // Omni lights
  390. for(U i = 0; i < ctx.m_sm.m_omniCacheIndices.getSize(); ++i)
  391. {
  392. for(U j = 0; j < 6; ++j)
  393. {
  394. U layer = ctx.m_sm.m_omniCacheIndices[i];
  395. cmdb->setTextureBarrier(m_omniTexArray,
  396. TextureUsageBit::NONE,
  397. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  398. TextureSurfaceInfo(0, 0, j, layer));
  399. }
  400. }
  401. ANKI_TRACE_STOP_EVENT(RENDER_SM);
  402. }
  403. //==============================================================================
  404. void Sm::setPostRunBarriers(RenderingContext& ctx)
  405. {
  406. ANKI_TRACE_START_EVENT(RENDER_SM);
  407. CommandBufferPtr& cmdb = ctx.m_commandBuffer;
  408. // Spot lights
  409. for(U i = 0; i < ctx.m_sm.m_spotCacheIndices.getSize(); ++i)
  410. {
  411. U layer = ctx.m_sm.m_spotCacheIndices[i];
  412. cmdb->setTextureBarrier(m_spotTexArray,
  413. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  414. TextureUsageBit::FRAGMENT_SHADER_SAMPLED,
  415. TextureSurfaceInfo(0, 0, 0, layer));
  416. }
  417. // Omni lights
  418. for(U i = 0; i < ctx.m_sm.m_omniCacheIndices.getSize(); ++i)
  419. {
  420. for(U j = 0; j < 6; ++j)
  421. {
  422. U layer = ctx.m_sm.m_omniCacheIndices[i];
  423. cmdb->setTextureBarrier(m_omniTexArray,
  424. TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE,
  425. TextureUsageBit::FRAGMENT_SHADER_SAMPLED,
  426. TextureSurfaceInfo(0, 0, j, layer));
  427. }
  428. }
  429. ANKI_TRACE_STOP_EVENT(RENDER_SM);
  430. }
  431. } // end namespace anki