CmRenderSystemContext.cpp 3.9 KB

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