2
0

CmDeferredRenderSystem.cpp 14 KB

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