BsRenderSystem.cpp 7.2 KB

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