BsRenderer.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Renderer/BsRenderer.h"
  4. #include "CoreThread/BsCoreThread.h"
  5. #include "RenderAPI/BsRenderAPI.h"
  6. #include "Mesh/BsMesh.h"
  7. #include "Material/BsMaterial.h"
  8. #include "Renderer/BsRendererExtension.h"
  9. #include "Renderer/BsRendererManager.h"
  10. #include "CoreThread/BsCoreObjectManager.h"
  11. #include "Scene/BsSceneManager.h"
  12. namespace bs { namespace ct
  13. {
  14. Renderer::Renderer()
  15. :mCallbacks(&compareCallback)
  16. { }
  17. SPtr<RendererMeshData> Renderer::_createMeshData(UINT32 numVertices, UINT32 numIndices, VertexLayout layout, IndexType indexType)
  18. {
  19. return bs_shared_ptr<RendererMeshData>(new (bs_alloc<RendererMeshData>())
  20. RendererMeshData(numVertices, numIndices, layout, indexType));
  21. }
  22. SPtr<RendererMeshData> Renderer::_createMeshData(const SPtr<MeshData>& meshData)
  23. {
  24. return bs_shared_ptr<RendererMeshData>(new (bs_alloc<RendererMeshData>())
  25. RendererMeshData(meshData));
  26. }
  27. bool Renderer::compareCallback(const RendererExtension* a, const RendererExtension* b)
  28. {
  29. // Sort by alpha setting first, then by cull mode, then by index
  30. if (a->getLocation() == b->getLocation())
  31. {
  32. if (a->getPriority() == b->getPriority())
  33. return a > b; // Use address, at this point it doesn't matter, but std::set requires us to differentiate
  34. else
  35. return a->getPriority() > b->getPriority();
  36. }
  37. else
  38. return (UINT32)a->getLocation() < (UINT32)b->getLocation();
  39. }
  40. void Renderer::update()
  41. {
  42. for(auto& entry : mUnresolvedTasks)
  43. {
  44. if (entry->isComplete())
  45. entry->onComplete();
  46. else if (!entry->isCanceled())
  47. mRemainingUnresolvedTasks.push_back(entry);
  48. }
  49. mUnresolvedTasks.clear();
  50. std::swap(mRemainingUnresolvedTasks, mUnresolvedTasks);
  51. }
  52. void Renderer::addTask(const SPtr<RendererTask>& task)
  53. {
  54. Lock lock(mTaskMutex);
  55. assert(task->mState != 1 && "Task is already executing, it cannot be executed again until it finishes.");
  56. task->mState.store(0); // Reset state in case the task is getting re-queued
  57. mQueuedTasks.push_back(task);
  58. mUnresolvedTasks.push_back(task);
  59. }
  60. void Renderer::processTasks(bool forceAll)
  61. {
  62. // Move all tasks to the core thread queue
  63. {
  64. Lock lock(mTaskMutex);
  65. mRunningTasks.insert(mRunningTasks.end(), mQueuedTasks.begin(), mQueuedTasks.end());
  66. mQueuedTasks.clear();
  67. }
  68. do
  69. {
  70. for (auto& entry : mRunningTasks)
  71. {
  72. if (entry->isCanceled() || entry->isComplete())
  73. continue;
  74. entry->mState.store(1);
  75. bool complete = entry->mTaskWorker();
  76. if (!complete)
  77. mRemainingTasks.push_back(entry);
  78. else
  79. entry->mState.store(2);
  80. }
  81. mRunningTasks.clear();
  82. std::swap(mRemainingTasks, mRunningTasks);
  83. } while (forceAll && !mRunningTasks.empty());
  84. }
  85. void Renderer::processTask(RendererTask& task, bool forceAll)
  86. {
  87. // Move all tasks to the core thread queue
  88. {
  89. Lock lock(mTaskMutex);
  90. mRunningTasks.insert(mRunningTasks.end(), mQueuedTasks.begin(), mQueuedTasks.end());
  91. mQueuedTasks.clear();
  92. }
  93. bool complete = task.isCanceled() || task.isComplete();
  94. while (!complete)
  95. {
  96. task.mState.store(1);
  97. complete = task.mTaskWorker();
  98. if (complete)
  99. task.mState.store(2);
  100. if (!forceAll)
  101. break;
  102. }
  103. }
  104. SPtr<Renderer> gRenderer()
  105. {
  106. return std::static_pointer_cast<Renderer>(RendererManager::instance().getActive());
  107. }
  108. RendererTask::RendererTask(const PrivatelyConstruct& dummy, const String& name, std::function<bool()> taskWorker)
  109. :mName(name), mTaskWorker(taskWorker)
  110. { }
  111. SPtr<RendererTask> RendererTask::create(const String& name, std::function<bool()> taskWorker)
  112. {
  113. return bs_shared_ptr_new<RendererTask>(PrivatelyConstruct(), name, taskWorker);
  114. }
  115. bool RendererTask::isComplete() const
  116. {
  117. return mState.load() == 2;
  118. }
  119. bool RendererTask::isCanceled() const
  120. {
  121. return mState.load() == 3;
  122. }
  123. void RendererTask::wait()
  124. {
  125. // Task is about to be executed outside of normal rendering workflow. Make sure to manually sync all changes to
  126. // the core thread first.
  127. // Note: wait() might only get called during serialization, in which case we might call these methods just once
  128. // before a level save, instead for every individual component
  129. gSceneManager()._updateCoreObjectTransforms();
  130. CoreObjectManager::instance().syncToCore();
  131. auto worker = [this]()
  132. {
  133. gRenderer()->processTask(*this, true);
  134. };
  135. gCoreThread().queueCommand(worker);
  136. gCoreThread().submit(true);
  137. // Note: Tigger on complete callback and clear it from Renderer?
  138. }
  139. void RendererTask::cancel()
  140. {
  141. mState.store(3);
  142. }
  143. }}