CmRenderSystemContext.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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. , waitForVerticalBlank(true)
  11. {
  12. mCommands = new vector<RenderSystemCommand>::type();
  13. }
  14. AsyncOp RenderSystemContext::queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, UINT32 _callbackId)
  15. {
  16. #if CM_DEBUG_MODE
  17. #if CM_THREAD_SUPPORT != 0
  18. if(CM_THREAD_CURRENT_ID != mMyThreadId)
  19. {
  20. CM_EXCEPT(InternalErrorException, "Render system context accessed from an invalid thread.");
  21. }
  22. #endif
  23. #endif
  24. RenderSystemCommand newCommand(commandCallback, _callbackId);
  25. mCommands->push_back(newCommand);
  26. return newCommand.asyncOp;
  27. }
  28. void RenderSystemContext::queueCommand(boost::function<void()> commandCallback, UINT32 _callbackId)
  29. {
  30. #if CM_DEBUG_MODE
  31. #if CM_THREAD_SUPPORT != 0
  32. if(CM_THREAD_CURRENT_ID != mMyThreadId)
  33. {
  34. CM_EXCEPT(InternalErrorException, "Render system context accessed from an invalid thread.");
  35. }
  36. #endif
  37. #endif
  38. RenderSystemCommand newCommand(commandCallback, _callbackId);
  39. mCommands->push_back(newCommand);
  40. }
  41. void RenderSystemContext::submitToGpu()
  42. {
  43. {
  44. CM_LOCK_MUTEX(mCommandBufferMutex);
  45. if(mReadyCommands != nullptr)
  46. {
  47. delete mReadyCommands;
  48. mReadyCommands = nullptr;
  49. }
  50. mReadyCommands = mCommands;
  51. mCommands = new vector<RenderSystemCommand>::type();
  52. }
  53. }
  54. void RenderSystemContext::playbackCommands()
  55. {
  56. #if CM_DEBUG_MODE
  57. RenderSystem* rs = RenderSystemManager::getActive();
  58. if(rs->getRenderThreadId() != CM_THREAD_CURRENT_ID)
  59. CM_EXCEPT(InternalErrorException, "This method should only be called from the render thread.");
  60. #endif
  61. vector<RenderSystemCommand>::type* currentCommands = nullptr;
  62. {
  63. CM_LOCK_MUTEX(mCommandBufferMutex)
  64. currentCommands = mReadyCommands;
  65. mReadyCommands = nullptr;
  66. mIsExecuting = true;
  67. }
  68. if(currentCommands == nullptr)
  69. {
  70. {
  71. CM_LOCK_MUTEX(mCommandBufferMutex);
  72. mIsExecuting = false;
  73. }
  74. CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
  75. return;
  76. }
  77. for(auto iter = currentCommands->begin(); iter != currentCommands->end(); ++iter)
  78. {
  79. RenderSystemCommand command = (*iter);
  80. if(command.returnsValue)
  81. {
  82. command.callbackWithReturnValue(command.asyncOp);
  83. if(!command.asyncOp.hasCompleted())
  84. {
  85. LOGDBG("Async operation return value wasn't resolved properly. Resolving automatically to nullptr. " \
  86. "Make sure to complete the operation before returning from the command callback method.");
  87. command.asyncOp.completeOperation(nullptr);
  88. }
  89. }
  90. else
  91. {
  92. command.callback();
  93. }
  94. }
  95. delete currentCommands;
  96. {
  97. CM_LOCK_MUTEX(mCommandBufferMutex);
  98. mIsExecuting = false;
  99. }
  100. CM_THREAD_NOTIFY_ALL(mContextPlaybackDoneCondition)
  101. }
  102. bool RenderSystemContext::hasReadyCommands()
  103. {
  104. CM_LOCK_MUTEX(mCommandBufferMutex);
  105. if(mReadyCommands != nullptr && mReadyCommands->size() > 0)
  106. return true;
  107. return false;
  108. }
  109. void RenderSystemContext::blockUntilExecuted()
  110. {
  111. #if CM_DEBUG_MODE
  112. RenderSystem* rs = RenderSystemManager::getActive();
  113. if(rs->getRenderThreadId() == CM_THREAD_CURRENT_ID)
  114. CM_EXCEPT(InternalErrorException, "This method should never be called from the render thread as it will cause a deadlock.");
  115. #endif
  116. {
  117. CM_LOCK_MUTEX_NAMED(mCommandBufferMutex, lock);
  118. while (mReadyCommands != nullptr && mReadyCommands->size() > 0 || mIsExecuting)
  119. {
  120. CM_THREAD_WAIT(mContextPlaybackDoneCondition, mCommandBufferMutex, lock)
  121. }
  122. }
  123. }
  124. }