Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / mesh_block_manager.cpp
blob64a24cbfbd04e6aa7e3a42597e5eb91eba09ada8
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/mesh_block_manager.h"
20 #include "nel/misc/hierarchical_timer.h"
22 using namespace NLMISC;
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 namespace NL3D
32 #define NL3D_MBM_MAX_VBHEAP 255
33 #define NL3D_MBM_VBHEAP_MESH_SHIFT 8
34 #define NL3D_MBM_VBHEAP_MESH_MASK 0xFFFFFF00
35 #define NL3D_MBM_VBHEAP_HEAP_MASK 0x000000FF
38 // ***************************************************************************
39 CMeshBlockManager::CMeshBlockManager()
41 _RenderCtx.Driver= NULL;
42 _RenderCtx.Scene= NULL;
43 _RenderCtx.RenderTrav= NULL;
45 // Allocate at least the 0th heap
46 _VBHeapBlocks.resize(1);
47 _VBHeapBlocks[0]= new CVBHeapBlock;
48 // some reserve, avoiding first reallocation.
49 _VBHeapBlocks[0]->RdrInstances.reserve(100);
50 _VBHeapBlocks[0]->RdrMeshGeoms.reserve(100);
53 // ***************************************************************************
54 CMeshBlockManager::~CMeshBlockManager()
56 // must release any user heap.
57 releaseVBHeaps();
58 // Release the 0th one.
59 delete _VBHeapBlocks[0];
60 _VBHeapBlocks.clear();
63 // ***************************************************************************
64 void CMeshBlockManager::addInstance(IMeshGeom *meshGeom, CMeshBaseInstance *inst, float polygonCount)
66 // If the meshGeom has never been added to the manager, may do some precalc
67 if(meshGeom->_MeshBlockManager==NULL)
69 // Fill
70 meshGeom->_MeshBlockManager= this;
71 // try to fit the meshGeom in one of our VBHeap.
72 allocateMeshVBHeap(meshGeom);
75 // TestYoyo
76 /*extern uint TEMP_Yoyo_NInstVBHeap;
77 extern uint TEMP_Yoyo_NInstNoVBHeap;
78 if( meshGeom->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK )
79 TEMP_Yoyo_NInstVBHeap++;
80 else
81 TEMP_Yoyo_NInstNoVBHeap++;*/
82 // End TestYoyo
84 // Choose the HeapBlock to fit in.
85 CVBHeapBlock *hb= _VBHeapBlocks[meshGeom->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK];
87 // If the mesh geom is not added to this manager, add it.
88 if(meshGeom->_RootInstanceId==-1)
90 hb->RdrMeshGeoms.push_back(meshGeom);
93 // setup the instance.
94 CInstanceInfo instInfo;
95 instInfo.MeshGeom= meshGeom;
96 instInfo.MBI= inst;
97 instInfo.PolygonCount= polygonCount;
99 // link to the head of the list.
100 instInfo.NextInstance= meshGeom->_RootInstanceId;
101 meshGeom->_RootInstanceId= (sint32)hb->RdrInstances.size();
103 // add this instance
104 hb->RdrInstances.push_back(instInfo);
108 // ***************************************************************************
109 void CMeshBlockManager::flush(IDriver *drv, CScene *scene, CRenderTrav *renderTrav)
111 uint i,j;
113 H_AUTO( NL3D_MeshBlockManager );
115 // setup the manager
116 nlassert(drv && scene && renderTrav);
117 _RenderCtx.Driver= drv;
118 _RenderCtx.Scene= scene;
119 _RenderCtx.RenderTrav= renderTrav;
121 // render
122 //==========
124 // sort by Heap first => small setup of VBs.
125 for(j=0; j<_VBHeapBlocks.size();j++)
127 CVBHeapBlock *hb= _VBHeapBlocks[j];
128 // if not the special 0th heap, must activate VB.
129 if(j==0)
131 _RenderCtx.RenderThroughVBHeap= false;
133 else
135 // set to true => avoid mesh to setup their own VB.
136 _RenderCtx.RenderThroughVBHeap= true;
137 // activate current VB in driver
138 #if 0 // todo hulud remove / restore VBHeap
139 hb->VBHeap.activate();
140 #endif // todo hulud remove / restore VBHeap
144 // Always sort by MeshGeom, in this heap
145 for(i=0; i<hb->RdrMeshGeoms.size();i++)
147 // render the meshGeom and his instances
148 render(hb, hb->RdrMeshGeoms[i], hb->RdrInstances);
152 // reset.
153 //==========
155 // For all vb heaps
156 for(j=0; j<_VBHeapBlocks.size();j++)
158 CVBHeapBlock *hb= _VBHeapBlocks[j];
160 // Parse all MehsGeoms, and flag them as Not Added to me
161 for(i=0; i<hb->RdrMeshGeoms.size();i++)
163 hb->RdrMeshGeoms[i]->_RootInstanceId= -1;
166 // clear rdr arrays
167 hb->RdrInstances.clear();
168 hb->RdrMeshGeoms.clear();
173 // ***************************************************************************
174 void CMeshBlockManager::render(CVBHeapBlock *vbHeapBlock, IMeshGeom *meshGeom, std::vector<CInstanceInfo> &rdrInstances)
176 // TestYoyo
177 /*extern uint TEMP_Yoyo_NMeshVBHeap;
178 extern uint TEMP_Yoyo_NMeshNoVBHeap;
179 if( _RenderCtx.RenderThroughVBHeap )
180 TEMP_Yoyo_NMeshVBHeap++;
181 else
182 TEMP_Yoyo_NMeshNoVBHeap++;*/
183 // End TestYoyo
185 // Start for this mesh.
186 meshGeom->beginMesh(_RenderCtx);
189 // sort per material first?
190 if( meshGeom->sortPerMaterial() )
192 // number of renderPasses for this mesh.
193 uint numRdrPass= meshGeom->getNumRdrPassesForMesh();
195 // for all material.
196 for(uint rdrPass=0;rdrPass<numRdrPass;rdrPass++)
198 // for all instance.
199 sint32 instId= meshGeom->_RootInstanceId;
200 while( instId!=-1 )
202 CInstanceInfo &instInfo= rdrInstances[instId];
204 // activate this instance
205 meshGeom->activeInstance(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, NULL);
207 // render the pass.
208 meshGeom->renderPass(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, rdrPass);
210 // next instance
211 instId= instInfo.NextInstance;
215 // else sort per instance first
216 else
218 // for all instance.
219 sint32 instId= meshGeom->_RootInstanceId;
220 while( instId!=-1 )
222 CInstanceInfo &instInfo= rdrInstances[instId];
224 // If the meshGeom need to change Some VB (geomorphs...)
225 bool needVBHeapLock= _RenderCtx.RenderThroughVBHeap && meshGeom->isActiveInstanceNeedVBFill();
226 void *vbDst= NULL;
227 if(needVBHeapLock)
229 // Lock the VBHeap
230 #if 0 // todo hulud remove / restore VBHeap
231 vbDst= vbHeapBlock->VBHeap.lock(meshGeom->_MeshVBHeapIndexStart);
232 #endif // todo hulud remove / restore VBHeap
235 // activate this instance
236 meshGeom->activeInstance(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, vbDst);
238 if(needVBHeapLock)
240 // unlock only what vertices have changed (ATI problem)
241 #if 0 // todo hulud remove / restore VBHeap
242 vbHeapBlock->VBHeap.unlock(meshGeom->_MeshVBHeapIndexStart,
243 meshGeom->_MeshVBHeapIndexStart + meshGeom->_MeshVBHeapNumVertices);
244 #endif // todo hulud remove / restore VBHeap
247 // number of renderPasses for this mesh.
248 uint numRdrPass= meshGeom->getNumRdrPassesForInstance(instInfo.MBI);
250 // for all material.
251 for(uint rdrPass=0;rdrPass<numRdrPass;rdrPass++)
253 // render the pass.
254 meshGeom->renderPass(_RenderCtx, instInfo.MBI, instInfo.PolygonCount, rdrPass);
257 // next instance
258 instId= instInfo.NextInstance;
262 // End for this mesh.
263 meshGeom->endMesh(_RenderCtx);
267 // ***************************************************************************
268 // ***************************************************************************
269 // VBHeap mgt
270 // ***************************************************************************
271 // ***************************************************************************
274 // ***************************************************************************
275 void CMeshBlockManager::allocateMeshVBHeap(IMeshGeom *mesh)
277 // Get info from mesh.
278 uint vertexFormat, numVertices;
279 // if the mesh do not support VBHeap, quit.
280 if( !mesh->getVBHeapInfo(vertexFormat, numVertices) )
281 return;
283 // In case of ...
284 if( numVertices==0 )
285 return;
287 // try to find a VBHeap with this vertexFormat.
288 TVBHeapMap::iterator it= _VBHeapMap.find(vertexFormat);
289 // if not found, abort
290 if(it==_VBHeapMap.end())
291 return;
293 // access to this VBHeap.
294 uint vbHeapId= it->second;
295 CVBHeapBlock *vbHeapBlock= _VBHeapBlocks[vbHeapId];
296 // try to allocate sapce into the heap. Fail=> abort.
297 #if 0 // todo hulud remove / restore VBHeap
298 uint indexStart;
299 if( !vbHeapBlock->VBHeap.allocate(numVertices, indexStart) )
300 return;
301 #endif // todo hulud remove / restore VBHeap
303 // All is Ok here => setup infos.
304 //==================
306 // Keep track of the mesh => allocate.
307 uint meshId;
308 // try to get a free id.
309 if( !vbHeapBlock->FreeIds.empty() )
311 meshId= vbHeapBlock->FreeIds.back();
312 vbHeapBlock->FreeIds.pop_back();
313 vbHeapBlock->AllocatedMeshGeoms[meshId]= mesh;
315 // else, must add to the array
316 else
318 meshId= (uint)vbHeapBlock->AllocatedMeshGeoms.size();
319 vbHeapBlock->AllocatedMeshGeoms.push_back(mesh);
322 // info for delete in mesh
323 #if 0 // todo hulud remove / restore VBHeap
324 mesh->_MeshVBHeapIndexStart= indexStart;
325 mesh->_MeshVBHeapId= vbHeapId + (meshId<<NL3D_MBM_VBHEAP_MESH_SHIFT);
326 mesh->_MeshVBHeapNumVertices= numVertices;
327 #endif // todo hulud remove / restore VBHeap
329 // Fill VB.
330 //==================
331 #if 0 // todo hulud remove / restore VBHeap
332 uint8 *dst= vbHeapBlock->VBHeap.lock(indexStart);
333 mesh->computeMeshVBHeap(dst, indexStart);
334 // unlock only what vertices have changed (ATI problem)
335 vbHeapBlock->VBHeap.unlock(indexStart, indexStart+numVertices);
336 #endif // todo hulud remove / restore VBHeap
339 // ***************************************************************************
340 void CMeshBlockManager::freeMeshVBHeap(IMeshGeom *mesh)
342 nlassert(mesh->_MeshVBHeapId);
344 // unpack heap and mesh id.
345 uint vbHeapId= mesh->_MeshVBHeapId & NL3D_MBM_VBHEAP_HEAP_MASK;
346 uint meshId= (mesh->_MeshVBHeapId & NL3D_MBM_VBHEAP_MESH_MASK) >> NL3D_MBM_VBHEAP_MESH_SHIFT;
348 // access to this VBHeap.
349 CVBHeapBlock *vbHeapBlock= _VBHeapBlocks[vbHeapId];
351 // free VB memory.
352 #if 0 // todo hulud remove / restore VBHeap
353 vbHeapBlock->VBHeap.free(mesh->_MeshVBHeapIndexStart);
354 #endif // todo hulud remove / restore VBHeap
356 // free this space
357 nlassert(meshId<vbHeapBlock->AllocatedMeshGeoms.size());
358 vbHeapBlock->AllocatedMeshGeoms[meshId]= NULL;
359 vbHeapBlock->FreeIds.push_back(meshId);
361 // reset mesh info.
362 mesh->_MeshVBHeapId= 0;
363 mesh->_MeshVBHeapIndexStart= 0;
366 // ***************************************************************************
367 void CMeshBlockManager::releaseVBHeaps()
369 uint i,j;
371 // For all blocks but the 0th
372 for(j=1; j<_VBHeapBlocks.size();j++)
374 CVBHeapBlock *hb= _VBHeapBlocks[j];
376 // For all allocated mesh of this heap.
377 for(i=0;i<hb->AllocatedMeshGeoms.size();i++)
379 IMeshGeom *mesh= hb->AllocatedMeshGeoms[i];
380 // if the mesh exist.
381 if(mesh)
383 // free his VBHeap Data.
384 freeMeshVBHeap(mesh);
385 nlassert( hb->AllocatedMeshGeoms[i] == NULL );
389 // delete the block. NB: VBHeap auto released
390 delete hb;
393 // erase all blocks but 0th
394 _VBHeapBlocks.resize(1);
396 // clear the map.
397 contReset(_VBHeapMap);
400 // ***************************************************************************
401 bool CMeshBlockManager::addVBHeap(IDriver *drv, uint vertexFormat, uint maxVertices)
403 return false; // todo hulud remove / restore VBHeap
405 // if find an existing vertexFormat, abort.
406 TVBHeapMap::iterator it= _VBHeapMap.find(vertexFormat);
407 // if found, abort
408 if( it!=_VBHeapMap.end() )
409 return false;
411 // create the block
412 CVBHeapBlock *hb= new CVBHeapBlock;
414 // allocate vertex space
415 #if 0 // todo hulud remove / restore VBHeap
416 hb->VBHeap.init(drv, vertexFormat, maxVertices);
417 #endif // todo hulud remove / restore VBHeap
419 // add an entry to the array, and the map.
420 _VBHeapBlocks.push_back(hb);
421 _VBHeapMap[vertexFormat]= (uint)_VBHeapBlocks.size()-1;
423 return true;
427 } // NL3D