From e68d5e248f73180def7c8928b32482347dd91de4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 Dec 2011 16:18:19 -0500 Subject: SH-2789 WIP - add asserts to check object address alignment where needed --- indra/llcommon/llmemory.h | 9 +++++++++ 1 file changed, 9 insertions(+) mode change 100644 => 100755 indra/llcommon/llmemory.h (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h old mode 100644 new mode 100755 index bbbdaa6497..baf91bb96d --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -512,4 +512,13 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr) // LLSingleton moved to llsingleton.h +#define CHECK_ALIGNMENT + +#ifdef CHECK_ALIGNMENT +#define ll_assert_aligned(ptr,alignment) llassert((reinterpret_cast(ptr))%(alignment) == 0) +#else +#define ll_assert_aligned(ptr,alignment) +#endif + + #endif -- cgit v1.3 From 9c2e0d84f84fe7c38b1e9f7a127efc540b43f5aa Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 19 Dec 2011 18:17:18 -0500 Subject: SH-2789 WIP - various fixes to force 16-byte alignment --- indra/llcommon/llmemory.cpp | 9 +++++ indra/llcommon/llmemory.h | 9 +++-- indra/llmath/lloctree.h | 4 +- indra/llmath/llvector4a.cpp | 7 +++- indra/llmath/llvolumeoctree.h | 14 ++++++- indra/llmath/tests/alignment_test.cpp | 74 +++++++++++++++-------------------- indra/newview/lldrawable.h | 10 +++++ indra/newview/lldynamictexture.h | 12 +++++- indra/newview/llface.h | 11 ++++++ indra/newview/llspatialpartition.cpp | 2 +- indra/newview/llspatialpartition.h | 24 +++++++++++- indra/newview/llviewercamera.h | 9 +++++ indra/newview/llvoavatar.h | 10 +++++ indra/newview/llvoavatarself.h | 10 +++++ 14 files changed, 151 insertions(+), 54 deletions(-) mode change 100644 => 100755 indra/llmath/llvector4a.cpp mode change 100644 => 100755 indra/llmath/llvolumeoctree.h mode change 100644 => 100755 indra/newview/lldynamictexture.h mode change 100644 => 100755 indra/newview/llface.h mode change 100644 => 100755 indra/newview/llvoavatarself.h (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 3b9758f996..22204e756a 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -61,6 +61,15 @@ BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sMemAllocationTracker; #endif +void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) +{ + if (ptr%alignment!=0) + { + llwarns << "alignment check failed" << llendl; + } + llassert(ptr%alignment==0); +} + //static void LLMemory::initClass() { diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index baf91bb96d..c61d06e924 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,7 @@ #define LLMEMORY_H #include "llmemtype.h" -#if LL_DEBUG +#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); @@ -94,7 +94,8 @@ inline void ll_aligned_free_32(void *p) free(p); // posix_memalign() is compatible with heap deallocator #endif } -#else // LL_DEBUG + +#else // USE_TCMALLOC // ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals) #define ll_aligned_malloc( size, align ) malloc(size) #define ll_aligned_free( ptr ) free(ptr) @@ -514,8 +515,10 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr) #define CHECK_ALIGNMENT +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); + #ifdef CHECK_ALIGNMENT -#define ll_assert_aligned(ptr,alignment) llassert((reinterpret_cast(ptr))%(alignment) == 0) +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast(ptr),((U32)alignment)) #else #define ll_assert_aligned(ptr,alignment) #endif diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 3c1ae45d68..374858be51 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -88,7 +88,7 @@ public: typedef LLOctreeNode oct_node; typedef LLOctreeListener oct_listener; - /*void* operator new(size_t size) + void* operator new(size_t size) { return ll_aligned_malloc_16(size); } @@ -96,7 +96,7 @@ public: void operator delete(void* ptr) { ll_aligned_free_16(ptr); - }*/ + } LLOctreeNode( const LLVector4a& center, const LLVector4a& size, diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp old mode 100644 new mode 100755 index 49b8754cd0..7602ef0cb2 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -41,11 +41,15 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F /*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes) { + memcpy((void*)dst,(const void*)src,bytes); +#if 0 assert(src != NULL); assert(dst != NULL); assert(bytes > 0); assert((bytes % sizeof(F32))== 0); - + ll_assert_aligned(src,16); + ll_assert_aligned(dst,16); + F32* end = dst + (bytes / sizeof(F32) ); if (bytes > 64) @@ -87,6 +91,7 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F dst += 4; src += 4; } +#endif } void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h old mode 100644 new mode 100755 index 688d91dc40..6de7b223be --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -73,6 +73,16 @@ class LLVolumeOctreeListener : public LLOctreeListener { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVolumeOctreeListener(LLOctreeNode* node); ~LLVolumeOctreeListener(); @@ -99,8 +109,8 @@ public: public: - LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) - LLVector4a mExtents[2]; // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children }; class LLOctreeTriangleRayIntersect : public LLOctreeTraveler diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp index 6b4a454fd2..51a7051e69 100755 --- a/indra/llmath/tests/alignment_test.cpp +++ b/indra/llmath/tests/alignment_test.cpp @@ -34,10 +34,21 @@ #include "../llsimdmath.h" #include "../llvector4a.h" +void* operator new(size_t size) +{ + return ll_aligned_malloc_16(size); +} + +void operator delete(void *p) +{ + ll_aligned_free_16(p); +} + namespace tut { #define is_aligned(ptr,alignment) ((reinterpret_cast(ptr))%(alignment)==0) +#define is_aligned_relative(ptr,base_ptr,alignment) ((reinterpret_cast(ptr)-reinterpret_cast(base_ptr))%(alignment)==0) struct alignment_test {}; @@ -51,38 +62,40 @@ class MyVector4a LLQuad mQ; } LL_ALIGN_POSTFIX(16); -LL_ALIGN_PREFIX(64) -class MyBigBlob +// Verify that aligned allocators perform as advertised. +template<> template<> +void alignment_test_object_t::test<1>() { -public: - ~MyBigBlob() {} -private: - LLQuad mQ[4]; -} LL_ALIGN_POSTFIX(64); + const int num_tests = 7; + void *align_ptr; + for (int i=0; i template<> -void alignment_test_object_t::test<1>() +void alignment_test_object_t::test<2>() { ensure("LLAlignment reality is broken: ", (1==1)); MyVector4a vec1; ensure("LLAlignment vec1 unaligned", is_aligned(&vec1,16)); - MyBigBlob bb1; - ensure("LLAlignment bb1 unaligned", is_aligned(&bb1,64)); - - MyVector4a veca[12]; ensure("LLAlignment veca unaligned", is_aligned(veca,16)); - - MyBigBlob bba[12]; - ensure("LLAlignment bba unaligned", is_aligned(bba,64)); } // Heap allocation of objects and arrays. template<> template<> -void alignment_test_object_t::test<2>() +void alignment_test_object_t::test<3>() { const int ARR_SIZE = 7; for(int i=0; i() } MyVector4a *veca = new MyVector4a[ARR_SIZE]; + ensure("LLAligment veca base", is_aligned(veca,16)); for(int i=0; i~MyBigBlob(); - _aligned_free(aligned_addr); - } - - ensure("LLAlignment big blob size",sizeof(MyBigBlob)==64); - void *aligned_addr = _aligned_malloc(ARR_SIZE*sizeof(MyBigBlob),64); - MyBigBlob *bba = new(aligned_addr) MyBigBlob[ARR_SIZE]; - std::cout << "aligned_addr " << aligned_addr << std::endl; - std::cout << "bba " << bba << std::endl; - for(int i=0; i instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; diff --git a/indra/newview/llface.h b/indra/newview/llface.h old mode 100644 new mode 100755 index 82e4ab61b7..feb6244f72 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -59,6 +59,17 @@ class LLFace { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + + LLFace(const LLFace& rhs) { *this = rhs; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index a8b5ee47d1..4c45ac6b47 100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1196,7 +1196,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mCurUpdatingSlotp(NULL), mCurUpdatingTexture (NULL) { - ll_assert_aligned(this,64); + ll_assert_aligned(this,16); sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index cbd4507f84..22bea69df3 100755 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -68,6 +68,16 @@ protected: ~LLDrawInfo(); public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLDrawInfo(const LLDrawInfo& rhs) { @@ -106,7 +116,7 @@ public: F32 mPartSize; F32 mVSize; LLSpatialGroup* mGroup; - LLFace* mFace; //associated face + LL_ALIGN_16(LLFace* mFace); //associated face F32 mDistance; U32 mDrawMode; @@ -181,7 +191,7 @@ public: }; }; -LL_ALIGN_PREFIX(64) +LL_ALIGN_PREFIX(16) class LLSpatialGroup : public LLOctreeListener { friend class LLSpatialPartition; @@ -193,6 +203,16 @@ public: *this = rhs; } + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + const LLSpatialGroup& operator=(const LLSpatialGroup& rhs) { llerrs << "Illegal operation!" << llendl; diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 7257297cfd..d2624ba14e 100755 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -55,6 +55,15 @@ LL_ALIGN_PREFIX(16) class LLViewerCamera : public LLCamera, public LLSingleton { public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } typedef enum { diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 82157436b9..20ea3686d6 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -90,6 +90,16 @@ protected: **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual void markDead(); static void initClass(); // Initialize data that's only init'd once per class. diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h old mode 100644 new mode 100755 index 74ff47a3e4..23a2025e70 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -48,6 +48,16 @@ class LLVOAvatarSelf : **/ public: + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + LLVOAvatarSelf(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOAvatarSelf(); virtual void markDead(); -- cgit v1.3 From c8682722ad6b889b13ce288c417cb6b82ed273ac Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 21 Dec 2011 17:02:47 -0500 Subject: SH-2789 WIP - aligned alloc and realloc --- indra/llcommon/llmemory.h | 15 +++++++++++++-- indra/llmath/llvector4a.cpp | 5 +++-- indra/llmath/llvolume.cpp | 22 +++++++++++++--------- indra/newview/llpolymesh.cpp | 24 ++++++++++++------------ 4 files changed, 41 insertions(+), 25 deletions(-) mode change 100644 => 100755 indra/newview/llpolymesh.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index c61d06e924..3eaf700bf1 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -46,7 +46,7 @@ inline void ll_aligned_free( void* ptr ) inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 16); + return _aligned_malloc(size, 16); #elif defined(LL_DARWIN) return malloc(size); // default osx malloc is 16 byte aligned. #else @@ -58,10 +58,21 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi #endif } +inline void* ll_aligned_realloc_16(void* ptr, size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). +{ +#if defined(LL_WINDOWS) + return _aligned_realloc(ptr, size, 16); +#elif defined(LL_DARWIN) + return realloc(ptr,size); // default osx malloc is 16 byte aligned. +#else + return realloc(ptr,size); // FIXME not guaranteed to be aligned. +#endif +} + inline void ll_aligned_free_16(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) return free(p); #else diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index 7602ef0cb2..480ccf4ed9 100755 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -41,14 +41,15 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F /*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes) { - memcpy((void*)dst,(const void*)src,bytes); -#if 0 +// memcpy((void*)dst,(const void*)src,bytes); +#if 1 assert(src != NULL); assert(dst != NULL); assert(bytes > 0); assert((bytes % sizeof(F32))== 0); ll_assert_aligned(src,16); ll_assert_aligned(dst,16); + assert(bytes%16==0); F32* end = dst + (bytes / sizeof(F32) ); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 113d4835bb..9499ca29ac 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -6914,14 +6914,17 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con // S32 old_size = mNumVertices*16; //positions - mPositions = (LLVector4a*) realloc(mPositions, new_size); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size); + ll_assert_aligned(mPositions,16); //normals - mNormals = (LLVector4a*) realloc(mNormals, new_size); - + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size); + ll_assert_aligned(mNormals,16); + //tex coords new_size = ((new_verts*8)+0xF) & ~0xF; - mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size); + ll_assert_aligned(mTexCoords,16); //just clear binormals @@ -6974,7 +6977,8 @@ void LLVolumeFace::pushIndex(const U16& idx) S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; if (new_size != old_size) { - mIndices = (U16*) realloc(mIndices, new_size); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size); + ll_assert_aligned(mIndices,16); } mIndices[mNumIndices++] = idx; @@ -7015,11 +7019,11 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat } //allocate new buffer space - mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); + mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a)); ll_assert_aligned(mPositions, 16); - mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); + mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a)); ll_assert_aligned(mNormals, 16); - mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); + mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); ll_assert_aligned(mTexCoords, 16); mNumVertices = new_count; @@ -7066,7 +7070,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat new_count = mNumIndices + face.mNumIndices; //allocate new index buffer - mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); + mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); //get destination address into new index buffer U16* dst_idx = mIndices+mNumIndices; diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp old mode 100644 new mode 100755 index 450f9b2be7..0860506086 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -129,22 +129,22 @@ void LLPolyMeshSharedData::freeMeshData() { mNumVertices = 0; - delete [] mBaseCoords; + ll_aligned_free_16(mBaseCoords); mBaseCoords = NULL; - delete [] mBaseNormals; + ll_aligned_free_16(mBaseNormals); mBaseNormals = NULL; - delete [] mBaseBinormals; + ll_aligned_free_16(mBaseBinormals); mBaseBinormals = NULL; - delete [] mTexCoords; + ll_aligned_free_16(mTexCoords); mTexCoords = NULL; - delete [] mDetailTexCoords; + ll_aligned_free_16(mDetailTexCoords); mDetailTexCoords = NULL; - delete [] mWeights; + ll_aligned_free_16(mWeights); mWeights = NULL; } @@ -229,12 +229,12 @@ U32 LLPolyMeshSharedData::getNumKB() BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { U32 i; - mBaseCoords = new LLVector3[ numVertices ]; - mBaseNormals = new LLVector3[ numVertices ]; - mBaseBinormals = new LLVector3[ numVertices ]; - mTexCoords = new LLVector2[ numVertices ]; - mDetailTexCoords = new LLVector2[ numVertices ]; - mWeights = new F32[ numVertices ]; + mBaseCoords = (LLVector3*) ll_aligned_malloc_16(numVertices*sizeof(LLVector3)); + mBaseNormals = (LLVector3*) ll_aligned_malloc_16(numVertices*sizeof(LLVector3)); + mBaseBinormals = (LLVector3*) ll_aligned_malloc_16(numVertices*sizeof(LLVector3)); + mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); for (i = 0; i < numVertices; i++) { mWeights[i] = 0.f; -- cgit v1.3 From 1435a8b9e6203911d2ebe9e3ba217f8eb20e3140 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 4 Jan 2012 15:21:23 -0500 Subject: SH-2789 WIP - stricter calling of memcpyNonAliased16 --- indra/llcommon/llmemory.cpp | 3 +++ indra/llcommon/llmemory.h | 12 ++++++------ indra/llmath/llvector4a.cpp | 3 --- indra/llmath/llvector4a.h | 1 + indra/llmath/tests/alignment_test.cpp | 6 ++++-- indra/newview/llfloatermodelpreview.cpp | 3 ++- indra/newview/llviewerjointmesh.cpp | 6 ++++-- 7 files changed, 20 insertions(+), 14 deletions(-) mode change 100644 => 100755 indra/llcommon/llmemory.cpp mode change 100644 => 100755 indra/newview/llviewerjointmesh.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp old mode 100644 new mode 100755 index 22204e756a..afaf366668 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -63,11 +63,14 @@ LLPrivateMemoryPoolManager::mem_allocation_info_t LLPrivateMemoryPoolManager::sM void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) { +#ifdef SHOW_ASSERT + // Redundant, place to set breakpoints. if (ptr%alignment!=0) { llwarns << "alignment check failed" << llendl; } llassert(ptr%alignment==0); +#endif } //static diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 3eaf700bf1..1b54b56107 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -83,7 +83,7 @@ inline void ll_aligned_free_16(void *p) inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { #if defined(LL_WINDOWS) - return _mm_malloc(size, 32); + return _aligned_malloc(size, 32); #elif defined(LL_DARWIN) return ll_aligned_malloc( size, 32 ); #else @@ -98,7 +98,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_32(void *p) { #if defined(LL_WINDOWS) - _mm_free(p); + _aligned_free(p); #elif defined(LL_DARWIN) ll_aligned_free( p ); #else @@ -107,10 +107,12 @@ inline void ll_aligned_free_32(void *p) } #else // USE_TCMALLOC -// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals) +// ll_aligned_foo are noops now that we use tcmalloc everywhere +// (tcmalloc aligns automatically at appropriate intervals) #define ll_aligned_malloc( size, align ) malloc(size) #define ll_aligned_free( ptr ) free(ptr) #define ll_aligned_malloc_16 malloc +#define ll_aligned_realloc_16 realloc #define ll_aligned_free_16 free #define ll_aligned_malloc_32 malloc #define ll_aligned_free_32 free @@ -524,11 +526,9 @@ void LLPrivateMemoryPoolTester::operator delete[](void* addr) // LLSingleton moved to llsingleton.h -#define CHECK_ALIGNMENT - LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); -#ifdef CHECK_ALIGNMENT +#ifdef SHOW_ASSERT #define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast(ptr),((U32)alignment)) #else #define ll_assert_aligned(ptr,alignment) diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index 480ccf4ed9..6edeb0fefe 100755 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -41,8 +41,6 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F /*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes) { -// memcpy((void*)dst,(const void*)src,bytes); -#if 1 assert(src != NULL); assert(dst != NULL); assert(bytes > 0); @@ -92,7 +90,6 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F dst += 4; src += 4; } -#endif } void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 9de0e66774..0526793d3a 100755 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -84,6 +84,7 @@ public: } // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. + // Source and dest must be 16-byte aligned and size must be multiple of 16. static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); //////////////////////////////////// diff --git a/indra/llmath/tests/alignment_test.cpp b/indra/llmath/tests/alignment_test.cpp index 51a7051e69..dc9b41957d 100755 --- a/indra/llmath/tests/alignment_test.cpp +++ b/indra/llmath/tests/alignment_test.cpp @@ -72,6 +72,10 @@ void alignment_test_object_t::test<1>() { align_ptr = ll_aligned_malloc_16(sizeof(MyVector4a)); ensure("ll_aligned_malloc_16 failed", is_aligned(align_ptr,16)); + + align_ptr = ll_aligned_realloc_16(2*sizeof(MyVector4a)); + ensure("ll_aligned_realloc_16 failed", is_aligned(align_ptr,16)); + ll_aligned_free_16(align_ptr); align_ptr = ll_aligned_malloc_32(sizeof(MyVector4a)); @@ -84,8 +88,6 @@ void alignment_test_object_t::test<1>() template<> template<> void alignment_test_object_t::test<2>() { - ensure("LLAlignment reality is broken: ", (1==1)); - MyVector4a vec1; ensure("LLAlignment vec1 unaligned", is_aligned(&vec1,16)); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 64bdcccd9f..8aa3b95578 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4770,7 +4770,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) if (vf.mTexCoords) { vb->getTexCoord0Strider(tc_strider); - LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + S32 tex_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, tex_size); } if (vf.mNormals) diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp old mode 100644 new mode 100755 index 76f4e18c27..d604687678 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -731,8 +731,10 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w F32* vw = (F32*) vertex_weightsp.get(); F32* cw = (F32*) clothing_weightsp.get(); - LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2*sizeof(F32)); - LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts*sizeof(F32)); + S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size); + S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size); LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); } -- cgit v1.3 From bfe6e94f5388b887253ba77f633ae332affe9f92 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 6 Jan 2012 13:01:17 -0500 Subject: SH-2789 WIP - fixing the LL_USE_TCMALLOC code, make tests build with the same tcmalloc options as the sl executable --- indra/cmake/GooglePerfTools.cmake | 16 +++++++++------- indra/cmake/LLAddBuildTest.cmake | 9 +++++++++ indra/llcommon/llallocator.cpp | 2 +- indra/newview/CMakeLists.txt | 8 +------- 4 files changed, 20 insertions(+), 15 deletions(-) mode change 100644 => 100755 indra/cmake/LLAddBuildTest.cmake mode change 100644 => 100755 indra/llcommon/llallocator.cpp (limited to 'indra/llcommon') diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 834da6d9b8..09501e0406 100755 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -14,8 +14,10 @@ else (STANDALONE) set(TCMALLOC_LIBRARIES debug libtcmalloc_minimal-debug optimized libtcmalloc_minimal) + set(TCMALLOC_LINK_FLAGS "/INCLUDE:__tcmalloc") else (USE_TCMALLOC) set(TCMALLOC_LIBRARIES) + set(TCMALLOC_LINK_FLAGS) endif (USE_TCMALLOC) set(GOOGLE_PERFTOOLS_FOUND "YES") endif (WINDOWS) @@ -44,13 +46,13 @@ if (WINDOWS) set(USE_GOOGLE_PERFTOOLS ON) endif (WINDOWS) -# Apparently buggy - LL_USE_TCMALLOC never gets set. Fix when we have time to test the -# corresponding source code. -if (USE_TCMALLOC) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) # was -ULL_USE_TCMALLOC=1 which makes no sense. -else (USE_TCMALLOC) - set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) -endif (USE_TCMALLOC) +if (USE_GOOGLE_PERFTOOLS) + if (USE_TCMALLOC) + set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1) + else (USE_TCMALLOC) + set(TCMALLOC_FLAG -ULL_USE_TCMALLOC) + endif (USE_TCMALLOC) +endif (USE_GOOGLE_PERFTOOLS) if (USE_GOOGLE_PERFTOOLS) include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR}) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake old mode 100644 new mode 100755 index 08feab6e36..a6f69a09e9 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -205,6 +205,15 @@ FUNCTION(LL_ADD_INTEGRATION_TEST SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") endif(STANDALONE) + if (WINDOWS) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} + PROPERTIES + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" + LINK_FLAGS_RELEASE "" + ) + endif (WINDOWS) + # Add link deps to the executable if(TEST_DEBUG) message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp old mode 100644 new mode 100755 index 6f6abefc67..87654b5b97 --- a/indra/llcommon/llallocator.cpp +++ b/indra/llcommon/llallocator.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include "llallocator.h" -#if LL_USE_TCMALLOC +#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER) #include "google/heap-profiler.h" #include "google/commandlineflags_public.h" diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 00cf1ba8df..f929e8d379 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1505,15 +1505,9 @@ set(PACKAGE ON CACHE BOOL "Add a package target that builds an installer package.") if (WINDOWS) - if (USE_TCMALLOC) - set(TCMALLOC_INCLUDE_FLAGS "/INCLUDE:__tcmalloc") - else (USE_TCMALLOC) - set(TCMALLOC_INCLUDE_FLAGS) - endif (USE_TCMALLOC) - set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_INCLUDE_FLAGS}" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS ${TCMALLOC_LINK_FLAGS}" LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO" LINK_FLAGS_RELEASE "" ) -- cgit v1.3 From 60a9c8d7abe102cefeb72666b9645a6dd34e84b8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 11 Jan 2012 15:59:34 -0500 Subject: Fixes for alignment tests with tcmalloc --- indra/llcommon/llmemory.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 1b54b56107..9dd776ff57 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,6 @@ #define LLMEMORY_H #include "llmemtype.h" -#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); @@ -43,6 +42,7 @@ inline void ll_aligned_free( void* ptr ) free( ((void**)ptr)[-1] ); } +#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { #if defined(LL_WINDOWS) @@ -79,6 +79,12 @@ inline void ll_aligned_free_16(void *p) free(p); // posix_memalign() is compatible with heap deallocator #endif } +#else // USE_TCMALLOC +// ll_aligned_foo_16 are not needed with tcmalloc +#define ll_aligned_malloc_16 malloc +#define ll_aligned_realloc_16 realloc +#define ll_aligned_free_16 free +#endif // USE_TCMALLOC inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { @@ -106,18 +112,6 @@ inline void ll_aligned_free_32(void *p) #endif } -#else // USE_TCMALLOC -// ll_aligned_foo are noops now that we use tcmalloc everywhere -// (tcmalloc aligns automatically at appropriate intervals) -#define ll_aligned_malloc( size, align ) malloc(size) -#define ll_aligned_free( ptr ) free(ptr) -#define ll_aligned_malloc_16 malloc -#define ll_aligned_realloc_16 realloc -#define ll_aligned_free_16 free -#define ll_aligned_malloc_32 malloc -#define ll_aligned_free_32 free -#endif // LL_DEBUG - #ifndef __DEBUG_PRIVATE_MEM__ #define __DEBUG_PRIVATE_MEM__ 0 #endif -- cgit v1.3 From f0d1afc2266e13b4f36f750ba5e721e427caf7b8 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Fri, 20 Jan 2012 18:07:35 +0100 Subject: STORM-276 Added spellcheck functionality to the LLLineEditor control --- indra/llcommon/llstring.h | 3 + indra/llui/lllineeditor.cpp | 217 ++++++++++++++++++++- indra/llui/lllineeditor.h | 29 ++- .../skins/default/xui/en/menu_text_editor.xml | 79 ++++++++ 4 files changed, 324 insertions(+), 4 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7e41e787b5..3a27badb5a 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -182,6 +182,9 @@ public: static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } static bool isPunct(llwchar a) { return iswpunct(a) != 0; } + static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; } + static bool isAlpha(llwchar a) { return iswalpha(a) != 0; } + static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 06dfc90d83..5479c080bd 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -45,6 +45,7 @@ #include "llkeyboard.h" #include "llrect.h" #include "llresmgr.h" +#include "llspellcheck.h" #include "llstring.h" #include "llwindow.h" #include "llui.h" @@ -65,6 +66,7 @@ const S32 SCROLL_INCREMENT_ADD = 0; // make space for typing const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing const F32 AUTO_SCROLL_TIME = 0.05f; const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval? +const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and showing spell checking feedback for the word the cursor is on const std::string PASSWORD_ASTERISK( "\xE2\x80\xA2" ); // U+2022 BULLET @@ -88,6 +90,7 @@ LLLineEditor::Params::Params() background_image_focused("background_image_focused"), select_on_focus("select_on_focus", false), revert_on_esc("revert_on_esc", true), + spellcheck("spellcheck", false), commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), is_password("is_password", false), @@ -134,6 +137,9 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mIgnoreArrowKeys( FALSE ), mIgnoreTab( p.ignore_tab ), mDrawAsterixes( p.is_password ), + mSpellCheck( p.spellcheck ), + mSpellCheckStart(-1), + mSpellCheckEnd(-1), mSelectAllonFocusReceived( p.select_on_focus ), mSelectAllonCommit( TRUE ), mPassDelete(FALSE), @@ -177,6 +183,12 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) updateTextPadding(); setCursor(mText.length()); + if (mSpellCheck) + { + LLSpellChecker::setSettingsChangeCallback(boost::bind(&LLLineEditor::onSpellCheckSettingsChange, this)); + } + mSpellCheckTimer.reset(); + setPrevalidateInput(p.prevalidate_input_callback()); setPrevalidate(p.prevalidate_callback()); @@ -519,6 +531,94 @@ void LLLineEditor::selectAll() updatePrimary(); } +bool LLLineEditor::getSpellCheck() const +{ + return (LLSpellChecker::getUseSpellCheck()) && (!mReadOnly) && (mSpellCheck); +} + +const std::string& LLLineEditor::getSuggestion(U32 index) const +{ + return (index < mSuggestionList.size()) ? mSuggestionList[index] : LLStringUtil::null; +} + +U32 LLLineEditor::getSuggestionCount() const +{ + return mSuggestionList.size(); +} + +void LLLineEditor::replaceWithSuggestion(U32 index) +{ + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + { + deselect(); + + // Delete the misspelled word + mText.erase(it->first, it->second - it->first); + + // Insert the suggestion in its place + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + mText.insert(it->first, suggestion); + setCursor(it->first + (S32)suggestion.length()); + + break; + } + } + mSpellCheckStart = mSpellCheckEnd = -1; +} + +void LLLineEditor::addToDictionary() +{ + if (canAddToDictionary()) + { + LLSpellChecker::instance().addToCustomDictionary(getMisspelledWord(mCursorPos)); + } +} + +bool LLLineEditor::canAddToDictionary() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +void LLLineEditor::addToIgnore() +{ + if (canAddToIgnore()) + { + LLSpellChecker::instance().addToIgnoreList(getMisspelledWord(mCursorPos)); + } +} + +bool LLLineEditor::canAddToIgnore() const +{ + return (getSpellCheck()) && (isMisspelledWord(mCursorPos)); +} + +std::string LLLineEditor::getMisspelledWord(U32 pos) const +{ + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + return wstring_to_utf8str(mText.getWString().substr(it->first, it->second - it->first)); + } + return LLStringUtil::null; +} + +bool LLLineEditor::isMisspelledWord(U32 pos) const +{ + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + if ( (it->first <= pos) && (it->second >= pos) ) + return true; + } + return false; +} + +void LLLineEditor::onSpellCheckSettingsChange() +{ + // Recheck the spelling on every change + mSpellCheckStart = mSpellCheckEnd = -1; +} BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask) { @@ -1453,6 +1553,10 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) { mKeystrokeCallback(this); } + if ( (!selection_modified) && (KEY_BACKSPACE == key) ) + { + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + } } } } @@ -1510,6 +1614,7 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) // We'll have to do something about this if something ever changes! - Doug mKeystrokeCallback( this ); } + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } return handled; @@ -1560,6 +1665,7 @@ void LLLineEditor::doDelete() { mKeystrokeCallback( this ); } + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } } } @@ -1756,7 +1862,7 @@ void LLLineEditor::draw() if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) ) { // unselected, right side - mGLFont->render( + rendered_text += mGLFont->render( mText, mScrollHPos + rendered_text, rendered_pixels_right, text_bottom, text_color, @@ -1770,7 +1876,7 @@ void LLLineEditor::draw() } else { - mGLFont->render( + rendered_text = mGLFont->render( mText, mScrollHPos, rendered_pixels_right, text_bottom, text_color, @@ -1785,6 +1891,80 @@ void LLLineEditor::draw() mBorder->setVisible(FALSE); // no more programmatic art. #endif + if ( (getSpellCheck()) && (mText.length() > 2) ) + { + // Calculate start and end indices for the first and last visible word + U32 start = prevWordPos(mScrollHPos), end = nextWordPos(mScrollHPos + rendered_text); + + if ( (mSpellCheckStart != start) || (mSpellCheckEnd = end) ) + { + const LLWString& text = mText.getWString().substr(start, end); + + // Find the start of the first word + U32 word_start = 0, word_end = 0; + while ( (word_start < text.length()) && (!LLStringOps::isAlpha(text[word_start])) ) + word_start++; + + // Iterate over all words in the text block and check them one by one + mMisspellRanges.clear(); + while (word_start < text.length()) + { + // Find the end of the current word (special case handling for "'" when it's used as a contraction) + word_end = word_start + 1; + while ( (word_end < text.length()) && + ((LLWStringUtil::isPartOfWord(text[word_end])) || + ((L'\'' == text[word_end]) && (word_end + 1 < text.length()) && + (LLStringOps::isAlnum(text[word_end - 1])) && (LLStringOps::isAlnum(text[word_end + 1])))) ) + { + word_end++; + } + if (word_end >= text.length()) + break; + + // Don't process words shorter than 3 characters + std::string word = wstring_to_utf8str(text.substr(word_start, word_end - word_start)); + if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) ) + mMisspellRanges.push_back(std::pair(start + word_start, start + word_end)); + + // Find the start of the next word + word_start = word_end + 1; + while ( (word_start < text.length()) && (!LLWStringUtil::isPartOfWord(text[word_start])) ) + word_start++; + } + + mSpellCheckStart = start; + mSpellCheckEnd = end; + } + + // Draw squiggly lines under any (visible) misspelled words + for (std::list >::const_iterator it = mMisspellRanges.begin(); it != mMisspellRanges.end(); ++it) + { + // Skip over words that aren't (partially) visible + if ( ((it->first < start) && (it->second < start)) || (it->first > end) ) + continue; + + // Skip the current word if the user is still busy editing it + if ( (!mSpellCheckTimer.hasExpired()) && (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) + continue; + + S32 pxWidth = getRect().getWidth(); + S32 pxStart = findPixelNearestPos(it->first - getCursor()); + if (pxStart > pxWidth) + continue; + S32 pxEnd = findPixelNearestPos(it->second - getCursor()); + if (pxEnd > pxWidth) + pxEnd = pxWidth; + + gGL.color4ub(255, 0, 0, 200); + while (pxStart < pxEnd) + { + gl_line_2d(pxStart, text_bottom - 2, pxStart + 3, text_bottom + 1); + gl_line_2d(pxStart + 3, text_bottom + 1, pxStart + 6, text_bottom - 2); + pxStart += 6; + } + } + } + // If we're editing... if( hasFocus()) { @@ -2242,6 +2422,7 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string, { mKeystrokeCallback( this ); } + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); } BOOL LLLineEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const @@ -2393,7 +2574,37 @@ void LLLineEditor::showContextMenu(S32 x, S32 y) S32 screen_x, screen_y; localPointToScreen(x, y, &screen_x, &screen_y); - menu->show(screen_x, screen_y); + + if (hasSelection()) + { + if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) ) + deselect(); + else + setCursor(llmax(mSelectionStart, mSelectionEnd)); + } + else + { + setCursorAtLocalPos(x); + } + + bool use_spellcheck = getSpellCheck(), is_misspelled = false; + if (use_spellcheck) + { + mSuggestionList.clear(); + + // If the cursor is on a misspelled word, retrieve suggestions for it + std::string misspelled_word = getMisspelledWord(mCursorPos); + if ((is_misspelled = !misspelled_word.empty()) == true) + { + LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList); + } + } + + menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + menu->show(screen_x, screen_y, this); } } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 2518dbe3c7..9513274f21 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -40,6 +40,7 @@ #include "llframetimer.h" #include "lleditmenuhandler.h" +#include "llspellcheckmenuhandler.h" #include "lluictrl.h" #include "lluiimage.h" #include "lluistring.h" @@ -54,7 +55,7 @@ class LLButton; class LLContextMenu; class LLLineEditor -: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor +: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor, public LLSpellCheckMenuHandler { public: @@ -86,6 +87,7 @@ public: Optional select_on_focus, revert_on_esc, + spellcheck, commit_on_focus_lost, ignore_tab, is_password; @@ -146,6 +148,24 @@ public: virtual void deselect(); virtual BOOL canDeselect() const; + // LLSpellCheckMenuHandler overrides + /*virtual*/ bool getSpellCheck() const; + + /*virtual*/ const std::string& getSuggestion(U32 index) const; + /*virtual*/ U32 getSuggestionCount() const; + /*virtual*/ void replaceWithSuggestion(U32 index); + + /*virtual*/ void addToDictionary(); + /*virtual*/ bool canAddToDictionary() const; + + /*virtual*/ void addToIgnore(); + /*virtual*/ bool canAddToIgnore() const; + + // Spell checking helper functions + std::string getMisspelledWord(U32 pos) const; + bool isMisspelledWord(U32 pos) const; + void onSpellCheckSettingsChange(); + // view overrides virtual void draw(); virtual void reshape(S32 width,S32 height,BOOL called_from_parent=TRUE); @@ -322,6 +342,13 @@ protected: S32 mLastSelectionStart; S32 mLastSelectionEnd; + bool mSpellCheck; + S32 mSpellCheckStart; + S32 mSpellCheckEnd; + LLTimer mSpellCheckTimer; + std::list > mMisspellRanges; + std::vector mSuggestionList; + LLTextValidate::validate_func_t mPrevalidateFunc; LLTextValidate::validate_func_t mPrevalidateInputFunc; diff --git a/indra/newview/skins/default/xui/en/menu_text_editor.xml b/indra/newview/skins/default/xui/en/menu_text_editor.xml index fe8489166b..70b40dd89b 100644 --- a/indra/newview/skins/default/xui/en/menu_text_editor.xml +++ b/indra/newview/skins/default/xui/en/menu_text_editor.xml @@ -1,6 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Wed, 25 Apr 2012 11:26:54 -0700 Subject: SEC-995 FIX viewer is easily spammed to death by chat removed a couple more unnecessary string copies from unfortunate LLSD behavior. reviewed with simon, post review from Richard. --- indra/llcommon/llsd.cpp | 1 + indra/llmessage/llsdmessagereader.cpp | 2 +- indra/llui/lltextbase.cpp | 16 ++++++++++++++-- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index e295e3c621..8276ec836a 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -269,6 +269,7 @@ namespace virtual LLSD::UUID asUUID() const { return LLUUID(mValue); } virtual LLSD::Date asDate() const { return LLDate(mValue); } virtual LLSD::URI asURI() const { return LLURI(mValue); } + virtual int size() const { return mValue.size(); } }; LLSD::Integer ImplString::asInteger() const diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp index 3d8ca2ad9f..a6fccd2a56 100644 --- a/indra/llmessage/llsdmessagereader.cpp +++ b/indra/llmessage/llsdmessagereader.cpp @@ -276,7 +276,7 @@ S32 getElementSize(const LLSD& llsd) case LLSD::TypeReal: return sizeof(F64); case LLSD::TypeString: - return llsd.asString().size(); + return llsd.size(); case LLSD::TypeUUID: return sizeof(LLUUID); case LLSD::TypeDate: diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index c2cd590acb..813f919505 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -280,11 +280,23 @@ bool LLTextBase::truncate() if (getLength() >= S32(mMaxTextByteLength / 4)) { // Have to check actual byte size - S32 utf8_byte_size = getViewModel()->getValue().asString().size(); + S32 utf8_byte_size = 0; + LLSD value = getViewModel()->getValue(); + if (value.type() == LLSD::TypeString) + { + // save a copy for strings. + utf8_byte_size = value.size(); + } + else + { + // non string LLSDs need explicit conversion to string + utf8_byte_size = value.asString().size(); + } + if ( utf8_byte_size > mMaxTextByteLength ) { // Truncate safely in UTF-8 - std::string temp_utf8_text = getViewModel()->getValue().asString(); + std::string temp_utf8_text = value.asString(); temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength ); LLWString text = utf8str_to_wstring( temp_utf8_text ); // remove extra bit of current string, to preserve formatting, etc. -- cgit v1.3 From 423659c68076f99a73985b9bd1befa5c0f5d3457 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 2 May 2012 15:45:38 -0500 Subject: MAINT-775 Particle vertex buffer management optimizations --- indra/llcommon/llstrider.h | 10 ++ indra/newview/llface.cpp | 19 ++- indra/newview/llspatialpartition.h | 7 +- indra/newview/llviewerpartsim.cpp | 2 +- indra/newview/llviewerpartsim.h | 2 + indra/newview/llviewerwindow.cpp | 6 +- indra/newview/llvograss.cpp | 139 +++++++++++++++++++ indra/newview/llvopartgroup.cpp | 265 +++++++++++++++++++++++++++---------- indra/newview/llvopartgroup.h | 13 ++ indra/newview/pipeline.cpp | 26 ++-- 10 files changed, 403 insertions(+), 86 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index f4c43bac61..ed9284d2c5 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -44,6 +44,15 @@ public: const LLStrider& operator = (Object *first) { mObjectp = first; return *this;} void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} + LLStrider operator+(const S32& index) + { + LLStrider ret; + ret.mBytep = mBytep + mSkip*index; + ret.mSkip = mSkip; + + return ret; + } + void skip(const U32 index) { mBytep += mSkip*index;} U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } @@ -51,6 +60,7 @@ public: Object& operator *() { return *mObjectp; } Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } + Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } }; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4108d69e82..97b832520d 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -44,6 +44,7 @@ #include "llsky.h" #include "llviewercamera.h" #include "llviewertexturelist.h" +#include "llvopartgroup.h" #include "llvosky.h" #include "llvovolume.h" #include "pipeline.h" @@ -161,7 +162,15 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mGeomCount = 0; mGeomIndex = 0; mIndicesCount = 0; - mIndicesIndex = 0; + if (drawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || + drawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) + { //indicate to LLParticlePartition that this particle is uninitialized + mIndicesIndex = 0xFFFFFFFF; + } + else + { + mIndicesIndex = 0; + } mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; @@ -203,6 +212,14 @@ void LLFace::destroy() mTexture->removeFace(this) ; } + if (mDrawablep.notNull() && + (mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || + mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES) && + mIndicesIndex != 0xFFFFFFFF) + { + LLVOPartGroup::freeVBSlot(getGeomIndex()/4); + } + if (mDrawPoolp) { if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index ccc65f3da0..65ae41eeee 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -657,6 +657,7 @@ class LLParticlePartition : public LLSpatialPartition { public: LLParticlePartition(); + virtual void rebuildGeom(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); @@ -671,10 +672,14 @@ public: }; //spatial partition for grass (implemented in LLVOGrass.cpp) -class LLGrassPartition : public LLParticlePartition +class LLGrassPartition : public LLSpatialPartition { public: LLGrassPartition(); + virtual void getGeometry(LLSpatialGroup* group); + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); +protected: + U32 mRenderPass; }; //class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 6b3e04348a..345023dbfa 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -476,7 +476,7 @@ void LLViewerPartSim::checkParticleCount(U32 size) LLViewerPartSim::LLViewerPartSim() { LLMemType mt(LLMemType::MTYPE_PARTICLES); - sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount"); + sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); static U32 id_seed = 0; mID = ++id_seed; } diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 3e20f999c0..c9959c63ec 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -39,6 +39,8 @@ class LLViewerRegion; class LLViewerTexture; class LLVOPartGroup; +#define LL_MAX_PARTICLE_COUNT 8192 + typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt); /////////////////// diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 35527d4977..0a582107af 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -175,6 +175,7 @@ #include "llviewershadermgr.h" #include "llviewerstats.h" #include "llvoavatarself.h" +#include "llvopartgroup.h" #include "llvovolume.h" #include "llworld.h" #include "llworldmapview.h" @@ -4654,6 +4655,8 @@ void LLViewerWindow::stopGL(BOOL save_state) LLVOAvatar::destroyGL(); stop_glerror(); + LLVOPartGroup::destroyGL(); + LLViewerDynamicTexture::destroyGL(); stop_glerror(); @@ -4707,7 +4710,8 @@ void LLViewerWindow::restoreGL(const std::string& progress_message) gBumpImageList.restoreGL(); LLViewerDynamicTexture::restoreGL(); LLVOAvatar::restoreGL(); - + LLVOPartGroup::restoreGL(); + gResizeScreenTexture = TRUE; gWindowResized = TRUE; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 8a79d564d3..be3558aad1 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -34,6 +34,7 @@ #include "llagentcamera.h" #include "llnotificationsutil.h" #include "lldrawable.h" +#include "lldrawpoolalpha.h" #include "llface.h" #include "llsky.h" #include "llsurface.h" @@ -594,6 +595,7 @@ U32 LLVOGrass::getPartitionType() const } LLGrassPartition::LLGrassPartition() +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) { mDrawableType = LLPipeline::RENDER_TYPE_GRASS; mPartitionType = LLViewerRegion::PARTITION_GRASS; @@ -604,6 +606,143 @@ LLGrassPartition::LLGrassPartition() mBufferUsage = GL_DYNAMIC_DRAW_ARB; } +void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) +{ + group->mBufferUsage = mBufferUsage; + + mFaceList.clear(); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawablep = *i; + + if (drawablep->isDead()) + { + continue; + } + + LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); + obj->mDepth = 0.f; + + if (drawablep->isAnimating()) + { + group->mBufferUsage = GL_STREAM_DRAW_ARB; + } + + U32 count = 0; + for (S32 j = 0; j < drawablep->getNumFaces(); ++j) + { + drawablep->updateFaceSize(j); + + LLFace* facep = drawablep->getFace(j); + if ( !facep || !facep->hasGeometry()) + { + continue; + } + + if ((facep->getGeomCount() + vertex_count) <= 65536) + { + count++; + facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); + obj->mDepth += facep->mDistance; + + mFaceList.push_back(facep); + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + llassert(facep->getIndicesCount() < 65536); + } + else + { + facep->clearVertexBuffer(); + } + } + + obj->mDepth /= count; + } +} + +static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); + +void LLGrassPartition::getGeometry(LLSpatialGroup* group) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + LLFastTimer ftm(FTM_REBUILD_GRASS_VB); + + std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); + + U32 index_count = 0; + U32 vertex_count = 0; + + group->clearDrawMap(); + + LLVertexBuffer* buffer = group->mVertexBuffer; + + LLStrider indicesp; + LLStrider verticesp; + LLStrider normalsp; + LLStrider texcoordsp; + LLStrider colorsp; + + buffer->getVertexStrider(verticesp); + buffer->getNormalStrider(normalsp); + buffer->getColorStrider(colorsp); + buffer->getTexCoord0Strider(texcoordsp); + buffer->getIndexStrider(indicesp); + + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; + + for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); + facep->setGeomIndex(vertex_count); + facep->setIndicesIndex(index_count); + facep->setVertexBuffer(buffer); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + S32 idx = draw_vec.size()-1; + + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + F32 vsize = facep->getVirtualSize(); + + if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + draw_vec[idx]->mTexture == facep->getTexture() && + (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && + //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && + draw_vec[idx]->mFullbright == fullbright) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + //facep->getTexture(), + buffer, fullbright); + info->mExtents[0] = group->mObjectExtents[0]; + info->mExtents[1] = group->mObjectExtents[1]; + info->mVSize = vsize; + draw_vec.push_back(info); + //for alpha sorting + facep->setDrawInfo(info); + } + } + + buffer->flush(); + mFaceList.clear(); +} + // virtual void LLVOGrass::updateDrawable(BOOL force_damped) { diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 6ce93d641c..42b35ff7a7 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -48,6 +48,92 @@ const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; +LLPointer LLVOPartGroup::sVB = NULL; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL; + +//static +void LLVOPartGroup::restoreGL() +{ + for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) + { + sVBSlotFree[i] = i; + } + + sVBSlotCursor = sVBSlotFree; + + sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + U32 count = LL_MAX_PARTICLE_COUNT; + sVB->allocateBuffer(count*4, count*6, true); + + //indices and texcoords are always the same, set once + LLStrider indicesp; + + sVB->getIndexStrider(indicesp); + + U16 vert_offset = 0; + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *indicesp++ = vert_offset + 0; + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 2; + + *indicesp++ = vert_offset + 1; + *indicesp++ = vert_offset + 3; + *indicesp++ = vert_offset + 2; + + vert_offset += 4; + } + + LLStrider texcoordsp; + sVB->getTexCoord0Strider(texcoordsp); + + for (U32 i = 0; i < LL_MAX_PARTICLE_COUNT; i++) + { + *texcoordsp++ = LLVector2(0.f, 1.f); + *texcoordsp++ = LLVector2(0.f, 0.f); + *texcoordsp++ = LLVector2(1.f, 1.f); + *texcoordsp++ = LLVector2(1.f, 0.f); + } + + sVB->flush(); + +} + +//static +void LLVOPartGroup::destroyGL() +{ + sVB = NULL; +} + +//static +S32 LLVOPartGroup::findAvailableVBSlot() +{ + if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) + { //no more available slots + return -1; + } + + S32 ret = *sVBSlotCursor; + sVBSlotCursor++; + + return ret; +} + +//static +void LLVOPartGroup::freeVBSlot(S32 idx) +{ + llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); + llassert(sVBSlotCursor > sVBSlotFree); + + if (sVBSlotCursor > sVBSlotFree) + { + sVBSlotCursor--; + *sVBSlotCursor = idx; + } +} + LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLAlphaObject(id, pcode, regionp), mViewerPartGroupp(NULL) @@ -62,7 +148,6 @@ LLVOPartGroup::~LLVOPartGroup() { } - BOOL LLVOPartGroup::isActive() const { return FALSE; @@ -287,9 +372,6 @@ void LLVOPartGroup::getGeometry(S32 idx, const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); - U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); - - LLVector4a part_pos_agent; part_pos_agent.load3(part.mPosAgent.mV); LLVector4a camera_agent; @@ -361,33 +443,18 @@ void LLVOPartGroup::getGeometry(S32 idx, verticesp->setAdd(ppamu, right); (*verticesp++).getF32ptr()[3] = 0.f; - //*verticesp++ = part_pos_agent + up - right; - //*verticesp++ = part_pos_agent - up - right; - //*verticesp++ = part_pos_agent + up + right; - //*verticesp++ = part_pos_agent - up + right; - *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; *colorsp++ = part.mColor; - *texcoordsp++ = LLVector2(0.f, 1.f); - *texcoordsp++ = LLVector2(0.f, 0.f); - *texcoordsp++ = LLVector2(1.f, 1.f); - *texcoordsp++ = LLVector2(1.f, 0.f); - - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - *normalsp++ = normal; - - *indicesp++ = vert_offset + 0; - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 2; - - *indicesp++ = vert_offset + 1; - *indicesp++ = vert_offset + 3; - *indicesp++ = vert_offset + 2; + if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK)) + { //not fullbright, needs normal + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + *normalsp++ = normal; + } } U32 LLVOPartGroup::getPartitionType() const @@ -412,6 +479,49 @@ LLHUDParticlePartition::LLHUDParticlePartition() : mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; } +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); + +void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) +{ + if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + + LLFastTimer ftm(FTM_REBUILD_PARTICLE_VBO); + + group->clearDrawMap(); + + //get geometry count + U32 index_count = 0; + U32 vertex_count = 0; + + addGeometryCount(group, vertex_count, index_count); + + + if (vertex_count > 0 && index_count > 0) + { + group->mBuilt = 1.f; + //use one vertex buffer for all groups + group->mVertexBuffer = LLVOPartGroup::sVB; + getGeometry(group); + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY); +} + void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) { group->mBufferUsage = mBufferUsage; @@ -431,11 +541,6 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get(); obj->mDepth = 0.f; - if (drawablep->isAnimating()) - { - group->mBufferUsage = GL_STREAM_DRAW_ARB; - } - U32 count = 0; for (S32 j = 0; j < drawablep->getNumFaces(); ++j) { @@ -447,36 +552,28 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co continue; } - if ((facep->getGeomCount() + vertex_count) <= 65536) - { - count++; - facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); - obj->mDepth += facep->mDistance; + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + count++; + facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis(); + obj->mDepth += facep->mDistance; - mFaceList.push_back(facep); - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - llassert(facep->getIndicesCount() < 65536); - } - else - { - facep->clearVertexBuffer(); - } + mFaceList.push_back(facep); + llassert(facep->getIndicesCount() < 65536); } obj->mDepth /= count; } } -static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB"); -static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB"); + +static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? - FTM_REBUILD_GRASS_VB : - FTM_REBUILD_PARTICLE_VB); + LLFastTimer ftm(FTM_REBUILD_PARTICLE_GEOM); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -496,21 +593,43 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); - buffer->getTexCoord0Strider(texcoordsp); - buffer->getIndexStrider(indicesp); - + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) { LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); - facep->setGeomIndex(vertex_count); - facep->setIndicesIndex(index_count); - facep->setVertexBuffer(buffer); - facep->setPoolType(LLDrawPool::POOL_ALPHA); - object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + if (facep->getIndicesStart() == 0xFFFFFFFF) + { //set the indices of this face + S32 idx = LLVOPartGroup::findAvailableVBSlot(); + if (idx >= 0) + { + facep->setGeomIndex(idx*4); + facep->setIndicesIndex(idx*6); + facep->setVertexBuffer(LLVOPartGroup::sVB); + facep->setPoolType(LLDrawPool::POOL_ALPHA); + } + else + { + continue; //out of space in particle buffer + } + } + + S32 geom_idx = (S32) facep->getGeomIndex(); + + object->getGeometry(facep->getTEOffset(), + verticesp+geom_idx, + normalsp+geom_idx, + texcoordsp+geom_idx, + colorsp+geom_idx, + indicesp+facep->getIndicesStart()); + llassert(facep->getGeomCount() == 4); + llassert(facep->getIndicesCount() == 6); + + vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); @@ -519,18 +638,31 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); F32 vsize = facep->getVirtualSize(); - if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + bool batched = false; + + if (idx >= 0 && draw_vec[idx]->mTexture == facep->getTexture() && - (U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange && - //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && - draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && draw_vec[idx]->mFullbright == fullbright) { - draw_vec[idx]->mCount += facep->getIndicesCount(); - draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else if (draw_vec[idx]->mStart == facep->getGeomIndex()+facep->getGeomCount()+1) + { + batched = true; + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mStart -= facep->getGeomCount(); + draw_vec[idx]->mOffset = facep->getIndicesStart(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } } - else + + + if (!batched) { U32 start = facep->getGeomIndex(); U32 end = start + facep->getGeomCount()-1; @@ -548,7 +680,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) } } - buffer->flush(); mFaceList.clear(); } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index e58fed86d9..dde0b0476d 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -31,12 +31,25 @@ #include "v3math.h" #include "v3color.h" #include "llframetimer.h" +#include "llviewerpartsim.h" +#include "llvertexbuffer.h" class LLViewerPartGroup; class LLVOPartGroup : public LLAlphaObject { public: + + //vertex buffer for holding all particles + static LLPointer sVB; + static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; + static S32* sVBSlotCursor; + + static void restoreGL(); + static void destroyGL(); + static S32 findAvailableVBSlot(); + static void freeVBSlot(S32 idx); + enum { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 93b6e9ae17..c40dafd433 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3334,21 +3334,7 @@ void LLPipeline::postSort(LLCamera& camera) rebuildPriorityGroups(); llpushcallstacks ; - const S32 bin_count = 1024*8; - - static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; - static U32 bin_size[bin_count]; - - //clear one bin per frame to avoid memory bloat - static S32 clear_idx = 0; - clear_idx = (1+clear_idx)%bin_count; - alpha_bins[clear_idx].clear(); - - for (U32 j = 0; j < bin_count; j++) - { - bin_size[j] = 0; - } - + //build render map for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { @@ -3425,6 +3411,10 @@ void LLPipeline::postSort(LLCamera& camera) { std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } + + //flush particle VB + LLVOPartGroup::sVB->flush(); + llpushcallstacks ; // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender) @@ -6239,11 +6229,15 @@ void LLPipeline::doResetVertexBuffers() gSky.resetVertexBuffers(); + LLVOPartGroup::destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches LLGLNamePool::cleanupPools(); + + if (LLVertexBuffer::sGLCount > 0) { llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6263,6 +6257,8 @@ void LLPipeline::doResetVertexBuffers() LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); + + LLVOPartGroup::restoreGL(); } void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture) -- cgit v1.3 From e25dee11ff8b3f4e068c18f39f813563c8b49dc6 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 29 May 2012 18:50:43 -0400 Subject: increment viewer version to 3.3.4 --- indra/llcommon/llversionviewer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index bfb30f900f..22d0aba51b 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 3; -const S32 LL_VERSION_PATCH = 3; +const S32 LL_VERSION_PATCH = 4; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; -- cgit v1.3 From cce8cd73414cdee65213bb6332a7a4c9315860ad Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 25 Jun 2012 16:58:53 -0400 Subject: increment version to 3.3.5 --- indra/llcommon/llversionviewer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 22d0aba51b..9af16a0ed8 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 3; -const S32 LL_VERSION_PATCH = 4; +const S32 LL_VERSION_PATCH = 5; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; -- cgit v1.3