From 1d86dcd846ed5ea7734df507d15adf057cb2ebd0 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Mon, 8 Jul 2019 10:10:22 -0700 Subject: SL-10625 another shot across the bow Move dynamic texture update (which does local back readback work) to just before swap which may keep the Intel driver from tripping on its own shoelaces and is also subjectively faster for bakes. --- indra/newview/lldynamictexture.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/lldynamictexture.cpp') diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index fa9a0712fa..5e283f7cd0 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -213,7 +213,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() sNumRenders = 0; if (gGLManager.mIsDisabled || LLPipeline::sMemAllocationThrottled) { - return TRUE; + return FALSE; } bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI; @@ -248,7 +248,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() result = TRUE; sNumRenders++; } - gGL.flush(); + //gGL.flush(); LLVertexBuffer::unbind(); dynamicTexture->postRender(result); @@ -261,6 +261,8 @@ BOOL LLViewerDynamicTexture::updateAllInstances() gPipeline.mWaterDis.flush(); } + gGL.flush(); + return ret; } -- cgit v1.3 From 946da4e507dd00e6e7a9e465d38494bcafe4f652 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Mon, 15 Jul 2019 15:04:48 -0700 Subject: SL-10761 Add work-around for broken intel drivers which can't use glReadPixels from RGBA FBOs to get alpha without locking up. --- indra/llappearance/lltexlayer.cpp | 73 +++++++++++++++++++++++++++----------- indra/llappearance/lltexlayer.h | 24 ++++++------- indra/newview/lldynamictexture.cpp | 3 +- indra/newview/lldynamictexture.h | 5 +++ indra/newview/llviewertexlayer.h | 2 +- 5 files changed, 72 insertions(+), 35 deletions(-) (limited to 'indra/newview/lldynamictexture.cpp') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 19a4f3e12d..9d294645db 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -137,7 +137,7 @@ void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) popProjection(); } -BOOL LLTexLayerSetBuffer::renderTexLayerSet() +BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) { // Default color mask for tex layer render gGL.setColorMask(true, true); @@ -161,7 +161,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet() // Composite the color data LLGLSUIDefault gls_ui; success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), - getCompositeWidth(), getCompositeHeight() ); + getCompositeWidth(), getCompositeHeight(), bound_target ); gGL.flush(); midRenderTexLayerSet(success); @@ -375,7 +375,7 @@ void LLTexLayerSet::deleteCaches() } -BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) +BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) { BOOL success = TRUE; mIsVisible = TRUE; @@ -427,7 +427,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) if (layer->getRenderPass() == LLTexLayer::RP_COLOR) { gGL.flush(); - success &= layer->render(x, y, width, height); + success &= layer->render(x, y, width, height, bound_target); gGL.flush(); } } @@ -523,7 +523,7 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const } static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); -void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height) +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target) { LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA); memset(data, 255, width * height); @@ -531,15 +531,15 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, origin_x, origin_y, width, height); + layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target); } // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(origin_x, origin_y, width, height, true); + renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true); } static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); -void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) +void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear) { LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES); const LLTexLayerSetInfo *info = getInfo(); @@ -1124,7 +1124,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL } } -BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) +BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) { LLGLEnable color_mat(GL_COLOR_MATERIAL); // *TODO: Is this correct? @@ -1185,7 +1185,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) }//*/ const bool force_render = true; - renderMorphMasks(x, y, width, height, net_color, force_render); + renderMorphMasks(x, y, width, height, net_color, bound_target, force_render); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1428,13 +1428,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) return success; } -/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { - addAlphaMask(data, originX, originY, width, height); + addAlphaMask(data, originX, originY, width, height, bound_target); } static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks"); -void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render) +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render) { if (!force_render && !hasMorph()) { @@ -1586,11 +1586,42 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC alpha_data = (U8*)ll_aligned_malloc_32(mem_size); - bool skip_readback = LLRender::sNsightDebugSupport || gGLManager.mIsIntel; // nSight doesn't support use of glReadPixels + bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels if (!skip_readback) { - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + if (gGLManager.mIsIntel) + { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO + // returning only the alpha portion without locking up downstream + U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA + + if (bound_target) + { + gGL.getTexUnit(0)->bind(bound_target); + } + else + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0); + } + + glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); + + U8* alpha_cursor = alpha_data; + U8* pixel = temp; + for (int i = 0; i < pixels; i++) + { + *alpha_cursor++ = pixel[3]; + pixel += 4; + } + + gGL.getTexUnit(0)->disable(); + + ll_aligned_free_32(temp); + } + else + { // platforms with working drivers... + glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + } } else { @@ -1609,7 +1640,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask"); -void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK); S32 size = width * height; @@ -1621,7 +1652,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 // TODO: eliminate need for layer morph mask valid flag invalidateMorphMasks(); const bool force_render = false; - renderMorphMasks(originX, originY, width, height, net_color, force_render); + renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render); alphaData = getAlphaData(); } if (alphaData) @@ -1755,7 +1786,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return layer; } -/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height) +/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) { if(!mInfo) { @@ -1782,7 +1813,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const { wearable->writeToAvatar(mAvatarAppearance); layer->setLTO(lto); - success &= layer->render(x,y,width,height); + success &= layer->render(x, y, width, height, bound_target); } } @@ -1804,14 +1835,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return success; } -/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { U32 num_wearables = updateWearableCache(); U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable LLTexLayer *layer = getLayer(i); if (layer) { - layer->addAlphaMask(data, originX, originY, width, height); + layer->addAlphaMask(data, originX, originY, width, height, bound_target); } } diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 9318b23fd1..6a5040cf0b 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -65,7 +65,7 @@ public: LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); virtual ~LLTexLayerInterface() {} - virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; + virtual BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; virtual void deleteCaches() = 0; virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; virtual BOOL isInvisibleAlphaMask() const = 0; @@ -85,7 +85,7 @@ public: BOOL isMorphValid() const { return mMorphMasksValid; } void requestUpdate(); - virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0; BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } ERenderPass getRenderPass() const; @@ -121,10 +121,10 @@ public: LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); LLTexLayerTemplate(const LLTexLayerTemplate &layer); /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ void setHasMorph(BOOL newval); /*virtual*/ void deleteCaches(); /*virtual*/ BOOL isInvisibleAlphaMask() const; @@ -152,16 +152,16 @@ public: /*virtual*/ ~LLTexLayer(); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ void deleteCaches(); const U8* getAlphaData() const; BOOL findNetColor(LLColor4* color) const; /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render); - void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ BOOL isInvisibleAlphaMask() const; void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } @@ -194,13 +194,13 @@ public: const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. virtual void createComposite() = 0; void destroyComposite(); - void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height); + void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target); const LLTexLayerSetInfo* getInfo() const { return mInfo; } BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions - BOOL render(S32 x, S32 y, S32 width, S32 height); - void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); + BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); + void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); BOOL isBodyRegion(const std::string& region) const; void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); @@ -282,7 +282,7 @@ protected: virtual S32 getCompositeOriginY() const = 0; virtual S32 getCompositeWidth() const = 0; virtual S32 getCompositeHeight() const = 0; - BOOL renderTexLayerSet(); + BOOL renderTexLayerSet(LLRenderTarget* bound_target); LLTexLayerSet* const mTexLayerSet; }; diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 5e283f7cd0..e1f41a9bd7 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -240,6 +240,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() gDepthDirty = TRUE; gGL.color4f(1,1,1,1); + dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mWaterDis : nullptr); dynamicTexture->preRender(); // Must be called outside of startRender() result = FALSE; if (dynamicTexture->render()) @@ -250,7 +251,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } //gGL.flush(); LLVertexBuffer::unbind(); - + dynamicTexture->setBoundTarget(nullptr); dynamicTexture->postRender(result); } } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index f3f57c9a6b..4bd74a8425 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -88,6 +88,9 @@ public: static BOOL updateAllInstances(); static void destroyGL() ; static void restoreGL() ; + + void setBoundTarget(LLRenderTarget* target) { mBoundTarget = target; } + protected: void generateGLTexture(); void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE); @@ -97,6 +100,8 @@ protected: LLCoordGL mOrigin; LL_ALIGN_16(LLCamera mCamera); + LLRenderTarget* mBoundTarget; + typedef std::set instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; static S32 sNumRenders; diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h index 027ae255ec..dec7f0ddfc 100644 --- a/indra/newview/llviewertexlayer.h +++ b/indra/newview/llviewertexlayer.h @@ -111,7 +111,7 @@ protected: // Pass these along for tex layer rendering. virtual void preRender(BOOL clear_depth) { preRenderTexLayerSet(); } virtual void postRender(BOOL success) { postRenderTexLayerSet(success); } - virtual BOOL render() { return renderTexLayerSet(); } + virtual BOOL render() { return renderTexLayerSet(mBoundTarget); } //-------------------------------------------------------------------- // Updates -- cgit v1.3 From dc7aa170b80bb7d3f7725b5bddce08ff2da5a7a7 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Tue, 16 Jul 2019 14:12:37 -0700 Subject: SL-11610 Give bake its own RT to avoid issues with sharing the water distortion map. Use glFinish to insure RTs will be complete. --- indra/newview/lldynamictexture.cpp | 13 ++++++++----- indra/newview/pipeline.cpp | 8 +++++--- indra/newview/pipeline.h | 2 ++ 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'indra/newview/lldynamictexture.cpp') diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index e1f41a9bd7..13d539b55f 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -129,7 +129,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) llassert(mFullHeight <= 512); llassert(mFullWidth <= 512); - if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI) + if (gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsATI) { //using offscreen render target, just use the bottom left corner mOrigin.set(0, 0); } @@ -216,11 +216,12 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return FALSE; } - bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI; + bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsATI; if (use_fbo) { - gPipeline.mWaterDis.bindTarget(); + gPipeline.mBake.bindTarget(); + gPipeline.mBake.clear(); } LLGLSLShader::bindNoShader(); @@ -240,7 +241,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() gDepthDirty = TRUE; gGL.color4f(1,1,1,1); - dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mWaterDis : nullptr); + dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr); dynamicTexture->preRender(); // Must be called outside of startRender() result = FALSE; if (dynamicTexture->render()) @@ -257,9 +258,11 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } } + glFinish(); + if (use_fbo) { - gPipeline.mWaterDis.flush(); + gPipeline.mBake.flush(); } gGL.flush(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 863785889f..eb1ffc91f7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1162,6 +1162,7 @@ void LLPipeline::releaseGLBuffers() mWaterRef.release(); mWaterDis.release(); + mBake.release(); mHighlight.release(); for (U32 i = 0; i < 3; i++) @@ -1221,12 +1222,13 @@ void LLPipeline::createGLBuffers() if (LLPipeline::sWaterReflections) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); - mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); - //always use FBO for mWaterDis so it can be used for avatar texture bakes - mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true); + mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE); } + // Use FBO for bake tex + mBake.allocate(512, 512, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, true); + mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); stop_glerror(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index b0c40d145b..cc9ec06f80 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -650,6 +650,8 @@ public: //water distortion texture (refraction) LLRenderTarget mWaterDis; + LLRenderTarget mBake; + //texture for making the glow LLRenderTarget mGlow[3]; -- cgit v1.3 From 1529c16201d332ce7bbff5c3637737ca58277eb9 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Wed, 24 Jul 2019 10:53:04 -0700 Subject: SL-11610 Revert attempted fix for 10625. --- indra/llappearance/lltexlayer.cpp | 77 ++++++++++++-------------------------- indra/llappearance/lltexlayer.h | 24 ++++++------ indra/newview/lldynamictexture.cpp | 20 ++++------ indra/newview/lldynamictexture.h | 5 --- indra/newview/llviewerdisplay.cpp | 30 +++++++-------- indra/newview/llviewertexlayer.h | 2 +- indra/newview/pipeline.cpp | 4 -- indra/newview/pipeline.h | 2 - 8 files changed, 56 insertions(+), 108 deletions(-) (limited to 'indra/newview/lldynamictexture.cpp') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index c90b11ae71..8ae7c9aa9b 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -137,7 +137,7 @@ void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) popProjection(); } -BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) +BOOL LLTexLayerSetBuffer::renderTexLayerSet() { // Default color mask for tex layer render gGL.setColorMask(true, true); @@ -161,7 +161,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) // Composite the color data LLGLSUIDefault gls_ui; success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), - getCompositeWidth(), getCompositeHeight(), bound_target ); + getCompositeWidth(), getCompositeHeight() ); gGL.flush(); midRenderTexLayerSet(success); @@ -375,7 +375,7 @@ void LLTexLayerSet::deleteCaches() } -BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) +BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { BOOL success = TRUE; mIsVisible = TRUE; @@ -427,12 +427,12 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* if (layer->getRenderPass() == LLTexLayer::RP_COLOR) { gGL.flush(); - success &= layer->render(x, y, width, height, bound_target); + success &= layer->render(x, y, width, height); gGL.flush(); } } - renderAlphaMaskTextures(x, y, width, height, bound_target, false); + renderAlphaMaskTextures(x, y, width, height, false); stop_glerror(); } @@ -523,7 +523,7 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const } static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); -void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target) +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height) { LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA); memset(data, 255, width * height); @@ -531,15 +531,15 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target); + layer->gatherAlphaMasks(data, origin_x, origin_y, width, height); } // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true); + renderAlphaMaskTextures(origin_x, origin_y, width, height, true); } static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); -void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear) +void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) { LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES); const LLTexLayerSetInfo *info = getInfo(); @@ -1124,7 +1124,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL } } -BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) +BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) { LLGLEnable color_mat(GL_COLOR_MATERIAL); // *TODO: Is this correct? @@ -1185,7 +1185,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou }//*/ const bool force_render = true; - renderMorphMasks(x, y, width, height, net_color, bound_target, force_render); + renderMorphMasks(x, y, width, height, net_color, force_render); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1428,13 +1428,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) return success; } -/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { - addAlphaMask(data, originX, originY, width, height, bound_target); + addAlphaMask(data, originX, originY, width, height); } static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks"); -void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render) +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render) { if (!force_render && !hasMorph()) { @@ -1586,42 +1586,11 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC alpha_data = (U8*)ll_aligned_malloc_32(mem_size); - bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels + bool skip_readback = LLRender::sNsightDebugSupport || gGLManager.mIsIntel; // nSight doesn't support use of glReadPixels if (!skip_readback) { - if (gGLManager.mIsIntel) - { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO - // returning only the alpha portion without locking up downstream - U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA - - if (bound_target) - { - gGL.getTexUnit(0)->bind(bound_target); - } - else - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0); - } - - glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); - - U8* alpha_cursor = alpha_data; - U8* pixel = temp; - for (int i = 0; i < pixels; i++) - { - *alpha_cursor++ = pixel[3]; - pixel += 4; - } - - gGL.getTexUnit(0)->disable(); - - ll_aligned_free_32(temp); - } - else - { // platforms with working drivers... - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); - } + glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); } else { @@ -1631,7 +1600,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC mAlphaCache[cache_index] = alpha_data; } - + getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); mMorphMasksValid = TRUE; @@ -1640,7 +1609,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask"); -void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK); S32 size = width * height; @@ -1652,7 +1621,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 // TODO: eliminate need for layer morph mask valid flag invalidateMorphMasks(); const bool force_render = false; - renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render); + renderMorphMasks(originX, originY, width, height, net_color, force_render); alphaData = getAlphaData(); } if (alphaData) @@ -1786,7 +1755,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return layer; } -/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) +/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height) { if(!mInfo) { @@ -1813,7 +1782,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const { wearable->writeToAvatar(mAvatarAppearance); layer->setLTO(lto); - success &= layer->render(x, y, width, height, bound_target); + success &= layer->render(x,y,width,height); } } @@ -1835,14 +1804,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return success; } -/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) { U32 num_wearables = updateWearableCache(); U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable LLTexLayer *layer = getLayer(i); if (layer) { - layer->addAlphaMask(data, originX, originY, width, height, bound_target); + layer->addAlphaMask(data, originX, originY, width, height); } } diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 6a5040cf0b..9318b23fd1 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -65,7 +65,7 @@ public: LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); virtual ~LLTexLayerInterface() {} - virtual BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; + virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; virtual void deleteCaches() = 0; virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; virtual BOOL isInvisibleAlphaMask() const = 0; @@ -85,7 +85,7 @@ public: BOOL isMorphValid() const { return mMorphMasksValid; } void requestUpdate(); - virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0; + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } ERenderPass getRenderPass() const; @@ -121,10 +121,10 @@ public: LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); LLTexLayerTemplate(const LLTexLayerTemplate &layer); /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); /*virtual*/ void setHasMorph(BOOL newval); /*virtual*/ void deleteCaches(); /*virtual*/ BOOL isInvisibleAlphaMask() const; @@ -152,16 +152,16 @@ public: /*virtual*/ ~LLTexLayer(); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); /*virtual*/ void deleteCaches(); const U8* getAlphaData() const; BOOL findNetColor(LLColor4* color) const; /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); - void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render); - void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); /*virtual*/ BOOL isInvisibleAlphaMask() const; void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } @@ -194,13 +194,13 @@ public: const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. virtual void createComposite() = 0; void destroyComposite(); - void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target); + void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height); const LLTexLayerSetInfo* getInfo() const { return mInfo; } BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions - BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); - void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); + BOOL render(S32 x, S32 y, S32 width, S32 height); + void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); BOOL isBodyRegion(const std::string& region) const; void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); @@ -282,7 +282,7 @@ protected: virtual S32 getCompositeOriginY() const = 0; virtual S32 getCompositeWidth() const = 0; virtual S32 getCompositeHeight() const = 0; - BOOL renderTexLayerSet(LLRenderTarget* bound_target); + BOOL renderTexLayerSet(); LLTexLayerSet* const mTexLayerSet; }; diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 13d539b55f..fa9a0712fa 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -129,7 +129,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) llassert(mFullHeight <= 512); llassert(mFullWidth <= 512); - if (gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsATI) + if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI) { //using offscreen render target, just use the bottom left corner mOrigin.set(0, 0); } @@ -213,15 +213,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances() sNumRenders = 0; if (gGLManager.mIsDisabled || LLPipeline::sMemAllocationThrottled) { - return FALSE; + return TRUE; } - bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsATI; + bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI; if (use_fbo) { - gPipeline.mBake.bindTarget(); - gPipeline.mBake.clear(); + gPipeline.mWaterDis.bindTarget(); } LLGLSLShader::bindNoShader(); @@ -241,7 +240,6 @@ BOOL LLViewerDynamicTexture::updateAllInstances() gDepthDirty = TRUE; gGL.color4f(1,1,1,1); - dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr); dynamicTexture->preRender(); // Must be called outside of startRender() result = FALSE; if (dynamicTexture->render()) @@ -250,23 +248,19 @@ BOOL LLViewerDynamicTexture::updateAllInstances() result = TRUE; sNumRenders++; } - //gGL.flush(); + gGL.flush(); LLVertexBuffer::unbind(); - dynamicTexture->setBoundTarget(nullptr); + dynamicTexture->postRender(result); } } } - glFinish(); - if (use_fbo) { - gPipeline.mBake.flush(); + gPipeline.mWaterDis.flush(); } - gGL.flush(); - return ret; } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index 4bd74a8425..f3f57c9a6b 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -88,9 +88,6 @@ public: static BOOL updateAllInstances(); static void destroyGL() ; static void restoreGL() ; - - void setBoundTarget(LLRenderTarget* target) { mBoundTarget = target; } - protected: void generateGLTexture(); void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE); @@ -100,8 +97,6 @@ protected: LLCoordGL mOrigin; LL_ALIGN_16(LLCamera mCamera); - LLRenderTarget* mBoundTarget; - typedef std::set instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; static S32 sNumRenders; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 0eafce7e1c..b78937e3b0 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -592,6 +592,18 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // Actually push all of our triangles to the screen. // + // do render-to-texture stuff here + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) + { + LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_DYNAMIC_TEXTURES); + if (LLViewerDynamicTexture::updateAllInstances()) + { + gGL.setColorMask(true, true); + glClear(GL_DEPTH_BUFFER_BIT); + } + } + gViewerWindow->setup3DViewport(); gPipeline.resetFrameStats(); // Reset per-frame statistics. @@ -1022,26 +1034,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (!for_snapshot) { render_ui(); - } - - // do render-to-texture stuff here - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); - LL_RECORD_BLOCK_TIME(FTM_UPDATE_DYNAMIC_TEXTURES); - if (LLViewerDynamicTexture::updateAllInstances()) - { - gGL.setColorMask(true, true); - glClear(GL_DEPTH_BUFFER_BIT); - } - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); - if (!for_snapshot) - { swap(); } + LLSpatialGroup::sNoDelete = FALSE; gPipeline.clearReferences(); diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h index dec7f0ddfc..027ae255ec 100644 --- a/indra/newview/llviewertexlayer.h +++ b/indra/newview/llviewertexlayer.h @@ -111,7 +111,7 @@ protected: // Pass these along for tex layer rendering. virtual void preRender(BOOL clear_depth) { preRenderTexLayerSet(); } virtual void postRender(BOOL success) { postRenderTexLayerSet(success); } - virtual BOOL render() { return renderTexLayerSet(mBoundTarget); } + virtual BOOL render() { return renderTexLayerSet(); } //-------------------------------------------------------------------- // Updates diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 448b65272b..fc7408a8e5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1162,7 +1162,6 @@ void LLPipeline::releaseGLBuffers() mWaterRef.release(); mWaterDis.release(); - mBake.release(); mHighlight.release(); for (U32 i = 0; i < 3; i++) @@ -1226,9 +1225,6 @@ void LLPipeline::createGLBuffers() mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE); } - // Use FBO for bake tex - mBake.allocate(512, 512, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, true); - mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); stop_glerror(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index cc9ec06f80..b0c40d145b 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -650,8 +650,6 @@ public: //water distortion texture (refraction) LLRenderTarget mWaterDis; - LLRenderTarget mBake; - //texture for making the glow LLRenderTarget mGlow[3]; -- cgit v1.3 From 41ede77744489c2a2d32849ea457bcbea516a588 Mon Sep 17 00:00:00 2001 From: Graham Linden Date: Wed, 24 Jul 2019 12:52:24 -0700 Subject: SL-10625 --- indra/llappearance/lltexlayer.cpp | 77 ++++++++++++++++++++++++++------------ indra/llappearance/lltexlayer.h | 24 ++++++------ indra/newview/lldynamictexture.cpp | 14 ++++--- indra/newview/lldynamictexture.h | 5 +++ indra/newview/llviewertexlayer.h | 2 +- indra/newview/pipeline.cpp | 6 ++- indra/newview/pipeline.h | 2 + 7 files changed, 88 insertions(+), 42 deletions(-) (limited to 'indra/newview/lldynamictexture.cpp') diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 8ae7c9aa9b..c90b11ae71 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -137,7 +137,7 @@ void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) popProjection(); } -BOOL LLTexLayerSetBuffer::renderTexLayerSet() +BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) { // Default color mask for tex layer render gGL.setColorMask(true, true); @@ -161,7 +161,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet() // Composite the color data LLGLSUIDefault gls_ui; success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), - getCompositeWidth(), getCompositeHeight() ); + getCompositeWidth(), getCompositeHeight(), bound_target ); gGL.flush(); midRenderTexLayerSet(success); @@ -375,7 +375,7 @@ void LLTexLayerSet::deleteCaches() } -BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) +BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) { BOOL success = TRUE; mIsVisible = TRUE; @@ -427,12 +427,12 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) if (layer->getRenderPass() == LLTexLayer::RP_COLOR) { gGL.flush(); - success &= layer->render(x, y, width, height); + success &= layer->render(x, y, width, height, bound_target); gGL.flush(); } } - renderAlphaMaskTextures(x, y, width, height, false); + renderAlphaMaskTextures(x, y, width, height, bound_target, false); stop_glerror(); } @@ -523,7 +523,7 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const } static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); -void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height) +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target) { LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA); memset(data, 255, width * height); @@ -531,15 +531,15 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) { LLTexLayerInterface* layer = *iter; - layer->gatherAlphaMasks(data, origin_x, origin_y, width, height); + layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target); } // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(origin_x, origin_y, width, height, true); + renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true); } static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); -void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear) +void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear) { LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES); const LLTexLayerSetInfo *info = getInfo(); @@ -1124,7 +1124,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL } } -BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) +BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) { LLGLEnable color_mat(GL_COLOR_MATERIAL); // *TODO: Is this correct? @@ -1185,7 +1185,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height) }//*/ const bool force_render = true; - renderMorphMasks(x, y, width, height, net_color, force_render); + renderMorphMasks(x, y, width, height, net_color, bound_target, force_render); alpha_mask_specified = TRUE; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1428,13 +1428,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) return success; } -/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { - addAlphaMask(data, originX, originY, width, height); + addAlphaMask(data, originX, originY, width, height, bound_target); } static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks"); -void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render) +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render) { if (!force_render && !hasMorph()) { @@ -1586,11 +1586,42 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC alpha_data = (U8*)ll_aligned_malloc_32(mem_size); - bool skip_readback = LLRender::sNsightDebugSupport || gGLManager.mIsIntel; // nSight doesn't support use of glReadPixels + bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels if (!skip_readback) { - glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + if (gGLManager.mIsIntel) + { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO + // returning only the alpha portion without locking up downstream + U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA + + if (bound_target) + { + gGL.getTexUnit(0)->bind(bound_target); + } + else + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0); + } + + glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); + + U8* alpha_cursor = alpha_data; + U8* pixel = temp; + for (int i = 0; i < pixels; i++) + { + *alpha_cursor++ = pixel[3]; + pixel += 4; + } + + gGL.getTexUnit(0)->disable(); + + ll_aligned_free_32(temp); + } + else + { // platforms with working drivers... + glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); + } } else { @@ -1600,7 +1631,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC mAlphaCache[cache_index] = alpha_data; } - + getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); mMorphMasksValid = TRUE; @@ -1609,7 +1640,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask"); -void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK); S32 size = width * height; @@ -1621,7 +1652,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 // TODO: eliminate need for layer morph mask valid flag invalidateMorphMasks(); const bool force_render = false; - renderMorphMasks(originX, originY, width, height, net_color, force_render); + renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render); alphaData = getAlphaData(); } if (alphaData) @@ -1755,7 +1786,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return layer; } -/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height) +/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) { if(!mInfo) { @@ -1782,7 +1813,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const { wearable->writeToAvatar(mAvatarAppearance); layer->setLTO(lto); - success &= layer->render(x,y,width,height); + success &= layer->render(x, y, width, height, bound_target); } } @@ -1804,14 +1835,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return success; } -/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { U32 num_wearables = updateWearableCache(); U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable LLTexLayer *layer = getLayer(i); if (layer) { - layer->addAlphaMask(data, originX, originY, width, height); + layer->addAlphaMask(data, originX, originY, width, height, bound_target); } } diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 9318b23fd1..6a5040cf0b 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -65,7 +65,7 @@ public: LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); virtual ~LLTexLayerInterface() {} - virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0; + virtual BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; virtual void deleteCaches() = 0; virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; virtual BOOL isInvisibleAlphaMask() const = 0; @@ -85,7 +85,7 @@ public: BOOL isMorphValid() const { return mMorphMasksValid; } void requestUpdate(); - virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0; + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0; BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } ERenderPass getRenderPass() const; @@ -121,10 +121,10 @@ public: LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); LLTexLayerTemplate(const LLTexLayerTemplate &layer); /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ void setHasMorph(BOOL newval); /*virtual*/ void deleteCaches(); /*virtual*/ BOOL isInvisibleAlphaMask() const; @@ -152,16 +152,16 @@ public: /*virtual*/ ~LLTexLayer(); /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height); + /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ void deleteCaches(); const U8* getAlphaData() const; BOOL findNetColor(LLColor4* color) const; /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); - void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render); - void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height); + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ BOOL isInvisibleAlphaMask() const; void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } @@ -194,13 +194,13 @@ public: const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. virtual void createComposite() = 0; void destroyComposite(); - void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height); + void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target); const LLTexLayerSetInfo* getInfo() const { return mInfo; } BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions - BOOL render(S32 x, S32 y, S32 width, S32 height); - void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false); + BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); + void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); BOOL isBodyRegion(const std::string& region) const; void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); @@ -282,7 +282,7 @@ protected: virtual S32 getCompositeOriginY() const = 0; virtual S32 getCompositeWidth() const = 0; virtual S32 getCompositeHeight() const = 0; - BOOL renderTexLayerSet(); + BOOL renderTexLayerSet(LLRenderTarget* bound_target); LLTexLayerSet* const mTexLayerSet; }; diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index fa9a0712fa..f9b4df679b 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -129,7 +129,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) llassert(mFullHeight <= 512); llassert(mFullWidth <= 512); - if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI) + if (gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete()) { //using offscreen render target, just use the bottom left corner mOrigin.set(0, 0); } @@ -216,11 +216,12 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } - bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI; + bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete(); if (use_fbo) { - gPipeline.mWaterDis.bindTarget(); + gPipeline.mBake.bindTarget(); + gPipeline.mBake.clear(); } LLGLSLShader::bindNoShader(); @@ -240,6 +241,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() gDepthDirty = TRUE; gGL.color4f(1,1,1,1); + dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr); dynamicTexture->preRender(); // Must be called outside of startRender() result = FALSE; if (dynamicTexture->render()) @@ -250,7 +252,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } gGL.flush(); LLVertexBuffer::unbind(); - + dynamicTexture->setBoundTarget(nullptr); dynamicTexture->postRender(result); } } @@ -258,9 +260,11 @@ BOOL LLViewerDynamicTexture::updateAllInstances() if (use_fbo) { - gPipeline.mWaterDis.flush(); + gPipeline.mBake.flush(); } + gGL.flush(); + return ret; } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index f3f57c9a6b..4bd74a8425 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -88,6 +88,9 @@ public: static BOOL updateAllInstances(); static void destroyGL() ; static void restoreGL() ; + + void setBoundTarget(LLRenderTarget* target) { mBoundTarget = target; } + protected: void generateGLTexture(); void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE); @@ -97,6 +100,8 @@ protected: LLCoordGL mOrigin; LL_ALIGN_16(LLCamera mCamera); + LLRenderTarget* mBoundTarget; + typedef std::set instance_list_t; static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; static S32 sNumRenders; diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h index 027ae255ec..dec7f0ddfc 100644 --- a/indra/newview/llviewertexlayer.h +++ b/indra/newview/llviewertexlayer.h @@ -111,7 +111,7 @@ protected: // Pass these along for tex layer rendering. virtual void preRender(BOOL clear_depth) { preRenderTexLayerSet(); } virtual void postRender(BOOL success) { postRenderTexLayerSet(success); } - virtual BOOL render() { return renderTexLayerSet(); } + virtual BOOL render() { return renderTexLayerSet(mBoundTarget); } //-------------------------------------------------------------------- // Updates diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ef88d43cc4..448b65272b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1162,6 +1162,7 @@ void LLPipeline::releaseGLBuffers() mWaterRef.release(); mWaterDis.release(); + mBake.release(); mHighlight.release(); for (U32 i = 0; i < 3; i++) @@ -1225,6 +1226,9 @@ void LLPipeline::createGLBuffers() mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE); } + // Use FBO for bake tex + mBake.allocate(512, 512, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, true); + mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); stop_glerror(); @@ -1395,7 +1399,7 @@ bool LLPipeline::canUseVertexShaders() bool LLPipeline::canUseWindLightShaders() const { return (!LLPipeline::sDisableShaders && - /*gWLSkyProgram.mProgramObject != 0 &&*/ + gWLSkyProgram.mProgramObject != 0 && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index b0c40d145b..cc9ec06f80 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -650,6 +650,8 @@ public: //water distortion texture (refraction) LLRenderTarget mWaterDis; + LLRenderTarget mBake; + //texture for making the glow LLRenderTarget mGlow[3]; -- cgit v1.3