CmDeferredRenderSystem.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. #include "CmDeferredRenderSystem.h"
  2. #include "CmDeferredGpuCommands.h"
  3. #include "CmRenderSystemManager.h"
  4. #include "CmException.h"
  5. namespace CamelotEngine
  6. {
  7. DeferredRenderSystem::DeferredRenderSystem(CM_THREAD_ID_TYPE threadId, boost::function<void()> commandsReadyCallback)
  8. :mMyThreadId(threadId), NotifyCommandsReady(commandsReadyCallback)
  9. {
  10. mActiveRenderCommandBuffer = new vector<DeferredGpuCommand*>::type();
  11. }
  12. DeferredRenderSystem::~DeferredRenderSystem()
  13. {
  14. CM_LOCK_MUTEX(mCommandBufferMutex)
  15. if(mReadyRenderCommandBuffer != nullptr)
  16. {
  17. for(auto iter = mReadyRenderCommandBuffer->begin(); iter != mReadyRenderCommandBuffer->end(); ++iter)
  18. delete *iter;
  19. delete mReadyRenderCommandBuffer;
  20. mReadyRenderCommandBuffer = nullptr;
  21. }
  22. if(mActiveRenderCommandBuffer != nullptr)
  23. {
  24. for(auto iter = mActiveRenderCommandBuffer->begin(); iter != mActiveRenderCommandBuffer->end(); ++iter)
  25. delete *iter;
  26. delete mActiveRenderCommandBuffer;
  27. mActiveRenderCommandBuffer = nullptr;
  28. }
  29. }
  30. void DeferredRenderSystem::render(const RenderOperation& op)
  31. {
  32. throwIfInvalidThread();
  33. RenderOperation opCopy = op;
  34. DfrdRenderGpuCommand* newCommand = new DfrdRenderGpuCommand(opCopy);
  35. mActiveRenderCommandBuffer->push_back(newCommand);
  36. }
  37. void DeferredRenderSystem::bindGpuProgram(GpuProgramPtr prg)
  38. {
  39. throwIfInvalidThread();
  40. DfrdBindGpuProgramCommand* newCommand = new DfrdBindGpuProgramCommand(prg);
  41. mActiveRenderCommandBuffer->push_back(newCommand);
  42. }
  43. void DeferredRenderSystem::bindGpuProgramParameters(GpuProgramType gptype, GpuProgramParametersSharedPtr params)
  44. {
  45. throwIfInvalidThread();
  46. // We need to copy the constant buffers in order to prevent the user from modifying the parameters before rendering is done.
  47. // Because of the way how GpuProgramParameters copy constructor works, only constants are copied and rest of the data is shared.
  48. // Shared data is data that is only modified on shader change, and that should only occur on render thread, so it won't interfere
  49. // with rendering.
  50. GpuProgramParametersSharedPtr paramCopy = GpuProgramParametersSharedPtr(new GpuProgramParameters(*params));
  51. DfrdBindGpuParamsCommand* newCommand = new DfrdBindGpuParamsCommand(gptype, paramCopy);
  52. mActiveRenderCommandBuffer->push_back(newCommand);
  53. }
  54. void DeferredRenderSystem::setInvertVertexWinding(bool invert)
  55. {
  56. throwIfInvalidThread();
  57. DfrdInvVertWindingCommand* newCommand = new DfrdInvVertWindingCommand(invert);
  58. mActiveRenderCommandBuffer->push_back(newCommand);
  59. }
  60. void DeferredRenderSystem::setScissorTest(bool enabled, size_t left, size_t top, size_t right, size_t bottom)
  61. {
  62. throwIfInvalidThread();
  63. DfrdScissorTestCommand* newCommand = new DfrdScissorTestCommand(enabled, left, top, right, bottom);
  64. mActiveRenderCommandBuffer->push_back(newCommand);
  65. }
  66. void DeferredRenderSystem::setStencilBufferParams(CompareFunction func, UINT32 refValue, UINT32 mask,
  67. StencilOperation stencilFailOp, StencilOperation depthFailOp, StencilOperation passOp, bool twoSidedOperation)
  68. {
  69. throwIfInvalidThread();
  70. DfrdStencilBufferParamsCommand* newCommand = new DfrdStencilBufferParamsCommand(func, refValue, mask, stencilFailOp, depthFailOp, passOp, twoSidedOperation);
  71. mActiveRenderCommandBuffer->push_back(newCommand);
  72. }
  73. void DeferredRenderSystem::setVertexDeclaration(VertexDeclarationPtr decl)
  74. {
  75. throwIfInvalidThread();
  76. DfrdVertexDeclCommand* newCommand = new DfrdVertexDeclCommand();
  77. mActiveRenderCommandBuffer->push_back(newCommand);
  78. }
  79. void DeferredRenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
  80. {
  81. throwIfInvalidThread();
  82. DfrdVertBufferBindCommand* newCommand = new DfrdVertBufferBindCommand();
  83. mActiveRenderCommandBuffer->push_back(newCommand);
  84. }
  85. void DeferredRenderSystem::setPolygonMode(PolygonMode mode)
  86. {
  87. throwIfInvalidThread();
  88. DfrdPolygonModeCommand* newCommand = new DfrdPolygonModeCommand(mode);
  89. mActiveRenderCommandBuffer->push_back(newCommand);
  90. }
  91. void DeferredRenderSystem::setStencilCheckEnabled(bool enabled)
  92. {
  93. throwIfInvalidThread();
  94. DfrdStencilCheckCommand* newCommand = new DfrdStencilCheckCommand(enabled);
  95. mActiveRenderCommandBuffer->push_back(newCommand);
  96. }
  97. void DeferredRenderSystem::setWaitForVerticalBlank(bool enabled)
  98. {
  99. throwIfInvalidThread();
  100. DfrdWaitForVerticalBlankCommand* newCommand = new DfrdWaitForVerticalBlankCommand(enabled);
  101. mActiveRenderCommandBuffer->push_back(newCommand);
  102. }
  103. void DeferredRenderSystem::setTextureUnitSettings(size_t texUnit, const TexturePtr& texture, const SamplerState& samplerState)
  104. {
  105. throwIfInvalidThread();
  106. DfrdTextureUnitSettingsCommand* newCommand = new DfrdTextureUnitSettingsCommand(texUnit, texture, samplerState);
  107. mActiveRenderCommandBuffer->push_back(newCommand);
  108. }
  109. void DeferredRenderSystem::setPointParameters(float size, bool attenuationEnabled,
  110. float constant, float linear, float quadratic, float minSize, float maxSize)
  111. {
  112. throwIfInvalidThread();
  113. DfrdPointParamsCommand* newCommand = new DfrdPointParamsCommand(size, attenuationEnabled, constant, linear, quadratic, minSize, maxSize);
  114. mActiveRenderCommandBuffer->push_back(newCommand);
  115. }
  116. void DeferredRenderSystem::setTexture(size_t unit, bool enabled, const TexturePtr &texPtr)
  117. {
  118. throwIfInvalidThread();
  119. DfrdTextureCommand* newCommand = new DfrdTextureCommand(unit, enabled, texPtr);
  120. mActiveRenderCommandBuffer->push_back(newCommand);
  121. }
  122. void DeferredRenderSystem::setVertexTexture(size_t unit, const TexturePtr& tex)
  123. {
  124. throwIfInvalidThread();
  125. DfrdVertexTextureCommand* newCommand = new DfrdVertexTextureCommand(unit, tex);
  126. mActiveRenderCommandBuffer->push_back(newCommand);
  127. }
  128. void DeferredRenderSystem::setTextureFiltering(size_t unit, FilterOptions minFilter,
  129. FilterOptions magFilter, FilterOptions mipFilter)
  130. {
  131. throwIfInvalidThread();
  132. setTextureFiltering(unit, FT_MIN, minFilter);
  133. setTextureFiltering(unit, FT_MAG, magFilter);
  134. setTextureFiltering(unit, FT_MIP, mipFilter);
  135. }
  136. void DeferredRenderSystem::setTextureFiltering(size_t unit, FilterType ftype, FilterOptions filter)
  137. {
  138. throwIfInvalidThread();
  139. DfrdTextureFilteringCommand* newCommand = new DfrdTextureFilteringCommand(unit, ftype, filter);
  140. mActiveRenderCommandBuffer->push_back(newCommand);
  141. }
  142. void DeferredRenderSystem::setTextureAnisotropy(size_t unit, unsigned int maxAnisotropy)
  143. {
  144. throwIfInvalidThread();
  145. DfrdTextureAnisotropyCommand* newCommand = new DfrdTextureAnisotropyCommand(unit, maxAnisotropy);
  146. mActiveRenderCommandBuffer->push_back(newCommand);
  147. }
  148. void DeferredRenderSystem::setTextureAddressingMode(size_t unit, const SamplerState::UVWAddressingMode& uvw)
  149. {
  150. throwIfInvalidThread();
  151. DfrdTextureAddrModeCommand* newCommand = new DfrdTextureAddrModeCommand(unit, uvw);
  152. mActiveRenderCommandBuffer->push_back(newCommand);
  153. }
  154. void DeferredRenderSystem::setTextureBorderColor(size_t unit, const Color& color)
  155. {
  156. throwIfInvalidThread();
  157. DfrdTextureBorderColorCommand* newCommand = new DfrdTextureBorderColorCommand(unit, color);
  158. mActiveRenderCommandBuffer->push_back(newCommand);
  159. }
  160. void DeferredRenderSystem::setTextureMipmapBias(size_t unit, float bias)
  161. {
  162. throwIfInvalidThread();
  163. DfrdTextureMipBiasCommand* newCommand = new DfrdTextureMipBiasCommand(unit, bias);
  164. mActiveRenderCommandBuffer->push_back(newCommand);
  165. }
  166. void DeferredRenderSystem::setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor, SceneBlendOperation op)
  167. {
  168. throwIfInvalidThread();
  169. DfrdSceneBlendingCommand* newCommand = new DfrdSceneBlendingCommand(sourceFactor, destFactor, op);
  170. mActiveRenderCommandBuffer->push_back(newCommand);
  171. }
  172. void DeferredRenderSystem::setSeparateSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor, SceneBlendFactor sourceFactorAlpha,
  173. SceneBlendFactor destFactorAlpha, SceneBlendOperation op, SceneBlendOperation alphaOp)
  174. {
  175. throwIfInvalidThread();
  176. DfrdSeparateSceneBlendingCommand* newCommand = new DfrdSeparateSceneBlendingCommand(sourceFactor, destFactor, sourceFactorAlpha, destFactorAlpha, op, alphaOp);
  177. mActiveRenderCommandBuffer->push_back(newCommand);
  178. }
  179. void DeferredRenderSystem::setAlphaRejectSettings(CompareFunction func, unsigned char value, bool alphaToCoverage)
  180. {
  181. throwIfInvalidThread();
  182. DfrdAlphaRejectParamsCommand* newCommand = new DfrdAlphaRejectParamsCommand(func, value, alphaToCoverage);
  183. mActiveRenderCommandBuffer->push_back(newCommand);
  184. }
  185. void DeferredRenderSystem::setViewport(Viewport *vp)
  186. {
  187. throwIfInvalidThread();
  188. DfrdViewportCommand* newCommand = new DfrdViewportCommand();
  189. mActiveRenderCommandBuffer->push_back(newCommand);
  190. }
  191. void DeferredRenderSystem::setCullingMode(CullingMode mode)
  192. {
  193. throwIfInvalidThread();
  194. DfrdCullingCommand* newCommand = new DfrdCullingCommand(mode);
  195. mActiveRenderCommandBuffer->push_back(newCommand);
  196. }
  197. void DeferredRenderSystem::setDepthBufferParams(bool depthTest, bool depthWrite, CompareFunction depthFunction)
  198. {
  199. throwIfInvalidThread();
  200. DfrdDepthBufferParamsCommand* newCommand = new DfrdDepthBufferParamsCommand(depthTest, depthWrite, depthFunction);
  201. mActiveRenderCommandBuffer->push_back(newCommand);
  202. }
  203. void DeferredRenderSystem::setDepthBufferCheckEnabled(bool enabled)
  204. {
  205. throwIfInvalidThread();
  206. DfrdDepthBufferCheckCommand* newCommand = new DfrdDepthBufferCheckCommand(enabled);
  207. mActiveRenderCommandBuffer->push_back(newCommand);
  208. }
  209. void DeferredRenderSystem::setDepthBufferWriteEnabled(bool enabled)
  210. {
  211. throwIfInvalidThread();
  212. DfrdDepthBufferWriteCommand* newCommand = new DfrdDepthBufferWriteCommand(enabled);
  213. mActiveRenderCommandBuffer->push_back(newCommand);
  214. }
  215. void DeferredRenderSystem::setDepthBufferFunction(CompareFunction func)
  216. {
  217. throwIfInvalidThread();
  218. DfrdDepthBufferFuncCommand* newCommand = new DfrdDepthBufferFuncCommand(func);
  219. mActiveRenderCommandBuffer->push_back(newCommand);
  220. }
  221. void DeferredRenderSystem::setDepthBias(float constantBias, float slopeScaleBias)
  222. {
  223. throwIfInvalidThread();
  224. DfrdDepthBiasCommand* newCommand = new DfrdDepthBiasCommand(constantBias, slopeScaleBias);
  225. mActiveRenderCommandBuffer->push_back(newCommand);
  226. }
  227. void DeferredRenderSystem::setColorBufferWriteEnabled(bool red, bool green, bool blue, bool alpha)
  228. {
  229. throwIfInvalidThread();
  230. DfrdColorBufferWriteCommand* newCommand = new DfrdColorBufferWriteCommand(red, green, blue, alpha);
  231. mActiveRenderCommandBuffer->push_back(newCommand);
  232. }
  233. void DeferredRenderSystem::disableTextureUnit(size_t texUnit)
  234. {
  235. throwIfInvalidThread();
  236. DfrdDisableTextureUnitCommand* newCommand = new DfrdDisableTextureUnitCommand(texUnit);
  237. mActiveRenderCommandBuffer->push_back(newCommand);
  238. }
  239. void DeferredRenderSystem::disableTextureUnitsFrom(size_t texUnit)
  240. {
  241. throwIfInvalidThread();
  242. DfrdDisableTextureUnitsFromCommand* newCommand = new DfrdDisableTextureUnitsFromCommand(texUnit);
  243. mActiveRenderCommandBuffer->push_back(newCommand);
  244. }
  245. void DeferredRenderSystem::beginFrame(void)
  246. {
  247. throwIfInvalidThread();
  248. DfrdBeginFrameCommand* newCommand = new DfrdBeginFrameCommand();
  249. mActiveRenderCommandBuffer->push_back(newCommand);
  250. }
  251. void DeferredRenderSystem::endFrame(void)
  252. {
  253. throwIfInvalidThread();
  254. DfrdEndFrameCommand* newCommand = new DfrdEndFrameCommand();
  255. mActiveRenderCommandBuffer->push_back(newCommand);
  256. }
  257. void DeferredRenderSystem::clearFrameBuffer(unsigned int buffers,
  258. const Color& color, float depth, unsigned short stencil)
  259. {
  260. throwIfInvalidThread();
  261. DfrdClearFrameBufferCommand* newCommand = new DfrdClearFrameBufferCommand(buffers, color, depth, stencil);
  262. mActiveRenderCommandBuffer->push_back(newCommand);
  263. }
  264. void DeferredRenderSystem::submitToGpu()
  265. {
  266. throwIfInvalidThread();
  267. {
  268. CM_LOCK_MUTEX(mCommandBufferMutex)
  269. if(mReadyRenderCommandBuffer != nullptr)
  270. {
  271. for(auto iter = mReadyRenderCommandBuffer->begin(); iter != mReadyRenderCommandBuffer->end(); ++iter)
  272. delete *iter;
  273. delete mReadyRenderCommandBuffer;
  274. mReadyRenderCommandBuffer = nullptr;
  275. }
  276. mReadyRenderCommandBuffer = mActiveRenderCommandBuffer;
  277. mActiveRenderCommandBuffer = new vector<DeferredGpuCommand*>::type();
  278. if(mReadyRenderCommandBuffer != nullptr && mReadyRenderCommandBuffer->size() > 0)
  279. NotifyCommandsReady();
  280. }
  281. }
  282. void DeferredRenderSystem::playbackCommands()
  283. {
  284. RenderSystem* rs = RenderSystemManager::getActive();
  285. if(rs->getRenderThreadId() != CM_THREAD_CURRENT_ID)
  286. CM_EXCEPT(InternalErrorException, "This method should only be called from the render thread.");
  287. vector<DeferredGpuCommand*>::type* currentCommands = nullptr;
  288. {
  289. CM_LOCK_MUTEX(mCommandBufferMutex)
  290. currentCommands = mReadyRenderCommandBuffer;
  291. mReadyRenderCommandBuffer = nullptr;
  292. }
  293. if(currentCommands == nullptr)
  294. return;
  295. for(auto iter = currentCommands->begin(); iter != currentCommands->end(); ++iter)
  296. {
  297. (*iter)->submitCommand(rs);
  298. delete *iter;
  299. }
  300. delete currentCommands;
  301. }
  302. bool DeferredRenderSystem::hasReadyCommands()
  303. {
  304. CM_LOCK_MUTEX(mCommandBufferMutex)
  305. if(mReadyRenderCommandBuffer != nullptr && mReadyRenderCommandBuffer->size() > 0)
  306. return true;
  307. return false;
  308. }
  309. void DeferredRenderSystem::throwIfInvalidThread()
  310. {
  311. #if CM_THREAD_SUPPORT != 0
  312. if(CM_THREAD_CURRENT_ID != mMyThreadId)
  313. {
  314. CM_EXCEPT(InternalErrorException, "Deferred render system method called on an invalid thread.");
  315. }
  316. #endif
  317. }
  318. }