From c1d2416826406631807f153e7de9d2b790b0caa5 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Thu, 28 Feb 2019 14:06:19 -0800 Subject: EEP performance WIP Mods to improve alpha obj render performance. Removes hacky fix for HUD elements getting atmospherics. Re-orders rendering of glow to remove ~10ms/frame of shader re-re-rebinding. Fix up default classes and basic shader loading (remove unused shared modules). --- indra/newview/lldrawpoolalpha.cpp | 621 +++++++++++++++++++++----------------- 1 file changed, 350 insertions(+), 271 deletions(-) (limited to 'indra/newview/lldrawpoolalpha.cpp') diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index b896ecde30..5396a8fdd2 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -53,6 +53,19 @@ BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; 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_MESH_REBUILD("Alpha Mesh Rebuild"); + LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), current_shader(NULL), target_shader(NULL), simple_shader(NULL), fullbright_shader(NULL), emissive_shader(NULL), @@ -115,7 +128,6 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) fullbright_shader->bind(); fullbright_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); fullbright_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); fullbright_shader->setMinimumAlpha(LLPipeline::sImpostorRender ? 0.5f : 0.0f); fullbright_shader->unbind(); @@ -185,25 +197,13 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) void LLDrawPoolAlpha::beginRenderPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP); if (LLPipeline::sImpostorRender) { simple_shader = &gObjectSimpleImpostorProgram; fullbright_shader = &gObjectFullbrightProgram; emissive_shader = &gObjectEmissiveProgram; - - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.5f); - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.5f); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK - } } else if (LLPipeline::sUnderWaterRender) { @@ -218,26 +218,18 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) emissive_shader = &gObjectEmissiveProgram; } - if (!LLPipeline::sImpostorRender) + if (mShaderLevel > 0) { - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.f); - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.f); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK - } - } + // Start out with no shaders. + current_shader = target_shader = NULL; + LLGLSLShader::bindNoShader(); + } gPipeline.enableLightsDynamic(); } void LLDrawPoolAlpha::endRenderPass( S32 pass ) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP); LLRenderPass::endRenderPass(pass); if(gPipeline.canUseWindLightShaders()) @@ -281,7 +273,34 @@ void LLDrawPoolAlpha::render(S32 pass) mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - + if (mShaderLevel > 0) + { + if (LLPipeline::sImpostorRender) + { + fullbright_shader->bind(); + fullbright_shader->setMinimumAlpha(0.5f); + simple_shader->bind(); + simple_shader->setMinimumAlpha(0.5f); + } + else + { + fullbright_shader->bind(); + fullbright_shader->setMinimumAlpha(0.f); + simple_shader->bind(); + simple_shader->setMinimumAlpha(0.f); + } + } + else + { + if (LLPipeline::sImpostorRender) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK + } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK + } + } } if (mShaderLevel > 0) @@ -368,268 +387,328 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) } } -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); - void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); + 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; - llassert(group); - llassert(group->getSpatialPartition()); - - if (group->getSpatialPartition()->mRenderByGroup && - !group->isDead()) - { - bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE - || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; - - bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow. - - - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP); - - bool disable_cull = is_particle_or_hud_particle; - LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); - - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; - - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - - if ((params.mVertexBuffer->getTypeMask() & mask) != mask) - { //FIXME! - LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask - << " present: " << (params.mVertexBuffer->getTypeMask() & mask) - << ". Skipping render batch." << LL_ENDL; - continue; - } - - // Fix for bug - NORSPEC-271 - // If the face is more than 90% transparent, then don't update the Depth buffer for Dof - // We don't want the nearly invisible objects to cause of DoF effects - if(pass == 1 && !LLPipeline::sImpostorRender) - { - LLFace* face = params.mFace; - if(face) - { - const LLTextureEntry* tep = face->getTextureEntry(); - if(tep) - { - if(tep->getColor().mV[3] < 0.1f) - continue; - } - } - } - LLRenderPass::applyModelMatrix(params); - - LLMaterial* mat = NULL; + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP); - if (deferred_render) - { - mat = params.mMaterial; - } + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + { + LLSpatialGroup* group = *i; + llassert(group); + llassert(group->getSpatialPartition()); + + if (group->getSpatialPartition()->mRenderByGroup && + !group->isDead()) + { + bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE + || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; + + bool disable_cull = is_particle_or_hud_particle; + LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); + + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; + + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo& params = **k; + + if ((params.mVertexBuffer->getTypeMask() & mask) != mask) + { //FIXME! + LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask + << " present: " << (params.mVertexBuffer->getTypeMask() & mask) + << ". Skipping render batch." << LL_ENDL; + continue; + } + + // Fix for bug - NORSPEC-271 + // If the face is more than 90% transparent, then don't update the Depth buffer for Dof + // We don't want the nearly invisible objects to cause of DoF effects + if(pass == 1 && !LLPipeline::sImpostorRender) + { + LLFace* face = params.mFace; + if(face) + { + const LLTextureEntry* tep = face->getTextureEntry(); + if(tep) + { + if(tep->getColor().mV[3] < 0.1f) + continue; + } + } + } + + LLRenderPass::applyModelMatrix(params); + + LLMaterial* mat = NULL; + + if (deferred_render) + { + mat = params.mMaterial; + } - if (params.mFullbright) - { - // Turn off lighting if it hasn't already been so. - if (light_enabled || !initialized_lighting) - { - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = fullbright_shader; - } - else - { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - } - light_enabled = FALSE; - } - } - // Turn on lighting if it isn't already. - else if (!light_enabled || !initialized_lighting) - { - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } - light_enabled = TRUE; - } - - if (deferred_render && mat) - { - U32 mask = params.mShaderMask; - - llassert(mask < LLMaterial::SHADER_COUNT); - target_shader = &(gDeferredMaterialProgram[mask]); - - if (LLPipeline::sUnderWaterRender) - { - target_shader = &(gDeferredMaterialWaterProgram[mask]); - } - - if (current_shader != target_shader) - { - gPipeline.bindDeferredShader(*target_shader); - } - } - else if (!params.mFullbright) - { - target_shader = simple_shader; - } - else - { - target_shader = fullbright_shader; - } + if (params.mFullbright) + { + // Turn off lighting if it hasn't already been so. + if (light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = fullbright_shader; + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + light_enabled = FALSE; + } + } + // Turn on lighting if it isn't already. + else if (!light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = simple_shader; + } + else + { + gPipeline.enableLightsDynamic(); + } + light_enabled = TRUE; + } + + if (deferred_render && mat) + { + U32 mask = params.mShaderMask; + + llassert(mask < LLMaterial::SHADER_COUNT); + target_shader = &(gDeferredMaterialProgram[mask]); + + if (LLPipeline::sUnderWaterRender) + { + target_shader = &(gDeferredMaterialWaterProgram[mask]); + } + + if (current_shader != target_shader) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); + gPipeline.bindDeferredShader(*target_shader); + current_shader = target_shader; + } + } + else if (!params.mFullbright) + { + target_shader = simple_shader; + } + else + { + target_shader = fullbright_shader; + } - if(use_shaders && (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). - current_shader = target_shader; - current_shader->bind(); - } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } - - if (use_shaders && mat) - { - // We have a material. Supply the appropriate data here. - if (LLPipeline::sRenderDeferred) - { - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]); - current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity); - current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f); - - if (params.mNormalMap) - { - params.mNormalMap->addTextureStats(params.mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap); - } + if(use_shaders && (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; + } + + if (use_shaders && mat) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MATS); + + // We have a material. Supply the appropriate data here. + if (LLPipeline::sRenderDeferred) + { + current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]); + current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity); + current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f); + + if (params.mNormalMap) + { + params.mNormalMap->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap); + } - if (params.mSpecularMap) - { - params.mSpecularMap->addTextureStats(params.mVSize); - current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap); - } - } - - } else if (LLPipeline::sRenderDeferred && current_shader && (current_shader == simple_shader)) - { - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); - current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f); - LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(params.mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); - LLViewerFetchedTexture::sWhiteImagep->addTextureStats(params.mVSize); - current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); - } - - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } + if (params.mSpecularMap) + { + params.mSpecularMap->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap); + } + } + + } + else if (LLPipeline::sRenderDeferred && current_shader && (current_shader == simple_shader)) + { + current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); + current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f); + LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); + LLViewerFetchedTexture::sWhiteImagep->addTextureStats(params.mVSize); + current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); + } + + if (params.mGroup) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MESH_REBUILD); + + params.mGroup->rebuildMesh(); + } + + bool tex_setup = false; + + if (use_shaders && params.mTextureList.size() > 1) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS); + for (U32 i = 0; i < params.mTextureList.size(); ++i) + { + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + } + } + } + else + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTexture.notNull()) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS); + + params.mTexture->addTextureStats(params.mVSize); + if (use_shaders && mat) + { + current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, params.mTexture); + } + else + { + gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + } + + if (params.mTextureMatrix) + { + tex_setup = true; + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + } + + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); + + LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); + + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETBUFFER); + 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)); + } + + { + 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); + } + + if (tex_setup) + { + gGL.getTexUnit(0)->activate(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + } + } + } + + bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow. + + if (use_shaders && draw_glow_for_this_partition) + { + // install glow-accumulating blend mode + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color + LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) - bool tex_setup = false; + emissive_shader->bind(); - if (use_shaders && params.mTextureList.size() > 1) - { - for (U32 i = 0; i < params.mTextureList.size(); ++i) - { - if (params.mTextureList[i].notNull()) - { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); - } - } - } - else - { //not batching textures or batch has only 1 texture -- might need a texture matrix - if (params.mTexture.notNull()) - { - params.mTexture->addTextureStats(params.mVSize); - if (use_shaders && mat) - { - current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, params.mTexture); - } - else - { - gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; - } - - if (params.mTextureMatrix) - { - tex_setup = true; - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - } - else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - } + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + { + LLSpatialGroup* group = *i; + llassert(group); + llassert(group->getSpatialPartition()); - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); + if (group->getSpatialPartition()->mRenderByGroup && + !group->isDead()) + { + bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE + || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; - 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)); + bool disable_cull = is_particle_or_hud_particle; + LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - } - - // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha. - if (current_shader && - draw_glow_for_this_partition && - params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) - { - // install glow-accumulating blend mode - gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color - LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; - emissive_shader->bind(); - - params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); - - // do the actual drawing, again - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo& params = **k; - // restore our alpha blend mode - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + if ((params.mVertexBuffer->getTypeMask() & mask) != mask) + { //FIXME! + LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask + << " present: " << (params.mVertexBuffer->getTypeMask() & mask) + << ". Skipping render batch." << LL_ENDL; + continue; + } - current_shader->bind(); - } - - if (tex_setup) - { - gGL.getTexUnit(0)->activate(); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - } - } - } + LLRenderPass::applyModelMatrix(params); + + // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha. + if (emissive_shader && + draw_glow_for_this_partition && + params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GLOW); + + params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); + + // do the actual drawing, again + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + } + } + } + } + + // restore our alpha blend mode + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + + emissive_shader->unbind(); + } + } gGL.setSceneBlendType(LLRender::BT_ALPHA); -- cgit v1.2.3