Performance improvements. Faster threadsaferefcount, faster instancetracker, use hashtable and pre-hashed strings for GLSL uniform lookup, and use dup_handles curl interface to avoid re-initing ares resolvers expensively.
commit
4e81a84abd
|
|
@ -5187,7 +5187,8 @@ LLVolumeFace::LLVolumeFace() :
|
|||
mTexCoords(NULL),
|
||||
mIndices(NULL),
|
||||
mWeights(NULL),
|
||||
mOctree(NULL)
|
||||
mOctree(NULL),
|
||||
mOptimized(FALSE)
|
||||
{
|
||||
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
|
||||
mExtents[0].splat(-0.5f);
|
||||
|
|
@ -5294,6 +5295,8 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
|||
LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);
|
||||
}
|
||||
|
||||
mOptimized = src.mOptimized;
|
||||
|
||||
//delete
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -5517,14 +5520,14 @@ class LLVCacheVertexData
|
|||
public:
|
||||
S32 mIdx;
|
||||
S32 mCacheTag;
|
||||
F32 mScore;
|
||||
F64 mScore;
|
||||
U32 mActiveTriangles;
|
||||
std::vector<LLVCacheTriangleData*> mTriangles;
|
||||
|
||||
LLVCacheVertexData()
|
||||
{
|
||||
mCacheTag = -1;
|
||||
mScore = 0.f;
|
||||
mScore = 0.0;
|
||||
mActiveTriangles = 0;
|
||||
mIdx = -1;
|
||||
}
|
||||
|
|
@ -5534,13 +5537,13 @@ class LLVCacheTriangleData
|
|||
{
|
||||
public:
|
||||
bool mActive;
|
||||
F32 mScore;
|
||||
F64 mScore;
|
||||
LLVCacheVertexData* mVertex[3];
|
||||
|
||||
LLVCacheTriangleData()
|
||||
{
|
||||
mActive = true;
|
||||
mScore = 0.f;
|
||||
mScore = 0.0;
|
||||
mVertex[0] = mVertex[1] = mVertex[2] = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -5551,7 +5554,7 @@ public:
|
|||
{
|
||||
if (mVertex[i])
|
||||
{
|
||||
llassert_always(mVertex[i]->mActiveTriangles > 0);
|
||||
llassert(mVertex[i]->mActiveTriangles > 0);
|
||||
mVertex[i]->mActiveTriangles--;
|
||||
}
|
||||
}
|
||||
|
|
@ -5563,44 +5566,44 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
const F32 FindVertexScore_CacheDecayPower = 1.5f;
|
||||
const F32 FindVertexScore_LastTriScore = 0.75f;
|
||||
const F32 FindVertexScore_ValenceBoostScale = 2.0f;
|
||||
const F32 FindVertexScore_ValenceBoostPower = 0.5f;
|
||||
const F64 FindVertexScore_CacheDecayPower = 1.5;
|
||||
const F64 FindVertexScore_LastTriScore = 0.75;
|
||||
const F64 FindVertexScore_ValenceBoostScale = 2.0;
|
||||
const F64 FindVertexScore_ValenceBoostPower = 0.5;
|
||||
const U32 MaxSizeVertexCache = 32;
|
||||
const F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3);
|
||||
|
||||
F32 find_vertex_score(LLVCacheVertexData& data)
|
||||
F64 find_vertex_score(LLVCacheVertexData& data)
|
||||
{
|
||||
if (data.mActiveTriangles == 0)
|
||||
{ //no triangle references this vertex
|
||||
return -1.f;
|
||||
}
|
||||
F64 score = -1.0;
|
||||
|
||||
F32 score = 0.f;
|
||||
if (data.mActiveTriangles >= 0)
|
||||
{
|
||||
score = 0.0;
|
||||
|
||||
S32 cache_idx = data.mCacheTag;
|
||||
|
||||
S32 cache_idx = data.mCacheTag;
|
||||
|
||||
if (cache_idx < 0)
|
||||
{
|
||||
//not in cache
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cache_idx < 3)
|
||||
{ //vertex was in the last triangle
|
||||
score = FindVertexScore_LastTriScore;
|
||||
if (cache_idx < 0)
|
||||
{
|
||||
//not in cache
|
||||
}
|
||||
else
|
||||
{ //more points for being higher in the cache
|
||||
F32 scaler = 1.f/(MaxSizeVertexCache-3);
|
||||
score = 1.f-((cache_idx-3)*scaler);
|
||||
score = powf(score, FindVertexScore_CacheDecayPower);
|
||||
{
|
||||
if (cache_idx < 3)
|
||||
{ //vertex was in the last triangle
|
||||
score = FindVertexScore_LastTriScore;
|
||||
}
|
||||
else
|
||||
{ //more points for being higher in the cache
|
||||
score = 1.0-((cache_idx-3)*FindVertexScore_Scaler);
|
||||
score = pow(score, FindVertexScore_CacheDecayPower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//bonus points for having low valence
|
||||
F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);
|
||||
score += FindVertexScore_ValenceBoostScale * valence_boost;
|
||||
//bonus points for having low valence
|
||||
F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);
|
||||
score += FindVertexScore_ValenceBoostScale * valence_boost;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
|
@ -5720,7 +5723,7 @@ public:
|
|||
if (mCache[i])
|
||||
{
|
||||
mCache[i]->mScore = find_vertex_score(*(mCache[i]));
|
||||
llassert_always(mCache[i]->mCacheTag == i);
|
||||
llassert(mCache[i]->mCacheTag == i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5728,11 +5731,14 @@ public:
|
|||
//update triangle scores
|
||||
for (U32 i = 0; i < MaxSizeVertexCache+3; ++i)
|
||||
{
|
||||
if (mCache[i])
|
||||
LLVCacheVertexData* data = mCache[i];
|
||||
if (data)
|
||||
{
|
||||
for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j)
|
||||
U32 count = data->mTriangles.size();
|
||||
|
||||
for (U32 j = 0; j < count; ++j)
|
||||
{
|
||||
LLVCacheTriangleData* tri = mCache[i]->mTriangles[j];
|
||||
LLVCacheTriangleData* tri = data->mTriangles[j];
|
||||
if (tri->mActive)
|
||||
{
|
||||
tri->mScore = tri->mVertex[0]->mScore;
|
||||
|
|
@ -5753,7 +5759,7 @@ public:
|
|||
{
|
||||
if (mCache[i])
|
||||
{
|
||||
llassert_always(mCache[i]->mCacheTag == -1);
|
||||
llassert(mCache[i]->mCacheTag == -1);
|
||||
mCache[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -5765,6 +5771,9 @@ void LLVolumeFace::cacheOptimize()
|
|||
{ //optimize for vertex cache according to Forsyth method:
|
||||
// http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
|
||||
|
||||
llassert(!mOptimized);
|
||||
mOptimized = TRUE;
|
||||
|
||||
LLVCacheLRU cache;
|
||||
|
||||
if (mNumVertices < 3)
|
||||
|
|
@ -5810,12 +5819,14 @@ void LLVolumeFace::cacheOptimize()
|
|||
|
||||
for (U32 i = 0; i < mNumVertices; i++)
|
||||
{ //initialize score values (no cache -- might try a fifo cache here)
|
||||
vertex_data[i].mScore = find_vertex_score(vertex_data[i]);
|
||||
vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size();
|
||||
LLVCacheVertexData& data = vertex_data[i];
|
||||
|
||||
for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j)
|
||||
data.mScore = find_vertex_score(data);
|
||||
data.mActiveTriangles = data.mTriangles.size();
|
||||
|
||||
for (U32 j = 0; j < data.mActiveTriangles; ++j)
|
||||
{
|
||||
vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore;
|
||||
data.mTriangles[j]->mScore += data.mScore;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -933,6 +933,9 @@ public:
|
|||
|
||||
LLOctreeNode<LLVolumeTriangle>* mOctree;
|
||||
|
||||
//whether or not face has been cache optimized
|
||||
BOOL mOptimized;
|
||||
|
||||
private:
|
||||
BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
|
||||
BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ BOOL gDebugGL = FALSE;
|
|||
BOOL gClothRipple = FALSE;
|
||||
BOOL gHeadlessClient = FALSE;
|
||||
BOOL gGLActive = FALSE;
|
||||
BOOL gGLDebugLoggingEnabled = TRUE;
|
||||
|
||||
static const std::string HEADLESS_VENDOR_STRING("Linden Lab");
|
||||
static const std::string HEADLESS_RENDERER_STRING("Headless");
|
||||
|
|
@ -72,6 +73,7 @@ std::ofstream gFailLog;
|
|||
#define APIENTRY
|
||||
#endif
|
||||
|
||||
|
||||
void APIENTRY gl_debug_callback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
|
|
@ -80,22 +82,25 @@ void APIENTRY gl_debug_callback(GLenum source,
|
|||
const GLchar* message,
|
||||
GLvoid* userParam)
|
||||
{
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
if (gGLDebugLoggingEnabled)
|
||||
{
|
||||
llwarns << "----- GL ERROR --------" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "----- GL WARNING -------" << llendl;
|
||||
}
|
||||
llwarns << "Type: " << std::hex << type << llendl;
|
||||
llwarns << "ID: " << std::hex << id << llendl;
|
||||
llwarns << "Severity: " << std::hex << severity << llendl;
|
||||
llwarns << "Message: " << message << llendl;
|
||||
llwarns << "-----------------------" << llendl;
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
llerrs << "Halting on GL Error" << llendl;
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
llwarns << "----- GL ERROR --------" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "----- GL WARNING -------" << llendl;
|
||||
}
|
||||
llwarns << "Type: " << std::hex << type << llendl;
|
||||
llwarns << "ID: " << std::hex << id << llendl;
|
||||
llwarns << "Severity: " << std::hex << severity << llendl;
|
||||
llwarns << "Message: " << message << llendl;
|
||||
llwarns << "-----------------------" << llendl;
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
llerrs << "Halting on GL Error" << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -253,6 +258,7 @@ PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;
|
|||
PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
|
||||
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
|
||||
PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
|
||||
PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
|
||||
|
||||
//GL_ARB_debug_output
|
||||
PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
|
||||
|
|
@ -1224,6 +1230,7 @@ void LLGLManager::initExtensions()
|
|||
glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
|
||||
glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
|
||||
glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
|
||||
glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
|
||||
}
|
||||
if (mHasDebugOutput)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -533,6 +533,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
|
|||
extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
|
||||
extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
|
||||
extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
|
||||
extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
|
||||
|
||||
|
||||
#elif LL_WINDOWS
|
||||
|
|
@ -771,6 +772,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
|
|||
extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
|
||||
extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
|
||||
extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
|
||||
extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
|
||||
|
||||
//GL_ARB_debug_output
|
||||
extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
|
||||
|
|
|
|||
|
|
@ -225,26 +225,15 @@ void LLTexUnit::disable(void)
|
|||
bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
|
||||
{
|
||||
stop_glerror();
|
||||
if (mIndex < 0) return false;
|
||||
|
||||
if (mIndex >= 0)
|
||||
{
|
||||
gGL.flush();
|
||||
|
||||
LLImageGL* gl_tex = NULL ;
|
||||
if (texture == NULL || !(gl_tex = texture->getGLTexture()))
|
||||
if (texture != NULL && (gl_tex = texture->getGLTexture()))
|
||||
{
|
||||
llwarns << "NULL LLTexUnit::bind texture" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gl_tex->getTexName()) //if texture does not exist
|
||||
if (gl_tex->getTexName()) //if texture exists
|
||||
{
|
||||
//if deleted, will re-generate it immediately
|
||||
texture->forceImmediateUpdate() ;
|
||||
|
||||
gl_tex->forceUpdateBindStats() ;
|
||||
return texture->bindDefaultImage(mIndex);
|
||||
}
|
||||
|
||||
//in audit, replace the selected texture by the default one.
|
||||
if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
|
||||
{
|
||||
|
|
@ -265,6 +254,27 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
|
|||
setTextureFilteringOption(gl_tex->mFilterOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if deleted, will re-generate it immediately
|
||||
texture->forceImmediateUpdate() ;
|
||||
|
||||
gl_tex->forceUpdateBindStats() ;
|
||||
return texture->bindDefaultImage(mIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "NULL LLTexUnit::bind texture" << llendl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // mIndex < 0
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
|
|||
//static
|
||||
LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
|
||||
LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
|
||||
LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_ARB, GL_ARRAY_BUFFER_ARB);
|
||||
LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||
|
||||
|
|
@ -199,7 +200,10 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
|
|||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
glBufferDataARB(mType, size, 0, mUsage);
|
||||
ret = (U8*) ll_aligned_malloc_16(size);
|
||||
if (mUsage != GL_DYNAMIC_COPY_ARB)
|
||||
{ //data will be provided by application
|
||||
ret = (U8*) ll_aligned_malloc_16(size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
||||
|
|
@ -393,6 +397,7 @@ void LLVertexBuffer::seedPools()
|
|||
{
|
||||
sStreamVBOPool.seedPool();
|
||||
sDynamicVBOPool.seedPool();
|
||||
sDynamicCopyVBOPool.seedPool();
|
||||
sStreamIBOPool.seedPool();
|
||||
sDynamicIBOPool.seedPool();
|
||||
}
|
||||
|
|
@ -875,6 +880,7 @@ void LLVertexBuffer::cleanupClass()
|
|||
sDynamicIBOPool.cleanup();
|
||||
sStreamVBOPool.cleanup();
|
||||
sDynamicVBOPool.cleanup();
|
||||
sDynamicCopyVBOPool.cleanup();
|
||||
|
||||
if(sPrivatePoolp)
|
||||
{
|
||||
|
|
@ -911,13 +917,16 @@ S32 LLVertexBuffer::determineUsage(S32 usage)
|
|||
|
||||
if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
|
||||
{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
|
||||
if (sDisableVBOMapping)
|
||||
{ //always use stream draw if VBO mapping is disabled
|
||||
ret_usage = GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
else
|
||||
if (ret_usage != GL_DYNAMIC_COPY_ARB)
|
||||
{
|
||||
ret_usage = GL_DYNAMIC_DRAW_ARB;
|
||||
if (sDisableVBOMapping)
|
||||
{ //always use stream draw if VBO mapping is disabled
|
||||
ret_usage = GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_usage = GL_DYNAMIC_DRAW_ARB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1067,10 +1076,15 @@ void LLVertexBuffer::genBuffer(U32 size)
|
|||
{
|
||||
mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
|
||||
}
|
||||
else
|
||||
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize);
|
||||
}
|
||||
|
||||
|
||||
sGLCount++;
|
||||
}
|
||||
|
|
@ -1820,6 +1834,8 @@ void LLVertexBuffer::unmapBuffer()
|
|||
|
||||
if (mMappedData && mVertexLocked)
|
||||
{
|
||||
llassert(mUsage != GL_DYNAMIC_COPY_ARB);
|
||||
|
||||
LLFastTimer t(FTM_VBO_UNMAP);
|
||||
bindGLBuffer(true);
|
||||
updated_all = mIndexLocked; //both vertex and index buffers done updating
|
||||
|
|
@ -2094,22 +2110,15 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)
|
|||
|
||||
if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
|
||||
{
|
||||
LLFastTimer t(FTM_BIND_GL_BUFFER);
|
||||
/*if (sMapped)
|
||||
{
|
||||
llerrs << "VBO bound while another VBO mapped!" << llendl;
|
||||
}*/
|
||||
//LLFastTimer t(FTM_BIND_GL_BUFFER); <-- this timer is showing up as a hotspot (irony)
|
||||
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
sBindCount++;
|
||||
sVBOActive = true;
|
||||
|
||||
if (mGLArray)
|
||||
{
|
||||
llassert(sGLRenderArray == mGLArray);
|
||||
//mCachedRenderBuffer = mGLBuffer;
|
||||
}
|
||||
|
||||
llassert(!mGLArray || sGLRenderArray == mGLArray);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,9 +125,10 @@ public:
|
|||
|
||||
static LLVBOPool sStreamVBOPool;
|
||||
static LLVBOPool sDynamicVBOPool;
|
||||
static LLVBOPool sDynamicCopyVBOPool;
|
||||
static LLVBOPool sStreamIBOPool;
|
||||
static LLVBOPool sDynamicIBOPool;
|
||||
|
||||
|
||||
static std::list<U32> sAvailableVAOName;
|
||||
static U32 sCurVAOName;
|
||||
|
||||
|
|
|
|||
|
|
@ -3062,6 +3062,30 @@ void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request)
|
|||
sendReliableMessage();
|
||||
}
|
||||
|
||||
// Send a message to the region to stop the NULL animation state
|
||||
// This will reset animation state overrides for the agent.
|
||||
void LLAgent::sendAnimationStateReset()
|
||||
{
|
||||
if (gAgentID.isNull() || !mRegionp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
msg->newMessageFast(_PREHASH_AgentAnimation);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast(_PREHASH_AgentID, getID());
|
||||
msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
|
||||
|
||||
msg->nextBlockFast(_PREHASH_AnimationList);
|
||||
msg->addUUIDFast(_PREHASH_AnimID, LLUUID::null );
|
||||
msg->addBOOLFast(_PREHASH_StartAnim, FALSE);
|
||||
|
||||
msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList);
|
||||
msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0);
|
||||
sendReliableMessage();
|
||||
}
|
||||
|
||||
void LLAgent::sendWalkRun(bool running)
|
||||
{
|
||||
LLMessageSystem* msgsys = gMessageSystem;
|
||||
|
|
@ -4140,6 +4164,8 @@ void LLAgent::stopCurrentAnimations()
|
|||
// avatar, propagating this change back to the server.
|
||||
if (isAgentAvatarValid())
|
||||
{
|
||||
LLDynamicArray<LLUUID> anim_ids;
|
||||
|
||||
for ( LLVOAvatar::AnimIterator anim_it =
|
||||
gAgentAvatarp->mPlayingAnimations.begin();
|
||||
anim_it != gAgentAvatarp->mPlayingAnimations.end();
|
||||
|
|
@ -4157,10 +4183,15 @@ void LLAgent::stopCurrentAnimations()
|
|||
// stop this animation locally
|
||||
gAgentAvatarp->stopMotion(anim_it->first, TRUE);
|
||||
// ...and tell the server to tell everyone.
|
||||
sendAnimationRequest(anim_it->first, ANIM_REQUEST_STOP);
|
||||
anim_ids.push_back(anim_it->first);
|
||||
}
|
||||
}
|
||||
|
||||
sendAnimationRequests(anim_ids, ANIM_REQUEST_STOP);
|
||||
|
||||
// Tell the region to clear any animation state overrides.
|
||||
sendAnimationStateReset();
|
||||
|
||||
// re-assert at least the default standing animation, because
|
||||
// viewers get confused by avs with no associated anims.
|
||||
sendAnimationRequest(ANIM_AGENT_STAND,
|
||||
|
|
|
|||
|
|
@ -431,6 +431,8 @@ public:
|
|||
void onAnimStop(const LLUUID& id);
|
||||
void sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request);
|
||||
void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request);
|
||||
void sendAnimationStateReset();
|
||||
|
||||
void endAnimationUpdateUI();
|
||||
void unpauseAnimation() { mPauseRequest = NULL; }
|
||||
BOOL getCustomAnim() const { return mCustomAnim; }
|
||||
|
|
|
|||
|
|
@ -461,6 +461,8 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&
|
|||
}
|
||||
}
|
||||
}
|
||||
// Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0
|
||||
// MAINT-755
|
||||
cube_map->disable();
|
||||
cube_map->restoreMatrix();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@
|
|||
#include "llviewerregion.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "llvoavatar.h"
|
||||
|
||||
extern BOOL gGLDebugLoggingEnabled;
|
||||
|
||||
#define LL_MAX_INDICES_COUNT 1000000
|
||||
|
||||
|
|
@ -328,6 +330,12 @@ void LLFace::dirtyTexture()
|
|||
if (vobj)
|
||||
{
|
||||
vobj->mLODChanged = TRUE;
|
||||
|
||||
LLVOAvatar* avatar = vobj->getAvatar();
|
||||
if (avatar)
|
||||
{ //avatar render cost may have changed
|
||||
avatar->updateVisualComplexity();
|
||||
}
|
||||
}
|
||||
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);
|
||||
}
|
||||
|
|
@ -1162,6 +1170,15 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color");
|
|||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal");
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK("Face Feedback");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_POSITION("Feedback Position");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_NORMAL("Feedback Normal");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_TEXTURE("Feedback Texture");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_COLOR("Feedback Color");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_EMISSIVE("Feedback Emissive");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_BINORMAL("Feedback Binormal");
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos");
|
||||
|
|
@ -1385,12 +1402,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
|
||||
if (use_transform_feedback &&
|
||||
mVertexBuffer->getUsage() == GL_DYNAMIC_COPY_ARB &&
|
||||
gTransformPositionProgram.mProgramObject && //transform shaders are loaded
|
||||
mVertexBuffer->useVBOs() && //target buffer is in VRAM
|
||||
!rebuild_weights && //TODO: add support for weights
|
||||
!volume.isUnique()) //source volume is NOT flexi
|
||||
{ //use transform feedback to pack vertex buffer
|
||||
|
||||
//gGLDebugLoggingEnabled = TRUE;
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK);
|
||||
LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get();
|
||||
|
||||
if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices)
|
||||
|
|
@ -1407,7 +1426,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
if (rebuild_pos)
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_GEOM_POSITION);
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_POSITION);
|
||||
gTransformPositionProgram.bind();
|
||||
|
||||
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount);
|
||||
|
|
@ -1420,7 +1439,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
vp[1] = 0;
|
||||
vp[2] = 0;
|
||||
vp[3] = 0;
|
||||
|
||||
|
||||
gTransformPositionProgram.uniform1i(sTextureIndexIn, val);
|
||||
glBeginTransformFeedback(GL_POINTS);
|
||||
buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||
|
|
@ -1432,7 +1451,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
if (rebuild_color)
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_GEOM_COLOR);
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_COLOR);
|
||||
gTransformColorProgram.bind();
|
||||
|
||||
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount);
|
||||
|
|
@ -1448,7 +1467,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
if (rebuild_emissive)
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_GEOM_EMISSIVE);
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_EMISSIVE);
|
||||
gTransformColorProgram.bind();
|
||||
|
||||
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount);
|
||||
|
|
@ -1469,7 +1488,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
if (rebuild_normal)
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_GEOM_NORMAL);
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_NORMAL);
|
||||
gTransformNormalProgram.bind();
|
||||
|
||||
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount);
|
||||
|
|
@ -1482,7 +1501,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
if (rebuild_binormal)
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_GEOM_BINORMAL);
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_BINORMAL);
|
||||
gTransformBinormalProgram.bind();
|
||||
|
||||
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount);
|
||||
|
|
@ -1495,7 +1514,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
|
||||
if (rebuild_tcoord)
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_GEOM_TEXTURE);
|
||||
LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_TEXTURE);
|
||||
gTransformTexCoordProgram.bind();
|
||||
|
||||
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount);
|
||||
|
|
@ -1518,13 +1537,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
}
|
||||
|
||||
glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
|
||||
|
||||
gGL.popMatrix();
|
||||
|
||||
if (cur_shader)
|
||||
{
|
||||
cur_shader->bind();
|
||||
}
|
||||
//gGLDebugLoggingEnabled = FALSE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -588,7 +588,7 @@ void LLMeshRepoThread::run()
|
|||
if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit
|
||||
{
|
||||
mMutex->lock();
|
||||
mLODReqQ.push(req) ;
|
||||
mLODReqQ.push(req);
|
||||
mMutex->unlock();
|
||||
}
|
||||
}
|
||||
|
|
@ -1200,8 +1200,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
|
|||
LLMutexLock lock(mHeaderMutex);
|
||||
mMeshHeaderSize[mesh_id] = header_size;
|
||||
mMeshHeader[mesh_id] = header;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.
|
||||
|
||||
|
|
|
|||
|
|
@ -688,6 +688,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
mFullyLoaded(FALSE),
|
||||
mPreviousFullyLoaded(FALSE),
|
||||
mFullyLoadedInitialized(FALSE),
|
||||
mVisualComplexity(0),
|
||||
mVisualComplexityStale(TRUE),
|
||||
mSupportsAlphaLayers(FALSE),
|
||||
mLoadedCallbacksPaused(FALSE),
|
||||
mHasPelvisOffset( FALSE ),
|
||||
|
|
@ -3434,12 +3436,23 @@ void LLVOAvatar::slamPosition()
|
|||
|
||||
bool LLVOAvatar::isVisuallyMuted() const
|
||||
{
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
bool ret = false;
|
||||
|
||||
if (!isSelf())
|
||||
{
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
|
||||
|
||||
return LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5));
|
||||
|
||||
ret = LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
|
||||
(mVisualComplexity > max_cost && max_render_cost > 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -4139,46 +4152,6 @@ bool LLVOAvatar::shouldAlphaMask()
|
|||
|
||||
}
|
||||
|
||||
U32 LLVOAvatar::renderSkinnedAttachments()
|
||||
{
|
||||
/*U32 num_indices = 0;
|
||||
|
||||
const U32 data_mask = LLVertexBuffer::MAP_VERTEX |
|
||||
LLVertexBuffer::MAP_NORMAL |
|
||||
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||
LLVertexBuffer::MAP_COLOR |
|
||||
LLVertexBuffer::MAP_WEIGHT4;
|
||||
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
for (S32 i = 0; i < drawable->getNumFaces(); ++i)
|
||||
{
|
||||
LLFace* face = drawable->getFace(i);
|
||||
if (face->isState(LLFace::RIGGED))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num_indices;*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// renderSkinned()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -4336,21 +4309,23 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
|
|||
BOOL first_pass = TRUE;
|
||||
if (!LLDrawPoolAvatar::sSkipOpaque)
|
||||
{
|
||||
bool muted = isVisuallyMuted();
|
||||
|
||||
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
|
||||
{
|
||||
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy)
|
||||
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
}
|
||||
}
|
||||
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy)
|
||||
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
}
|
||||
|
||||
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy)
|
||||
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || muted)
|
||||
{
|
||||
num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
|
||||
first_pass = FALSE;
|
||||
|
|
@ -6090,6 +6065,8 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o
|
|||
return 0;
|
||||
}
|
||||
|
||||
mVisualComplexityStale = TRUE;
|
||||
|
||||
if (viewer_object->isSelected())
|
||||
{
|
||||
LLSelectMgr::getInstance()->updateSelectionCenter();
|
||||
|
|
@ -6244,6 +6221,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
|
|||
|
||||
if (attachment->isObjectAttached(viewer_object))
|
||||
{
|
||||
mVisualComplexityStale = TRUE;
|
||||
cleanupAttachedMesh( viewer_object );
|
||||
attachment->removeObject(viewer_object);
|
||||
lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
|
||||
|
|
@ -8456,7 +8434,7 @@ void LLVOAvatar::updateImpostors()
|
|||
|
||||
BOOL LLVOAvatar::isImpostor() const
|
||||
{
|
||||
return (isVisuallyMuted() || (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
|
||||
return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -8501,6 +8479,8 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
|
|||
|
||||
void LLVOAvatar::idleUpdateRenderCost()
|
||||
{
|
||||
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
|
||||
|
||||
static const U32 ARC_BODY_PART_COST = 200;
|
||||
static const U32 ARC_LIMIT = 20000;
|
||||
|
||||
|
|
@ -8511,123 +8491,147 @@ void LLVOAvatar::idleUpdateRenderCost()
|
|||
setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
|
||||
}
|
||||
|
||||
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME) && max_render_cost == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
U32 cost = 0;
|
||||
LLVOVolume::texture_cost_t textures;
|
||||
|
||||
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
|
||||
if (mVisualComplexityStale)
|
||||
{
|
||||
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
|
||||
ETextureIndex tex_index = baked_dict->mTextureIndex;
|
||||
if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
|
||||
{
|
||||
if (isTextureVisible(tex_index))
|
||||
{
|
||||
cost +=ARC_BODY_PART_COST;
|
||||
}
|
||||
}
|
||||
}
|
||||
mVisualComplexityStale = FALSE;
|
||||
U32 cost = 0;
|
||||
LLVOVolume::texture_cost_t textures;
|
||||
|
||||
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
|
||||
{
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
|
||||
ETextureIndex tex_index = baked_dict->mTextureIndex;
|
||||
if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
|
||||
{
|
||||
textures.clear();
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
if (isTextureVisible(tex_index))
|
||||
{
|
||||
const LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
{
|
||||
cost += volume->getRenderCost(textures);
|
||||
|
||||
const_child_list_t children = volume->getChildren();
|
||||
for (const_child_list_t::const_iterator child_iter = children.begin();
|
||||
child_iter != children.end();
|
||||
++child_iter)
|
||||
{
|
||||
LLViewerObject* child_obj = *child_iter;
|
||||
LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
|
||||
if (child)
|
||||
{
|
||||
cost += child->getRenderCost(textures);
|
||||
}
|
||||
}
|
||||
|
||||
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
|
||||
{
|
||||
// add the cost of each individual texture in the linkset
|
||||
cost += iter->second;
|
||||
}
|
||||
}
|
||||
cost +=ARC_BODY_PART_COST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Diagnostic output to identify all avatar-related textures.
|
||||
// Does not affect rendering cost calculation.
|
||||
// Could be wrapped in a debug option if output becomes problematic.
|
||||
if (isSelf())
|
||||
{
|
||||
// print any attachment textures we didn't already know about.
|
||||
for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
|
||||
{
|
||||
LLUUID image_id = it->first;
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
// attachment texture not previously seen.
|
||||
llinfos << "attachment_texture: " << image_id.asString() << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
|
||||
// print any avatar textures we didn't already know about
|
||||
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
|
||||
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
|
||||
// TODO: MULTI-WEARABLE: handle multiple textures for self
|
||||
const LLViewerTexture* te_image = getImage(iter->first,0);
|
||||
if (!te_image)
|
||||
continue;
|
||||
LLUUID image_id = te_image->getID();
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
attachment_iter != attachment->mAttachedObjects.end();
|
||||
++attachment_iter)
|
||||
{
|
||||
llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl;
|
||||
all_textures.insert(image_id);
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
textures.clear();
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
const LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
{
|
||||
cost += volume->getRenderCost(textures);
|
||||
|
||||
const_child_list_t children = volume->getChildren();
|
||||
for (const_child_list_t::const_iterator child_iter = children.begin();
|
||||
child_iter != children.end();
|
||||
++child_iter)
|
||||
{
|
||||
LLViewerObject* child_obj = *child_iter;
|
||||
LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
|
||||
if (child)
|
||||
{
|
||||
cost += child->getRenderCost(textures);
|
||||
}
|
||||
}
|
||||
|
||||
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
|
||||
{
|
||||
// add the cost of each individual texture in the linkset
|
||||
cost += iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Diagnostic output to identify all avatar-related textures.
|
||||
// Does not affect rendering cost calculation.
|
||||
// Could be wrapped in a debug option if output becomes problematic.
|
||||
if (isSelf())
|
||||
{
|
||||
// print any attachment textures we didn't already know about.
|
||||
for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
|
||||
{
|
||||
LLUUID image_id = it->first;
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
// attachment texture not previously seen.
|
||||
llinfos << "attachment_texture: " << image_id.asString() << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
|
||||
// print any avatar textures we didn't already know about
|
||||
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
|
||||
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
|
||||
++iter)
|
||||
{
|
||||
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
|
||||
// TODO: MULTI-WEARABLE: handle multiple textures for self
|
||||
const LLViewerTexture* te_image = getImage(iter->first,0);
|
||||
if (!te_image)
|
||||
continue;
|
||||
LLUUID image_id = te_image->getID();
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSelf() && max_render_cost > 0 && mVisualComplexity != cost)
|
||||
{ //pop up notification that you have exceeded a render cost limit
|
||||
if (cost > max_render_cost+max_render_cost/2)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededHighDetailRenderCost");
|
||||
}
|
||||
else if (cost > max_render_cost)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededMidDetailRenderCost");
|
||||
}
|
||||
else if (cost > max_render_cost/2)
|
||||
{
|
||||
LLNotificationsUtil::add("ExceededLowDetailRenderCost");
|
||||
}
|
||||
}
|
||||
|
||||
mVisualComplexity = cost;
|
||||
}
|
||||
|
||||
|
||||
std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
|
||||
setDebugText(llformat("%s %d", viz_string.c_str(), cost));
|
||||
mVisualComplexity = cost;
|
||||
F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
|
||||
F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
|
||||
mText->setColor(LLColor4(red,green,0,1));
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
{
|
||||
std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
|
||||
setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity));
|
||||
F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
|
||||
F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f);
|
||||
mText->setColor(LLColor4(red,green,0,1));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ public:
|
|||
static void invalidateNameTags();
|
||||
void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
|
||||
void idleUpdateRenderCost();
|
||||
void updateVisualComplexity() { mVisualComplexityStale = TRUE; }
|
||||
void idleUpdateBelowWater();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -314,6 +315,7 @@ private:
|
|||
BOOL mFullyLoadedInitialized;
|
||||
S32 mFullyLoadedFrameCounter;
|
||||
S32 mVisualComplexity;
|
||||
BOOL mVisualComplexityStale;
|
||||
LLFrameTimer mFullyLoadedTimer;
|
||||
LLFrameTimer mRuthTimer;
|
||||
|
||||
|
|
@ -437,7 +439,6 @@ public:
|
|||
U32 renderRigid();
|
||||
U32 renderSkinned(EAvatarRenderPass pass);
|
||||
F32 getLastSkinTime() { return mLastSkinTime; }
|
||||
U32 renderSkinnedAttachments();
|
||||
U32 renderTransparent(BOOL first_pass);
|
||||
void renderCollisionVolumes();
|
||||
static void deleteCachedImages(bool clearAll=true);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");
|
|||
static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
|
||||
static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures");
|
||||
|
||||
extern BOOL gGLDebugLoggingEnabled;
|
||||
|
||||
// Implementation class of LLMediaDataClientObject. See llmediadataclient.h
|
||||
class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
|
||||
{
|
||||
|
|
@ -1067,7 +1069,9 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo
|
|||
break;
|
||||
}
|
||||
volume->genBinormals(i);
|
||||
//gGLDebugLoggingEnabled = TRUE;
|
||||
LLFace::cacheFaceInVRAM(face);
|
||||
//gGLDebugLoggingEnabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1116,6 +1120,12 @@ void LLVOVolume::notifyMeshLoaded()
|
|||
{
|
||||
mSculptChanged = TRUE;
|
||||
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
|
||||
|
||||
LLVOAvatar* avatar = getAvatar();
|
||||
if (avatar)
|
||||
{
|
||||
avatar->updateVisualComplexity();
|
||||
}
|
||||
}
|
||||
|
||||
// sculpt replaces generate() for sculpted surfaces
|
||||
|
|
@ -4830,6 +4840,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
|
||||
U32 buffer_usage = group->mBufferUsage;
|
||||
|
||||
static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback");
|
||||
|
||||
if (use_transform_feedback &&
|
||||
gTransformPositionProgram.mProgramObject && //transform shaders are loaded
|
||||
buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM
|
||||
!(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights
|
||||
{
|
||||
buffer_usage = GL_DYNAMIC_COPY_ARB;
|
||||
}
|
||||
|
||||
#if LL_DARWIN
|
||||
// HACK from Leslie:
|
||||
// Disable VBO usage for alpha on Mac OS X because it kills the framerate
|
||||
|
|
@ -4889,6 +4909,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
//NEVER use more than 16 texture index channels (workaround for prevalent driver bug)
|
||||
texture_index_channels = llmin(texture_index_channels, 16);
|
||||
|
||||
bool flexi = false;
|
||||
|
||||
while (face_iter != faces.end())
|
||||
{
|
||||
//pull off next face
|
||||
|
|
@ -4915,6 +4937,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
U32 index_count = facep->getIndicesCount();
|
||||
U32 geom_count = facep->getGeomCount();
|
||||
|
||||
flexi = flexi || facep->getViewerObject()->getVolume()->isUnique();
|
||||
|
||||
//sum up vertices needed for this render batch
|
||||
std::vector<LLFace*>::iterator i = face_iter;
|
||||
++i;
|
||||
|
|
@ -4983,6 +5007,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
}
|
||||
|
||||
++i;
|
||||
|
||||
flexi = flexi || facep->getViewerObject()->getVolume()->isUnique();
|
||||
|
||||
index_count += facep->getIndicesCount();
|
||||
geom_count += facep->getGeomCount();
|
||||
|
||||
|
|
@ -5012,10 +5039,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
++i;
|
||||
index_count += facep->getIndicesCount();
|
||||
geom_count += facep->getGeomCount();
|
||||
|
||||
flexi = flexi || facep->getViewerObject()->getVolume()->isUnique();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB)
|
||||
{
|
||||
buffer_usage = GL_STREAM_DRAW_ARB;
|
||||
}
|
||||
|
||||
//create vertex buffer
|
||||
LLVertexBuffer* buffer = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -253,15 +253,15 @@ LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
|
|||
static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
|
||||
static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
|
||||
|
||||
static LLStaticHashedString sTint("tint");
|
||||
static LLStaticHashedString sAmbiance("ambiance");
|
||||
static LLStaticHashedString sAlphaScale("alpha_scale");
|
||||
static LLStaticHashedString sNormMat("norm_mat");
|
||||
static LLStaticHashedString sOffset("offset");
|
||||
static LLStaticHashedString sScreenRes("screenRes");
|
||||
static LLStaticHashedString sDelta("delta");
|
||||
static LLStaticHashedString sDistFactor("dist_factor");
|
||||
static LLStaticHashedString sKern("kern");
|
||||
static LLStaticHashedString sTint("tint");
|
||||
static LLStaticHashedString sAmbiance("ambiance");
|
||||
static LLStaticHashedString sAlphaScale("alpha_scale");
|
||||
static LLStaticHashedString sNormMat("norm_mat");
|
||||
static LLStaticHashedString sOffset("offset");
|
||||
static LLStaticHashedString sScreenRes("screenRes");
|
||||
static LLStaticHashedString sDelta("delta");
|
||||
static LLStaticHashedString sDistFactor("dist_factor");
|
||||
static LLStaticHashedString sKern("kern");
|
||||
static LLStaticHashedString sKernScale("kern_scale");
|
||||
|
||||
//----------------------------------------
|
||||
|
|
@ -10258,6 +10258,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
avatar->mImpostor.bindTarget();
|
||||
}
|
||||
|
||||
F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
|
||||
|
||||
if (muted)
|
||||
{ //disable alpha masking for muted avatars (get whole skin silhouette)
|
||||
LLDrawPoolAvatar::sMinimumAlpha = 0.f;
|
||||
}
|
||||
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
avatar->mImpostor.clear();
|
||||
|
|
@ -10272,6 +10279,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
renderGeom(camera);
|
||||
}
|
||||
|
||||
LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
|
||||
|
||||
{ //create alpha mask based on depth buffer (grey out if muted)
|
||||
LLFastTimer t(FTM_IMPOSTOR_BACKGROUND);
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
|
|
@ -10285,6 +10294,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
if (muted)
|
||||
{
|
||||
gGL.setColorMask(true, true);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -10303,14 +10313,24 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
gGL.pushMatrix();
|
||||
gGL.loadIdentity();
|
||||
|
||||
static const F32 clip_plane = 0.99999f;
|
||||
static const F32 clip_plane = 0.999f;
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gUIProgram.bind();
|
||||
gDebugProgram.bind();
|
||||
}
|
||||
|
||||
gGL.color4ub(64,64,64,255);
|
||||
|
||||
if (LLMuteList::getInstance()->isMuted(avatar->getID()))
|
||||
{ //grey muted avatar
|
||||
gGL.diffuseColor4ub(64,64,64,255);
|
||||
}
|
||||
else
|
||||
{ //blue visually muted avatar
|
||||
gGL.diffuseColor4ub(72,61,139,255);
|
||||
}
|
||||
|
||||
{
|
||||
gGL.begin(LLRender::QUADS);
|
||||
gGL.vertex3f(-1, -1, clip_plane);
|
||||
gGL.vertex3f(1, -1, clip_plane);
|
||||
|
|
@ -10318,10 +10338,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
gGL.vertex3f(-1, 1, clip_plane);
|
||||
gGL.end();
|
||||
gGL.flush();
|
||||
}
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gUIProgram.unbind();
|
||||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
|
|
|
|||
|
|
@ -202,6 +202,45 @@ Message Template [PATH] not found.
|
|||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="ExceededHighDetailRenderCost"
|
||||
persist="false"
|
||||
type="alertmodal">
|
||||
Your avatar has become too complex to be rendered by even high performance computers. Almost all Residents will see a low detail stand in instead of your actual avatar.
|
||||
<unique/>
|
||||
<usetemplate
|
||||
ignoretext="Avatar exceeded high detail complexity."
|
||||
name="okignore"
|
||||
yestext="Close"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="ExceededMidDetailRenderCost"
|
||||
persist="false"
|
||||
type="alertmodal">
|
||||
Your avatar has become too complex to be rendered by most computers. Many Residents will see a low detail stand in instead of your actual avatar.
|
||||
<unique/>
|
||||
<usetemplate
|
||||
ignoretext="Avatar exceeded mid detail complexity."
|
||||
name="okignore"
|
||||
yestext="Close"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="ExceededLowDetailRenderCost"
|
||||
persist="false"
|
||||
type="alertmodal">
|
||||
Your avatar has become too complex to be rendered by some computers. Some Residents will see a low detail stand in instead of your actual avatar.
|
||||
<unique/>
|
||||
<usetemplate
|
||||
ignoretext="Avatar exceeded low detail complexity."
|
||||
name="okignore"
|
||||
yestext="Close"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="WearableSave"
|
||||
|
|
@ -9935,5 +9974,5 @@ An internal error prevented us from properly updating your viewer. The L$ balan
|
|||
<tag>fail</tag>
|
||||
Cannot create large prims that intersect other players. Please re-try when other players have moved.
|
||||
</notification>
|
||||
|
||||
|
||||
</notifications>
|
||||
|
|
|
|||
Loading…
Reference in New Issue