DrawLayer.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include "BFApp.h"
  2. #include "gfx/DrawLayer.h"
  3. #include "gfx/Texture.h"
  4. #include "gfx/RenderDevice.h"
  5. #include "gfx/Shader.h"
  6. #include "util/PerfTimer.h"
  7. #include "util/BeefPerf.h"
  8. USING_NS_BF;
  9. static int sCurBatchId = 0;
  10. DrawBatch::DrawBatch()
  11. {
  12. mId = ++sCurBatchId;
  13. mVtxIdx = 0;
  14. mIdxIdx = 0;
  15. mAllocatedVertices = 0;
  16. mAllocatedIndices = 0;
  17. mIsIndexBufferHead = false;
  18. mIsVertexBufferHead = false;
  19. mVertices = NULL;
  20. mIndices = NULL;
  21. mRenderState = NULL;
  22. mDrawLayer = NULL;
  23. mNext = NULL;
  24. Clear();
  25. }
  26. DrawBatch::~DrawBatch()
  27. {
  28. }
  29. void DrawBatch::Clear()
  30. {
  31. mVtxIdx = 0;
  32. mIdxIdx = 0;
  33. for (int texIdx = 0; texIdx < MAX_TEXTURES; texIdx++)
  34. mCurTextures[texIdx] = (Texture*)(intptr)-1;
  35. }
  36. void DrawBatch::Free()
  37. {
  38. RenderDevice* renderDevice = mDrawLayer->mRenderDevice;
  39. if (mIsVertexBufferHead)
  40. renderDevice->mPooledVertexBuffers.FreeMemoryBlock(mVertices);
  41. if (mIsIndexBufferHead)
  42. renderDevice->mPooledIndexBuffers.FreeMemoryBlock(mIndices);
  43. mIsVertexBufferHead = false;
  44. mIsIndexBufferHead = false;
  45. Clear();
  46. auto& pool = renderDevice->mDrawBatchPool;
  47. pool.push_back(this);
  48. }
  49. DrawBatch* DrawBatch::AllocateChainedBatch(int minVtxCount, int minIdxCount)
  50. {
  51. mDrawLayer->CloseDrawBatch();
  52. return mDrawLayer->AllocateBatch(minVtxCount, minIdxCount);
  53. }
  54. void* DrawBatch::AllocTris(int vtxCount)
  55. {
  56. int idxCount = vtxCount;
  57. bool fits = (idxCount + mIdxIdx <= mAllocatedIndices) && (vtxCount + mVtxIdx <= mAllocatedVertices);
  58. if ((mRenderState != gBFApp->mRenderDevice->mCurRenderState) || (!fits))
  59. {
  60. if ((mVtxIdx > 0) || (!fits))
  61. {
  62. DrawBatch* nextBatch = AllocateChainedBatch(vtxCount, idxCount);
  63. return nextBatch->AllocTris(vtxCount);
  64. }
  65. mRenderState = gBFApp->mRenderDevice->mCurRenderState;
  66. }
  67. uint16* idxPtr = mIndices + mIdxIdx;
  68. void* vtxPtr = (uint8*)mVertices + (mVtxIdx * mVtxSize);
  69. for (int idxNum = 0; idxNum < idxCount; idxNum++)
  70. {
  71. *idxPtr++ = mVtxIdx++;
  72. mIdxIdx++;
  73. }
  74. return vtxPtr;
  75. }
  76. void* DrawBatch::AllocStrip(int vtxCount)
  77. {
  78. int idxCount = (vtxCount - 2) * 3;
  79. bool fits = (idxCount + mIdxIdx <= mAllocatedIndices) && (vtxCount + mVtxIdx <= mAllocatedVertices);
  80. if ((mRenderState != gBFApp->mRenderDevice->mCurRenderState) || (!fits))
  81. {
  82. if ((mVtxIdx > 0) || (!fits))
  83. {
  84. DrawBatch* nextBatch = AllocateChainedBatch(vtxCount, idxCount);
  85. return nextBatch->AllocStrip(vtxCount);
  86. }
  87. mRenderState = gBFApp->mRenderDevice->mCurRenderState;
  88. }
  89. uint16* idxPtr = mIndices + mIdxIdx;
  90. void* vtxPtr = (uint8*)mVertices + (mVtxIdx * mVtxSize);
  91. mVtxIdx += 2;
  92. for (int idxNum = 0; idxNum < idxCount; idxNum += 3)
  93. {
  94. *idxPtr++ = mVtxIdx - 2;
  95. *idxPtr++ = mVtxIdx - 1;
  96. *idxPtr++ = mVtxIdx;
  97. mVtxIdx++;
  98. mIdxIdx += 3;
  99. }
  100. return vtxPtr;
  101. }
  102. void DrawBatch::AllocIndexed(int vtxCount, int idxCount, void** verticesOut, uint16** indicesOut, uint16* idxOfsOut)
  103. {
  104. bool fits = (idxCount + mIdxIdx <= mAllocatedIndices) && (vtxCount + mVtxIdx <= mAllocatedVertices);
  105. if ((mRenderState != gBFApp->mRenderDevice->mCurRenderState) || (!fits))
  106. {
  107. if ((mVtxIdx > 0) || (!fits))
  108. {
  109. DrawBatch* nextBatch = AllocateChainedBatch(vtxCount, idxCount);
  110. return nextBatch->AllocIndexed(vtxCount, idxCount, verticesOut, indicesOut, idxOfsOut);
  111. }
  112. mRenderState = gBFApp->mRenderDevice->mCurRenderState;
  113. }
  114. *verticesOut = (uint8*)mVertices + (mVtxIdx * mVtxSize);
  115. *indicesOut = mIndices + mIdxIdx;
  116. *idxOfsOut = mVtxIdx;
  117. mVtxIdx += vtxCount;
  118. mIdxIdx += idxCount;
  119. }
  120. //
  121. DrawLayer::DrawLayer()
  122. {
  123. mRenderWindow = NULL;
  124. mRenderDevice = NULL;
  125. mIdxBuffer = NULL;
  126. mVtxBuffer = NULL;
  127. mRenderCmdBuffer = NULL;
  128. mIdxByteIdx = 0;
  129. mVtxByteIdx = 0;
  130. mRenderCmdByteIdx = 0;
  131. mCurDrawBatch = NULL;
  132. for (int textureIdx = 0; textureIdx < MAX_TEXTURES; textureIdx++)
  133. mCurTextures[textureIdx] = NULL;
  134. }
  135. DrawLayer::~DrawLayer()
  136. {
  137. }
  138. void DrawLayer::CloseDrawBatch()
  139. {
  140. if (mCurDrawBatch == NULL)
  141. return;
  142. mIdxByteIdx += mCurDrawBatch->mIdxIdx * sizeof(uint16);
  143. mVtxByteIdx += mCurDrawBatch->mVtxIdx * mCurDrawBatch->mVtxSize;
  144. BF_ASSERT(mVtxByteIdx <= DRAWBUFFER_VTXBUFFER_SIZE);
  145. mCurDrawBatch = NULL;
  146. }
  147. void DrawLayer::QueueRenderCmd(RenderCmd* renderCmd)
  148. {
  149. CloseDrawBatch();
  150. mRenderCmdList.PushBack(renderCmd);
  151. renderCmd->CommandQueued(this);
  152. }
  153. DrawBatch* DrawLayer::AllocateBatch(int minVtxCount, int minIdxCount)
  154. {
  155. BP_ZONE("DrawLayer::AllocateBatch");
  156. BF_ASSERT(mRenderDevice->mCurRenderState->mShader != NULL);
  157. int vtxSize = mRenderDevice->mCurRenderState->mShader->mVertexSize;
  158. minIdxCount = BF_MAX(minIdxCount, 512);
  159. minVtxCount = BF_MAX(minIdxCount, 512);
  160. BF_ASSERT(minIdxCount * sizeof(uint16) <= DRAWBUFFER_IDXBUFFER_SIZE);
  161. BF_ASSERT(minVtxCount * vtxSize <= DRAWBUFFER_VTXBUFFER_SIZE);
  162. DrawBatch* drawBatch = NULL;
  163. auto& pool = mRenderDevice->mDrawBatchPool;
  164. if (pool.size() == 0)
  165. {
  166. drawBatch = CreateDrawBatch();
  167. }
  168. else
  169. {
  170. drawBatch = pool.back();
  171. pool.pop_back();
  172. }
  173. drawBatch->mDrawLayer = this;
  174. int needIdxBytes = minIdxCount * sizeof(uint16);
  175. int needVtxBytes = minVtxCount * vtxSize;
  176. if (needVtxBytes < DRAWBUFFER_VTXBUFFER_SIZE - mVtxByteIdx)
  177. {
  178. //mVtxByteIdx = ((mVtxByteIdx + vtxSize - 1) / vtxSize) * vtxSize;
  179. drawBatch->mVertices = (Vertex3D*)((uint8*) mVtxBuffer + mVtxByteIdx);
  180. drawBatch->mAllocatedVertices = (int)((DRAWBUFFER_VTXBUFFER_SIZE - mVtxByteIdx) / vtxSize);
  181. drawBatch->mIsVertexBufferHead = false;
  182. }
  183. else
  184. {
  185. mVtxBuffer = mRenderDevice->mPooledVertexBuffers.AllocMemoryBlock();
  186. mVtxByteIdx = 0;
  187. drawBatch->mVertices = (Vertex3D*)mVtxBuffer;
  188. drawBatch->mAllocatedVertices = DRAWBUFFER_VTXBUFFER_SIZE / vtxSize;
  189. drawBatch->mIsVertexBufferHead = true;
  190. }
  191. if (needIdxBytes < DRAWBUFFER_IDXBUFFER_SIZE - mIdxByteIdx)
  192. {
  193. drawBatch->mIndices = (uint16*)((uint8*)mIdxBuffer + mIdxByteIdx);
  194. drawBatch->mAllocatedIndices = (DRAWBUFFER_IDXBUFFER_SIZE - mIdxByteIdx) / sizeof(uint16);
  195. drawBatch->mIsIndexBufferHead = false;
  196. }
  197. else
  198. {
  199. mIdxBuffer = mRenderDevice->mPooledIndexBuffers.AllocMemoryBlock();
  200. mIdxByteIdx = 0;
  201. drawBatch->mIndices = (uint16*)mIdxBuffer;
  202. drawBatch->mAllocatedIndices = DRAWBUFFER_IDXBUFFER_SIZE / sizeof(uint16);
  203. drawBatch->mIsIndexBufferHead = true;
  204. }
  205. drawBatch->mAllocatedIndices = std::min(drawBatch->mAllocatedVertices, drawBatch->mAllocatedIndices);
  206. drawBatch->mVtxSize = vtxSize;
  207. mRenderCmdList.PushBack(drawBatch);
  208. mCurDrawBatch = drawBatch;
  209. return drawBatch;
  210. }
  211. void DrawLayer::Draw()
  212. {
  213. BP_ZONE("DrawLayer::Draw");
  214. RenderCmd* curRenderCmd = mRenderCmdList.mHead;
  215. while (curRenderCmd != NULL)
  216. {
  217. curRenderCmd->Render(mRenderDevice, mRenderWindow);
  218. curRenderCmd = curRenderCmd->mNext;
  219. }
  220. }
  221. void DrawLayer::Flush()
  222. {
  223. Draw();
  224. Clear();
  225. }
  226. void DrawLayer::Clear()
  227. {
  228. for (int texIdx = 0; texIdx < MAX_TEXTURES; texIdx++)
  229. mCurTextures[texIdx] = (Texture*) (intptr) -1;
  230. RenderCmd* curBatch = mRenderCmdList.mHead;
  231. while (curBatch != NULL)
  232. {
  233. RenderCmd* nextBatch = curBatch->mNext;
  234. curBatch->Free();
  235. curBatch = nextBatch;
  236. }
  237. /*if ((mIdxBuffer == NULL) || (mCurDrawBatch != NULL))
  238. mIdxBuffer = mRenderDevice->mPooledIndexBuffers.AllocMemoryBlock();
  239. if ((mVtxBuffer == NULL) || (mCurDrawBatch != NULL))
  240. mVtxBuffer = mRenderDevice->mPooledVertexBuffers.AllocMemoryBlock();
  241. if ((mRenderCmdBuffer == NULL) || (mRenderCmdByteIdx != 0))
  242. mRenderCmdBuffer = mRenderDevice->mPooledRenderCmdBuffers.AllocMemoryBlock();
  243. mIdxByteIdx = 0;
  244. mVtxByteIdx = 0;
  245. mRenderCmdByteIdx = 0;*/
  246. mIdxBuffer = NULL;
  247. mVtxByteIdx = 0;
  248. mRenderCmdBuffer = NULL;
  249. mIdxByteIdx = DRAWBUFFER_IDXBUFFER_SIZE;
  250. mVtxByteIdx = DRAWBUFFER_VTXBUFFER_SIZE;
  251. mRenderCmdByteIdx = DRAWBUFFER_CMDBUFFER_SIZE;
  252. mRenderCmdList.Clear();
  253. mCurDrawBatch = NULL;
  254. }
  255. void* DrawLayer::AllocTris(int vtxCount)
  256. {
  257. if (mCurDrawBatch == NULL)
  258. AllocateBatch(0, 0);
  259. return mCurDrawBatch->AllocTris(vtxCount);
  260. }
  261. void* DrawLayer::AllocStrip(int vtxCount)
  262. {
  263. if (mCurDrawBatch == NULL)
  264. AllocateBatch(0, 0);
  265. return mCurDrawBatch->AllocStrip(vtxCount);
  266. }
  267. void DrawLayer::AllocIndexed(int vtxCount, int idxCount, void** verticesOut, uint16** indicesOut, uint16* idxOfsOut)
  268. {
  269. if (mCurDrawBatch == NULL)
  270. AllocateBatch(0, 0);
  271. mCurDrawBatch->AllocIndexed(vtxCount, idxCount, verticesOut, indicesOut, idxOfsOut);
  272. }
  273. void DrawLayer::SetTexture(int texIdx, Texture* texture)
  274. {
  275. if (mCurTextures[texIdx] != texture)
  276. {
  277. QueueRenderCmd(CreateSetTextureCmd(texIdx, texture));
  278. mCurTextures[texIdx] = texture;
  279. }
  280. }
  281. void DrawLayer::SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount)
  282. {
  283. SetShaderConstantData(usageIdx, slotIdx, constData, size);
  284. }
  285. ///
  286. BF_EXPORT DrawLayer* BF_CALLTYPE DrawLayer_Create(BFWindow* window)
  287. {
  288. DrawLayer* aDrawLayer = gBFApp->CreateDrawLayer(window);
  289. aDrawLayer->Clear();
  290. return aDrawLayer;
  291. }
  292. BF_EXPORT void BF_CALLTYPE DrawLayer_Delete(DrawLayer* drawLayer)
  293. {
  294. if (drawLayer->mRenderWindow != NULL)
  295. {
  296. drawLayer->mRenderWindow->mDrawLayerList.Remove(drawLayer);
  297. }
  298. delete drawLayer;
  299. }
  300. BF_EXPORT void BF_CALLTYPE DrawLayer_Clear(DrawLayer* drawLayer)
  301. {
  302. drawLayer->Clear();
  303. }
  304. BF_EXPORT void BF_CALLTYPE DrawLayer_Activate(DrawLayer* drawLayer)
  305. {
  306. if (drawLayer->mRenderWindow != NULL)
  307. {
  308. drawLayer->mRenderWindow->SetAsTarget();
  309. }
  310. else
  311. {
  312. gBFApp->mRenderDevice->mCurRenderTarget = NULL;
  313. }
  314. gBFApp->mRenderDevice->mCurDrawLayer = drawLayer;
  315. }
  316. BF_EXPORT void BF_CALLTYPE DrawLayer_DrawToRenderTarget(DrawLayer* drawLayer, TextureSegment* textureSegment)
  317. {
  318. RenderDevice* renderDevice = gBFApp->mRenderDevice;
  319. BP_ZONE("DrawLayer_DrawToRenderTarget DrawPart");
  320. RenderTarget* prevTarget = renderDevice->mCurRenderTarget;
  321. renderDevice->PhysSetRenderState(renderDevice->mDefaultRenderState);
  322. renderDevice->PhysSetRenderTarget(textureSegment->mTexture);
  323. drawLayer->Draw();
  324. drawLayer->Clear();
  325. renderDevice->mCurRenderTarget = prevTarget;
  326. }