CmRenderSystemContext.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #pragma once
  2. #include "CmPrerequisites.h"
  3. #include "CmAsyncOp.h"
  4. #include "CmCommon.h"
  5. #include "boost/function.hpp"
  6. namespace CamelotEngine
  7. {
  8. /**
  9. * @brief Contains context specific information for a render system.
  10. * Usually each thread will have its own RenderSystemContext,
  11. * but you are allowed to have multiple contexts per thread.
  12. * Contexts can't be shared between threads though.
  13. */
  14. class RenderSystemContext
  15. {
  16. public:
  17. CM_THREAD_ID_TYPE getThreadId() const { return mMyThreadId; }
  18. protected:
  19. struct RenderSystemCommand
  20. {
  21. RenderSystemCommand(boost::function<void(AsyncOp&)> _callback, UINT32 _callbackId = 0)
  22. :callbackWithReturnValue(_callback), returnsValue(true), callbackId(_callbackId)
  23. { }
  24. RenderSystemCommand(boost::function<void()> _callback, UINT32 _callbackId = 0)
  25. :callback(_callback), returnsValue(false), callbackId(_callbackId)
  26. { }
  27. boost::function<void()> callback;
  28. boost::function<void(AsyncOp&)> callbackWithReturnValue;
  29. AsyncOp asyncOp;
  30. bool returnsValue;
  31. UINT32 callbackId;
  32. };
  33. /************************************************************************/
  34. /* CALLABLE ONLY FROM RENDERSYSTEM */
  35. /************************************************************************/
  36. friend class RenderSystem;
  37. // Actively being filled up
  38. vector<RenderSystemCommand>::type* mCommands;
  39. bool mIsShutdown;
  40. bool mIsExecuting;
  41. CM_THREAD_ID_TYPE mMyThreadId;
  42. CM_MUTEX(mCommandBufferMutex)
  43. CM_THREAD_SYNCHRONISER(mContextPlaybackDoneCondition)
  44. RenderSystemContext(CM_THREAD_ID_TYPE threadId);
  45. /**
  46. * @brief Queue up a new command to execute. Make sure the provided function has all of its
  47. * parameters properly bound. Last parameter must be unbound and of AsyncOp&amp; type.
  48. * This is used to signal that the command is completed, and also for storing the return
  49. * value.
  50. *
  51. * @note Callback method also needs to call AsyncOp::markAsResolved once it is done
  52. * processing. (If it doesn't it will still be called automatically, but the return
  53. * value will default to nullptr)
  54. *
  55. * @param _callbackId (optional) Identifier for the callback so you can then later find it
  56. * if needed.
  57. *
  58. * @return Async operation object you can continuously check until the command completes. After
  59. * it completes AsyncOp::isResolved will return true and return data will be valid (if
  60. * the callback provided any).
  61. */
  62. virtual AsyncOp queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, UINT32 _callbackId = 0) = 0;
  63. /**
  64. * @brief Queue up a new command to execute. Make sure the provided function has all of its
  65. * parameters properly bound. Provided command is not expected to return a value.
  66. * If you wish to return a value from the callback use the other overload of queueCommand
  67. * which accepts AsyncOp parameter.
  68. *
  69. * @param _callbackId (optional) Identifier for the callback so you can then later find it
  70. * if needed.
  71. */
  72. virtual void queueCommand(boost::function<void()> commandCallback, UINT32 _callbackId = 0) = 0;
  73. /**
  74. * @brief Plays all queued commands. Should only be called from the render thread,
  75. * and is normally called by the RenderSystem internally.
  76. */
  77. virtual void playbackCommands() = 0;
  78. /**
  79. * @brief Query if this object has any commands ready for rendering.
  80. */
  81. virtual bool hasReadyCommands() = 0;
  82. /**
  83. * @brief Makes all the currently queued commands available to the GPU. They will be executed
  84. * as soon as the render thread is ready.
  85. *
  86. * @note This is expected to be called once per frame. If the previous set of commands hasn't even started rendering
  87. * yet, it will be discarded. This is to prevent lag if the simulation executes faster than the render thread.
  88. */
  89. virtual void submitToGpu() = 0;
  90. /**
  91. * @brief Blocks the current thread until all commands in the context are processed.
  92. *
  93. * @note Do not call from render thread. Render thread is the thread doing the processing and blocking
  94. * it will cause a deadlock since processing will never be completed.
  95. */
  96. virtual void blockUntilExecuted() = 0;
  97. /************************************************************************/
  98. /* STATES */
  99. /* These are various states we cache per RenderSystemContext. They are */
  100. /* used as a quick way of accessing the current state. If we didn't keep*/
  101. /* these, then whenever user wanted to know a certain state we would */
  102. /* have to go and execute all commands to find what it is. */
  103. /************************************************************************/
  104. // TODO - This is actually a clumsy way of keeping state. Better and more generic way would be to
  105. // search through all commands for a specific state change and find what it is.
  106. bool waitForVerticalBlank;
  107. CullingMode cullingMode;
  108. bool vertexProgramBound;
  109. bool geometryProgramBound;
  110. bool fragmentProgramBound;
  111. bool invertVertexWinding;
  112. };
  113. /**
  114. * @brief Render system context where commands are added and meant to be executed once per frame.
  115. * Obsolete commands get discarded as new ones are submitted.
  116. */
  117. class RenderSystemFrameContext : public RenderSystemContext
  118. {
  119. protected:
  120. /************************************************************************/
  121. /* CALLABLE ONLY FROM RENDERSYSTEM */
  122. /************************************************************************/
  123. friend class RenderSystem;
  124. // Finalized and ready for rendering
  125. vector<RenderSystemCommand>::type* mReadyCommands;
  126. RenderSystemFrameContext(CM_THREAD_ID_TYPE threadId);
  127. /**
  128. * @copydoc RenderSystemContext::queueReturnCommand()
  129. */
  130. AsyncOp queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, UINT32 _callbackId = 0);
  131. /**
  132. * @copydoc RenderSystemContext::queueCommand()
  133. */
  134. void queueCommand(boost::function<void()> commandCallback, UINT32 _callbackId = 0);
  135. /**
  136. * @copydoc RenderSystemContext::playbackCommands()
  137. */
  138. void playbackCommands();
  139. /**
  140. * @copydoc RenderSystemContext::hasReadyCommands()
  141. */
  142. bool hasReadyCommands();
  143. /**
  144. * @copydoc RenderSystemContext::submitToGpu()
  145. */
  146. void submitToGpu();
  147. /**
  148. * @copydoc RenderSystemContext::blockUntilExecuted()
  149. */
  150. void blockUntilExecuted();
  151. };
  152. /**
  153. * @brief Render system context where commands are added and scheduled for execution immediately.
  154. */
  155. class RenderSystemImmediateContext : public RenderSystemContext
  156. {
  157. protected:
  158. /************************************************************************/
  159. /* CALLABLE ONLY FROM RENDERSYSTEM */
  160. /************************************************************************/
  161. friend class RenderSystem;
  162. RenderSystemImmediateContext(CM_THREAD_ID_TYPE threadId);
  163. /**
  164. * @copydoc RenderSystemContext::queueReturnCommand()
  165. */
  166. AsyncOp queueReturnCommand(boost::function<void(AsyncOp&)> commandCallback, UINT32 _callbackId = 0);
  167. /**
  168. * @copydoc RenderSystemContext::queueCommand()
  169. */
  170. void queueCommand(boost::function<void()> commandCallback, UINT32 _callbackId = 0);
  171. /**
  172. * @copydoc RenderSystemContext::playbackCommands()
  173. */
  174. void playbackCommands();
  175. /**
  176. * @copydoc RenderSystemContext::hasReadyCommands()
  177. */
  178. bool hasReadyCommands();
  179. /**
  180. * @copydoc RenderSystemContext::submitToGpu()
  181. */
  182. void submitToGpu();
  183. /**
  184. * @copydoc RenderSystemContext::blockUntilExecuted()
  185. */
  186. void blockUntilExecuted();
  187. };
  188. }