CmRenderSystemContext.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "CmRenderSystemContext.h"
  2. #include "CmException.h"
  3. #include "CmRenderSystemManager.h"
  4. #include "CmRenderSystem.h"
  5. #include "CmDebug.h"
  6. namespace CamelotEngine
  7. {
  8. RenderSystemContext::RenderSystemContext(CM_THREAD_ID_TYPE threadId)
  9. :mMyThreadId(threadId), mReadyCommands(nullptr), mIsExecuting(false)
  10. {
  11. mCommands = new vector<RenderSystemCommand>::type();
  12. }
  13. AsyncOp RenderSystemContext::queueCommand(boost::function<void(AsyncOp&)> commandCallback)
  14. {
  15. #if CM_DEBUG_MODE
  16. #if CM_THREAD_SUPPORT != 0
  17. if(CM_THREAD_CURRENT_ID != mMyThreadId)
  18. {
  19. CM_EXCEPT(InternalErrorException, "Render system context accessed from an invalid thread.");
  20. }
  21. #endif
  22. #endif
  23. RenderSystemCommand newCommand(commandCallback);
  24. mCommands->push_back(newCommand);
  25. return newCommand.asyncOp;
  26. }
  27. void RenderSystemContext::submitToGpu()
  28. {
  29. {
  30. CM_LOCK_MUTEX(mCommandBufferMutex);
  31. if(mReadyCommands != nullptr)
  32. {
  33. delete mReadyCommands;
  34. mReadyCommands = nullptr;
  35. }
  36. mReadyCommands = mCommands;
  37. mCommands = new vector<RenderSystemCommand>::type();
  38. }
  39. }
  40. void RenderSystemContext::playbackCommands()
  41. {
  42. #if CM_DEBUG_MODE
  43. RenderSystem* rs = RenderSystemManager::getActive();
  44. if(rs->getRenderThreadId() != CM_THREAD_CURRENT_ID)
  45. CM_EXCEPT(InternalErrorException, "This method should only be called from the render thread.");
  46. #endif
  47. vector<RenderSystemCommand>::type* currentCommands = nullptr;
  48. {
  49. CM_LOCK_MUTEX(mCommandBufferMutex)
  50. currentCommands = mReadyCommands;
  51. mReadyCommands = nullptr;
  52. mIsExecuting = true;
  53. }
  54. if(currentCommands == nullptr)
  55. {
  56. {
  57. CM_LOCK_MUTEX(mCommandBufferMutex);
  58. mIsExecuting = false;
  59. }
  60. CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
  61. return;
  62. }
  63. for(auto iter = currentCommands->begin(); iter != currentCommands->end(); ++iter)
  64. {
  65. (*iter).callback((*iter).asyncOp);
  66. if(!(*iter).asyncOp.hasCompleted())
  67. {
  68. LOGDBG("Async operation wasn't resolved properly. Resolving automatically to nullptr.");
  69. (*iter).asyncOp.completeOperation(nullptr);
  70. }
  71. }
  72. delete currentCommands;
  73. {
  74. CM_LOCK_MUTEX(mCommandBufferMutex);
  75. mIsExecuting = false;
  76. }
  77. CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
  78. }
  79. bool RenderSystemContext::hasReadyCommands()
  80. {
  81. CM_LOCK_MUTEX(mCommandBufferMutex);
  82. if(mReadyCommands != nullptr && mReadyCommands->size() > 0)
  83. return true;
  84. return false;
  85. }
  86. void RenderSystemContext::blockUntilExecuted()
  87. {
  88. #if CM_DEBUG_MODE
  89. RenderSystem* rs = RenderSystemManager::getActive();
  90. if(rs->getRenderThreadId() == CM_THREAD_CURRENT_ID)
  91. CM_EXCEPT(InternalErrorException, "This method should never be called from the render thread as it will cause a deadlock.");
  92. #endif
  93. {
  94. CM_LOCK_MUTEX_NAMED(mCommandBufferMutex, lock);
  95. while (mReadyCommands != nullptr && mReadyCommands->size() > 0 || mIsExecuting)
  96. {
  97. CM_THREAD_WAIT(mContextPlaybackDoneCondition, mCommandBufferMutex, lock)
  98. }
  99. }
  100. }
  101. }