diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 51543c924..2cca1e5e2 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -2,31 +2,25 @@ * @file llvertexbuffer.cpp * @brief LLVertexBuffer implementation * - * $LicenseInfo:firstyear=2003&license=viewergpl$ - * - * Copyright (c) 2003-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -155,7 +149,7 @@ U32 wpo2(U32 i) return r; } -U8* LLVBOPool::allocate(U32& name, U32 size) +volatile U8* LLVBOPool::allocate(U32& name, U32 size) { llassert(nhpo2(size) == size); @@ -166,20 +160,24 @@ U8* LLVBOPool::allocate(U32& name, U32 size) mFreeList.resize(i+1); } - U8* ret = NULL; + volatile U8* ret = NULL; if (mFreeList[i].empty()) { //make a new buffer glGenBuffersARB(1, &name); glBindBufferARB(mType, name); - glBufferDataARB(mType, size, 0, mUsage); LLVertexBuffer::sAllocatedBytes += size; - if (LLVertexBuffer::sDisableVBOMapping) + if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) { + glBufferDataARB(mType, size, 0, mUsage); ret = (U8*) ll_aligned_malloc_16(size); } + else + { //always use a true hint of static draw when allocating non-client-backed buffers + glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB); + } glBindBufferARB(mType, 0); } else @@ -195,7 +193,7 @@ U8* LLVBOPool::allocate(U32& name, U32 size) return ret; } -void LLVBOPool::release(U32 name, U8* buffer, U32 size) +void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) { llassert(nhpo2(size) == size); @@ -208,8 +206,15 @@ void LLVBOPool::release(U32 name, U8* buffer, U32 size) rec.mClientData = buffer; sBytesPooled += size; - - mFreeList[i].push_back(rec); + + if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB) + { + glDeleteBuffersARB(1, &rec.mGLName); + } + else + { + mFreeList[i].push_back(rec); + } } void LLVBOPool::cleanup() @@ -228,7 +233,7 @@ void LLVBOPool::cleanup() if (r.mClientData) { - ll_aligned_free_16(r.mClientData); + ll_aligned_free_16((void*) r.mClientData); } l.pop_front(); @@ -543,7 +548,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { validateRange(start, end, count, indices_offset); - + mMappable = FALSE; gGL.syncMatrices(); llassert(mNumVerts >= 0); @@ -598,7 +603,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - + mMappable = FALSE; gGL.syncMatrices(); llassert(mNumIndices >= 0); @@ -644,7 +649,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - + mMappable = FALSE; gGL.syncMatrices(); llassert(mNumVerts >= 0); @@ -794,9 +799,25 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : if (mUsage && mUsage != GL_STREAM_DRAW_ARB) { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default - mUsage = GL_DYNAMIC_DRAW_ARB; + if (sDisableVBOMapping) + { //always use stream draw if VBO mapping is disabled + mUsage = GL_STREAM_DRAW_ARB; + } + else + { + mUsage = GL_DYNAMIC_DRAW_ARB; + } } + if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping) + { + mMappable = TRUE; + } + else + { + mMappable = FALSE; + } + //zero out offsets for (U32 i = 0; i < TYPE_MAX; i++) { @@ -812,6 +833,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : sCount++; } +//static S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices) { S32 offset = 0; @@ -944,11 +966,11 @@ void LLVertexBuffer::releaseBuffer() { if (mUsage == GL_STREAM_DRAW_ARB) { - sStreamVBOPool.release(mGLBuffer, /*(U8*)*/mMappedData, mSize); + sStreamVBOPool.release(mGLBuffer, mMappedData, mSize); } else { - sDynamicVBOPool.release(mGLBuffer, /*(U8*)*/mMappedData, mSize); + sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize); } mGLBuffer = 0; @@ -961,11 +983,11 @@ void LLVertexBuffer::releaseIndices() { if (mUsage == GL_STREAM_DRAW_ARB) { - sStreamIBOPool.release(mGLIndices, /*(U8*)*/mMappedIndexData, mIndicesSize); + sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize); } else { - sDynamicIBOPool.release(mGLIndices, /*(U8*)*/mMappedIndexData, mIndicesSize); + sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize); } mGLIndices = 0; @@ -1048,7 +1070,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - FREE_MEM(sPrivatePoolp, /*(U8*)*/mMappedData) ; + FREE_MEM(sPrivatePoolp, (void*) mMappedData) ; mMappedData = NULL; mEmpty = TRUE; } @@ -1069,7 +1091,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - FREE_MEM(sPrivatePoolp, /*(U8*)*/mMappedIndexData) ; + FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ; mMappedIndexData = NULL; mEmpty = TRUE; } @@ -1289,7 +1311,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) } // Map for data access -/*volatile */U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) +volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { bindGLBuffer(true); LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); @@ -1304,7 +1326,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) if (useVBOs()) { - if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (count == -1) { @@ -1329,7 +1351,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) if (!mapped) { //not already mapped, map new region - MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count); + MappedRegion region(type, mMappable && map_range ? -1 : index, count); mMappedVertexRegions.push_back(region); } } @@ -1345,13 +1367,13 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) sMappedCount++; stop_glerror(); - if(sDisableVBOMapping) + if(!mMappable) { map_range = false; } else { - U8* src = NULL; + volatile U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { @@ -1408,7 +1430,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) llassert(src != NULL); - mMappedData = LL_NEXT_ALIGNED_ADDRESS(src); + mMappedData = LL_NEXT_ALIGNED_ADDRESS(src); mAlignedOffset = mMappedData - src; stop_glerror(); @@ -1421,7 +1443,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) //check the availability of memory LLMemory::logMemoryInfo(TRUE) ; - if(!sDisableVBOMapping) + if(mMappable) { //-------------------- //print out more debug info before crash @@ -1453,7 +1475,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) map_range = false; } - if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) + if (map_range && gGLManager.mHasMapBufferRange && mMappable) { return mMappedData; } @@ -1463,7 +1485,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) } } -/*volatile */U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) +volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); bindGLIndices(true); @@ -1478,7 +1500,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) if (useVBOs()) { - if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) { if (count == -1) { @@ -1500,7 +1522,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) if (!mapped) { //not already mapped, map new region - MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count); + MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count); mMappedIndexRegions.push_back(region); } } @@ -1529,13 +1551,13 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) } } - if(sDisableVBOMapping) + if(!mMappable) { map_range = false; } else { - U8* src = NULL; + volatile U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { @@ -1592,7 +1614,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) log_glerror(); LLMemory::logMemoryInfo(TRUE) ; - if(!sDisableVBOMapping) + if(mMappable) { GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); @@ -1614,7 +1636,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) map_range = false; } - if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) + if (map_range && gGLManager.mHasMapBufferRange && mMappable) { return mMappedIndexData; } @@ -1639,7 +1661,7 @@ void LLVertexBuffer::unmapBuffer() bindGLBuffer(true); updated_all = mIndexLocked; //both vertex and index buffers done updating - if(sDisableVBOMapping) + if(!mMappable) { if (!mMappedVertexRegions.empty()) { @@ -1649,7 +1671,7 @@ void LLVertexBuffer::unmapBuffer() const MappedRegion& region = mMappedVertexRegions[i]; S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; S32 length = sTypeSize[region.mType]*region.mCount; - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, /*(U8*)*/mMappedData+offset); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset); stop_glerror(); } @@ -1658,7 +1680,7 @@ void LLVertexBuffer::unmapBuffer() else { stop_glerror(); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), /*(U8*)*/mMappedData); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData); stop_glerror(); } } @@ -1704,7 +1726,7 @@ void LLVertexBuffer::unmapBuffer() if (mMappedIndexData && mIndexLocked) { bindGLIndices(); - if(sDisableVBOMapping) + if(!mMappable) { if (!mMappedIndexRegions.empty()) { @@ -1713,7 +1735,7 @@ void LLVertexBuffer::unmapBuffer() const MappedRegion& region = mMappedIndexRegions[i]; S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; S32 length = sizeof(U16)*region.mCount; - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, /*(U8*)*/mMappedIndexData+offset); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedIndexData+offset); stop_glerror(); } @@ -1722,7 +1744,7 @@ void LLVertexBuffer::unmapBuffer() else { stop_glerror(); - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), /*(U8*)*/mMappedIndexData); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (U8*) mMappedIndexData); stop_glerror(); } } @@ -1783,7 +1805,7 @@ template struct VertexBufferStrider { if (type == LLVertexBuffer::TYPE_INDEX) { - /*volatile*/ U8* ptr = vbo.mapIndexBuffer(index, count, map_range); + volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range); if (ptr == NULL) { @@ -1798,8 +1820,8 @@ template struct VertexBufferStrider else if (vbo.hasDataType(type)) { S32 stride = LLVertexBuffer::sTypeSize[type]; - - /*volatile */U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); + + volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); if (ptr == NULL) { @@ -2117,7 +2139,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); stop_glerror(); - U8* base = useVBOs() ? (U8*)mAlignedOffset : /*(U8*)*/mMappedData; + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; /*if ((data_mask & mTypeMask) != data_mask) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 85ad44693..baff56286 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -2,31 +2,25 @@ * @file llvertexbuffer.h * @brief LLVertexBuffer wrapper for OpengGL vertex buffer objects * - * $LicenseInfo:firstyear=2003&license=viewergpl$ - * - * Copyright (c) 2003-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -67,10 +61,10 @@ public: U32 mType; //size MUST be a power of 2 - U8* allocate(U32& name, U32 size); + volatile U8* allocate(U32& name, U32 size); //size MUST be the size provided to allocate that returned the given name - void release(U32 name, U8* buffer, U32 size); + void release(U32 name, volatile U8* buffer, U32 size); //destroy all records in mFreeList void cleanup(); @@ -79,7 +73,7 @@ public: { public: U32 mGLName; - U8* mClientData; + volatile U8* mClientData; }; typedef std::list record_list_t; @@ -215,8 +209,8 @@ public: LLVertexBuffer(U32 typemask, S32 usage); // map for data access - /*volatile */U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); - /*volatile */U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); + volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); // set for rendering virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 @@ -251,17 +245,18 @@ public: S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } - /*volatile */U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } - /*volatile */U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } U32 getTypeMask() const { return mTypeMask; } bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } S32 getSize() const; S32 getIndicesSize() const { return mIndicesSize; } - /*volatile */U8* getMappedData() const { return mMappedData; } - /*volatile */U8* getMappedIndices() const { return mMappedIndexData; } + volatile U8* getMappedData() const { return mMappedData; } + volatile U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } - + BOOL isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; } + void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; @@ -285,12 +280,13 @@ protected: U32 mGLIndices; // GL IBO handle U32 mGLArray; // GL VAO handle - /*volatile */U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) - /*volatile */U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) + volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) + volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory BOOL mFinal; // if TRUE, buffer can not be mapped again BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded. + mutable BOOL mMappable; // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) S32 mOffsets[TYPE_MAX]; std::vector mMappedVertexRegions; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 162c2e33f..b54a1495a 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1301,7 +1301,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face->setGeomIndex(0); face->setIndicesIndex(0); - if (buffer.isNull() || buffer->getTypeMask() != data_mask) + if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) { //make a new buffer if (sShaderLevel > 0) { @@ -1335,7 +1335,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* LLMatrix3 mat_normal(mat3); //let getGeometryVolume know if alpha should override shiny - if (face->getFaceColor().mV[3] < 1.f) + U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); + + if (type == LLDrawPool::POOL_ALPHA) { face->setPoolType(LLDrawPool::POOL_ALPHA); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 06d4bdc03..b41481e26 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -695,6 +695,49 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of tex_coord.mV[1] = t; } +// Transform the texture coordinates for this face. +static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale) +{ + //tex coord is two coords, + LLVector4a st; + + // Texture transforms are done about the center of the face. + st.setAdd(tex_coord, trans); + + // Handle rotation + LLVector4a rot_st; + + // + LLVector4a s0; + s0.splat(st, 0); + LLVector4a s1; + s1.splat(st, 2); + LLVector4a ss; + ss.setSelectWithMask(mask, s1, s0); + + LLVector4a a; + a.setMul(rot0, ss); + + // + LLVector4a t0; + t0.splat(st, 1); + LLVector4a t1; + t1.splat(st, 3); + LLVector4a tt; + tt.setSelectWithMask(mask, t1, t0); + + LLVector4a b; + b.setMul(rot1, tt); + + st.setAdd(a,b); + + // Then scale + st.mul(scale); + + // Then offset + tex_coord.setAdd(st, offset); +} + bool less_than_max_mag(const LLVector4a& vec) { @@ -1069,7 +1112,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, updateRebuildFlags(); } - bool map_range = gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange; + + //don't use map range (generates many redundant unmap calls) + bool map_range = false; //gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange; if (mVertexBuffer.notNull()) { @@ -1095,16 +1140,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } LLStrider vert; - LLVector4a* vertices = NULL; LLStrider tex_coords; LLStrider tex_coords2; - LLVector4a* normals = NULL; LLStrider norm; LLStrider colors; - LLVector4a* binormals = NULL; LLStrider binorm; LLStrider indicesp; - LLVector4a* weights = NULL; LLStrider wght; BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); @@ -1172,7 +1213,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLFastTimer t(LLFastTimer::FTM_FACE_GEOM_INDEX); mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range); - __m128i* dst = (__m128i*) indicesp.get(); + volatile __m128i* dst = (__m128i*) indicesp.get(); __m128i* src = (__m128i*) vf.mIndices; __m128i offset = _mm_set1_epi16(index_offset); @@ -1181,12 +1222,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < end; i++) { __m128i res = _mm_add_epi16(src[i], offset); - _mm_storeu_si128(dst+i, res); + _mm_storeu_si128((__m128i*) dst++, res); } - for (S32 i = end*8; i < num_indices; ++i) { - indicesp[i] = vf.mIndices[i]+index_offset; + //LLFastTimer t(LLFastTimer::FTM_FACE_GEOM_INDEX_TAIL); + U16* idx = (U16*) dst; + + for (S32 i = end*8; i < num_indices; ++i) + { + *idx++ = vf.mIndices[i]+index_offset; + } } if (map_range) @@ -1351,11 +1397,37 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { - for (S32 i = 0; i < num_vertices; i++) + F32* dst = (F32*) tex_coords.get(); + LLVector4a* src = (LLVector4a*) vf.mTexCoords; + + LLVector4a trans; + trans.splat(-0.5f); + + LLVector4a rot0; + rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); + + LLVector4a rot1; + rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); + + LLVector4a scale; + scale.set(ms, mt, ms, mt); + + LLVector4a offset; + offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<2>(); + mask.setElement<3>(); + + U32 count = num_vertices/2 + num_vertices%2; + + for (U32 i = 0; i < count; i++) { - LLVector2 tc(vf.mTexCoords[i]); - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - *tex_coords++ = tc; + LLVector4a res = *src++; + xform4a(res, trans, mask, rot0, rot1, offset, scale); + res.store4a(dst); + dst += 4; } } } @@ -1526,44 +1598,53 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); - vertices = (LLVector4a*) vert.get(); - + + LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); LLVector4a* src = vf.mPositions; - LLVector4a* dst = vertices; + volatile F32* dst = (volatile F32*) vert.get(); - LLVector4a* end = dst+num_vertices; - do - { - mat_vert.affineTransform(*src++, *dst++); - } - while(dst < end); + volatile F32* end = dst+num_vertices*4; + LLVector4a res; + + LLVector4a texIdx; F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); - llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); - F32 *index_dst = (F32*) vertices; - F32 *index_end = (F32*) end; - index_dst += 3; - index_end += 3; - do - { - *index_dst = index; - index_dst += 4; - } - while (index_dst < index_end); + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); - S32 aligned_pad_vertices = mGeomCount - num_vertices; - LLVector4a* last_vec = end - 1; - while (aligned_pad_vertices > 0) + texIdx.set(0,0,0,index); + { - --aligned_pad_vertices; - *dst++ = *last_vec; + LLVector4a tmp; + + do + { + mat_vert.affineTransform(*src++, res); + tmp.setSelectWithMask(mask, texIdx, res); + tmp.store4a((F32*) dst); + dst += 4; + } + while(dst < end); } - + + { + S32 aligned_pad_vertices = mGeomCount - num_vertices; + res.set(res[0], res[1], res[2], 0.f); + + while (aligned_pad_vertices > 0) + { + --aligned_pad_vertices; + res.store4a((F32*) dst); + dst += 4; + } + } + if (map_range) { mVertexBuffer->flush(); @@ -1574,14 +1655,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(LLFastTimer::FTM_FACE_GEOM_NORMAL); mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); - normals = (LLVector4a*) norm.get(); + F32* normals = (F32*) norm.get(); for (S32 i = 0; i < num_vertices; i++) { LLVector4a normal; mat_normal.rotate(vf.mNormals[i], normal); normal.normalize3fast(); - normals[i] = normal; + normal.store4a(normals); + normals += 4; } if (map_range) @@ -1594,14 +1676,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(LLFastTimer::FTM_FACE_GEOM_BINORMAL); mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range); - binormals = (LLVector4a*) binorm.get(); + F32* binormals = (F32*) binorm.get(); for (S32 i = 0; i < num_vertices; i++) { LLVector4a binormal; mat_normal.rotate(vf.mBinormals[i], binormal); binormal.normalize3fast(); - binormals[i] = binormal; + binormal.store4a(binormals); + binormals += 4; } if (map_range) @@ -1614,8 +1697,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { LLFastTimer t(LLFastTimer::FTM_FACE_GEOM_WEIGHTS); mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); - weights = (LLVector4a*) wght.get(); - LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); + F32* weights = (F32*) wght.get(); + LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); if (map_range) { mVertexBuffer->flush(); @@ -1634,7 +1717,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, src.loadua((F32*) vec); - LLVector4a* dst = (LLVector4a*) colors.get(); + F32* dst = (F32*) colors.get(); S32 num_vecs = num_vertices/4; if (num_vertices%4 > 0) { @@ -1643,7 +1726,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < num_vecs; i++) { - dst[i] = src; + src.store4a(dst); + dst += 4; } if (map_range) @@ -1673,7 +1757,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, src.loadua((F32*) vec); - LLVector4a* dst = (LLVector4a*) emissive.get(); + F32* dst = (F32*) emissive.get(); S32 num_vecs = num_vertices/4; if (num_vertices%4 > 0) { @@ -1682,7 +1766,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < num_vecs; i++) { - dst[i] = src; + src.store4a(dst); + dst += 4; } if (map_range) diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 72de68d0c..1733cac0d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5571,38 +5571,37 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) //helper function for pushing relevant vertices from drawable to GL void pushWireframe(LLDrawable* drawable) { - if (drawable->isState(LLDrawable::RIGGED)) - { //render straight from rigged volume if this is a rigged attachment - LLVOVolume* vobj = drawable->getVOVolume(); - if (vobj) - { - vobj->updateRiggedVolume(); - LLRiggedVolume* rigged_volume = vobj->getRiggedVolume(); - if (rigged_volume) - { - LLVertexBuffer::unbind(); - gGL.pushMatrix(); - gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); - for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = rigged_volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); - } - gGL.popMatrix(); - } - } - } - else + LLVOVolume* vobj = drawable->getVOVolume(); + if (vobj) { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) + LLVertexBuffer::unbind(); + gGL.pushMatrix(); + gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); + + LLVolume* volume = NULL; + + if (drawable->isState(LLDrawable::RIGGED)) { - LLFace* face = drawable->getFace(i); - if (face->verify()) + vobj->updateRiggedVolume(); + volume = vobj->getRiggedVolume(); + } + else + { + volume = vobj->getVolume(); + } + + if (volume) + { + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { - pushVerts(face, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + const LLVolumeFace& face = volume->getVolumeFace(i); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, face.mTexCoords, face.mNumIndices, face.mIndices); } } + + gGL.popMatrix(); } + } void LLSelectNode::renderOneWireframe(const LLColor4& color) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 83c9833c4..9e766bb2a 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -34,6 +34,10 @@ #include "llspatialpartition.h" +#include "llappviewer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h" #include "llviewerwindow.h" #include "llviewerobjectlist.h" #include "llvovolume.h" @@ -43,14 +47,13 @@ #include "llface.h" #include "llfloatertools.h" #include "llviewercontrol.h" -#include "llagent.h" #include "llviewerregion.h" #include "llcamera.h" #include "pipeline.h" #include "llmeshrepository.h" #include "llrender.h" #include "lloctree.h" -#include "llvoavatar.h" +#include "llphysicsshapebuilderutil.h" #include "llvoavatar.h" #include "llvolumemgr.h" #include "llglslshader.h" @@ -262,7 +265,7 @@ U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center) void LLSpatialGroup::buildOcclusion() { - if (mOcclusionVerts.isNull()) + //if (mOcclusionVerts.isNull()) { mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, @@ -608,7 +611,9 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node group->mBuilt = 1.f; - if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) + if (group->mVertexBuffer.isNull() || + !group->mVertexBuffer->isWriteable() || + (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) { group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); @@ -1106,6 +1111,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) { mOcclusionQuery[i] = 0; + mOcclusionIssued[i] = 0; mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0; mVisible[i] = 0; } @@ -1440,10 +1446,27 @@ void LLSpatialGroup::checkOcclusion() } else if (isOcclusionState(QUERY_PENDING)) { //otherwise, if a query is pending, read it back + GLuint available = 0; if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) { glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); + + if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) + { //query was issued last frame, wait until it's available + S32 max_loop = 1024; + //LLFastTimer t(LLFastTimer::FTM_OCCLUSION_WAIT); + while (!available && max_loop-- > 0) + { + F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); + //do some usefu work while we wait + LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread + LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread + LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread + + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); + } + } } else { @@ -1549,6 +1572,8 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) { //LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS); + //store which frame this query was issued on + mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); @@ -2987,11 +3012,7 @@ void renderRaycast(LLDrawable* drawablep) for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) { const LLVolumeFace& face = volume->getVolumeFace(i); - if (!face.mOctree) - { - ((LLVolumeFace*) &face)->createOctree(); - } - + gGL.pushMatrix(); gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); @@ -3014,9 +3035,6 @@ void renderRaycast(LLDrawable* drawablep) LLVector4a dir; dir.setSub(enda, starta); - F32 t = 1.f; - - LLRenderOctreeRaycast render(starta, dir, &t); gGL.flush(); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -3028,8 +3046,20 @@ void renderRaycast(LLDrawable* drawablep) gGL.syncMatrices(); glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); } - - render.traverse(face.mOctree); + + if (!volume->isUnique()) + { + F32 t = 1.f; + + if (!face.mOctree) + { + ((LLVolumeFace*) &face)->createOctree(); + } + + LLRenderOctreeRaycast render(starta, dir, &t); + + render.traverse(face.mOctree); + } gGL.popMatrix(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index f43a21d6a..c36b29752 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -46,7 +46,7 @@ #include "lldrawpool.h" #include "llface.h" #include "llviewercamera.h" - +#include "llvector4a.h" #include #define SG_STATE_INHERIT_MASK (OCCLUDED) @@ -368,6 +368,7 @@ protected: U32 mState; U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS]; + U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS]; S32 mLODHash; static S32 sLODSeed; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index d7ae2822a..062d0695a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5457,11 +5457,12 @@ void LLViewerObject::dirtyMesh() { if (mDrawable) { - LLSpatialGroup* group = mDrawable->getSpatialGroup(); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + /*LLSpatialGroup* group = mDrawable->getSpatialGroup(); if (group) { group->dirtyMesh(); - } + }*/ } } diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 0381a7c90..d3c1c3421 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -71,7 +71,7 @@ public: return; } - U8* base = useVBOs() ? (U8*) mAlignedOffset : /*(U8*)*/ mMappedData; + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; //assume tex coords 2 and 3 are present U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 79c560088..4b5c0375d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4052,17 +4052,20 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: //create/delete/resize vertex buffer if needed LLVertexBuffer* buffer = NULL; - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); + + { //try to find a buffer to reuse + LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); - if (found_iter != group->mBufferMap[mask].end()) - { - if ((U32) buffer_index < found_iter->second.size()) + if (found_iter != group->mBufferMap[mask].end()) { - buffer = found_iter->second[buffer_index]; + if ((U32) buffer_index < found_iter->second.size()) + { + buffer = found_iter->second[buffer_index]; + } } } - if (!buffer) + if (!buffer || !buffer->isWriteable()) { //create new buffer if needed buffer = createVertexBuffer(mask, buffer_usage); buffer->allocateBuffer(geom_count, index_count, TRUE); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 66af97b81..d02229b90 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -171,7 +171,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) indices_per_quad * num_quads); LLVertexBuffer* buff = face->getVertexBuffer(); - if (!buff) + if (!buff || !buff->isWriteable()) { buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index bdfe68f2d..eae95e716 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -775,7 +775,7 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) LLStrider colorsp; LLStrider texcoordsp; - if (mStarsVerts.isNull()) + if (mStarsVerts.isNull() || !mStarsVerts->isWriteable()) { mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW); mStarsVerts->allocateBuffer(getStarsNumVerts()*6, 0, TRUE);