BsRenderSystem.cpp 7.1 KB

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