From e045d212d35354d679c2d2e05c6d4689f9f8ac95 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 27 Sep 2010 22:56:08 -0400 Subject: STORM-1126 WIP Windlight Estate Settings port from 1.23: first pass at merging in windlight estate settings to viewer-dev codebase. not built, not tested. Probably needs a bunch of fixes to be able to be integrated. (resubmitted by Vadim ProductEngine) --- indra/newview/llviewerdisplay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llviewerdisplay.cpp') diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 916cbe2267..5b0cf72ac5 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -178,8 +178,8 @@ void display_update_camera() gViewerWindow->setup3DRender(); // update all the sky/atmospheric/water settings - LLWLParamManager::instance()->update(LLViewerCamera::getInstance()); - LLWaterParamManager::instance()->update(LLViewerCamera::getInstance()); + LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance()); + LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance()); // Update land visibility too LLWorld::getInstance()->setLandFarClip(final_far); -- cgit v1.3 From f4ff1430f0d6ae7dd5a6be0bd665678b30a63aca Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Fri, 3 Dec 2010 22:16:16 -0700 Subject: first iteration of memory pool code --- indra/llcommon/llmemory.cpp | 955 ++++++++++++++++++++- indra/llcommon/llmemory.h | 174 +++- indra/llcommon/llsys.cpp | 8 +- indra/llcommon/llsys.h | 2 +- indra/llrender/llvertexbuffer.cpp | 9 +- indra/llxml/llcontrol.h | 3 +- indra/newview/app_settings/settings.xml | 22 + indra/newview/llappviewer.cpp | 128 ++- indra/newview/llappviewer.h | 10 +- indra/newview/lldynamictexture.cpp | 6 +- indra/newview/llfloatermemleak.cpp | 5 + indra/newview/llviewerdisplay.cpp | 7 +- indra/newview/llviewertexture.cpp | 12 +- indra/newview/llviewertexture.h | 2 +- indra/newview/llviewerwindow.cpp | 13 + indra/newview/pipeline.cpp | 22 +- indra/newview/pipeline.h | 5 +- .../newview/skins/default/xui/en/notifications.xml | 16 +- 18 files changed, 1342 insertions(+), 57 deletions(-) (limited to 'indra/newview/llviewerdisplay.cpp') diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index a502d1a7eb..ca06589611 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -26,8 +26,9 @@ #include "linden_common.h" +#include "llthread.h" #if defined(LL_WINDOWS) -# include +//# include # include #elif defined(LL_DARWIN) # include @@ -38,11 +39,19 @@ #endif #include "llmemory.h" +#include "llsys.h" + //---------------------------------------------------------------------------- //static char* LLMemory::reserveMem = 0; +U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ; +U32 LLMemory::sMaxPhysicalMemInKB = 0; +U32 LLMemory::sAllocatedMemInKB = 0; +U32 LLMemory::sAllocatedPageSizeInKB = 0 ; +U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ; +BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE; //static void LLMemory::initClass() @@ -67,6 +76,131 @@ void LLMemory::freeReserve() reserveMem = NULL; } +//static +void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure) +{ + sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ; + sEnableMemoryFailurePrevention = prevent_heap_failure ; +} + +//static +void LLMemory::updateMemoryInfo() +{ +#if LL_WINDOWS + HANDLE self = GetCurrentProcess(); + PROCESS_MEMORY_COUNTERS counters; + + if (!GetProcessMemoryInfo(self, &counters, sizeof(counters))) + { + llwarns << "GetProcessMemoryInfo failed" << llendl; + return ; + } + + sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ; + sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ; + sMaxPhysicalMemInKB = llmin(LLMemoryInfo::getAvailableMemoryKB() + sAllocatedMemInKB, sMaxHeapSizeInKB); + + if(sMaxPhysicalMemInKB > sAllocatedMemInKB) + { + sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ; + } + else + { + sAvailPhysicalMemInKB = 0 ; + } +#else + //not valid for other systems for now. + sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ; + sMaxPhysicalMemInKB = U32_MAX ; + sAvailPhysicalMemInKB = U32_MAX ; +#endif + + return ; +} + +// +//this function is to test if there is enough space with the size in the virtual address space. +//it does not do any real allocation +//if success, it returns the address where the memory chunk can fit in; +//otherwise it returns NULL. +// +//static +void* LLMemory::tryToAlloc(void* address, U32 size) +{ +#if LL_WINDOWS + address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ; + if(address) + { + if(!VirtualFree(address, 0, MEM_RELEASE)) + { + llerrs << "error happens when free some memory reservation." << llendl ; + } + } +#else +#endif + + return address ; +} + +//static +void LLMemory::logMemoryInfo(BOOL update) +{ + if(update) + { + updateMemoryInfo() ; + } + + llinfos << "Current allocated physical memory(KB): " << sAllocatedMemInKB << llendl ; + llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ; + llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ; + llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ; +} + +//return 0: everything is normal; +//return 1: the memory pool is low, but not in danger; +//return -1: the memory pool is in danger, is about to crash. +//static +S32 LLMemory::isMemoryPoolLow() +{ + static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use + + if(!sEnableMemoryFailurePrevention) + { + return 0 ; //no memory failure prevention. + } + + if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory + { + return -1 ; + } + + if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space. + { + return -1 ; + } + + return (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || + sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ; +} + +//static +U32 LLMemory::getAvailableMemKB() +{ + return sAvailPhysicalMemInKB ; +} + +//static +U32 LLMemory::getMaxMemKB() +{ + return sMaxPhysicalMemInKB ; +} + +//static +U32 LLMemory::getAllocatedMemKB() +{ + return sAllocatedMemInKB ; +} + void* ll_allocate (size_t size) { if (size == 0) @@ -221,3 +355,822 @@ U64 LLMemory::getCurrentRSS() } #endif + +//------------------------------------------------------------- +//class LLPrivateMemoryPool::LLMemoryBlock +//------------------------------------------------------------- +// +//each memory block could fit for two page sizes: 0.75 * mSlotSize, which starts from the beginning of the memory chunk and grow towards the end of the +//the block; another is mSlotSize, which starts from the end of the block and grows towards the beginning of the block. +// +LLPrivateMemoryPool::LLMemoryBlock::LLMemoryBlock() +{ + //empty +} + +LLPrivateMemoryPool::LLMemoryBlock::~LLMemoryBlock() +{ + //empty +} + +void LLPrivateMemoryPool::LLMemoryBlock::init(char* buffer, U32 buffer_size, U32 slot_size) +{ + mBuffer = buffer ; + mBufferSize = buffer_size ; + mSlotSize = slot_size ; + mTotalSlots = buffer_size / mSlotSize ; + llassert_always(mTotalSlots < 256) ; //max number is 256 + mAllocatedSlots = 0 ; + + //mark free bits + S32 usage_bit_len = (mTotalSlots + 31) / 32 ; + mDummySize = usage_bit_len - 1 ; + if(mDummySize > 0) //extra space to store mUsageBits + { + mTotalSlots -= (mDummySize * sizeof(mUsageBits) + mSlotSize - 1) / mSlotSize ; + usage_bit_len = (mTotalSlots + 31) / 32 ; + mDummySize = usage_bit_len - 1 ; + + if(mDummySize > 0) + { + mUsageBits = 0 ; + for(S32 i = 0 ; i < mDummySize ; i++) + { + *((U32*)mBuffer + i) = 0 ; + } + if(mTotalSlots & 31) + { + *((U32*)mBuffer + mDummySize - 1) = (0xffffffff << (mTotalSlots & 31)) ; + } + } + } + + if(mDummySize < 1) + { + mUsageBits = 0 ; + if(mTotalSlots & 31) + { + mUsageBits = (0xffffffff << (mTotalSlots & 31)) ; + } + } + + mSelf = NULL ; + mNext = NULL ; +} + +void LLPrivateMemoryPool::LLMemoryBlock::setBuffer(char* buffer, U32 buffer_size) +{ + mBuffer = buffer ; + mBufferSize = buffer_size ; + mTotalSlots = 0 ; //set the block is free. +} + +char* LLPrivateMemoryPool::LLMemoryBlock::allocate() +{ + llassert_always(mAllocatedSlots < mTotalSlots) ; + + //find a free slot + U32* bits = NULL ; + U32 k = 0 ; + if(mUsageBits != 0xffffffff) + { + bits = &mUsageBits ; + } + else if(mDummySize > 0)//go to extra space + { + for(S32 i = 0 ; i < mDummySize; i++) + { + if(*((U32*)mBuffer + i) != 0xffffffff) + { + bits = (U32*)mBuffer + i ; + k = i + 1 ; + break ; + } + } + } + S32 idx = 0 ; + U32 tmp = *bits ; + for(; tmp & 1 ; tmp >>= 1, idx++) ; + + //set the slot reserved + if(!idx) + { + *bits |= 1 ; + } + else + { + *bits |= (1 << idx) ; + } + + mAllocatedSlots++ ; + + return mBuffer + mDummySize * sizeof(U32) + (k * 32 + idx) * mSlotSize ; +} + +void LLPrivateMemoryPool::LLMemoryBlock::free(void* addr) +{ + U32 idx = ((char*) addr - mBuffer - mDummySize * sizeof(U32)) / mSlotSize ; + + U32* bits = &mUsageBits ; + if(idx > 32) + { + bits = (U32*)mBuffer + (idx - 32) / 32 ; + } + if(idx & 31) + { + *bits &= ~(1 << (idx & 31)) ; + } + else + { + *bits &= ~1 ; + } + + mAllocatedSlots-- ; +} + +//------------------------------------------------------------------- +//class LLMemoryChunk +//-------------------------------------------------------------------- +LLPrivateMemoryPool::LLMemoryChunk::LLMemoryChunk() +{ + //empty +} + +LLPrivateMemoryPool::LLMemoryChunk::~LLMemoryChunk() +{ + //empty +} + +void LLPrivateMemoryPool::LLMemoryChunk::init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) +{ + mBuffer = buffer ; + mBufferSize = buffer_size ; + + mMetaBuffer = mBuffer + sizeof(LLMemoryChunk) ; + + mMinBlockSize = min_block_size; + mMaxBlockSize = max_block_size; + mMinSlotSize = min_slot_size; + mBlockLevels = max_block_size / min_block_size ; + mPartitionLevels = mMaxBlockSize / mMinBlockSize + 1 ; + + S32 max_num_blocks = (buffer_size - sizeof(LLMemoryChunk) - mBlockLevels * sizeof(LLMemoryBlock*) - mPartitionLevels * sizeof(LLMemoryBlock*)) / + (mMinBlockSize + sizeof(LLMemoryBlock)) ; + //meta data space + mBlocks = (LLMemoryBlock*)mMetaBuffer ; + mAvailBlockList = (LLMemoryBlock**)((char*)mBlocks + sizeof(LLMemoryBlock) * max_num_blocks) ; + mFreeSpaceList = (LLMemoryBlock**)((char*)mAvailBlockList + sizeof(LLMemoryBlock*) * mBlockLevels) ; + + //data buffer + mDataBuffer = (char*)mFreeSpaceList + sizeof(LLMemoryBlock*) * mPartitionLevels ; + + //init + for(U32 i = 0 ; i < mBlockLevels; i++) + { + mAvailBlockList[i] = NULL ; + } + for(U32 i = 0 ; i < mPartitionLevels ; i++) + { + mFreeSpaceList[i] = NULL ; + } + + mBlocks[0].setBuffer(mDataBuffer, buffer_size - (mDataBuffer - mBuffer)) ; + addToFreeSpace(&mBlocks[0]) ; + + mKey = (U32)mBuffer ; + mNext = NULL ; + mPrev = NULL ; +} + +//static +U32 LLPrivateMemoryPool::LLMemoryChunk::getMaxOverhead(U32 data_buffer_size, U32 min_page_size) +{ + return 2048 + + sizeof(LLMemoryBlock) * (data_buffer_size / min_page_size) ; +} + +char* LLPrivateMemoryPool::LLMemoryChunk::allocate(U32 size) +{ + char* p = NULL ; + U32 blk_idx = size / mMinSlotSize ; + if(mMinSlotSize * blk_idx < size) + { + blk_idx++ ; + } + + //check if there is free block available + if(mAvailBlockList[blk_idx]) + { + LLMemoryBlock* blk = mAvailBlockList[blk_idx] ; + p = blk->allocate() ; + + if(blk->isFull()) + { + //removeFromFreelist + popAvailBlockList(blk_idx) ; + } + } + + //ask for a new block + if(!p) + { + LLMemoryBlock* blk = addBlock(blk_idx) ; + if(blk) + { + p = blk->allocate() ; + + if(blk->isFull()) + { + //removeFromFreelist + popAvailBlockList(blk_idx) ; + } + } + } + + //ask for space from higher level blocks + if(!p) + { + for(S32 i = blk_idx + 1 ; i < mBlockLevels; i++) + { + if(mAvailBlockList[i]) + { + LLMemoryBlock* blk = mAvailBlockList[i] ; + p = blk->allocate() ; + + if(blk->isFull()) + { + //removeFromFreelist + popAvailBlockList(i) ; + } + break ; + } + } + } + + return p ; +} + +void LLPrivateMemoryPool::LLMemoryChunk::free(void* addr) +{ + LLMemoryBlock* blk = (LLMemoryBlock*)(mMetaBuffer + (((char*)addr - mDataBuffer) / mMinBlockSize) * sizeof(LLMemoryBlock)) ; + blk = blk->mSelf ; + + bool was_full = blk->isFull() ; + blk->free(addr) ; + + if(blk->empty()) + { + removeBlock(blk) ; + } + else if(was_full) + { + addToAvailBlockList(blk) ; + } +} + +LLPrivateMemoryPool::LLMemoryBlock* LLPrivateMemoryPool::LLMemoryChunk::addBlock(U32 blk_idx) +{ + U32 slot_size = mMinSlotSize * (blk_idx + 1) ; + U32 preferred_block_size = llmax(mMinBlockSize, slot_size * 32) ; + preferred_block_size = llmin(preferred_block_size, mMaxBlockSize) ; + + U32 idx = preferred_block_size / mMinBlockSize ; + preferred_block_size = idx * mMinBlockSize ; //round to integer times of mMinBlockSize. + + LLMemoryBlock* blk = NULL ; + + if(mFreeSpaceList[idx])//if there is free slot for blk_idx + { + blk = createNewBlock(&mFreeSpaceList[idx], preferred_block_size, slot_size, blk_idx) ; + } + else if(mFreeSpaceList[mPartitionLevels - 1]) //search free pool + { + blk = createNewBlock(&mFreeSpaceList[mPartitionLevels - 1], preferred_block_size, slot_size, blk_idx) ; + } + else //search for other non-preferred but enough space slot. + { + for(U32 i = idx - 1 ; i >= 0 ; i--) //search the small slots first + { + if(mFreeSpaceList[i]) + { + //create a NEW BLOCK THERE. + if(mFreeSpaceList[i]->getBufferSize() >= slot_size) //at least there is space for one slot. + { + blk = createNewBlock(&mFreeSpaceList[i], preferred_block_size, slot_size, blk_idx) ; + } + break ; + } + } + + if(!blk) + { + for(U16 i = idx + 1 ; i < mPartitionLevels - 1; i++) //search the large slots + { + if(mFreeSpaceList[i]) + { + //create a NEW BLOCK THERE. + blk = createNewBlock(&mFreeSpaceList[i], preferred_block_size, slot_size, blk_idx) ; + break ; + } + } + } + } + + return blk ; +} + +LLPrivateMemoryPool::LLMemoryBlock* LLPrivateMemoryPool::LLMemoryChunk::createNewBlock(LLMemoryBlock** cur_idxp, U32 buffer_size, U32 slot_size, U32 blk_idx) +{ + LLMemoryBlock* blk = *cur_idxp ; + + buffer_size = llmin(buffer_size, blk->getBufferSize()) ; + U32 new_free_blk_size = blk->getBufferSize() - buffer_size ; + if(new_free_blk_size < mMinBlockSize) //can not partition the memory into size smaller than mMinBlockSize + { + buffer_size += new_free_blk_size ; + new_free_blk_size = 0 ; + } + blk->init(blk->getBuffer(), buffer_size, slot_size) ; + + if(new_free_blk_size > 0) //cur_idx still has free space + { + LLMemoryBlock* next_blk = blk + (buffer_size / mMinBlockSize) ; + next_blk->setBuffer(blk->getBuffer() + buffer_size, new_free_blk_size) ; + + if(new_free_blk_size > mMaxBlockSize) //stays in the free pool + { + next_blk->mPrev = NULL ; + next_blk->mNext = blk->mNext ; + if(next_blk->mNext) + { + next_blk->mNext->mPrev = next_blk ; + } + *cur_idxp = next_blk ; + } + else + { + *cur_idxp = blk->mNext ; //move to the next slot + (*cur_idxp)->mPrev = NULL ; + + addToFreeSpace(next_blk) ; + } + } + else //move to the next block + { + *cur_idxp = blk->mNext ; + (*cur_idxp)->mPrev = NULL ; + } + + //insert to the available block list... + blk->mNext = NULL ; + blk->mPrev = NULL ; + blk->mSelf = blk ; + mAvailBlockList[blk_idx] = blk ; + + //mark the address map + U32 end = (buffer_size / mMinBlockSize) ; + for(U32 i = 1 ; i < end ; i++) + { + (blk + i)->mSelf = blk ; + } + + return blk ; +} + +void LLPrivateMemoryPool::LLMemoryChunk::removeBlock(LLMemoryBlock* blk) +{ + //remove from the available block list + if(blk->mPrev) + { + blk->mPrev->mNext = blk->mNext ; + } + if(blk->mNext) + { + blk->mNext->mPrev = blk->mPrev ; + } + + //mark it free + blk->setBuffer(blk->getBuffer(), blk->getBufferSize()) ; + + //merge blk with neighbors if possible + if(blk->getBuffer() > mDataBuffer) //has the left neighbor + { + if((blk - 1)->mSelf->isFree()) + { + removeFromFreeSpace((blk - 1)->mSelf); + (blk - 1)->mSelf->setBuffer((blk-1)->mSelf->getBuffer(), (blk-1)->mSelf->getBufferSize() + blk->getBufferSize()) ; + blk = (blk - 1)->mSelf ; + } + } + if(blk->getBuffer() + blk->getBufferSize() < mBuffer + mBufferSize) //has the right neighbor + { + U32 d = blk->getBufferSize() / mMinBlockSize ; + if((blk + d)->isFree()) + { + removeFromFreeSpace(blk + d) ; + blk->setBuffer(blk->getBuffer(), blk->getBufferSize() + (blk + d)->getBufferSize()) ; + } + } + + addToFreeSpace(blk) ; + + return ; +} + +//the top block in the list is full, pop it out of the list +void LLPrivateMemoryPool::LLMemoryChunk::popAvailBlockList(U32 blk_idx) +{ + if(mAvailBlockList[blk_idx]) + { + LLMemoryBlock* next = mAvailBlockList[blk_idx]->mNext ; + next->mPrev = NULL ; + mAvailBlockList[blk_idx]->mNext = NULL ; + mAvailBlockList[blk_idx] = next ; + } +} + +void LLPrivateMemoryPool::LLMemoryChunk::addToFreeSpace(LLMemoryBlock* blk) +{ + U16 free_idx = blk->getBufferSize() / mMinBlockSize ; + (blk + free_idx)->mSelf = blk ; //mark the end pointing back to the head. + free_idx = llmin(free_idx, (U16)(mPartitionLevels - 1)) ; + + blk->mNext = mFreeSpaceList[free_idx] ; + if(mFreeSpaceList[free_idx]) + { + mFreeSpaceList[free_idx]->mPrev = blk ; + } + mFreeSpaceList[free_idx] = blk ; + blk->mPrev = NULL ; + blk->mSelf = blk ; + + return ; +} + +void LLPrivateMemoryPool::LLMemoryChunk::removeFromFreeSpace(LLMemoryBlock* blk) +{ + U16 free_idx = blk->getBufferSize() / mMinBlockSize ; + free_idx = llmin(free_idx, (U16)(mPartitionLevels - 1)) ; + + if(mFreeSpaceList[free_idx] == blk) + { + mFreeSpaceList[free_idx] = blk->mNext ; + } + if(blk->mPrev) + { + blk->mPrev->mNext = blk->mNext ; + } + if(blk->mNext) + { + blk->mNext->mPrev = blk->mPrev ; + } + + return ; +} + +void LLPrivateMemoryPool::LLMemoryChunk::addToAvailBlockList(LLMemoryBlock* blk) +{ + U32 blk_idx = blk->getSlotSize() / mMinSlotSize ; + + blk->mNext = mAvailBlockList[blk_idx] ; + if(blk->mNext) + { + blk->mNext->mPrev = blk ; + } + blk->mPrev = NULL ; + + return ; +} + +//------------------------------------------------------------------- +//class LLPrivateMemoryPool +//-------------------------------------------------------------------- +LLPrivateMemoryPool::LLPrivateMemoryPool(U32 max_size, bool threaded) : + mMutexp(NULL), + mMaxPoolSize(max_size), + mReservedPoolSize(0) +{ + if(threaded) + { + mMutexp = new LLMutex(NULL) ; + } + + for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) + { + mChunkList[i] = NULL ; + } + + mChunkVectorCapacity = 128 ; + mChunks.resize(mChunkVectorCapacity) ; //at most 128 chunks + mNumOfChunks = 0 ; +} + +LLPrivateMemoryPool::~LLPrivateMemoryPool() +{ + destroyPool(); + delete mMutexp ; +} + +char* LLPrivateMemoryPool::allocate(U32 size) +{ + const static U32 MAX_BLOCK_SIZE = 4 * 1024 * 1024 ; //4MB + + //if the asked size larger than MAX_BLOCK_SIZE, fetch from heap directly, the pool does not manage it + if(size >= MAX_BLOCK_SIZE) + { + return new char[size] ; + } + + char* p = NULL ; + + //find the appropriate chunk + S32 chunk_idx = getChunkIndex(size) ; + + lock() ; + + LLMemoryChunk* chunk = mChunkList[chunk_idx]; + while(chunk) + { + if(p = chunk->allocate(size)) + { + break ; + } + chunk = chunk->mNext ; + } + + //fetch new memory chunk + if(!p) + { + chunk = addChunk(chunk_idx) ; + p = chunk->allocate(size) ; + } + + unlock() ; + + return p ; +} + +void LLPrivateMemoryPool::free(void* addr) +{ + lock() ; + + LLMemoryChunk* chunk = mChunks[findChunk((char*)addr)] ; + if(!chunk) + { + delete[] (char*)addr ; //release from heap + } + else + { + chunk->free(addr) ; + + if(chunk->empty()) + { + removeChunk(chunk) ; + } + } + + unlock() ; +} + +void LLPrivateMemoryPool::dump() +{ +} + +void LLPrivateMemoryPool::lock() +{ + if(mMutexp) + { + mMutexp->lock() ; + } +} + +void LLPrivateMemoryPool::unlock() +{ + if(mMutexp) + { + mMutexp->unlock() ; + } +} + +S32 LLPrivateMemoryPool::getChunkIndex(U32 size) +{ + if(size < 2048) + { + return 0 ; + } + else if(size < (512 << 10)) + { + return 1 ; + } + else + { + return 2 ; + } +} + +//destroy the entire pool +void LLPrivateMemoryPool::destroyPool() +{ + for(U16 i = 0 ; i < mNumOfChunks ; i++) + { + delete[] mChunks[i]->getBuffer() ; + } + mNumOfChunks = 0 ; + for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++) + { + mChunkList[i] = NULL ; + } +} + +LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_index) +{ + static const U32 MIN_BLOCK_SIZES[SUPER_ALLOCATION] = {2 << 10, 32 << 10, 64 << 10} ; + static const U32 MAX_BLOCK_SIZES[SUPER_ALLOCATION] = {64 << 10, 1 << 20, 4 << 20} ; + static const U32 MIN_SLOT_SIZES[SUPER_ALLOCATION] = {8, 2 << 10, 512 << 10}; + static const U32 MAX_SLOT_SIZES[SUPER_ALLOCATION] = {(2 << 10) - 8, (512 - 2) << 10, 4 << 20}; + + U32 preferred_size ; + U32 overhead ; + if(chunk_index < LARGE_ALLOCATION) + { + preferred_size = (4 << 20) ; //4MB + overhead = LLMemoryChunk::getMaxOverhead(preferred_size, MIN_BLOCK_SIZES[chunk_index]) ; + } + else + { + preferred_size = (16 << 20) ; //16MB + overhead = LLMemoryChunk::getMaxOverhead(preferred_size, MIN_BLOCK_SIZES[chunk_index]) ; + } + char* buffer = new(std::nothrow) char[preferred_size + overhead] ; + if(!buffer) + { + return NULL ; + } + + LLMemoryChunk* chunk = new (buffer) LLMemoryChunk() ; + chunk->init(buffer, preferred_size + overhead, MIN_SLOT_SIZES[chunk_index], + MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ; + + //add to the head of the linked list + chunk->mNext = mChunkList[chunk_index] ; + if(mChunkList[chunk_index]) + { + mChunkList[chunk_index]->mPrev = chunk ; + } + chunk->mPrev = NULL ; + mChunkList[chunk_index] = chunk ; + + //insert into the array + llassert_always(mNumOfChunks + 1 < mChunkVectorCapacity) ; + if(!mNumOfChunks) + { + mChunks[0] = chunk ; + } + else + { + U16 k ; + if(mChunks[0]->getBuffer() > chunk->getBuffer()) + { + k = 0 ; + } + else + { + k = findChunk(chunk->getBuffer()) + 1 ; + } + for(U16 i = mNumOfChunks ; i > k ; i++) + { + mChunks[i] = mChunks[i-1] ; + } + mChunks[k] = chunk ; + } + mNumOfChunks++; + + return chunk ; +} + +void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk) +{ + //remove from the linked list + if(chunk->mPrev) + { + chunk->mPrev->mNext = chunk->mNext ; + } + if(chunk->mNext) + { + chunk->mNext->mPrev = chunk->mPrev ; + } + + //remove from the array + U16 k = findChunk(chunk->getBuffer()) ; + mNumOfChunks--; + for(U16 i = k ; i < mNumOfChunks ; i++) + { + mChunks[i] = mChunks[i+1] ; + } + + //release memory + delete[] chunk->getBuffer() ; +} + +U16 LLPrivateMemoryPool::findChunk(const char* addr) +{ + llassert_always(mNumOfChunks > 0) ; + + U16 s = 0, e = mNumOfChunks; + U16 k = (s + e) / 2 ; + while(s < e) + { + if(mChunks[k]->mKey > (U32)addr) + { + e = k ; + } + else if(k < mNumOfChunks - 1 && mChunks[k+1]->mKey < (U32)addr) + { + s = k ; + } + else + { + break ; + } + + k = (s + e) / 2 ; + } + + return k ; +} + +//-------------------------------------------------------------------- +//class LLPrivateMemoryPoolTester +LLPrivateMemoryPoolTester* LLPrivateMemoryPoolTester::sInstance = NULL ; +LLPrivateMemoryPool* LLPrivateMemoryPoolTester::sPool = NULL ; +LLPrivateMemoryPoolTester::LLPrivateMemoryPoolTester() +{ +} + +LLPrivateMemoryPoolTester::~LLPrivateMemoryPoolTester() +{ +} + +//static +LLPrivateMemoryPoolTester* LLPrivateMemoryPoolTester::getInstance() +{ + if(!sInstance) + { + sInstance = new LLPrivateMemoryPoolTester() ; + } + return sInstance ; +} + +//static +void LLPrivateMemoryPoolTester::destroy() +{ + if(sInstance) + { + delete sInstance ; + sInstance = NULL ; + } + + if(sPool) + { + delete sPool ; + sPool = NULL ; + } +} + +void LLPrivateMemoryPoolTester::run() +{ + const U32 max_pool_size = 16 << 20 ; + const bool threaded = false ; + if(!sPool) + { + sPool = new LLPrivateMemoryPool(max_pool_size, threaded) ; + } + + //run the test + correctnessTest() ; + reliabilityTest() ; + performanceTest() ; + fragmentationtest() ; +} + +void LLPrivateMemoryPoolTester::correctnessTest() +{ + //try many different sized allocation, fill the memory fully to see if allocation is right. + +} + +void LLPrivateMemoryPoolTester::reliabilityTest() +void LLPrivateMemoryPoolTester::performanceTest() +void LLPrivateMemoryPoolTester::fragmentationtest() + +void* LLPrivateMemoryPoolTester::operator new(size_t size) +{ + return (void*)sPool->allocate(size) ; +} + +void LLPrivateMemoryPoolTester::operator delete(void* addr) +{ + sPool->free(addr) ; +} + +//-------------------------------------------------------------------- diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 9bf4248bb7..d9e93d0e96 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -26,8 +26,6 @@ #ifndef LLMEMORY_H #define LLMEMORY_H - - extern S32 gTotalDAlloc; extern S32 gTotalDAUse; extern S32 gDACount; @@ -44,8 +42,180 @@ public: // Return the resident set size of the current process, in bytes. // Return value is zero if not known. static U64 getCurrentRSS(); + + static void* tryToAlloc(void* address, U32 size); + static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure); + static void updateMemoryInfo() ; + static void logMemoryInfo(BOOL update = FALSE); + static S32 isMemoryPoolLow(); + + static U32 getAvailableMemKB() ; + static U32 getMaxMemKB() ; + static U32 getAllocatedMemKB() ; private: static char* reserveMem; + static U32 sAvailPhysicalMemInKB ; + static U32 sMaxPhysicalMemInKB ; + static U32 sAllocatedMemInKB; + static U32 sAllocatedPageSizeInKB ; + + static U32 sMaxHeapSizeInKB; + static BOOL sEnableMemoryFailurePrevention; +}; + +class LL_COMMON_API LLPrivateMemoryPool +{ +public: + class LL_COMMON_API LLMemoryBlock //each block is devided into slots uniformly + { + public: + LLMemoryBlock() ; + ~LLMemoryBlock() ; + + void init(char* buffer, U32 buffer_size, U32 slot_size) ; + void setBuffer(char* buffer, U32 buffer_size) ; + + char* allocate() ; + void free(void* addr) ; + + bool empty() {return !mAllocatedSlots;} + bool isFull() {return mAllocatedSlots == mTotalSlots;} + bool isFree() {return !mTotalSlots;} + + U32 getSlotSize()const {return mSlotSize;} + U32 getTotalSlots()const {return mTotalSlots;} + U32 getBufferSize()const {return mBufferSize;} + char* getBuffer() const {return mBuffer;} + + private: + char* mBuffer; + U32 mSlotSize ; //when the block is not initialized, it is the buffer size. + U32 mBufferSize ; + U32 mUsageBits ; + U8 mTotalSlots ; + U8 mAllocatedSlots ; + U8 mDummySize ; //size of extra U32 reserved for mUsageBits. + + public: + LLMemoryBlock* mPrev ; + LLMemoryBlock* mNext ; + LLMemoryBlock* mSelf ; + }; + + class LL_COMMON_API LLMemoryChunk //is divided into memory blocks. + { + public: + LLMemoryChunk() ; + ~LLMemoryChunk() ; + + void init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) ; + void setBuffer(char* buffer, U32 buffer_size) ; + + bool empty() ; + + char* allocate(U32 size) ; + void free(void* addr) ; + + const char* getBuffer() const {return mBuffer;} + U32 getBufferSize() const {return mBufferSize;} + + static U32 getMaxOverhead(U32 data_buffer_size, U32 min_page_size) ; + + private: + LLMemoryBlock* addBlock(U32 blk_idx) ; + void popAvailBlockList(U32 blk_idx) ; + void addToFreeSpace(LLMemoryBlock* blk) ; + void removeFromFreeSpace(LLMemoryBlock* blk) ; + void removeBlock(LLMemoryBlock* blk) ; + void addToAvailBlockList(LLMemoryBlock* blk) ; + LLMemoryBlock* createNewBlock(LLMemoryBlock** cur_idxp, U32 buffer_size, U32 slot_size, U32 blk_idx) ; + + private: + LLMemoryBlock** mAvailBlockList ;//256 by mMinSlotSize + LLMemoryBlock** mFreeSpaceList; + LLMemoryBlock* mBlocks ; //index of blocks by address. + + char* mBuffer ; + U32 mBufferSize ; + char* mDataBuffer ; + char* mMetaBuffer ; + U32 mMinBlockSize ; + U32 mMaxBlockSize; + U32 mMinSlotSize ; + U16 mBlockLevels; + U16 mPartitionLevels; + + public: + //form a linked list + LLMemoryChunk* mNext ; + LLMemoryChunk* mPrev ; + + U32 mKey ; //= mBuffer + } ; + +public: + LLPrivateMemoryPool(U32 max_size, bool threaded) ; + ~LLPrivateMemoryPool() ; + + char *allocate(U32 size) ; + void free(void* addr) ; + void dump() ; + +private: + void lock() ; + void unlock() ; + S32 getChunkIndex(U32 size) ; + LLMemoryChunk* addChunk(S32 chunk_index) ; + void removeChunk(LLMemoryChunk* chunk) ; + U16 findChunk(const char* addr) ; + void destroyPool() ; + +private: + LLMutex* mMutexp ; + U32 mMaxPoolSize; + U32 mReservedPoolSize ; + + enum + { + SMALL_ALLOCATION = 0, //from 8 bytes to 2KB(exclusive), page size 2KB, max chunk size is 4MB. + MEDIUM_ALLOCATION, //from 2KB to 512KB(exclusive), page size 32KB, max chunk size 4MB + LARGE_ALLOCATION, //from 512KB to 4MB(inclusive), page size 64KB, max chunk size 16MB + SUPER_ALLOCATION //allocation larger than 4MB. + }; + + LLMemoryChunk* mChunkList[SUPER_ALLOCATION] ; //all memory chunks reserved by this pool, sorted by address + std::vector mChunks ; + U16 mNumOfChunks ; + U16 mChunkVectorCapacity ; +}; + +// +//the below singleton is used to test the private memory pool. +// +class LLPrivateMemoryPoolTester +{ +private: + LLPrivateMemoryPoolTester() ; + ~LLPrivateMemoryPoolTester() ; + +public: + static LLPrivateMemoryPoolTester* getInstance() ; + static void destroy() ; + + void run() ; + +private: + void correctnessTest() ; + void reliabilityTest() ; + void performanceTest() ; + void fragmentationtest() ; + + void* operator new(size_t); + void operator delete(void*); + +private: + static LLPrivateMemoryPoolTester* sInstance; + static LLPrivateMemoryPool* sPool ; }; // LLRefCount moved to llrefcount.h diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 10cdc7087b..7968e53c13 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -636,22 +636,20 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const } //static -void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb) +U32 LLMemoryInfo::getAvailableMemoryKB() { #if LL_WINDOWS MEMORYSTATUSEX state; state.dwLength = sizeof(state); GlobalMemoryStatusEx(&state); - avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ; - avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ; + return (U32)(state.ullAvailPhys/1024) ; #else //do not know how to collect available memory info for other systems. //leave it blank here for now. - avail_physical_mem_kb = -1 ; - avail_virtual_mem_kb = -1 ; + return -1; #endif } diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 41a4f25000..580eee4e8d 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -116,7 +116,7 @@ public: U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes //get the available memory infomation in KiloBytes. - static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb); + static U32 getAvailableMemoryKB(); }; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 02160b09c4..19269c2a31 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -33,6 +33,7 @@ #include "llglheaders.h" #include "llmemtype.h" #include "llrender.h" +#include "llmemory.h" //============================================================================ @@ -857,11 +858,8 @@ U8* LLVertexBuffer::mapBuffer(S32 access) log_glerror(); //check the availability of memory - U32 avail_phy_mem, avail_vir_mem; - LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ; - llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; - llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl; - + LLMemory::logMemoryInfo(TRUE) ; + //-------------------- //print out more debug info before crash llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; @@ -884,6 +882,7 @@ U8* LLVertexBuffer::mapBuffer(S32 access) if (!mMappedIndexData) { log_glerror(); + LLMemory::logMemoryInfo(TRUE) ; GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 93975579cc..70749b8ee9 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -385,7 +385,8 @@ class LLCachedControl { public: LLCachedControl(LLControlGroup& group, - const std::string& name, + const std::string& name, + const T& default_value, const std::string& comment = "Declared In Code") { diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 535bc95287..905c683f69 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5153,6 +5153,17 @@ Value 48.0 + MaxHeapSize + + Comment + Maximum heap size (GB) + Persist + 1 + Type + F32 + Value + 1.6 + MaxSelectDistance Comment @@ -5329,6 +5340,17 @@ Value 1 + MemeoyFailurePreventionEnabled + + Comment + If set, the viewer will quit to avoid crash when memory failure happens + Persist + 0 + Type + Boolean + Value + 1 + MemoryLogFrequency Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3a98749c0f..84e36ac3c7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -604,7 +604,7 @@ LLAppViewer::~LLAppViewer() } bool LLAppViewer::init() -{ +{ // // Start of the application // @@ -632,6 +632,9 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; + //set the max heap size. + initMaxHeapSize() ; + // write Google Breakpad minidump files to our log directory std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); logdir += gDirUtilp->getDirDelimiter(); @@ -949,6 +952,96 @@ bool LLAppViewer::init() return true; } +void LLAppViewer::initMaxHeapSize() +{ + //set the max heap size. + //here is some info regarding to the max heap size: + //------------------------------------------------------------------------------------------ + // OS | setting | SL address bits | max manageable memory space | max heap size + // Win 32 | default | 32-bit | 2GB | < 1.7GB + // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB + //Linux 32 | default | 32-bit | 3GB | < 2.7GB + //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB + //64-bit OS |default | 32-bit | 4GB | < 3.7GB + //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB) + //------------------------------------------------------------------------------------------ + //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB. + + //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ; + F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ; + BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemeoyFailurePreventionEnabled") ; + + LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ; +} + +void LLAppViewer::checkMemory() +{ + const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second + const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds + const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB + //static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ; + static void* last_reserved_address = NULL ; + + if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32()) + { + return ; + } + mMemCheckTimer.reset() ; + + if(gGLManager.mDebugGPU) + { + //update the availability of memory + LLMemory::updateMemoryInfo() ; + } + + //check the virtual address space fragmentation + if(!last_reserved_address) + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + } + else + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + if(!last_reserved_address) //failed, try once more + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + } + } + + S32 is_low = !last_reserved_address || LLMemory::isMemoryPoolLow() ; + + //if(is_low < 0) //to force quit + //{ + // if(force_quit_timer > MAX_QUIT_WAIT_TIME) //just hit the limit for the first time + // { + // //send out the notification to tell the viewer is about to quit in 30 seconds. + // LLNotification::Params params("ForceQuitDueToLowMemory"); + // LLNotifications::instance().add(params); + + // force_quit_timer = MAX_QUIT_WAIT_TIME - MEMORY_CHECK_INTERVAL ; + // } + // else + // { + // force_quit_timer -= MEMORY_CHECK_INTERVAL ; + // if(force_quit_timer < 0.f) + // { + // forceQuit() ; //quit + // } + // } + //} + //else + //{ + // force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ; + //} + + LLPipeline::throttleNewMemoryAllocation(!is_low ? FALSE : TRUE) ; + + if(is_low) + { + LLMemory::logMemoryInfo() ; + } +} + static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages"); static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache"); @@ -983,8 +1076,7 @@ bool LLAppViewer::mainLoop() LLVoiceChannel::initClass(); LLVoiceClient::getInstance()->init(gServicePump); LLTimer frameTimer,idleTimer; - LLTimer debugTime; - LLFrameTimer memCheckTimer; + LLTimer debugTime; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); joystick->setNeedsReset(true); @@ -993,9 +1085,7 @@ bool LLAppViewer::mainLoop() // with each frame, no need to instantiate a new LLSD event object each // time. Obviously, if that changes, just instantiate the LLSD at the // point of posting. - LLSD newFrame; - - const F32 memory_check_interval = 1.0f ; //second + LLSD newFrame; // Handle messages while (!LLApp::isExiting()) @@ -1006,18 +1096,8 @@ bool LLAppViewer::mainLoop() llclearcallstacks; //check memory availability information - { - if(memory_check_interval < memCheckTimer.getElapsedTimeF32()) - { - memCheckTimer.reset() ; - - //update the availability of memory - LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; - } - llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ; - llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ; - } - + checkMemory() ; + try { pingMainloopTimeout("Main:MiscNativeWindowEvents"); @@ -1181,7 +1261,7 @@ bool LLAppViewer::mainLoop() idleTimer.reset(); bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ; S32 total_work_pending = 0; - S32 total_io_pending = 0; + S32 total_io_pending = 0; while(!is_slow)//do not unpause threads if the frame rates are very low. { S32 work_pending = 0; @@ -1248,15 +1328,7 @@ bool LLAppViewer::mainLoop() } catch(std::bad_alloc) { - { - llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ; - llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ; - - LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; - - llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ; - llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ; - } + LLMemory::logMemoryInfo(TRUE) ; //stop memory leaking simulation LLFloaterMemLeak* mem_leak_instance = diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index a70a727c5d..7761a10f1c 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -166,8 +166,8 @@ public: // mute/unmute the system's master audio virtual void setMasterSystemAudioMute(bool mute); - virtual bool getMasterSystemAudioMute(); - + virtual bool getMasterSystemAudioMute(); + protected: virtual bool initWindow(); // Initialize the viewer's window. virtual bool initLogging(); // Initialize log files, logging system, return false on failure. @@ -184,11 +184,12 @@ protected: private: + void initMaxHeapSize(); bool initThreads(); // Initialize viewer threads, return false on failure. bool initConfiguration(); // Initialize settings from the command line/config file. bool initCache(); // Initialize local client cache. - + void checkMemory() ; // We have switched locations of both Mac and Windows cache, make sure // files migrate and old cache is cleared out. @@ -258,8 +259,7 @@ private: std::set mPlugins; - U32 mAvailPhysicalMemInKB ; - U32 mAvailVirtualMemInKB ; + LLFrameTimer mMemCheckTimer; public: //some information for updater typedef struct diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index a3d2941114..58eef45935 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -40,6 +40,7 @@ #include "llvertexbuffer.h" #include "llviewerdisplay.h" #include "llrender.h" +#include "pipeline.h" // static LLViewerDynamicTexture::instance_list_t LLViewerDynamicTexture::sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; @@ -205,7 +206,7 @@ void LLViewerDynamicTexture::postRender(BOOL success) BOOL LLViewerDynamicTexture::updateAllInstances() { sNumRenders = 0; - if (gGLManager.mIsDisabled) + if (gGLManager.mIsDisabled || LLPipeline::sMemAllocationThrottled) { return TRUE; } @@ -221,9 +222,8 @@ BOOL LLViewerDynamicTexture::updateAllInstances() if (dynamicTexture->needsRender()) { if(gGLManager.mDebugGPU) - { + { llinfos << "class type: " << (S32)dynamicTexture->getType() << llendl; - LLGLState::dumpStates() ; } glClear(GL_DEPTH_BUFFER_BIT); diff --git a/indra/newview/llfloatermemleak.cpp b/indra/newview/llfloatermemleak.cpp index 58931d112e..9edfe1e354 100644 --- a/indra/newview/llfloatermemleak.cpp +++ b/indra/newview/llfloatermemleak.cpp @@ -90,6 +90,11 @@ LLFloaterMemLeak::~LLFloaterMemLeak() void LLFloaterMemLeak::release() { + if(mLeakedMem.empty()) + { + return ; + } + for(S32 i = 0 ; i < (S32)mLeakedMem.size() ; i++) { delete[] mLeakedMem[i] ; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 7c8b52d0b6..e7153f7ffc 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -202,6 +202,7 @@ void display_stats() gMemoryAllocated = LLMemory::getCurrentRSS(); U32 memory = (U32)(gMemoryAllocated / (1024*1024)); llinfos << llformat("MEMORY: %d MB", memory) << llendl; + LLMemory::logMemoryInfo() ; gRecentMemoryTime.reset(); } } @@ -672,7 +673,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) glh::matrix4f mod = glh_get_current_modelview(); glViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; - LLVOAvatar::updateImpostors(); + + if(!LLPipeline::sMemAllocationThrottled) + { + LLVOAvatar::updateImpostors(); + } glh_set_current_projection(proj); glh_set_current_modelview(mod); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index f96b93da4d..260023a802 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3068,9 +3068,16 @@ void LLViewerLODTexture::processTextureStats() { mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ; } + else if(LLPipeline::sMemAllocationThrottled)//release memory of large textures by decrease their resolutions. + { + if(scaleDown()) + { + mDesiredDiscardLevel = mCachedRawDiscardLevel ; + } + } } -void LLViewerLODTexture::scaleDown() +bool LLViewerLODTexture::scaleDown() { if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) { @@ -3080,7 +3087,10 @@ void LLViewerLODTexture::scaleDown() { LLViewerTextureManager::sTesterp->setStablizingTime() ; } + + return true ; } + return false ; } //---------------------------------------------------------------------------------------------- //end of LLViewerLODTexture diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index b779396293..ffcbba3efd 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -595,7 +595,7 @@ public: private: void init(bool firstinit) ; - void scaleDown() ; + bool scaleDown() ; private: F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 64698ed006..943b5b5886 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3874,6 +3874,19 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { return FALSE; } + //check if there is enough memory for the snapshot image + if(LLPipeline::sMemAllocationThrottled) + { + return FALSE ; //snapshot taking is disabled due to memory restriction. + } + if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K + { + if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3)) + { + llwarns << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << llendl ; + return FALSE ; //there is no enough memory for taking this snapshot. + } + } // PRE SNAPSHOT gDisplaySwapBuffers = FALSE; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index b4a5777f10..7c69af17f2 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -98,6 +98,7 @@ #include "llspatialpartition.h" #include "llmutelist.h" #include "lltoolpie.h" +#include "llnotifications.h" #ifdef _DEBUG @@ -281,6 +282,7 @@ BOOL LLPipeline::sRenderAttachedLights = TRUE; BOOL LLPipeline::sRenderAttachedParticles = TRUE; BOOL LLPipeline::sRenderDeferred = FALSE; BOOL LLPipeline::sAllowRebuildPriorityGroup = FALSE ; +BOOL LLPipeline::sMemAllocationThrottled = FALSE; S32 LLPipeline::sVisibleLightCount = 0; F32 LLPipeline::sMinRenderSize = 0.f; @@ -513,6 +515,24 @@ void LLPipeline::destroyGL() static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); +//static +void LLPipeline::throttleNewMemoryAllocation(BOOL disable) +{ + if(sMemAllocationThrottled != disable) + { + sMemAllocationThrottled = disable ; + + if(sMemAllocationThrottled) + { + //send out notification + LLNotification::Params params("LowMemory"); + LLNotifications::instance().add(params); + + //release some memory. + } + } +} + void LLPipeline::resizeScreenTexture() { LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE); @@ -8792,7 +8812,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu void LLPipeline::generateImpostor(LLVOAvatar* avatar) { - LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR); + LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index b80765dac6..f4a7dfd38d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -334,6 +334,8 @@ public: static void updateRenderDeferred(); + static void throttleNewMemoryAllocation(BOOL disable); + private: void unloadShaders(); void addToQuickLookup( LLDrawPool* new_poolp ); @@ -477,8 +479,9 @@ public: static BOOL sRenderAttachedParticles; static BOOL sRenderDeferred; static BOOL sAllowRebuildPriorityGroup; + static BOOL sMemAllocationThrottled; static S32 sVisibleLightCount; - static F32 sMinRenderSize; + static F32 sMinRenderSize; //screen texture U32 mScreenWidth; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dfbb408d96..5183788c98 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6450,6 +6450,20 @@ Mute everyone? Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars. + + Your memory pool is low. Some functions of SL are disabled to avoid crash. Please close other applications. Restart SL if this persists. + + + + SL will quit in 30 seconds due to out of memory. + + - + \ No newline at end of file -- cgit v1.3 From 6469f1c2f21ecd3b15a18957d882ef6a16b17ecf Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sun, 17 Jul 2011 00:24:08 -0500 Subject: SH-2031 High risk changeset, but potentially high reward. Addresses frame stalls in renderer by never using the fixed function pipeline if shaders are available. --- indra/llrender/llcubemap.cpp | 12 +- indra/llrender/llgl.cpp | 23 ++-- indra/llrender/llglslshader.cpp | 3 + indra/llrender/llglslshader.h | 1 + indra/llrender/llimagegl.cpp | 12 ++ indra/llrender/llrender.cpp | 29 ++++- indra/llrender/llrender.h | 2 + indra/llrender/llvertexbuffer.cpp | 14 +-- indra/llui/llui.cpp | 21 +++- indra/llui/llui.h | 5 + indra/newview/app_settings/logcontrol.xml | 1 - .../shaders/class1/interface/customalphaF.glsl | 17 +++ .../shaders/class1/interface/customalphaV.glsl | 16 +++ .../shaders/class1/interface/glowcombineF.glsl | 17 +++ .../shaders/class1/interface/glowcombineV.glsl | 15 +++ .../shaders/class1/interface/occlusionF.glsl | 11 ++ .../shaders/class1/interface/occlusionV.glsl | 12 ++ .../shaders/class1/interface/solidcolorF.glsl | 15 +++ .../shaders/class1/interface/solidcolorV.glsl | 15 +++ .../shaders/class1/interface/twotextureaddF.glsl | 14 +++ .../shaders/class1/interface/twotextureaddV.glsl | 16 +++ .../app_settings/shaders/class1/interface/uiF.glsl | 13 +++ .../app_settings/shaders/class1/interface/uiV.glsl | 16 +++ .../app_settings/shaders/class1/objects/bumpF.glsl | 17 +++ .../app_settings/shaders/class1/objects/bumpV.glsl | 16 +++ indra/newview/lldrawpool.cpp | 5 +- indra/newview/lldrawpoolalpha.cpp | 4 +- indra/newview/lldrawpoolbump.cpp | 103 +++++++++++------ indra/newview/lldrawpoolsimple.cpp | 16 ++- indra/newview/lldrawpoolsky.cpp | 5 + indra/newview/lldrawpooltree.cpp | 2 +- indra/newview/lldrawpoolwlsky.cpp | 36 +++++- indra/newview/llhudnametag.cpp | 2 +- indra/newview/llspatialpartition.cpp | 5 +- indra/newview/lltexlayer.cpp | 7 ++ indra/newview/llviewerdisplay.cpp | 27 ++++- indra/newview/llviewershadermgr.cpp | 126 +++++++++++++++++++++ indra/newview/llviewershadermgr.h | 13 +++ indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewertexturelist.cpp | 2 +- indra/newview/llviewerwindow.cpp | 10 ++ indra/newview/llvoicevivox.cpp | 3 + indra/newview/llvotree.cpp | 1 + indra/newview/pipeline.cpp | 116 +++++++++++++------ shining-fixes_rev18977.patch | 41 +++++++ 45 files changed, 742 insertions(+), 117 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/uiF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/uiV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/bumpF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/bumpV.glsl create mode 100644 shining-fixes_rev18977.patch (limited to 'indra/newview/llviewerdisplay.cpp') diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index fb22d7f1f5..1b10354c22 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -259,7 +259,7 @@ void LLCubeMap::setMatrix(S32 stage) if (mMatrixStage < 0) return; - if (stage > 0) + //if (stage > 0) { gGL.getTexUnit(stage)->activate(); } @@ -278,17 +278,17 @@ void LLCubeMap::setMatrix(S32 stage) glLoadMatrixf((F32 *)trans.mMatrix); glMatrixMode(GL_MODELVIEW); - if (stage > 0) + /*if (stage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::restoreMatrix() { if (mMatrixStage < 0) return; - if (mMatrixStage > 0) + //if (mMatrixStage > 0) { gGL.getTexUnit(mMatrixStage)->activate(); } @@ -296,10 +296,10 @@ void LLCubeMap::restoreMatrix() glPopMatrix(); glMatrixMode(GL_MODELVIEW); - if (mMatrixStage > 0) + /*if (mMatrixStage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::setReflection (void) diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index e07ff0015c..8937726209 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -986,12 +986,12 @@ void LLGLManager::initExtensions() } if (mHasSync) { - glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync"); - glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync"); - glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync"); - glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync"); - glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync"); - glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v"); + glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync"); + glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync"); + glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync"); + glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync"); + glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync"); + glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v"); glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv"); } if (mHasMapBufferRange) @@ -1379,6 +1379,8 @@ void LLGLState::checkStates(const std::string& msg) glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); + stop_glerror(); + BOOL error = FALSE; if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) @@ -1399,7 +1401,9 @@ void LLGLState::checkStates(const std::string& msg) { LLGLenum state = iter->first; LLGLboolean cur_state = iter->second; + stop_glerror(); LLGLboolean gl_state = glIsEnabled(state); + stop_glerror(); if(cur_state != gl_state) { dumpStates(); @@ -1424,11 +1428,11 @@ void LLGLState::checkStates(const std::string& msg) void LLGLState::checkTextureChannels(const std::string& msg) { +#if 0 if (!gDebugGL) { return; } - stop_glerror(); GLint activeTexture; @@ -1594,6 +1598,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; } } +#endif } void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) @@ -1710,7 +1715,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) } } - if (glIsEnabled(GL_TEXTURE_2D)) + /*if (glIsEnabled(GL_TEXTURE_2D)) { if (!(data_mask & 0x0008)) { @@ -1733,7 +1738,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; } } - } + }*/ glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ad2c662dfc..c582858413 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -49,6 +49,7 @@ using std::make_pair; using std::string; GLhandleARB LLGLSLShader::sCurBoundShader = 0; +bool LLGLSLShader::sNoFixedFunction = false; BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) { @@ -376,6 +377,7 @@ BOOL LLGLSLShader::link(BOOL suppress_errors) void LLGLSLShader::bind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { glUseProgramObjectARB(mProgramObject); @@ -390,6 +392,7 @@ void LLGLSLShader::bind() void LLGLSLShader::unbind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { stop_glerror(); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 4922eb6d67..24562c3c42 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -67,6 +67,7 @@ public: LLGLSLShader(); static GLhandleARB sCurBoundShader; + static bool sNoFixedFunction; void unload(); BOOL createShader(std::vector * attributes, diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 60a5962234..9ca3a23d52 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1414,6 +1414,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre void LLImageGL::deleteDeadTextures() { + bool reset = false; + while (!sDeadTextureList.empty()) { GLuint tex = sDeadTextureList.front(); @@ -1426,12 +1428,22 @@ void LLImageGL::deleteDeadTextures() { tex_unit->unbind(tex_unit->getCurrType()); stop_glerror(); + + if (i > 0) + { + reset = true; + } } } glDeleteTextures(1, &tex); stop_glerror(); } + + if (reset) + { + gGL.getTexUnit(0)->activate(); + } } void LLImageGL::destroyGLTexture() diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 1d82dda30f..70df1dd1d1 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -46,6 +46,7 @@ S32 gGLViewport[4]; U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; +U32 LLTexUnit::sWhiteTexture = 0; static const U32 LL_NUM_TEXTURE_LAYERS = 32; static const U32 LL_NUM_LIGHT_UNITS = 8; @@ -126,7 +127,8 @@ void LLTexUnit::refreshState(void) // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html // - bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE; + bool enableDisable = !LLGLSLShader::sNoFixedFunction && + (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE; if (mCurrTexType != TT_NONE) { @@ -184,7 +186,8 @@ void LLTexUnit::enable(eTextureType type) mCurrTexType = type; gGL.flush(); - if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + if (!LLGLSLShader::sNoFixedFunction && + type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && mIndex < gGLManager.mNumTextureUnits) { glEnable(sGLTextureType[type]); @@ -201,7 +204,8 @@ void LLTexUnit::disable(void) activate(); unbind(mCurrTexType); gGL.flush(); - if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + if (!LLGLSLShader::sNoFixedFunction && + mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && mIndex < gGLManager.mNumTextureUnits) { glDisable(sGLTextureType[mCurrTexType]); @@ -403,7 +407,14 @@ void LLTexUnit::unbind(eTextureType type) activate(); mCurrTexture = 0; - glBindTexture(sGLTextureType[type], 0); + if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } stop_glerror(); } } @@ -474,6 +485,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio void LLTexUnit::setTextureBlendType(eTextureBlendType type) { + if (LLGLSLShader::sNoFixedFunction) + { //texture blend type means nothing when using shaders + return; + } + if (mIndex < 0) return; // Do nothing if it's already correctly set. @@ -594,6 +610,11 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha) { + if (LLGLSLShader::sNoFixedFunction) + { //register combiners do nothing when not using fixed function + return; + } + if (mIndex < 0) return; activate(); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 41e7b35341..9eedebe2ce 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -52,6 +52,8 @@ class LLTexUnit { friend class LLRender; public: + static U32 sWhiteTexture; + typedef enum { TT_TEXTURE = 0, // Standard 2D Texture diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 82c5efe0ac..1180afa631 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -35,6 +35,8 @@ #include "llmemtype.h" #include "llrender.h" #include "llvector4a.h" +#include "llglslshader.h" + //============================================================================ @@ -1113,8 +1115,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_UNSYNCHRONIZED_BIT); + GL_MAP_INVALIDATE_RANGE_BIT); #endif } else @@ -1122,8 +1123,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran #ifdef GL_ARB_map_buffer_range src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT); + GL_MAP_FLUSH_EXPLICIT_BIT); #endif } } @@ -1280,8 +1280,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_UNSYNCHRONIZED_BIT); + GL_MAP_INVALIDATE_RANGE_BIT); #endif } else @@ -1289,8 +1288,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) #ifdef GL_ARB_map_buffer_range src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT); + GL_MAP_FLUSH_EXPLICIT_BIT); #endif } } diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 8020ca802b..28d7e0a5ba 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -95,7 +95,6 @@ static LLDefaultChildRegistry::Register register_search_editor(" // register other widgets which otherwise may not be linked in static LLDefaultChildRegistry::Register register_loading_indicator("loading_indicator"); - // // Functions // @@ -524,8 +523,15 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex if (solid_color) { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + if (LLGLSLShader::sNoFixedFunction) + { + gSolidColorProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + } } gGL.getTexUnit(0)->bind(image); @@ -699,7 +705,14 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex if (solid_color) { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } } } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c583d58d5a..a04b232a28 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -33,6 +33,7 @@ #include "llrect.h" #include "llcontrol.h" #include "llcoord.h" +#include "llglslshader.h" #include "llinitparam.h" #include "llregistry.h" #include "lluicolor.h" @@ -47,6 +48,7 @@ // for initparam specialization #include "llfontgl.h" + class LLColor4; class LLVector3; class LLVector2; @@ -484,4 +486,7 @@ namespace LLInitParam }; } +extern LLGLSLShader gSolidColorProgram; +extern LLGLSLShader gUIProgram; + #endif diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 9f4e89691f..ae72dee900 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -44,7 +44,6 @@ - Capabilities diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl new file mode 100644 index 0000000000..3827c72f4c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl @@ -0,0 +1,17 @@ +/** + * @file customalphaF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D diffuseMap; + +uniform float custom_alpha; + +void main() +{ + vec4 color = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); + color.a *= custom_alpha; + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl new file mode 100644 index 0000000000..04bfff22c1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl @@ -0,0 +1,16 @@ +/** + * @file customalphaV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl new file mode 100644 index 0000000000..a60fb1eaa7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl @@ -0,0 +1,17 @@ +/** + * @file glowcombineF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D glowMap; +uniform sampler2DRect screenMap; + +void main() +{ + gl_FragColor = texture2D(glowMap, gl_TexCoord[0].xy) + + texture2DRect(screenMap, gl_TexCoord[1].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl new file mode 100644 index 0000000000..ce183ec154 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl @@ -0,0 +1,15 @@ +/** + * @file glowcombineV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl new file mode 100644 index 0000000000..b140712f18 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl @@ -0,0 +1,11 @@ +/** + * @file occlusionF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +void main() +{ + gl_FragColor = vec4(1,1,1,1); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl new file mode 100644 index 0000000000..5a5d0ec506 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl @@ -0,0 +1,12 @@ +/** + * @file uiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl new file mode 100644 index 0000000000..ae943cc438 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl @@ -0,0 +1,15 @@ +/** + * @file twotextureaddF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D tex0; + +void main() +{ + float alpha = texture2D(tex0, gl_TexCoord[0].xy).a; + + gl_FragColor = vec4(gl_Color.rgb, alpha); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl new file mode 100644 index 0000000000..5a854b4e02 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl @@ -0,0 +1,15 @@ +/** + * @file solidcolorV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl new file mode 100644 index 0000000000..d81b56fdb9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl @@ -0,0 +1,14 @@ +/** + * @file twotextureaddF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D tex0; +uniform sampler2D tex1; + +void main() +{ + gl_FragColor = texture2D(tex0, gl_TexCoord[0].xy)+texture2D(tex1, gl_TexCoord[1].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl new file mode 100644 index 0000000000..f685b112b4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl @@ -0,0 +1,16 @@ +/** + * @file twotextureaddV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/uiF.glsl b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl new file mode 100644 index 0000000000..9dec7a56ba --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl @@ -0,0 +1,13 @@ +/** + * @file uiF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D diffuseMap; + +void main() +{ + gl_FragColor = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/uiV.glsl b/indra/newview/app_settings/shaders/class1/interface/uiV.glsl new file mode 100644 index 0000000000..9ca6cae5c5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/uiV.glsl @@ -0,0 +1,16 @@ +/** + * @file uiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} + diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl new file mode 100644 index 0000000000..587ab93a80 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl @@ -0,0 +1,17 @@ +/** + * @file bumpF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D texture0; +uniform sampler2D texture1; + +void main() +{ + float tex0 = texture2D(texture0, gl_TexCoord[0].xy).a; + float tex1 = texture2D(texture1, gl_TexCoord[1].xy).a; + + gl_FragColor = vec4(tex0+(1.0-tex1)-0.5); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl new file mode 100644 index 0000000000..056d1a9582 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl @@ -0,0 +1,16 @@ +/** + * @file bumpV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +void main() +{ + //transform vertex + gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index fa7d6e2a40..286284f828 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -190,15 +190,16 @@ void LLDrawPool::renderPostDeferred(S32 pass) //virtual void LLDrawPool::endRenderPass( S32 pass ) { - for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) + /*for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) { //dummy cleanup of any currently bound textures if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) { gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); gGL.getTexUnit(i)->disable(); } - } + }*/ + //make sure channel 0 is active channel gGL.getTexUnit(0)->activate(); } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index ad7e3ad593..ddcf42e523 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -138,6 +138,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) gPipeline.mDeferredDepth.bindTarget(); simple_shader = NULL; fullbright_shader = NULL; + gObjectFullbrightProgram.bind(); } deferred_render = TRUE; @@ -156,6 +157,7 @@ void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) { gPipeline.mDeferredDepth.flush(); gPipeline.mScreen.bindTarget(); + gObjectFullbrightProgram.unbind(); } deferred_render = FALSE; @@ -238,7 +240,7 @@ void LLDrawPoolAlpha::render(S32 pass) fullbright_shader->bind(); } pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - LLGLSLShader::bindNoShader(); + //LLGLSLShader::bindNoShader(); } else { diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 813b3820ee..d801f6df18 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -464,11 +464,15 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& } } } - gGL.getTexUnit(diffuse_channel)->disable(); - gGL.getTexUnit(cube_channel)->disable(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + if (!LLGLSLShader::sNoFixedFunction) + { + gGL.getTexUnit(diffuse_channel)->disable(); + gGL.getTexUnit(cube_channel)->disable(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } } void LLDrawPoolBump::endShiny(bool invisible) @@ -583,19 +587,19 @@ void LLDrawPoolBump::endFullbrightShiny() cube_map->disable(); cube_map->restoreMatrix(); - if (diffuse_channel != 0) + /*if (diffuse_channel != 0) { shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);*/ shader->unbind(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); diffuse_channel = -1; cube_channel = 0; @@ -706,36 +710,44 @@ void LLDrawPoolBump::beginBump(U32 pass) // Optional second pass: emboss bump map stop_glerror(); - // TEXTURE UNIT 0 - // Output.rgb = texture at texture coord 0 - gGL.getTexUnit(0)->activate(); + if (LLGLSLShader::sNoFixedFunction) + { + gObjectBumpProgram.bind(); + } + else + { + // TEXTURE UNIT 0 + // Output.rgb = texture at texture coord 0 + gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // TEXTURE UNIT 1 - gGL.getTexUnit(1)->activate(); + // TEXTURE UNIT 1 + gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + + gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA); + gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + // src = tex0 + (1 - tex1) - 0.5 + // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5 + // = (1 + bump0 - bump1) / 2 - // src = tex0 + (1 - tex1) - 0.5 - // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5 - // = (1 + bump0 - bump1) / 2 + // Blend: src * dst + dst * src + // = 2 * src * dst + // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst] + // = (1 + bump0 - bump1) * dst.rgb + // = dst.rgb + dst.rgb * (bump0 - bump1) + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); + } - // Blend: src * dst + dst * src - // = 2 * src * dst - // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst] - // = (1 + bump0 - bump1) * dst.rgb - // = dst.rgb + dst.rgb * (bump0 - bump1) gGL.setSceneBlendType(LLRender::BT_MULT_X2); - gGL.getTexUnit(0)->activate(); stop_glerror(); - - gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); } //static @@ -765,14 +777,21 @@ void LLDrawPoolBump::endBump(U32 pass) return; } - // Disable texture unit 1 - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + if (LLGLSLShader::sNoFixedFunction) + { + gObjectBumpProgram.unbind(); + } + else + { + // Disable texture blending on unit 1 + gGL.getTexUnit(1)->activate(); + //gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - // Disable texture unit 0 - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + // Disable texture blending on unit 0 + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -1407,6 +1426,11 @@ void LLDrawPoolInvisible::render(S32 pass) { //render invisiprims LLFastTimer t(FTM_RENDER_INVISIBLE); + if (gPipeline.canUseVertexShaders()) + { + gOcclusionProgram.bind(); + } + U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; glStencilMask(0); gGL.setColorMask(false, false); @@ -1414,6 +1438,11 @@ void LLDrawPoolInvisible::render(S32 pass) gGL.setColorMask(true, false); glStencilMask(0xFFFFFFFF); + if (gPipeline.canUseVertexShaders()) + { + gOcclusionProgram.unbind(); + } + if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { beginShiny(true); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 5dbb27cabb..224f149c6b 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -49,6 +49,8 @@ void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) gDeferredFullbrightProgram.bind(); } +static LLFastTimer::DeclareTimer FTM_RENDER_GLOW_PUSH("Glow Push"); + void LLDrawPoolGlow::renderPostDeferred(S32 pass) { LLFastTimer t(FTM_RENDER_GLOW); @@ -62,7 +64,11 @@ void LLDrawPoolGlow::renderPostDeferred(S32 pass) LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.setColorMask(false, true); - pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + + { + LLFastTimer t(FTM_RENDER_GLOW_PUSH); + pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } gGL.setColorMask(true, false); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -374,10 +380,14 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass) LLFastTimer t(FTM_RENDER_FULLBRIGHT); LLRenderPass::endRenderPass(pass); + stop_glerror(); + if (mVertexShaderLevel > 0) { fullbright_shader->unbind(); } + + stop_glerror(); } void LLDrawPoolFullbright::render(S32 pass) @@ -385,6 +395,8 @@ void LLDrawPoolFullbright::render(S32 pass) LLFastTimer t(FTM_RENDER_FULLBRIGHT); gGL.setSceneBlendType(LLRender::BT_ALPHA); + stop_glerror(); + if (mVertexShaderLevel > 0) { fullbright_shader->bind(); @@ -398,6 +410,8 @@ void LLDrawPoolFullbright::render(S32 pass) U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); } + + stop_glerror(); } S32 LLDrawPoolFullbright::getNumPasses() diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index 030d6e1110..efffb2df9e 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -82,6 +82,10 @@ void LLDrawPoolSky::render(S32 pass) mShader = &gObjectFullbrightWaterProgram; mShader->bind(); } + else if (LLGLSLShader::sNoFixedFunction) + { //just use the UI shader (generic single texture no lighting) + gUIProgram.bind(); + } else { // don't use shaders! @@ -139,6 +143,7 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) if (LLSkyTex::doInterpolate()) { + LLGLEnable blend(GL_BLEND); mSkyTex[side].bindTexture(FALSE); glColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 81c796b146..429e06b227 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -73,7 +73,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) shader = &gObjectSimpleNonIndexedProgram; } - if (gPipeline.canUseWindLightShadersOnObjects()) + if (gPipeline.canUseVertexShaders()) { shader->bind(); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index bf79c2100c..f9fd501072 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -189,16 +189,31 @@ void LLDrawPoolWLSky::renderStars(void) const glRotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); // gl_FragColor.rgb = gl_Color.rgb; // gl_FragColor.a = gl_Color.a * star_alpha.a; - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); + if (LLGLSLShader::sNoFixedFunction) + { + gCustomAlphaProgram.bind(); + gCustomAlphaProgram.uniform1f("custom_alpha", star_alpha.mV[3]); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); + } gSky.mVOWLSkyp->drawStars(); gGL.popMatrix(); - - // and disable the combiner states - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + + if (LLGLSLShader::sNoFixedFunction) + { + gCustomAlphaProgram.unbind(); + } + else + { + // and disable the combiner states + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } } void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const @@ -242,6 +257,10 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() if (gSky.mVOSkyp->getMoon().getDraw() && face->getGeomCount()) { + if (gPipeline.canUseVertexShaders()) + { + gUIProgram.bind(); + } // *NOTE: even though we already bound this texture above for the // stars register combiners, we bind again here for defensive reasons, // since LLImageGL::bind detects that it's a noop, and optimizes it out. @@ -257,6 +276,11 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLFacePool::LLOverrideFaceColor color_override(this, color); face->renderIndexed(); + + if (gPipeline.canUseVertexShaders()) + { + gUIProgram.unbind(); + } } } diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 82e1f2dfb5..482294c8a6 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -477,7 +477,7 @@ void LLHUDNameTag::renderText(BOOL for_select) // Render label { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); for(std::vector::iterator segment_iter = mLabelSegments.begin(); segment_iter != mLabelSegments.end(); ++segment_iter ) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f99afa923b..e23b431457 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -47,6 +47,7 @@ #include "llvoavatar.h" #include "llvolumemgr.h" #include "lltextureatlas.h" +#include "llglslshader.h" static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling"); static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); @@ -3176,6 +3177,8 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) glColor4fv(line_color.mV); LLVertexBuffer::unbind(); + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); + glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); @@ -3257,7 +3260,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) if (phys_volume->mHullPoints && phys_volume->mHullIndices) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); LLVertexBuffer::unbind(); glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); glColor4fv(line_color.mV); diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index bd41aa64f0..e8abee2fb7 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -45,6 +45,7 @@ #include "llagentwearables.h" #include "llwearable.h" #include "llviewercontrol.h" +#include "llviewershadermgr.h" #include "llviewervisualparam.h" //#include "../tools/imdebug/imdebug.h" @@ -294,11 +295,17 @@ BOOL LLTexLayerSetBuffer::render() BOOL success = TRUE; + //hack to use fixed function when updating tex layer sets + bool no_ff = LLGLSLShader::sNoFixedFunction; + LLGLSLShader::sNoFixedFunction = false; + // Composite the color data LLGLSUIDefault gls_ui; success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); gGL.flush(); + LLGLSLShader::sNoFixedFunction = no_ff; + if(upload_now) { if (!success) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 911fc8e1ed..39053fe9e4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -616,6 +616,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; + LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) { //force occlusion on for all render types if doing deferred render (tighter shadow frustum) @@ -709,6 +710,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + //if (!for_snapshot) { LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION); @@ -717,6 +721,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.generateHighlight(*LLViewerCamera::getInstance()); } + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + ////////////////////////////////////// // // Update images, using the image stats generated during object update/culling @@ -743,6 +750,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLImageGL::deleteDeadTextures(); stop_glerror(); } + + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + /////////////////////////////////// // // StateSort @@ -770,6 +781,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } } + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + LLPipeline::sUseOcclusion = occlusion; { @@ -828,6 +842,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; LLPipeline::refreshRenderDeferred(); + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + stop_glerror(); if (to_texture) @@ -878,6 +895,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) stop_glerror(); } + for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) @@ -1339,7 +1364,7 @@ void render_ui_2d() } stop_glerror(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); // render outline for HUD if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e473901609..812b03a2e6 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -61,6 +61,14 @@ BOOL LLViewerShaderMgr::sInitialized = FALSE; LLVector4 gShinyOrigin; +//utility shaders +LLGLSLShader gOcclusionProgram; +LLGLSLShader gUIProgram; +LLGLSLShader gCustomAlphaProgram; +LLGLSLShader gGlowCombineProgram; +LLGLSLShader gTwoTextureAddProgram; +LLGLSLShader gSolidColorProgram; + //object shaders LLGLSLShader gObjectSimpleProgram; LLGLSLShader gObjectSimpleWaterProgram; @@ -70,6 +78,7 @@ LLGLSLShader gObjectFullbrightShinyProgram; LLGLSLShader gObjectFullbrightShinyWaterProgram; LLGLSLShader gObjectShinyProgram; LLGLSLShader gObjectShinyWaterProgram; +LLGLSLShader gObjectBumpProgram; LLGLSLShader gObjectSimpleNonIndexedProgram; LLGLSLShader gObjectSimpleNonIndexedWaterProgram; @@ -169,6 +178,13 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gWaterProgram); mShaderList.push_back(&gAvatarEyeballProgram); mShaderList.push_back(&gObjectSimpleProgram); + mShaderList.push_back(&gObjectBumpProgram); + mShaderList.push_back(&gUIProgram); + mShaderList.push_back(&gCustomAlphaProgram); + mShaderList.push_back(&gGlowCombineProgram); + mShaderList.push_back(&gTwoTextureAddProgram); + mShaderList.push_back(&gSolidColorProgram); + mShaderList.push_back(&gOcclusionProgram); mShaderList.push_back(&gObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); mShaderList.push_back(&gObjectFullbrightShinyWaterProgram); @@ -410,9 +426,13 @@ void LLViewerShaderMgr::setShaders() } mMaxAvatarShaderLevel = 0; + LLGLSLShader::sNoFixedFunction = false; if (LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") && gSavedSettings.getBOOL("VertexShaderEnable")) { + //using shaders, disable fixed function + LLGLSLShader::sNoFixedFunction = true; + S32 light_class = 2; S32 env_class = 2; S32 obj_class = 2; @@ -554,6 +574,7 @@ void LLViewerShaderMgr::setShaders() } else { + LLGLSLShader::sNoFixedFunction = false; gPipeline.mVertexShadersEnabled = FALSE; gPipeline.mVertexShadersLoaded = 0; mVertexShaderLevel[SHADER_LIGHTING] = 0; @@ -568,6 +589,7 @@ void LLViewerShaderMgr::setShaders() } else { + LLGLSLShader::sNoFixedFunction = false; gPipeline.mVertexShadersEnabled = FALSE; gPipeline.mVertexShadersLoaded = 0; mVertexShaderLevel[SHADER_LIGHTING] = 0; @@ -591,7 +613,15 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { + gOcclusionProgram.unload(); + gUIProgram.unload(); + gCustomAlphaProgram.unload(); + gGlowCombineProgram.unload(); + gTwoTextureAddProgram.unload(); + gSolidColorProgram.unload(); + gObjectSimpleProgram.unload(); + gObjectBumpProgram.unload(); gObjectSimpleWaterProgram.unload(); gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); @@ -1581,6 +1611,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyWaterProgram.unload(); gObjectShinyWaterProgram.unload(); gObjectSimpleProgram.unload(); + gObjectBumpProgram.unload(); gObjectSimpleWaterProgram.unload(); gObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); @@ -1751,6 +1782,22 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectSimpleProgram.createShader(NULL, NULL); } + if (success) + { + gObjectBumpProgram.mName = "Bump Shader"; + /*gObjectBumpProgram.mFeatures.calculatesLighting = true; + gObjectBumpProgram.mFeatures.calculatesAtmospherics = true; + gObjectBumpProgram.mFeatures.hasGamma = true; + gObjectBumpProgram.mFeatures.hasAtmospherics = true; + gObjectBumpProgram.mFeatures.hasLighting = true; + gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/ + gObjectBumpProgram.mShaderFiles.clear(); + gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectBumpProgram.createShader(NULL, NULL); + } + if (success) { gObjectSimpleWaterProgram.mName = "Simple Water Shader"; @@ -2135,6 +2182,85 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gHighlightProgram.createShader(NULL, NULL); } + if (success) + { + gUIProgram.mName = "UI Shader"; + gUIProgram.mShaderFiles.clear(); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB)); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB)); + gUIProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gUIProgram.createShader(NULL, NULL); + } + + if (success) + { + gCustomAlphaProgram.mName = "Custom Alpha Shader"; + gCustomAlphaProgram.mShaderFiles.clear(); + gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB)); + gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gCustomAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gCustomAlphaProgram.createShader(NULL, NULL); + } + + if (success) + { + gGlowCombineProgram.mName = "Glow Combine Shader"; + gGlowCombineProgram.mShaderFiles.clear(); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB)); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB)); + gGlowCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gGlowCombineProgram.createShader(NULL, NULL); + if (success) + { + gGlowCombineProgram.bind(); + gGlowCombineProgram.uniform1i("glowMap", 0); + gGlowCombineProgram.uniform1i("screenMap", 1); + gGlowCombineProgram.unbind(); + } + } + + if (success) + { + gTwoTextureAddProgram.mName = "Two Texture Add Shader"; + gTwoTextureAddProgram.mShaderFiles.clear(); + gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB)); + gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTwoTextureAddProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gTwoTextureAddProgram.createShader(NULL, NULL); + if (success) + { + gTwoTextureAddProgram.bind(); + gTwoTextureAddProgram.uniform1i("tex0", 0); + gTwoTextureAddProgram.uniform1i("tex1", 1); + } + } + + if (success) + { + gSolidColorProgram.mName = "Solid Color Shader"; + gSolidColorProgram.mShaderFiles.clear(); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB)); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSolidColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gSolidColorProgram.createShader(NULL, NULL); + if (success) + { + gSolidColorProgram.bind(); + gSolidColorProgram.uniform1i("tex0", 0); + gSolidColorProgram.unbind(); + } + } + + if (success) + { + gOcclusionProgram.mName = "Occlusion Shader"; + gOcclusionProgram.mShaderFiles.clear(); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB)); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOcclusionProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gOcclusionProgram.createShader(NULL, NULL); + } + if( !success ) { mVertexShaderLevel[SHADER_INTERFACE] = 0; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index efef9ec5b2..6b22e83a9f 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -287,6 +287,18 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade extern LLVector4 gShinyOrigin; +//utility shaders +extern LLGLSLShader gOcclusionProgram; +extern LLGLSLShader gUIProgram; +extern LLGLSLShader gCustomAlphaProgram; +extern LLGLSLShader gGlowCombineProgram; + +//output tex0[tc0] + tex1[tc1] +extern LLGLSLShader gTwoTextureAddProgram; + +//output vec4(color.rgb,color.a*tex0[tc0].a) +extern LLGLSLShader gSolidColorProgram; + //object shaders extern LLGLSLShader gObjectSimpleProgram; extern LLGLSLShader gObjectSimpleWaterProgram; @@ -296,6 +308,7 @@ extern LLGLSLShader gObjectFullbrightProgram; extern LLGLSLShader gObjectFullbrightWaterProgram; extern LLGLSLShader gObjectFullbrightNonIndexedProgram; extern LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; +extern LLGLSLShader gObjectBumpProgram; extern LLGLSLShader gObjectSimpleLODProgram; extern LLGLSLShader gObjectFullbrightLODProgram; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 4da0f80a00..5fcc57bc91 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -599,7 +599,7 @@ bool LLViewerTexture::bindDefaultImage(S32 stage) } if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep)) { - res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep) ; + res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep); } if (!res) { diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index d24174adea..30ef8b8a29 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -115,7 +115,7 @@ void LLViewerTextureList::doPreloadImages() // Set the "white" image LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); - + LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); LLUIImageList* image_list = LLUIImageList::getInstance(); image_list->initFromFile(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index cff166b825..1e056898d5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2296,6 +2296,11 @@ void LLViewerWindow::draw() // Draw all nested UI views. // No translation needed, this view is glued to 0,0 + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + gGL.pushMatrix(); LLUI::pushMatrix(); { @@ -2370,6 +2375,11 @@ void LLViewerWindow::draw() LLUI::popMatrix(); gGL.popMatrix(); + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } + //#if LL_DEBUG LLView::sIsDrawing = FALSE; //#endif diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index cd2bbad620..9dc6b5194e 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -7049,6 +7049,8 @@ LLVivoxProtocolParser::~LLVivoxProtocolParser() XML_ParserFree(parser); } +//static LLFastTimer::DeclareTimer FTM_VIVOX_PROCESS("Vivox Process"); + // virtual LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( const LLChannelDescriptors& channels, @@ -7057,6 +7059,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( LLSD& context, LLPumpIO* pump) { + //LLFastTimer t(FTM_VIVOX_PROCESS); LLBufferStream istr(channels, buffer.get()); std::ostringstream ostr; while (istr.good()) diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 3c7fe708e6..890861df71 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -51,6 +51,7 @@ #include "llspatialpartition.h" #include "llnotificationsutil.h" #include "raytrace.h" +#include "llglslshader.h" extern LLPipeline gPipeline; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e74bf2a620..8372c2430b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1983,6 +1983,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDepthTest depth(GL_TRUE, GL_FALSE); + bool bound_shader = false; + if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0) + { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can + // (shadow render uses a special shader that clamps to clip planes) + bound_shader = true; + gOcclusionProgram.bind(); + } + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -2010,6 +2018,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } } + if (bound_shader) + { + gOcclusionProgram.unbind(); + } + camera.disableUserClipPlane(); if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && @@ -2133,7 +2146,12 @@ void LLPipeline::doOcclusion(LLCamera& camera) LLGLDepthTest depth(GL_TRUE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); - + + if (canUseVertexShaders()) + { + gOcclusionProgram.bind(); + } + for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; @@ -2141,6 +2159,11 @@ void LLPipeline::doOcclusion(LLCamera& camera) group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } + if (canUseVertexShaders()) + { + gOcclusionProgram.unbind(); + } + gGL.setColorMask(true, false); } } @@ -3249,6 +3272,11 @@ void render_hud_elements() gGL.color4f(1,1,1,1); if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + LLGLEnable multisample(gSavedSettings.getU32("RenderFSAASamples") > 0 ? GL_MULTISAMPLE_ARB : 0); gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() @@ -3262,6 +3290,10 @@ void render_hud_elements() // Render name tags. LLHUDObject::renderAll(); + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } } else if (gForceRenderLandFence) { @@ -3599,8 +3631,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) check_stack_depth(stack_depth); std::string msg = llformat("pass %d", i); LLGLState::checkStates(msg); - LLGLState::checkTextureChannels(msg); - LLGLState::checkClientArrays(msg); + //LLGLState::checkTextureChannels(msg); + //LLGLState::checkClientArrays(msg); } } } @@ -3638,16 +3670,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - - - stop_glerror(); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights"); @@ -3701,8 +3725,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); +// LLGLState::checkTextureChannels(); +// LLGLState::checkClientArrays(); } void LLPipeline::renderGeomDeferred(LLCamera& camera) @@ -6449,30 +6473,39 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) LLGLDisable blend(GL_BLEND); - //tex unit 0 - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - - gGL.getTexUnit(0)->bind(&mGlow[1]); - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE); - - - //tex unit 1 - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + if (LLGLSLShader::sNoFixedFunction) + { + gGlowCombineProgram.bind(); + } + else + { + //tex unit 0 + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); + //tex unit 1 + gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + } + gGL.getTexUnit(0)->bind(&mGlow[1]); gGL.getTexUnit(1)->bind(&mScreen); - gGL.getTexUnit(1)->activate(); LLGLEnable multisample(gSavedSettings.getU32("RenderFSAASamples") > 0 ? GL_MULTISAMPLE_ARB : 0); buff->setBuffer(mask); buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + if (LLGLSLShader::sNoFixedFunction) + { + gGlowCombineProgram.unbind(); + } + else + { + gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } + } if (LLRenderTarget::sUseFBO) @@ -6485,6 +6518,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) { + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + gGL.setColorMask(true, false); LLVector2 tc1(0,0); @@ -6508,6 +6546,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.end(); gGL.flush(); + + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } + } glMatrixMode(GL_PROJECTION); @@ -8063,8 +8107,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLViewerCamera::getInstance()->setUserClipPlane(npnorm); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); if (!skip_avatar_update) { @@ -8197,6 +8241,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLVertexBuffer::unbind(); { + if (!use_shader) + { //occlusion program is general purpose depth-only no-textures + gOcclusionProgram.bind(); + } LLFastTimer ftm(FTM_SHADOW_SIMPLE); LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->disable(); @@ -8205,6 +8253,10 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); } gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + if (!use_shader) + { + gOcclusionProgram.unbind(); + } } if (use_shader) diff --git a/shining-fixes_rev18977.patch b/shining-fixes_rev18977.patch new file mode 100644 index 0000000000..b711da870a --- /dev/null +++ b/shining-fixes_rev18977.patch @@ -0,0 +1,41 @@ +# HG changeset patch +# User Dave Parks +# Date 1308673064 18000 +# Node ID 95c5639a3f80920e8dc54703d894517dd7694edf +# Parent 6af10678de4736222b2c3f7e010e984fb5b327de +SH-208 Disable VBO on all intel graphics chips (stability improvement). + +diff -r 6af10678de47 -r 95c5639a3f80 indra/newview/featuretable.txt +--- a/indra/newview/featuretable.txt Mon Jun 20 16:42:31 2011 -0700 ++++ b/indra/newview/featuretable.txt Tue Jun 21 11:17:44 2011 -0500 +@@ -1,4 +1,4 @@ +-version 29 ++version 30 + + // NOTE: This is mostly identical to featuretable_mac.txt with a few differences + // Should be combined into one table +@@ -297,6 +297,7 @@ + + list Intel + RenderAnisotropic 1 0 ++RenderVBOEnable 1 0 + + list GeForce2 + RenderAnisotropic 1 0 +diff -r 6af10678de47 -r 95c5639a3f80 indra/newview/featuretable_xp.txt +--- a/indra/newview/featuretable_xp.txt Mon Jun 20 16:42:31 2011 -0700 ++++ b/indra/newview/featuretable_xp.txt Tue Jun 21 11:17:44 2011 -0500 +@@ -1,4 +1,4 @@ +-version 29 ++version 30 + + // NOTE: This is mostly identical to featuretable_mac.txt with a few differences + // Should be combined into one table +@@ -295,6 +295,7 @@ + + list Intel + RenderAnisotropic 1 0 ++RenderVBOEnable 1 0 + + list GeForce2 + RenderAnisotropic 1 0 -- cgit v1.3