CmDeferredRenderSystem.cpp 13 KB

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