BsRenderSystem.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "BsRenderSystem.h"
  2. #include "BsCoreThread.h"
  3. #include "BsViewport.h"
  4. #include "BsException.h"
  5. #include "BsRenderTarget.h"
  6. #include "BsRenderWindow.h"
  7. #include "BsPixelBuffer.h"
  8. #include "BsOcclusionQuery.h"
  9. #include "BsGpuResource.h"
  10. #include "BsCoreThread.h"
  11. #include "BsMesh.h"
  12. #include "BsProfilerCPU.h"
  13. #include "BsRenderStats.h"
  14. using namespace std::placeholders;
  15. namespace BansheeEngine {
  16. static const TexturePtr sNullTexPtr;
  17. RenderSystem::RenderSystem()
  18. : mCullingMode(CULL_COUNTERCLOCKWISE)
  19. , mDisabledTexUnitsFrom(0)
  20. , mVertexProgramBound(false)
  21. , mGeometryProgramBound(false)
  22. , mFragmentProgramBound(false)
  23. , mDomainProgramBound(false)
  24. , mHullProgramBound(false)
  25. , mComputeProgramBound(false)
  26. , mClipPlanesDirty(true)
  27. , mCurrentCapabilities(nullptr)
  28. {
  29. }
  30. RenderSystem::~RenderSystem()
  31. {
  32. // Base classes need to call virtual destroy_internal method instead of a destructor
  33. bs_delete(mCurrentCapabilities);
  34. mCurrentCapabilities = nullptr;
  35. }
  36. RenderWindowPtr RenderSystem::initialize(const RENDER_WINDOW_DESC& primaryWindowDesc)
  37. {
  38. mPrimaryWindowDesc = primaryWindowDesc;
  39. AsyncOp op = gCoreThread().queueReturnCommand(std::bind(&RenderSystem::initialize_internal, this, _1), true);
  40. return op.getReturnValue<RenderWindowPtr>();
  41. }
  42. void RenderSystem::initialize_internal(AsyncOp& asyncOp)
  43. {
  44. THROW_IF_NOT_CORE_THREAD;
  45. mVertexProgramBound = false;
  46. mGeometryProgramBound = false;
  47. mFragmentProgramBound = false;
  48. mDomainProgramBound = false;
  49. mHullProgramBound = false;
  50. mComputeProgramBound = false;
  51. }
  52. void RenderSystem::destroy()
  53. {
  54. gCoreAccessor().queueCommand(std::bind(&RenderSystem::destroy_internal, this));
  55. gCoreThread().submitAccessors(true);
  56. }
  57. void RenderSystem::destroy_internal()
  58. {
  59. mActiveRenderTarget = nullptr;
  60. }
  61. const RenderSystemCapabilities* RenderSystem::getCapabilities(void) const
  62. {
  63. return mCurrentCapabilities;
  64. }
  65. const DriverVersion& RenderSystem::getDriverVersion(void) const
  66. {
  67. THROW_IF_NOT_CORE_THREAD;
  68. return mDriverVersion;
  69. }
  70. void RenderSystem::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
  71. {
  72. THROW_IF_NOT_CORE_THREAD;
  73. setTexture(gptype, texUnit, false, sNullTexPtr);
  74. }
  75. void RenderSystem::addClipPlane (const Plane &p)
  76. {
  77. THROW_IF_NOT_CORE_THREAD;
  78. mClipPlanes.push_back(p);
  79. mClipPlanesDirty = true;
  80. }
  81. void RenderSystem::setClipPlanes(const PlaneList& clipPlanes)
  82. {
  83. THROW_IF_NOT_CORE_THREAD;
  84. if (clipPlanes != mClipPlanes)
  85. {
  86. mClipPlanes = clipPlanes;
  87. mClipPlanesDirty = true;
  88. }
  89. }
  90. void RenderSystem::resetClipPlanes()
  91. {
  92. THROW_IF_NOT_CORE_THREAD;
  93. if (!mClipPlanes.empty())
  94. {
  95. mClipPlanes.clear();
  96. mClipPlanesDirty = true;
  97. }
  98. }
  99. void RenderSystem::bindGpuProgram(HGpuProgram prg)
  100. {
  101. THROW_IF_NOT_CORE_THREAD;
  102. switch(prg->getType())
  103. {
  104. case GPT_VERTEX_PROGRAM:
  105. if (!mVertexProgramBound && !mClipPlanes.empty())
  106. mClipPlanesDirty = true;
  107. mVertexProgramBound = true;
  108. break;
  109. case GPT_GEOMETRY_PROGRAM:
  110. mGeometryProgramBound = true;
  111. break;
  112. case GPT_FRAGMENT_PROGRAM:
  113. mFragmentProgramBound = true;
  114. break;
  115. case GPT_DOMAIN_PROGRAM:
  116. mDomainProgramBound = true;
  117. break;
  118. case GPT_HULL_PROGRAM:
  119. mHullProgramBound = true;
  120. break;
  121. case GPT_COMPUTE_PROGRAM:
  122. mComputeProgramBound = true;
  123. break;
  124. }
  125. }
  126. void RenderSystem::unbindGpuProgram(GpuProgramType gptype)
  127. {
  128. THROW_IF_NOT_CORE_THREAD;
  129. switch(gptype)
  130. {
  131. case GPT_VERTEX_PROGRAM:
  132. if (mVertexProgramBound && !mClipPlanes.empty())
  133. mClipPlanesDirty = true;
  134. mVertexProgramBound = false;
  135. break;
  136. case GPT_GEOMETRY_PROGRAM:
  137. mGeometryProgramBound = false;
  138. break;
  139. case GPT_FRAGMENT_PROGRAM:
  140. mFragmentProgramBound = false;
  141. break;
  142. case GPT_DOMAIN_PROGRAM:
  143. mDomainProgramBound = false;
  144. break;
  145. case GPT_HULL_PROGRAM:
  146. mHullProgramBound = false;
  147. break;
  148. case GPT_COMPUTE_PROGRAM:
  149. mComputeProgramBound = false;
  150. break;
  151. }
  152. }
  153. bool RenderSystem::isGpuProgramBound(GpuProgramType gptype)
  154. {
  155. THROW_IF_NOT_CORE_THREAD;
  156. switch(gptype)
  157. {
  158. case GPT_VERTEX_PROGRAM:
  159. return mVertexProgramBound;
  160. case GPT_GEOMETRY_PROGRAM:
  161. return mGeometryProgramBound;
  162. case GPT_FRAGMENT_PROGRAM:
  163. return mFragmentProgramBound;
  164. case GPT_DOMAIN_PROGRAM:
  165. return mDomainProgramBound;
  166. case GPT_HULL_PROGRAM:
  167. return mHullProgramBound;
  168. case GPT_COMPUTE_PROGRAM:
  169. return mComputeProgramBound;
  170. }
  171. return false;
  172. }
  173. void RenderSystem::render(const MeshBasePtr& mesh, UINT32 indexOffset, UINT32 indexCount, bool useIndices, DrawOperationType drawOp)
  174. {
  175. THROW_IF_NOT_CORE_THREAD;
  176. gProfilerCPU().beginSample("render");
  177. if (mClipPlanesDirty)
  178. {
  179. setClipPlanesImpl(mClipPlanes);
  180. mClipPlanesDirty = false;
  181. }
  182. std::shared_ptr<VertexData> vertexData = mesh->_getVertexData();
  183. setVertexDeclaration(vertexData->vertexDeclaration);
  184. auto vertexBuffers = vertexData->getBuffers();
  185. if(vertexBuffers.size() > 0)
  186. {
  187. VertexBufferPtr buffers[MAX_BOUND_VERTEX_BUFFERS];
  188. UINT32 endSlot = 0;
  189. UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS;
  190. for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
  191. {
  192. if(iter->first >= MAX_BOUND_VERTEX_BUFFERS)
  193. BS_EXCEPT(InvalidParametersException, "Buffer index out of range");
  194. startSlot = std::min(iter->first, startSlot);
  195. endSlot = std::max(iter->first, endSlot);
  196. }
  197. for(auto iter = vertexBuffers.begin(); iter != vertexBuffers.end() ; ++iter)
  198. {
  199. buffers[iter->first - startSlot] = iter->second;
  200. }
  201. setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
  202. }
  203. setDrawOperation(drawOp);
  204. if (useIndices)
  205. {
  206. IndexBufferPtr indexBuffer = mesh->_getIndexBuffer();
  207. if(indexCount == 0)
  208. indexCount = indexBuffer->getNumIndices();
  209. setIndexBuffer(indexBuffer);
  210. drawIndexed(indexOffset + mesh->_getIndexOffset(), indexCount, mesh->_getVertexOffset(), vertexData->vertexCount);
  211. }
  212. else
  213. draw(mesh->_getVertexOffset(), vertexData->vertexCount);
  214. mesh->_notifyUsedOnGPU();
  215. gProfilerCPU().endSample("render");
  216. }
  217. void RenderSystem::swapBuffers(RenderTargetPtr target)
  218. {
  219. THROW_IF_NOT_CORE_THREAD;
  220. if (target->isInitialized())
  221. {
  222. target->swapBuffers();
  223. BS_INC_RENDER_STAT(NumPresents);
  224. }
  225. }
  226. void RenderSystem::writeSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, const GpuResourceDataPtr& data, bool discardEntireBuffer, AsyncOp& asyncOp)
  227. {
  228. THROW_IF_NOT_CORE_THREAD;
  229. gProfilerCPU().beginSample("writeSubresource");
  230. resource->writeSubresource(subresourceIdx, *data, discardEntireBuffer);
  231. gProfilerCPU().endSample("writeSubresource");
  232. gProfilerCPU().beginSample("writeSubresourceB");
  233. data->_unlock();
  234. asyncOp._completeOperation();
  235. gProfilerCPU().endSample("writeSubresourceB");
  236. }
  237. void RenderSystem::readSubresource(GpuResourcePtr resource, UINT32 subresourceIdx, GpuResourceDataPtr& data, AsyncOp& asyncOp)
  238. {
  239. THROW_IF_NOT_CORE_THREAD;
  240. gProfilerCPU().beginSample("readSubresource");
  241. resource->readSubresource(subresourceIdx, *data);
  242. data->_unlock();
  243. asyncOp._completeOperation();
  244. gProfilerCPU().endSample("readSubresource");
  245. }
  246. }