//----------------------------------------------------------------------- HardwareVertexBufferSharedPtr HardwareBufferManagerBase::allocateVertexBufferCopy( const HardwareVertexBufferSharedPtr& sourceBuffer, BufferLicenseType licenseType, HardwareBufferLicensee* licensee, bool copyData) { // pre-lock the mVertexBuffers mutex, which would usually get locked in // makeBufferCopy / createVertexBuffer // this prevents a deadlock in _notifyVertexBufferDestroyed // which locks the same mutexes (via other methods) but in reverse order OGRE_LOCK_MUTEX(mVertexBuffersMutex); { OGRE_LOCK_MUTEX(mTempBuffersMutex); HardwareVertexBufferSharedPtr vbuf; // Locate existing buffer copy in temporary vertex buffers FreeTemporaryVertexBufferMap::iterator i = mFreeTempVertexBufferMap.find(sourceBuffer.get()); if (i == mFreeTempVertexBufferMap.end()) { // copy buffer, use shadow buffer and make dynamic vbuf = makeBufferCopy( sourceBuffer, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, true); } else { // Allocate existing copy vbuf = i->second; mFreeTempVertexBufferMap.erase(i); } // Copy data? if (copyData) { vbuf->copyData(*(sourceBuffer.get()), 0, 0, sourceBuffer->getSizeInBytes(), true); } // Insert copy into licensee list mTempVertexBufferLicenses.insert( TemporaryVertexBufferLicenseMap::value_type( vbuf.get(), VertexBufferLicense(sourceBuffer.get(), licenseType, EXPIRED_DELAY_FRAME_THRESHOLD, vbuf, licensee))); return vbuf; } }
//----------------------------------------------------------------------- void HardwareBufferManagerBase::registerVertexBufferSourceAndCopy( const HardwareVertexBufferSharedPtr& sourceBuffer, const HardwareVertexBufferSharedPtr& copy) { OGRE_LOCK_MUTEX(mTempBuffersMutex) // Add copy to free temporary vertex buffers mFreeTempVertexBufferMap.insert( FreeTemporaryVertexBufferMap::value_type(sourceBuffer.get(), copy)); }
void HardwareBufferManagerBase::touchVertexBufferCopy(const HardwareVertexBufferSharedPtr& bufferCopy) { TemporayVertexBufferLicenseMap::iterator i = mTempVertexBufferLicenses.find(bufferCopy.get()); if (i != mTempVertexBufferLicenses.end()) { VertexBufferLicense& vbl = i->second; assert(vbl.licenseType == BLT_AUTOMATIC_RELEASE); vbl.expiredDelay = EXPIRED_DELAY_FRAME_THRESHOLD; } }
void HardwareBufferManagerBase::releaseVertexBufferCopy(const HardwareVertexBufferSharedPtr& bufferCopy) { TemporayVertexBufferLicenseMap::iterator i = mTempVertexBufferLicenses.find(bufferCopy.get()); if (i != mTempVertexBufferLicenses.end()) { const VertexBufferLicense& vbl = i->second; vbl.licensee->licenseExpired(vbl.buffer.get()); mFreeTempVertexBufferMap.insert( FreeTemporaryVertexBufferMap::value_type(vbl.originalBufferPtr, vbl.buffer)); mTempVertexBufferLicenses.erase(i); } }
//--------------------------------------------------------------------- void TangentSpaceCalc::extendBuffers(VertexSplits& vertexSplits) { if (!vertexSplits.empty()) { // ok, need to increase the vertex buffer size, and alter some indexes // vertex buffers first VertexBufferBinding* newBindings = HardwareBufferManager::getSingleton().createVertexBufferBinding(); const VertexBufferBinding::VertexBufferBindingMap& bindmap = mVData->vertexBufferBinding->getBindings(); for (VertexBufferBinding::VertexBufferBindingMap::const_iterator i = bindmap.begin(); i != bindmap.end(); ++i) { HardwareVertexBufferSharedPtr srcbuf = i->second; // Derive vertex count from buffer not vertex data, in case using // the vertexStart option in vertex data size_t newVertexCount = srcbuf->getNumVertices() + vertexSplits.size(); // Create new buffer & bind HardwareVertexBufferSharedPtr newBuf = HardwareBufferManager::getSingleton().createVertexBuffer( srcbuf->getVertexSize(), newVertexCount, srcbuf->getUsage(), srcbuf->hasShadowBuffer()); newBindings->setBinding(i->first, newBuf); // Copy existing contents (again, entire buffer, not just elements referenced) newBuf->copyData(*(srcbuf.get()), 0, 0, srcbuf->getNumVertices() * srcbuf->getVertexSize(), true); // Split vertices, read / write from new buffer char* pBase = static_cast<char*>(newBuf->lock(HardwareBuffer::HBL_NORMAL)); for (VertexSplits::iterator spliti = vertexSplits.begin(); spliti != vertexSplits.end(); ++spliti) { const char* pSrcBase = pBase + spliti->first * newBuf->getVertexSize(); char* pDstBase = pBase + spliti->second * newBuf->getVertexSize(); memcpy(pDstBase, pSrcBase, newBuf->getVertexSize()); } newBuf->unlock(); } // Update vertex data // Increase vertex count according to num splits mVData->vertexCount += vertexSplits.size(); // Flip bindings over to new buffers (old buffers released) HardwareBufferManager::getSingleton().destroyVertexBufferBinding(mVData->vertexBufferBinding); mVData->vertexBufferBinding = newBindings; } }
HardwareVertexBufferSharedPtr HardwareBufferManagerBase::allocateVertexBufferCopy(const HardwareVertexBufferSharedPtr& sourceBuffer, BufferLicenseType licenseType, HardwareBufferLicensee* licensee, BOOL copyData /* = FALSE */) { HardwareVertexBufferSharedPtr vbuf; FreeTemporaryVertexBufferMap::iterator i = mFreeTempVertexBufferMap.find(sourceBuffer.get()); if (i == mFreeTempVertexBufferMap.end()) { vbuf = makeBufferCopy(sourceBuffer, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, TRUE); } else { vbuf = i->second; mFreeTempVertexBufferMap.erase(i); } if (copyData) { vbuf->copyData(*(sourceBuffer.get()), 0, 0, sourceBuffer->getSizeInBytes(), TRUE); } mTempVertexBufferLicenses.insert( TemporayVertexBufferLicenseMap::value_type( vbuf.get(), VertexBufferLicense(sourceBuffer.get(), licenseType, EXPIRED_DELAY_FRAME_THRESHOLD, vbuf, licensee))); return vbuf; }
//--------------------------------------------------------------------- void Animation::apply(Entity* entity, Real timePos, Real weight, bool software, bool hardware) { // Calculate time index for fast keyframe search TimeIndex timeIndex = _getTimeIndex(timePos); VertexTrackList::iterator i; for (i = mVertexTrackList.begin(); i != mVertexTrackList.end(); ++i) { unsigned short handle = i->first; VertexAnimationTrack* track = i->second; VertexData* swVertexData; VertexData* hwVertexData; VertexData* origVertexData; bool firstAnim = false; if (handle == 0) { // shared vertex data firstAnim = !entity->_getBuffersMarkedForAnimation(); swVertexData = entity->_getSoftwareVertexAnimVertexData(); hwVertexData = entity->_getHardwareVertexAnimVertexData(); origVertexData = entity->getMesh()->sharedVertexData; entity->_markBuffersUsedForAnimation(); } else { // sub entity vertex data (-1) SubEntity* s = entity->getSubEntity(handle - 1); // Skip this track if subentity is not visible if (!s->isVisible()) continue; firstAnim = !s->_getBuffersMarkedForAnimation(); swVertexData = s->_getSoftwareVertexAnimVertexData(); hwVertexData = s->_getHardwareVertexAnimVertexData(); origVertexData = s->getSubMesh()->vertexData; s->_markBuffersUsedForAnimation(); } // Apply to both hardware and software, if requested if (software) { if (firstAnim && track->getAnimationType() == VAT_POSE) { // First time through for a piece of pose animated vertex data // We need to copy the original position values to the temp accumulator const VertexElement* origelem = origVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION); const VertexElement* destelem = swVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr origBuffer = origVertexData->vertexBufferBinding->getBuffer(origelem->getSource()); HardwareVertexBufferSharedPtr destBuffer = swVertexData->vertexBufferBinding->getBuffer(destelem->getSource()); destBuffer->copyData(*origBuffer.get(), 0, 0, destBuffer->getSizeInBytes(), true); } track->setTargetMode(VertexAnimationTrack::TM_SOFTWARE); track->applyToVertexData(swVertexData, timeIndex, weight, &(entity->getMesh()->getPoseList())); } if (hardware) { track->setTargetMode(VertexAnimationTrack::TM_HARDWARE); track->applyToVertexData(hwVertexData, timeIndex, weight, &(entity->getMesh()->getPoseList())); } } }
//--------------------------------------------------------------------- void TangentSpaceCalc::extendBuffers(VertexSplits& vertexSplits) { if (!vertexSplits.empty()) { // ok, need to increase the vertex buffer size, and alter some indexes // vertex buffers first VertexBufferBinding* newBindings = HardwareBufferManager::getSingleton().createVertexBufferBinding(); const VertexBufferBinding::VertexBufferBindingMap& bindmap = mVData->vertexBufferBinding->getBindings(); for (VertexBufferBinding::VertexBufferBindingMap::const_iterator i = bindmap.begin(); i != bindmap.end(); ++i) { HardwareVertexBufferSharedPtr srcbuf = i->second; // Derive vertex count from buffer not vertex data, in case using // the vertexStart option in vertex data size_t newVertexCount = srcbuf->getNumVertices() + vertexSplits.size(); // Create new buffer & bind HardwareVertexBufferSharedPtr newBuf = HardwareBufferManager::getSingleton().createVertexBuffer( srcbuf->getVertexSize(), newVertexCount, srcbuf->getUsage(), srcbuf->hasShadowBuffer()); newBindings->setBinding(i->first, newBuf); // Copy existing contents (again, entire buffer, not just elements referenced) newBuf->copyData(*(srcbuf.get()), 0, 0, srcbuf->getNumVertices() * srcbuf->getVertexSize(), true); // Split vertices, read / write from new buffer char* pBase = static_cast<char*>(newBuf->lock(HardwareBuffer::HBL_NORMAL)); for (VertexSplits::iterator spliti = vertexSplits.begin(); spliti != vertexSplits.end(); ++spliti) { const char* pSrcBase = pBase + spliti->first * newBuf->getVertexSize(); char* pDstBase = pBase + spliti->second * newBuf->getVertexSize(); memcpy(pDstBase, pSrcBase, newBuf->getVertexSize()); } newBuf->unlock(); } // Update vertex data // Increase vertex count according to num splits mVData->vertexCount += vertexSplits.size(); // Flip bindings over to new buffers (old buffers released) HardwareBufferManager::getSingleton().destroyVertexBufferBinding(mVData->vertexBufferBinding); mVData->vertexBufferBinding = newBindings; // If vertex size requires 32bit index buffer if (mVData->vertexCount > 65536) { for (size_t i = 0; i < mIDataList.size(); ++i) { // check index size IndexData* idata = mIDataList[i]; HardwareIndexBufferSharedPtr srcbuf = idata->indexBuffer; if (srcbuf->getType() == HardwareIndexBuffer::IT_16BIT) { size_t indexCount = srcbuf->getNumIndexes(); // convert index buffer to 32bit. HardwareIndexBufferSharedPtr newBuf = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_32BIT, indexCount, srcbuf->getUsage(), srcbuf->hasShadowBuffer()); uint16* pSrcBase = static_cast<uint16*>(srcbuf->lock(HardwareBuffer::HBL_NORMAL)); uint32* pBase = static_cast<uint32*>(newBuf->lock(HardwareBuffer::HBL_NORMAL)); size_t j = 0; while (j < indexCount) { *pBase++ = *pSrcBase++; ++j; } srcbuf->unlock(); newBuf->unlock(); // assign new index buffer. idata->indexBuffer = newBuf; } } } } }
//----------------------------------------------------------------------- void HardwareBufferManagerBase::_forceReleaseBufferCopies( const HardwareVertexBufferSharedPtr& sourceBuffer) { _forceReleaseBufferCopies(sourceBuffer.get()); }
void HardwareBufferManagerBase::registerVertexBufferSourceAndCopy(const HardwareVertexBufferSharedPtr& sourceBuffer, const HardwareVertexBufferSharedPtr& copy) { mFreeTempVertexBufferMap.insert(FreeTemporaryVertexBufferMap::value_type(sourceBuffer.get(), copy)); }