SL-16166 Apply optimizations from pushBatch to other render call sites. Optimize out a map lookup in rigged face rendering.

master
Runitai Linden 2021-10-14 13:02:40 -05:00
parent aa2169aa37
commit e7227afe02
11 changed files with 151 additions and 307 deletions

View File

@ -1017,7 +1017,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
if (uniform > -1)
{
gGL.getTexUnit(uniform)->bind(texture, mode);
gGL.getTexUnit(uniform)->bindFast(texture);
gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
}
@ -1048,7 +1048,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
if (uniform > -1)
{
gGL.getTexUnit(uniform)->unbind(mode);
gGL.getTexUnit(uniform)->unbindFast(mode);
}
return uniform;

View File

@ -169,7 +169,6 @@ void LLTexUnit::refreshState(void)
void LLTexUnit::activate(void)
{
LL_PROFILE_ZONE_SCOPED;
if (mIndex < 0) return;
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
@ -1956,9 +1955,9 @@ void LLRender::end()
}
void LLRender::flush()
{
LL_PROFILE_ZONE_SCOPED;
if (mCount > 0)
{
LL_PROFILE_ZONE_SCOPED;
if (!mUIOffset.empty())
{
sUICalls++;

View File

@ -234,8 +234,6 @@ void LLDrawable::markDead()
LLVOVolume* LLDrawable::getVOVolume() const
{
LL_PROFILE_ZONE_SCOPED
LLViewerObject* objectp = mVObjp;
if ( !isDead() && objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{

View File

@ -55,19 +55,7 @@ static BOOL deferred_render = FALSE;
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETUP("Alpha Setup");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED("Alpha Deferred");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETBUFFER("Alpha SetBuffer");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DRAW("Alpha Draw");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_TEX_BINDS("Alpha Tex Binds");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MATS("Alpha Mat Tex Binds");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GLOW("Alpha Glow Binds");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SHADER_BINDS("Alpha Shader Binds");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS("Alpha Def Binds");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS("Alpha Def Tex Binds");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MESH_REBUILD("Alpha Mesh Rebuild");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_EMISSIVE("Alpha Emissive");
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_LIGHT_SETUP("Alpha Light Setup");
LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
LLRenderPass(type), current_shader(NULL), target_shader(NULL),
@ -86,6 +74,10 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
void LLDrawPoolAlpha::prerender()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
// TODO: is this even necessay? These are probably set to never discard
LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f);
LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f);
}
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
@ -309,7 +301,7 @@ void LLDrawPoolAlpha::render(S32 pass)
gGL.diffuseColor4f(1,0,0,1);
LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ;
gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep);
renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD0);
@ -358,9 +350,8 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
{
params.mGroup->rebuildMesh();
}
params.mVertexBuffer->setBuffer(mask);
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
params.mVertexBuffer->setBufferFast(mask);
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
}
}
}
@ -383,27 +374,23 @@ inline bool IsEmissive(LLDrawInfo& params)
inline void Draw(LLDrawInfo* draw, U32 mask)
{
draw->mVertexBuffer->setBuffer(mask);
draw->mVertexBuffer->setBufferFast(mask);
LLRenderPass::applyModelMatrix(*draw);
draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode);
draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
}
bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader)
bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS);
bool tex_setup = false;
if (deferred_render && use_material && current_shader)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS);
if (draw->mNormalMap)
{
{
draw->mNormalMap->addTextureStats(draw->mVSize);
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
}
if (draw->mSpecularMap)
{
draw->mSpecularMap->addTextureStats(draw->mVSize);
@ -412,18 +399,16 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate
}
else if (current_shader == simple_shader)
{
LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(draw->mVSize);
LLViewerFetchedTexture::sWhiteImagep->addTextureStats(draw->mVSize);
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
}
if (use_shaders && draw->mTextureList.size() > 1)
if (draw->mTextureList.size() > 1)
{
for (U32 i = 0; i < draw->mTextureList.size(); ++i)
{
if (draw->mTextureList[i].notNull())
{
gGL.getTexUnit(i)->bind(draw->mTextureList[i], TRUE);
gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]);
}
}
}
@ -431,16 +416,15 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate
{ //not batching textures or batch has only 1 texture -- might need a texture matrix
if (draw->mTexture.notNull())
{
draw->mTexture->addTextureStats(draw->mVSize);
if (use_shaders && use_material)
if (use_material)
{
current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture);
}
else
{
gGL.getTexUnit(0)->bind(draw->mTexture, TRUE) ;
gGL.getTexUnit(0)->bindFast(draw->mTexture);
}
if (draw->mTextureMatrix)
{
tex_setup = true;
@ -452,7 +436,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate
}
else
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE);
}
}
@ -470,37 +454,15 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup)
}
}
void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples)
{
gPipeline.enableLightsDynamic();
simple_shader->bind();
simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
simple_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
simple_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f);
simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f);
bool use_shaders = gPipeline.canUseVertexShaders();
for (LLDrawInfo* draw : simples)
{
bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader);
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
Draw(draw, mask);
RestoreTexSetup(tex_setup);
}
simple_shader->unbind();
}
void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights)
{
gPipeline.enableLightsFullbright();
fullbright_shader->bind();
fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f);
bool use_shaders = gPipeline.canUseVertexShaders();
for (LLDrawInfo* draw : fullbrights)
{
bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader);
bool tex_setup = TexSetup(draw, false, fullbright_shader);
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
@ -511,65 +473,10 @@ void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& full
fullbright_shader->unbind();
}
void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials)
{
LLGLSLShader::bindNoShader();
current_shader = NULL;
gPipeline.enableLightsDynamic();
bool use_shaders = gPipeline.canUseVertexShaders();
for (LLDrawInfo* draw : materials)
{
U32 mask = draw->mShaderMask;
llassert(mask < LLMaterial::SHADER_COUNT);
target_shader = (LLPipeline::sUnderWaterRender) ? &(gDeferredMaterialWaterProgram[mask]) : &(gDeferredMaterialProgram[mask]);
if (current_shader != target_shader)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS);
if (current_shader)
{
gPipeline.unbindDeferredShader(*current_shader);
}
gPipeline.bindDeferredShader(*target_shader);
current_shader = target_shader;
}
bool tex_setup = TexSetup(draw, use_shaders, true, current_shader);
current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, draw->mSpecColor.mV[0], draw->mSpecColor.mV[1], draw->mSpecColor.mV[2], draw->mSpecColor.mV[3]);
current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, draw->mEnvIntensity);
current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, draw->mFullbright ? 1.f : 0.f);
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS);
if (draw->mNormalMap)
{
draw->mNormalMap->addTextureStats(draw->mVSize);
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
}
if (draw->mSpecularMap)
{
draw->mSpecularMap->addTextureStats(draw->mVSize);
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
}
}
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
Draw(draw, mask);
RestoreTexSetup(tex_setup);
}
}
void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
{
draw->mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode);
draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
}
void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw)
@ -599,10 +506,10 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
// install glow-accumulating blend mode
// don't touch color, add to alpha (glow)
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
bool use_shaders = gPipeline.canUseVertexShaders();
for (LLDrawInfo* draw : emissives)
{
bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader);
bool tex_setup = TexSetup(draw, false, emissive_shader);
drawEmissive(mask, draw);
RestoreTexSetup(tex_setup);
}
@ -620,8 +527,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
BOOL initialized_lighting = FALSE;
BOOL light_enabled = TRUE;
BOOL use_shaders = gPipeline.canUseVertexShaders();
for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
{
LLSpatialGroup* group = *i;
@ -631,8 +536,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
if (group->getSpatialPartition()->mRenderByGroup &&
!group->isDead())
{
std::vector<LLDrawInfo*> emissives;
std::vector<LLDrawInfo*> fullbrights;
static std::vector<LLDrawInfo*> emissives;
static std::vector<LLDrawInfo*> fullbrights;
emissives.resize(0);
fullbrights.resize(0);
bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE
|| group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE;
@ -649,6 +556,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LL_PROFILE_ZONE_NAMED("ra - push batch")
LLDrawInfo& params = **k;
U32 have_mask = params.mVertexBuffer->getTypeMask() & mask;
if (have_mask != mask)
@ -696,34 +604,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
// Turn off lighting if it hasn't already been so.
if (light_enabled || !initialized_lighting)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP);
initialized_lighting = TRUE;
if (use_shaders)
{
target_shader = fullbright_shader;
}
else
{
gPipeline.enableLightsFullbright();
}
target_shader = fullbright_shader;
light_enabled = FALSE;
}
}
// Turn on lighting if it isn't already.
else if (!light_enabled || !initialized_lighting)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP);
initialized_lighting = TRUE;
if (use_shaders)
{
target_shader = simple_shader;
}
else
{
gPipeline.enableLightsDynamic();
}
target_shader = simple_shader;
light_enabled = TRUE;
}
@ -741,7 +632,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
if (current_shader != target_shader)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS);
gPipeline.bindDeferredShader(*target_shader);
current_shader = target_shader;
}
@ -755,25 +645,19 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
target_shader = fullbright_shader;
}
if(use_shaders && (current_shader != target_shader))
if(current_shader != target_shader)
{// If we need shaders, and we're not ALREADY using the proper shader, then bind it
// (this way we won't rebind shaders unnecessarily).
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SHADER_BINDS);
current_shader = target_shader;
current_shader->bind();
}
else if (!use_shaders && current_shader != NULL)
{
LLGLSLShader::bindNoShader();
current_shader = NULL;
}
LLVector4 spec_color(1, 1, 1, 1);
F32 env_intensity = 0.0f;
F32 brightness = 1.0f;
// We have a material. Supply the appropriate data here.
if (use_shaders && mat && deferred_render)
if (mat && deferred_render)
{
spec_color = params.mSpecColor;
env_intensity = params.mEnvIntensity;
@ -792,20 +676,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
params.mGroup->rebuildMesh();
}
bool tex_setup = TexSetup(&params, use_shaders, use_shaders && (mat != nullptr), current_shader);
bool tex_setup = TexSetup(&params, (mat != nullptr), current_shader);
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH);
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
params.mVertexBuffer->setBufferFast(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DRAW);
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
}
}
@ -814,8 +694,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
draw_glow_for_this_partition &&
params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_EMISSIVE);
if (batch_emissives)
{
emissives.push_back(&params);
@ -835,19 +713,29 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
}
}
bool rebind = false;
if (batch_fullbrights)
{
light_enabled = false;
renderFullbrights(mask, fullbrights);
if (!fullbrights.empty())
{
light_enabled = false;
renderFullbrights(mask, fullbrights);
rebind = true;
}
}
if (batch_emissives)
{
light_enabled = true;
renderEmissives(mask, emissives);
if (!emissives.empty())
{
light_enabled = true;
renderEmissives(mask, emissives);
rebind = true;
}
}
if (current_shader)
if (current_shader && rebind)
{
current_shader->bind();
}

View File

@ -75,15 +75,13 @@ private:
LLGLSLShader* fullbright_shader;
LLGLSLShader* emissive_shader;
void renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples);
void renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
void renderMaterials(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
void drawEmissive(U32 mask, LLDrawInfo* draw);
void drawEmissiveInline(U32 mask, LLDrawInfo* draw);
bool TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader);
bool TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader);
void RestoreTexSetup(bool tex_setup);
// our 'normal' alpha blend function for this pass

View File

@ -1685,7 +1685,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
renderRigged(avatarp, RIGGED_NORMMAP);
renderRigged(avatarp, RIGGED_NORMMAP_MASK);
renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
renderRigged(avatarp, RIGGED_SPECMAP);
renderRigged(avatarp, RIGGED_SPECMAP_MASK);
renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
@ -2067,56 +2067,12 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
LLVector4a* pos = (LLVector4a*) position.get();
LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;
if (skin == nullptr)
{
skin = vobj->getSkinInfo();
}
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, skin);
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, vobj->getMeshID());
const LLMatrix4a* mat = &(mpc.mMatrixPalette[0]);
const LLMatrix4a& bind_shape_matrix = mpc.mBindShapeMatrix;
LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin);
const LLMatrix4a& bind_shape_matrix = skin->mBindShapeMatrix;
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
U8* joint_indices_cursor = vol_face.mJointIndices;
// fast path with joint indices separate from weights
if (joint_indices_cursor)
{
LLMatrix4a src[4];
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
LLMatrix4a final_mat;
//LLMatrix4a final_mat_correct;
F32* jw = just_weights[j].getF32ptr();
LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src);
joint_indices_cursor += 4;
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;
LLVector4a dst;
bind_shape_matrix.affineTransform(v, t);
final_mat.affineTransform(t, dst);
pos[j] = dst;
if (norm)
{
LLVector4a& n = vol_face.mNormals[j];
bind_shape_matrix.rotate(n, t);
final_mat.rotate(t, dst);
dst.normalize3fast();
norm[j] = dst;
}
}
}
// slow path with joint indices calculated from weights
else
#endif
if (!mpc.mMatrixPalette.empty())
{
for (U32 j = 0; j < buffer->getNumVerts(); ++j)
{
@ -2152,9 +2108,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
return;
}
stop_glerror();
const LLMeshSkinInfo* lastSkin = nullptr;
LLUUID lastMeshId;
for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
{
@ -2188,19 +2142,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
continue;
}
const LLMeshSkinInfo* skin = vobj->getSkinInfo();
if (!skin)
{
continue;
}
//stop_glerror();
//const LLVolumeFace& vol_face = volume->getVolumeFace(te);
//updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face);
//stop_glerror();
U32 data_mask = LLFace::getRiggedDataMask(type);
LLVertexBuffer* buff = face->getVertexBuffer();
@ -2290,34 +2231,33 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
if (sShaderLevel > 0)
{
if (lastSkin != skin) // <== only upload matrix palette to GL if the skininfo changed
auto& meshId = vobj->getMeshID();
if (lastMeshId != meshId) // <== only upload matrix palette to GL if the skininfo changed
{
// upload matrix palette to shader
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, skin);
const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, meshId);
U32 count = mpc.mMatrixPalette.size();
stop_glerror();
if (count == 0)
{
//skin info not loaded yet, don't render
continue;
}
LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
count,
FALSE,
(GLfloat*) &(mpc.mGLMp[0]));
stop_glerror();
}
lastMeshId = meshId;
}
else
{
data_mask &= ~LLVertexBuffer::MAP_WEIGHT4;
}
lastSkin = skin;
/*if (glow)
{
gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow());
}*/
if (mat)
{
//order is important here LLRender::DIFFUSE_MAP should be last, becouse it change
@ -2332,13 +2272,17 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
specular = face->getTexture(LLRender::SPECULAR_MAP);
}
if (specular)
if (specular && specular_channel >= 0)
{
gGL.getTexUnit(specular_channel)->bind(specular);
gGL.getTexUnit(specular_channel)->bindFast(specular);
}
gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP));
gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP), false, true);
if (normal_channel >= 0)
{
gGL.getTexUnit(normal_channel)->bindFast(face->getTexture(LLRender::NORMAL_MAP));
}
gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture(LLRender::DIFFUSE_MAP));
LLColor4 col = mat->getSpecularLightColor();
@ -2369,23 +2313,28 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
sVertexProgram->setMinimumAlpha(0.f);
}
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
LLViewerTexture* tex = face->getTexture(i);
if (tex)
{
tex->addTextureStats(avatar->getPixelArea());
}
}
if (!LLPipeline::sShadowRender && !LLPipeline::sReflectionRender)
{
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
LLViewerTexture* tex = face->getTexture(i);
if (tex)
{
tex->addTextureStats(avatar->getPixelArea());
}
}
}
}
else
{
gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture());
sVertexProgram->setMinimumAlpha(0.f);
if (normal_channel > -1)
{
LLDrawPoolBump::bindBumpMap(face, normal_channel);
}
gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture());
}
if (face->mTextureMatrix && vobj->mTexAnimMode)
@ -2399,8 +2348,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix);
}
buff->setBuffer(data_mask);
buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
buff->setBufferFast(data_mask);
buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset);
if (tex_index <= 1)
{
@ -2411,11 +2360,9 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
}
else
{
buff->setBuffer(data_mask);
buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
buff->setBufferFast(data_mask);
buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset);
}
gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES);
}
}
}
@ -2476,8 +2423,6 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
continue;
}
stop_glerror();
LLVolumeFace& vol_face = volume->getVolumeFace(te);
updateRiggedFaceVertexBuffer(avatar, face, vobj, volume, vol_face);
}
@ -2501,47 +2446,58 @@ void LLDrawPoolAvatar::updateSkinInfoMatrixPalettes(LLVOAvatar* avatarp)
}
}
const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLMeshSkinInfo* skin)
const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLUUID& meshId)
{
MatrixPaletteCache& entry = mMatrixPaletteCache[skin];
MatrixPaletteCache& entry = mMatrixPaletteCache[meshId];
if (entry.mFrame != gFrameCount)
{
LL_PROFILE_ZONE_SCOPED;
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(meshId);
entry.mFrame = gFrameCount;
//build matrix palette
U32 count = LLSkinningUtil::getMeshJointCount(skin);
entry.mMatrixPalette.resize(count);
LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp);
const LLMatrix4a* mat = &(entry.mMatrixPalette[0]);
stop_glerror();
entry.mGLMp.resize(count * 12);
F32* mp = &(entry.mGLMp[0]);
for (U32 i = 0; i < count; ++i)
if (skin != nullptr)
{
F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
entry.mBindShapeMatrix = skin->mBindShapeMatrix;
U32 idx = i * 12;
//build matrix palette
U32 count = LLSkinningUtil::getMeshJointCount(skin);
entry.mMatrixPalette.resize(count);
LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp);
mp[idx + 0] = m[0];
mp[idx + 1] = m[1];
mp[idx + 2] = m[2];
mp[idx + 3] = m[12];
const LLMatrix4a* mat = &(entry.mMatrixPalette[0]);
mp[idx + 4] = m[4];
mp[idx + 5] = m[5];
mp[idx + 6] = m[6];
mp[idx + 7] = m[13];
entry.mGLMp.resize(count * 12);
mp[idx + 8] = m[8];
mp[idx + 9] = m[9];
mp[idx + 10] = m[10];
mp[idx + 11] = m[14];
F32* mp = &(entry.mGLMp[0]);
for (U32 i = 0; i < count; ++i)
{
F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
U32 idx = i * 12;
mp[idx + 0] = m[0];
mp[idx + 1] = m[1];
mp[idx + 2] = m[2];
mp[idx + 3] = m[12];
mp[idx + 4] = m[4];
mp[idx + 5] = m[5];
mp[idx + 6] = m[6];
mp[idx + 7] = m[13];
mp[idx + 8] = m[8];
mp[idx + 9] = m[9];
mp[idx + 10] = m[10];
mp[idx + 11] = m[14];
}
}
else
{
entry.mMatrixPalette.resize(0);
entry.mGLMp.resize(0);
}
}

View File

@ -283,12 +283,13 @@ typedef enum
std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES];
LL_ALIGN_PREFIX(16)
class MatrixPaletteCache
{
public:
U32 mFrame;
LLMeshSkinInfo::matrix_list_t mMatrixPalette;
LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
// Float array ready to be sent to GL
std::vector<F32> mGLMp;
@ -296,11 +297,11 @@ typedef enum
mFrame(gFrameCount-1)
{
}
};
} LL_ALIGN_POSTFIX(16);
const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLMeshSkinInfo* skin);
const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLUUID& meshId);
typedef std::unordered_map<const LLMeshSkinInfo*, MatrixPaletteCache> matrix_palette_cache_t;
typedef std::unordered_map<LLUUID, MatrixPaletteCache> matrix_palette_cache_t;
matrix_palette_cache_t mMatrixPaletteCache;
/*virtual*/ LLViewerTexture *getDebugTexture();

View File

@ -4045,7 +4045,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj)
{
LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
LL_PROFILE_ZONE_SCOPED;
if (mesh_id.notNull())
{
skin_map::iterator iter = mSkinMap.find(mesh_id);
@ -4055,6 +4055,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const
}
//no skin info known about given mesh, try to fetch it
if (requesting_obj != nullptr)
{
LLMutexLock lock(mMeshMutex);
//add volume to list of loading meshes

View File

@ -586,7 +586,7 @@ public:
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
static S32 getActualMeshLOD(LLSD& header, S32 lod);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);

View File

@ -3555,7 +3555,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const
{
if (getVolume())
{
return gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this);
return gMeshRepo.getSkinInfo(getMeshID(), this);
}
else
{

View File

@ -296,6 +296,9 @@ public:
BOOL setIsFlexible(BOOL is_flexible);
const LLMeshSkinInfo* getSkinInfo() const;
//convenience accessor for mesh ID (which is stored in sculpt id for legacy reasons)
const LLUUID& getMeshID() const { return getVolume()->getParams().getSculptID(); }
// Extended Mesh Properties
U32 getExtendedMeshFlags() const;