123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #include "BFApp.h"
- #include "gfx/DrawLayer.h"
- #include "gfx/Texture.h"
- #include "gfx/RenderDevice.h"
- #include "gfx/Shader.h"
- #include "util/PerfTimer.h"
- #include "util/BeefPerf.h"
- USING_NS_BF;
- static int sCurBatchId = 0;
- DrawBatch::DrawBatch()
- {
- mId = ++sCurBatchId;
- mVtxIdx = 0;
- mIdxIdx = 0;
- mAllocatedVertices = 0;
- mAllocatedIndices = 0;
- mIsIndexBufferHead = false;
- mIsVertexBufferHead = false;
- mVertices = NULL;
- mIndices = NULL;
- mRenderState = NULL;
- mDrawLayer = NULL;
- mNext = NULL;
- Clear();
- }
- DrawBatch::~DrawBatch()
- {
- }
- void DrawBatch::Clear()
- {
- mVtxIdx = 0;
- mIdxIdx = 0;
- for (int texIdx = 0; texIdx < MAX_TEXTURES; texIdx++)
- mCurTextures[texIdx] = (Texture*)(intptr)-1;
- }
- void DrawBatch::Free()
- {
- RenderDevice* renderDevice = mDrawLayer->mRenderDevice;
- if (mIsVertexBufferHead)
- renderDevice->mPooledVertexBuffers.FreeMemoryBlock(mVertices);
- if (mIsIndexBufferHead)
- renderDevice->mPooledIndexBuffers.FreeMemoryBlock(mIndices);
- mIsVertexBufferHead = false;
- mIsIndexBufferHead = false;
- Clear();
- auto& pool = renderDevice->mDrawBatchPool;
- pool.push_back(this);
- }
- DrawBatch* DrawBatch::AllocateChainedBatch(int minVtxCount, int minIdxCount)
- {
- mDrawLayer->CloseDrawBatch();
- return mDrawLayer->AllocateBatch(minVtxCount, minIdxCount);
- }
- void* DrawBatch::AllocTris(int vtxCount)
- {
- int idxCount = vtxCount;
- bool fits = (idxCount + mIdxIdx <= mAllocatedIndices) && (vtxCount + mVtxIdx <= mAllocatedVertices);
- if ((mRenderState != gBFApp->mRenderDevice->mCurRenderState) || (!fits))
- {
- if ((mVtxIdx > 0) || (!fits))
- {
- DrawBatch* nextBatch = AllocateChainedBatch(vtxCount, idxCount);
- return nextBatch->AllocTris(vtxCount);
- }
- mRenderState = gBFApp->mRenderDevice->mCurRenderState;
- }
- uint16* idxPtr = mIndices + mIdxIdx;
- void* vtxPtr = (uint8*)mVertices + (mVtxIdx * mVtxSize);
- for (int idxNum = 0; idxNum < idxCount; idxNum++)
- {
- *idxPtr++ = mVtxIdx++;
- mIdxIdx++;
- }
- return vtxPtr;
- }
- void* DrawBatch::AllocStrip(int vtxCount)
- {
- int idxCount = (vtxCount - 2) * 3;
- bool fits = (idxCount + mIdxIdx <= mAllocatedIndices) && (vtxCount + mVtxIdx <= mAllocatedVertices);
- if ((mRenderState != gBFApp->mRenderDevice->mCurRenderState) || (!fits))
- {
- if ((mVtxIdx > 0) || (!fits))
- {
- DrawBatch* nextBatch = AllocateChainedBatch(vtxCount, idxCount);
- return nextBatch->AllocStrip(vtxCount);
- }
- mRenderState = gBFApp->mRenderDevice->mCurRenderState;
- }
- uint16* idxPtr = mIndices + mIdxIdx;
- void* vtxPtr = (uint8*)mVertices + (mVtxIdx * mVtxSize);
- mVtxIdx += 2;
- for (int idxNum = 0; idxNum < idxCount; idxNum += 3)
- {
- *idxPtr++ = mVtxIdx - 2;
- *idxPtr++ = mVtxIdx - 1;
- *idxPtr++ = mVtxIdx;
- mVtxIdx++;
- mIdxIdx += 3;
- }
- return vtxPtr;
- }
- void DrawBatch::AllocIndexed(int vtxCount, int idxCount, void** verticesOut, uint16** indicesOut, uint16* idxOfsOut)
- {
- bool fits = (idxCount + mIdxIdx <= mAllocatedIndices) && (vtxCount + mVtxIdx <= mAllocatedVertices);
- if ((mRenderState != gBFApp->mRenderDevice->mCurRenderState) || (!fits))
- {
- if ((mVtxIdx > 0) || (!fits))
- {
- DrawBatch* nextBatch = AllocateChainedBatch(vtxCount, idxCount);
- return nextBatch->AllocIndexed(vtxCount, idxCount, verticesOut, indicesOut, idxOfsOut);
- }
- mRenderState = gBFApp->mRenderDevice->mCurRenderState;
- }
- *verticesOut = (uint8*)mVertices + (mVtxIdx * mVtxSize);
- *indicesOut = mIndices + mIdxIdx;
- *idxOfsOut = mVtxIdx;
- mVtxIdx += vtxCount;
- mIdxIdx += idxCount;
- }
- //
- DrawLayer::DrawLayer()
- {
- mRenderWindow = NULL;
- mRenderDevice = NULL;
- mIdxBuffer = NULL;
- mVtxBuffer = NULL;
- mRenderCmdBuffer = NULL;
- mIdxByteIdx = 0;
- mVtxByteIdx = 0;
- mRenderCmdByteIdx = 0;
- mCurDrawBatch = NULL;
- for (int textureIdx = 0; textureIdx < MAX_TEXTURES; textureIdx++)
- mCurTextures[textureIdx] = NULL;
- }
- DrawLayer::~DrawLayer()
- {
- }
- void DrawLayer::CloseDrawBatch()
- {
- if (mCurDrawBatch == NULL)
- return;
- mIdxByteIdx += mCurDrawBatch->mIdxIdx * sizeof(uint16);
- mVtxByteIdx += mCurDrawBatch->mVtxIdx * mCurDrawBatch->mVtxSize;
- BF_ASSERT(mVtxByteIdx <= DRAWBUFFER_VTXBUFFER_SIZE);
- mCurDrawBatch = NULL;
- }
- void DrawLayer::QueueRenderCmd(RenderCmd* renderCmd)
- {
- CloseDrawBatch();
- mRenderCmdList.PushBack(renderCmd);
- renderCmd->CommandQueued(this);
- }
- DrawBatch* DrawLayer::AllocateBatch(int minVtxCount, int minIdxCount)
- {
- BP_ZONE("DrawLayer::AllocateBatch");
- BF_ASSERT(mRenderDevice->mCurRenderState->mShader != NULL);
- int vtxSize = mRenderDevice->mCurRenderState->mShader->mVertexSize;
- minIdxCount = BF_MAX(minIdxCount, 512);
- minVtxCount = BF_MAX(minIdxCount, 512);
- BF_ASSERT(minIdxCount * sizeof(uint16) <= DRAWBUFFER_IDXBUFFER_SIZE);
- BF_ASSERT(minVtxCount * vtxSize <= DRAWBUFFER_VTXBUFFER_SIZE);
- DrawBatch* drawBatch = NULL;
- auto& pool = mRenderDevice->mDrawBatchPool;
- if (pool.size() == 0)
- {
- drawBatch = CreateDrawBatch();
- }
- else
- {
- drawBatch = pool.back();
- pool.pop_back();
- }
- drawBatch->mDrawLayer = this;
- int needIdxBytes = minIdxCount * sizeof(uint16);
- int needVtxBytes = minVtxCount * vtxSize;
- if (needVtxBytes < DRAWBUFFER_VTXBUFFER_SIZE - mVtxByteIdx)
- {
- //mVtxByteIdx = ((mVtxByteIdx + vtxSize - 1) / vtxSize) * vtxSize;
- drawBatch->mVertices = (Vertex3D*)((uint8*) mVtxBuffer + mVtxByteIdx);
- drawBatch->mAllocatedVertices = (int)((DRAWBUFFER_VTXBUFFER_SIZE - mVtxByteIdx) / vtxSize);
- drawBatch->mIsVertexBufferHead = false;
- }
- else
- {
- mVtxBuffer = mRenderDevice->mPooledVertexBuffers.AllocMemoryBlock();
- mVtxByteIdx = 0;
- drawBatch->mVertices = (Vertex3D*)mVtxBuffer;
- drawBatch->mAllocatedVertices = DRAWBUFFER_VTXBUFFER_SIZE / vtxSize;
- drawBatch->mIsVertexBufferHead = true;
- }
- if (needIdxBytes < DRAWBUFFER_IDXBUFFER_SIZE - mIdxByteIdx)
- {
- drawBatch->mIndices = (uint16*)((uint8*)mIdxBuffer + mIdxByteIdx);
- drawBatch->mAllocatedIndices = (DRAWBUFFER_IDXBUFFER_SIZE - mIdxByteIdx) / sizeof(uint16);
- drawBatch->mIsIndexBufferHead = false;
- }
- else
- {
- mIdxBuffer = mRenderDevice->mPooledIndexBuffers.AllocMemoryBlock();
- mIdxByteIdx = 0;
- drawBatch->mIndices = (uint16*)mIdxBuffer;
- drawBatch->mAllocatedIndices = DRAWBUFFER_IDXBUFFER_SIZE / sizeof(uint16);
- drawBatch->mIsIndexBufferHead = true;
- }
- drawBatch->mAllocatedIndices = std::min(drawBatch->mAllocatedVertices, drawBatch->mAllocatedIndices);
- drawBatch->mVtxSize = vtxSize;
- mRenderCmdList.PushBack(drawBatch);
- mCurDrawBatch = drawBatch;
- return drawBatch;
- }
- void DrawLayer::Draw()
- {
- BP_ZONE("DrawLayer::Draw");
- RenderCmd* curRenderCmd = mRenderCmdList.mHead;
- while (curRenderCmd != NULL)
- {
- curRenderCmd->Render(mRenderDevice, mRenderWindow);
- curRenderCmd = curRenderCmd->mNext;
- }
- }
- void DrawLayer::Flush()
- {
- Draw();
- Clear();
- }
- void DrawLayer::Clear()
- {
- for (int texIdx = 0; texIdx < MAX_TEXTURES; texIdx++)
- mCurTextures[texIdx] = (Texture*) (intptr) -1;
- RenderCmd* curBatch = mRenderCmdList.mHead;
- while (curBatch != NULL)
- {
- RenderCmd* nextBatch = curBatch->mNext;
- curBatch->Free();
- curBatch = nextBatch;
- }
- /*if ((mIdxBuffer == NULL) || (mCurDrawBatch != NULL))
- mIdxBuffer = mRenderDevice->mPooledIndexBuffers.AllocMemoryBlock();
- if ((mVtxBuffer == NULL) || (mCurDrawBatch != NULL))
- mVtxBuffer = mRenderDevice->mPooledVertexBuffers.AllocMemoryBlock();
- if ((mRenderCmdBuffer == NULL) || (mRenderCmdByteIdx != 0))
- mRenderCmdBuffer = mRenderDevice->mPooledRenderCmdBuffers.AllocMemoryBlock();
- mIdxByteIdx = 0;
- mVtxByteIdx = 0;
- mRenderCmdByteIdx = 0;*/
- mIdxBuffer = NULL;
- mVtxByteIdx = 0;
- mRenderCmdBuffer = NULL;
- mIdxByteIdx = DRAWBUFFER_IDXBUFFER_SIZE;
- mVtxByteIdx = DRAWBUFFER_VTXBUFFER_SIZE;
- mRenderCmdByteIdx = DRAWBUFFER_CMDBUFFER_SIZE;
- mRenderCmdList.Clear();
- mCurDrawBatch = NULL;
- }
- void* DrawLayer::AllocTris(int vtxCount)
- {
- if (mCurDrawBatch == NULL)
- AllocateBatch(0, 0);
- return mCurDrawBatch->AllocTris(vtxCount);
- }
- void* DrawLayer::AllocStrip(int vtxCount)
- {
- if (mCurDrawBatch == NULL)
- AllocateBatch(0, 0);
- return mCurDrawBatch->AllocStrip(vtxCount);
- }
- void DrawLayer::AllocIndexed(int vtxCount, int idxCount, void** verticesOut, uint16** indicesOut, uint16* idxOfsOut)
- {
- if (mCurDrawBatch == NULL)
- AllocateBatch(0, 0);
- mCurDrawBatch->AllocIndexed(vtxCount, idxCount, verticesOut, indicesOut, idxOfsOut);
- }
- void DrawLayer::SetTexture(int texIdx, Texture* texture)
- {
- if (mCurTextures[texIdx] != texture)
- {
- QueueRenderCmd(CreateSetTextureCmd(texIdx, texture));
- mCurTextures[texIdx] = texture;
- }
- }
- void DrawLayer::SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount)
- {
- SetShaderConstantData(usageIdx, slotIdx, constData, size);
- }
- ///
- BF_EXPORT DrawLayer* BF_CALLTYPE DrawLayer_Create(BFWindow* window)
- {
- DrawLayer* aDrawLayer = gBFApp->CreateDrawLayer(window);
- aDrawLayer->Clear();
- return aDrawLayer;
- }
- BF_EXPORT void BF_CALLTYPE DrawLayer_Delete(DrawLayer* drawLayer)
- {
- if (drawLayer->mRenderWindow != NULL)
- {
- drawLayer->mRenderWindow->mDrawLayerList.Remove(drawLayer);
- }
- delete drawLayer;
- }
- BF_EXPORT void BF_CALLTYPE DrawLayer_Clear(DrawLayer* drawLayer)
- {
- drawLayer->Clear();
- }
- BF_EXPORT void BF_CALLTYPE DrawLayer_Activate(DrawLayer* drawLayer)
- {
- if (drawLayer->mRenderWindow != NULL)
- {
- drawLayer->mRenderWindow->SetAsTarget();
- }
- else
- {
- gBFApp->mRenderDevice->mCurRenderTarget = NULL;
- }
- gBFApp->mRenderDevice->mCurDrawLayer = drawLayer;
- }
- BF_EXPORT void BF_CALLTYPE DrawLayer_DrawToRenderTarget(DrawLayer* drawLayer, TextureSegment* textureSegment)
- {
- RenderDevice* renderDevice = gBFApp->mRenderDevice;
- BP_ZONE("DrawLayer_DrawToRenderTarget DrawPart");
- RenderTarget* prevTarget = renderDevice->mCurRenderTarget;
- renderDevice->PhysSetRenderState(renderDevice->mDefaultRenderState);
- renderDevice->PhysSetRenderTarget(textureSegment->mTexture);
- drawLayer->Draw();
- drawLayer->Clear();
- renderDevice->mCurRenderTarget = prevTarget;
- }
|