diff options
| author | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2023-08-18 21:47:40 -0700 | 
|---|---|---|
| committer | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2023-08-18 21:47:40 -0700 | 
| commit | d5845fe3e7f3a620453f00421608211d6353905f (patch) | |
| tree | 7821b75dab3be6e87ac0afa7c2f22614adc47a5a | |
| parent | 423820475c7201c39d03c0622dedbf4b1e8b1879 (diff) | |
Latest updates to the hero probe manager.
DRTVWR-583
| -rw-r--r-- | indra/newview/llappviewer.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llheroprobemanager.cpp | 923 | ||||
| -rw-r--r-- | indra/newview/llheroprobemanager.h | 87 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 31 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 2 | 
5 files changed, 75 insertions, 969 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 343778fe03..3b0ba77ea2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1517,6 +1517,7 @@ bool LLAppViewer::doFrame()                      LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot");                      pingMainloopTimeout("Main:Snapshot");                      gPipeline.mReflectionMapManager.update(); +                    gPipeline.mHeroProbeManager.update();                      LLFloaterSnapshot::update(); // take snapshots                      LLFloaterSimpleOutfitSnapshot::update();                      gGLActive = FALSE; diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 54a61d000e..5edf819fff 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -57,55 +57,6 @@ static void touch_default_probe(LLReflectionMap* probe)  LLHeroProbeManager::LLHeroProbeManager()  { -    initCubeFree(); -} - -void LLHeroProbeManager::initCubeFree() -{ -    // start at 1 because index 0 is reserved for mDefaultProbe -    for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) -    { -        mCubeFree.push_back(i); -    } -} - -struct CompareProbeDistance -{ -    LLReflectionMap* mDefaultProbe; - -    bool operator()(const LLPointer<LLReflectionMap>& lhs, const LLPointer<LLReflectionMap>& rhs) -    { -        return lhs->mDistance < rhs->mDistance; -    } -}; - -static F32 update_score(LLReflectionMap* p) -{ -    return gFrameTimeSeconds - p->mLastUpdateTime  - p->mDistance*0.1f; -} - -// return true if a is higher priority for an update than b -static bool check_priority(LLReflectionMap* a, LLReflectionMap* b) -{ -    if (a->mCubeIndex == -1) -    { // not a candidate for updating -        return false; -    } -    else if (b->mCubeIndex == -1) -    { // certainly higher priority than b -        return true; -    } -    else if (!a->mComplete && !b->mComplete) -    { //neither probe is complete, use distance -        return a->mDistance < b->mDistance; -    } -    else if (a->mComplete && b->mComplete) -    { //both probes are complete, use update_score metric -        return update_score(a) > update_score(b); -    } - -    // one of these probes is not complete, if b is complete, a is higher priority -    return b->mComplete;  }  // helper class to seed octree with probes @@ -131,17 +82,10 @@ void LLHeroProbeManager::update()          U32 targetRes = mProbeResolution * 4; // super sample          mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);      } -     -    if (!mHeroRenderTarget.isComplete()) -    { -        U32 color_fmt = GL_RGB16F; -        U32 targetRes = mHeroProbeResolution * 2; -        mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); -    }      if (mMipChain.empty())      { -        U32 res = mHeroProbeResolution; +        U32 res = mProbeResolution;          U32 count = log2((F32)res) + 0.5f;          mMipChain.resize(count); @@ -156,422 +100,22 @@ void LLHeroProbeManager::update()      LLVector4a camera_pos;      camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); - -    // process kill list -    for (auto& probe : mKillList) -    { -        auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe); -        if (iter != mProbes.end()) -        { -            deleteProbe(iter - mProbes.begin()); -        } -    } - -    mKillList.clear(); -    // process create list -    for (auto& probe : mCreateList) -    { -        mProbes.push_back(probe); -    } - -    mCreateList.clear(); - -    if (mProbes.empty()) -    { -        return; -    } - - -    bool did_update = false; -     -    static LLCachedControl<S32> sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); -    static LLCachedControl<S32> sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); - -    bool realtime = sDetail >= (S32)LLHeroProbeManager::DetailLevel::REALTIME; -     -    LLReflectionMap* closestDynamic = nullptr; - -    LLReflectionMap* oldestProbe = nullptr; -    LLReflectionMap* oldestOccluded = nullptr; - -    if (mUpdatingProbe != nullptr) -    { -        did_update = true; -        doProbeUpdate(); -    } - -    // update distance to camera for all probes -    std::sort(mProbes.begin()+1, mProbes.end(), CompareProbeDistance()); -    llassert(mProbes[0] == mDefaultProbe); -    llassert(mProbes[0]->mCubeArray == mTexture); -    llassert(mProbes[0]->mCubeIndex == 0); - -    // make sure we're assigning cube slots to the closest probes +    static LLCachedControl<S32> sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); +    static LLCachedControl<S32> sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); -    // first free any cube indices for distant probes -    for (U32 i = mReflectionProbeCount; i < mProbes.size(); ++i) -    { -        LLReflectionMap* probe = mProbes[i]; -        llassert(probe != nullptr); - -        if (probe->mCubeIndex != -1 && mUpdatingProbe != probe) -        { // free this index -            mCubeFree.push_back(probe->mCubeIndex); - -            probe->mCubeArray = nullptr; -            probe->mCubeIndex = -1; -            probe->mComplete = false; -        } -    } - -    // next distribute the free indices -    U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size()); - -    for (S32 i = 1; i < count && !mCubeFree.empty(); ++i) -    { -        // find the closest probe that needs a cube index -        LLReflectionMap* probe = mProbes[i]; - -        if (probe->mCubeIndex == -1) -        { -            S32 idx = allocateCubeIndex(); -            llassert(idx > 0); //if we're still in this loop, mCubeFree should not be empty and allocateCubeIndex should be returning good indices -            probe->mCubeArray = mTexture; -            probe->mCubeIndex = idx; -        } -    } - -    for (int i = 0; i < mProbes.size(); ++i) -    { -        LLReflectionMap* probe = mProbes[i]; -        if (probe->getNumRefs() == 1) -        { // no references held outside manager, delete this probe -            deleteProbe(i); -            --i; -            continue; -        } -         -        if (probe != mDefaultProbe && !probe->isRelevant()) -        { -            continue; -        } - -        LLVector4a d; - -        if (probe != mDefaultProbe) -        { -            if (probe->mViewerObject) //make sure probes track the viewer objects they are attached to -            { -                probe->mOrigin.load3(probe->mViewerObject->getPositionAgent().mV); -            } -            d.setSub(camera_pos, probe->mOrigin); -            probe->mDistance = d.getLength3().getF32() - probe->mRadius; -        } -        else if (probe->mComplete) -        { -            // make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once) -            probe->mDistance = 64.f; -        } -        else -        { -            probe->mDistance = -4096.f; //boost priority of default probe when it's not complete -        } - -        if (probe->mComplete) -        { -            probe->autoAdjustOrigin(); -            probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f); -        } -        if (probe->mOccluded && probe->mComplete) -        { -            if (oldestOccluded == nullptr) -            { -                oldestOccluded = probe; -            } -            else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime) -            { -                oldestOccluded = probe; -            } -        } -        else -        { -            if (!did_update && -                i < mReflectionProbeCount && -                (oldestProbe == nullptr || -                    check_priority(probe, oldestProbe))) -            { -               oldestProbe = probe; -            } -        } - -        if (realtime &&  -            closestDynamic == nullptr &&  -            probe->mCubeIndex != -1 && -            probe->getIsDynamic()) -        { -            closestDynamic = probe; -        } -    } - -    if (realtime && closestDynamic != nullptr) -    { -        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); -        // update the closest dynamic probe realtime -        // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames -        closestDynamic->autoAdjustOrigin(); - -        // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set  -        // lighting values etc -        bool radiance_pass = isRadiancePass(); -        mRadiancePass = mRealtimeRadiancePass; -        for (U32 i = 0; i < 6; ++i) -        { -            updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); -        } -        mRealtimeRadiancePass = !mRealtimeRadiancePass; - -        // restore "isRadiancePass" -        mRadiancePass = radiance_pass; -    } -     -          {          LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); -        mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); -        bool radiance_pass = isRadiancePass(); -        mRadiancePass = true; -        for (U32 i = 0; i < 6; ++i) -        { -            updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); -        } - -        // restore "isRadiancePass" -        mRadiancePass = radiance_pass; -    } - -    static LLCachedControl<F32> sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); -    if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) -    { -        if (sLevel == 0) -        { // when probes are disabled don't update the default probe more often than the prescribed update period -            oldestProbe = nullptr; -        } -    } -    else if (sLevel > 0) -    { // when probes are enabled don't update the default probe less often than the prescribed update period -      oldestProbe = mDefaultProbe; -    } - -    // switch to updating the next oldest probe -    if (!did_update && oldestProbe != nullptr) -    { -        LLReflectionMap* probe = oldestProbe; -        llassert(probe->mCubeIndex != -1); -         -        probe->autoAdjustOrigin(); - -        mUpdatingProbe = probe; -        doProbeUpdate(); -    } - -    if (oldestOccluded) -    { -        // as far as this occluded probe is concerned, an origin/radius update is as good as a full update -        oldestOccluded->autoAdjustOrigin(); -        oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; -    } -} - -LLReflectionMap* LLHeroProbeManager::addProbe(LLSpatialGroup* group) -{ -    LLReflectionMap* probe = new LLReflectionMap(); -    probe->mGroup = group; - -    if (mDefaultProbe.isNull()) -    {  //safety check to make sure default probe is always first probe added -        mDefaultProbe = new LLReflectionMap(); -        mProbes.push_back(mDefaultProbe); -    } - -    llassert(mProbes[0] == mDefaultProbe); - -    if (group) -    { -        probe->mOrigin = group->getOctreeNode()->getCenter(); -    } - -    if (gCubeSnapshot) -    { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update -        mCreateList.push_back(probe); -    } -    else -    { -        mProbes.push_back(probe); -    } - -    return probe; -} - -struct CompareProbeDepth -{ -    bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) -    { -        return lhs->mMinDepth < rhs->mMinDepth; -    } -}; - -void LLHeroProbeManager::getReflectionMaps(std::vector<LLReflectionMap*>& maps) -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - -    LLMatrix4a modelview; -    modelview.loadu(gGLModelView); -    LLVector4a oa; // scratch space for transformed origin - -    U32 count = 0; -    U32 lastIdx = 0; -    for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i) -    { -        mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested -        if (mProbes[i]->mCubeIndex != -1) +        // Probe 0 is always our mirror probe.  Probe N - 1 is our water probe. +        mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); +        for (U32 j = 0; j < mProbes.size(); j++)          { -            if (!mProbes[i]->mOccluded && mProbes[i]->mComplete) +            for (U32 i = 0; i < 6; ++i)              { -                maps[count++] = mProbes[i]; -                modelview.affineTransform(mProbes[i]->mOrigin, oa); -                mProbes[i]->mMinDepth = -oa.getF32ptr()[2] - mProbes[i]->mRadius; -                mProbes[i]->mMaxDepth = -oa.getF32ptr()[2] + mProbes[i]->mRadius; +                updateProbeFace(mProbes[j], i);              }          } -        else -        { -            mProbes[i]->mProbeIndex = -1; -        } -        lastIdx = i; -    } - -    // set remaining probe indices to -1 -    for (U32 i = lastIdx+1; i < mProbes.size(); ++i) -    { -        mProbes[i]->mProbeIndex = -1; -    } - -    if (count > 1) -    { -        std::sort(maps.begin(), maps.begin() + count, CompareProbeDepth()); -    } - -    for (U32 i = 0; i < count; ++i) -    { -        maps[i]->mProbeIndex = i; -    } - -    // null terminate list -    if (count < maps.size()) -    { -        maps[count] = nullptr; -    } -} - -LLReflectionMap* LLHeroProbeManager::registerSpatialGroup(LLSpatialGroup* group) -{ -    if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) -    { -        OctreeNode* node = group->getOctreeNode(); -        F32 size = node->getSize().getF32ptr()[0]; -        if (size >= 15.f && size <= 17.f) -        { -            return addProbe(group); -        } -    } - -    return nullptr; -} - -LLReflectionMap* LLHeroProbeManager::registerViewerObject(LLViewerObject* vobj) -{ -    llassert(vobj != nullptr); - -    LLReflectionMap* probe = new LLReflectionMap(); -    probe->mViewerObject = vobj; -    probe->mOrigin.load3(vobj->getPositionAgent().mV); - -    if (gCubeSnapshot) -    { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update -        mCreateList.push_back(probe); -    } -    else -    { -        mProbes.push_back(probe); -    } - -    return probe; -} - -S32 LLHeroProbeManager::allocateCubeIndex() -{ -    if (!mCubeFree.empty()) -    { -        S32 ret = mCubeFree.front(); -        mCubeFree.pop_front(); -        return ret; -    } - -    return -1; -} - -void LLHeroProbeManager::deleteProbe(U32 i) -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; -    LLReflectionMap* probe = mProbes[i]; - -    llassert(probe != mDefaultProbe); - -    if (probe->mCubeIndex != -1) -    { // mark the cube index used by this probe as being free -        mCubeFree.push_back(probe->mCubeIndex); -    } -    if (mUpdatingProbe == probe) -    { -        mUpdatingProbe = nullptr; -        mUpdatingFace = 0; -    } - -    // remove from any Neighbors lists -    for (auto& other : probe->mNeighbors) -    { -        auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); -        llassert(iter != other->mNeighbors.end()); -        other->mNeighbors.erase(iter); -    } - -    mProbes.erase(mProbes.begin() + i); -} - - -void LLHeroProbeManager::doProbeUpdate() -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; -    llassert(mUpdatingProbe != nullptr); - -    updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); -     -    if (++mUpdatingFace == 6) -    { -        updateNeighbors(mUpdatingProbe); -        mUpdatingFace = 0; -        if (isRadiancePass()) -        { -            mUpdatingProbe->mComplete = true; -            mUpdatingProbe = nullptr; -            mRadiancePass = false; -        } -        else -        { -            mRadiancePass = true; -        }      }  } @@ -583,53 +127,36 @@ void LLHeroProbeManager::doProbeUpdate()  // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.  // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe.  // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer<LLCubeMapArray> cubeArray, std::vector<LLRenderTarget> &mipChain, U32 probeCount) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face)  {      // hacky hot-swap of camera specific render targets      gPipeline.mRT = &gPipeline.mAuxillaryRT; -     -    LLRenderTarget* target = &mRenderTarget; -     -    S32 sourceIdx = probeCount; -     -    if (probeResolution == mHeroProbeResolution) -    { -        sourceIdx = 0; -        target = &mHeroRenderTarget; -    }      mLightScale = 1.f;      static LLCachedControl<F32> max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); -    if (!isRadiancePass() && probe->getAmbiance() > max_local_light_ambiance) +    if (probe->getAmbiance() > max_local_light_ambiance)      {          mLightScale = max_local_light_ambiance / probe->getAmbiance();      } -    if (probe == mDefaultProbe)      { -        touch_default_probe(probe); -          gPipeline.pushRenderTypeMask();          //only render sky, water, terrain, and clouds          gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, -            LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); +            LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::END_RENDER_TYPES); -        probe->update(target->getWidth(), face); +        probe->update(mRenderTarget.getWidth(), face);          gPipeline.popRenderTypeMask();      } -    else -    { -        probe->update(target->getWidth(), face); -    }      gPipeline.mRT = &gPipeline.mMainRT; -    if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) -    { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel -        sourceIdx += 1; -    } +    S32 sourceIdx = mReflectionProbeCount; + +    // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. +    sourceIdx += 1;      gGL.setColorMask(true, true);      LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -647,7 +174,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p          gGL.loadIdentity();          gGL.flush(); -        U32 res = probeResolution * 2; +        U32 res = mProbeResolution * 2;          static LLStaticHashedString resScale("resScale");          static LLStaticHashedString direction("direction"); @@ -659,20 +186,20 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p          // perform a gaussian blur on the super sampled render before downsampling          {              gGaussianProgram.bind(); -            gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); +            gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2));              S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);              // horizontal              gGaussianProgram.uniform2f(direction, 1.f, 0.f);              gGL.getTexUnit(diffuseChannel)->bind(screen_rt); -            target->bindTarget(); +            mRenderTarget.bindTarget();              gPipeline.mScreenTriangleVB->setBuffer();              gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); -            target->flush(); +            mRenderTarget.flush();              // vertical              gGaussianProgram.uniform2f(direction, 0.f, 1.f); -            gGL.getTexUnit(diffuseChannel)->bind(target); +            gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);              screen_rt->bindTarget();              gPipeline.mScreenTriangleVB->setBuffer();              gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -680,7 +207,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p          } -        S32 mips = log2((F32)probeResolution) + 0.5f; +        S32 mips = log2((F32)mProbeResolution) + 0.5f;          gReflectionMipProgram.bind();          S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); @@ -699,7 +226,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p              } -            gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); +            gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));              gPipeline.mScreenTriangleVB->setBuffer();              gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -711,11 +238,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p              if (mip >= 0)              {                  LL_PROFILE_GPU_ZONE("probe mip copy"); -                cubeArray->bind(0); -                 +                mTexture->bind(0); +                //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);                  glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); -                 -                cubeArray->unbind(); +                //if (i == 0) +                //{ +                    //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); +                //} +                mTexture->unbind();              }              mMipChain[i].flush();          } @@ -733,14 +263,13 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p          mMipChain[0].bindTarget();          static LLStaticHashedString sSourceIdx("sourceIdx"); -        if (isRadiancePass())          {              //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)              gRadianceGenProgram.bind();              mVertexBuffer->setBuffer();              S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); -            cubeArray->bind(channel); +            mTexture->bind(channel);              gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);              gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -755,7 +284,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p                  gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));                  gRadianceGenProgram.uniform1f(sMipLevel, i); -                gRadianceGenProgram.uniform1i(sWidth, probeResolution); +                gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);                  for (int cf = 0; cf < 6; ++cf)                  { // for each cube face @@ -780,50 +309,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p              gRadianceGenProgram.unbind();          } -        else -        { -            //generate irradiance map -            gIrradianceGenProgram.bind(); -            S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); -            cubeArray->bind(channel); - -            gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); -            gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); -             -            mVertexBuffer->setBuffer(); -            int start_mip = 0; -            // find the mip target to start with based on irradiance map resolution -            for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) -            { -                if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) -                { -                    break; -                } -            } - -            //for (int i = start_mip; i < mMipChain.size(); ++i) -            { -                int i = start_mip; -                LL_PROFILE_GPU_ZONE("probe irradiance gen"); -                glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); -                for (int cf = 0; cf < 6; ++cf) -                { // for each cube face -                    LLCoordFrame frame; -                    frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); - -                    F32 mat[16]; -                    frame.getOpenGLRotation(mat); -                    gGL.loadMatrix(mat); - -                    mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); - -                    S32 res = mMipChain[i].getWidth(); -                    mIrradianceMaps->bind(channel); -                    glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); -                    cubeArray->bind(channel); -                } -            } -        }          mMipChain[0].flush(); @@ -831,59 +316,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p      }  } -void LLHeroProbeManager::reset() -{ -    mReset = true; -} - -void LLHeroProbeManager::shift(const LLVector4a& offset) -{ -    for (auto& probe : mProbes) -    { -        probe->mOrigin.add(offset); -    } -} - -void LLHeroProbeManager::updateNeighbors(LLReflectionMap* probe) -{ -    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; -    if (mDefaultProbe == probe) -    { -        return; -    } - -    //remove from existing neighbors -    { -        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear"); -     -        for (auto& other : probe->mNeighbors) -        { -            auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); -            llassert(iter != other->mNeighbors.end()); // <--- bug davep if this ever happens, something broke badly -            other->mNeighbors.erase(iter); -        } - -        probe->mNeighbors.clear(); -    } - -    // search for new neighbors -    if (probe->isRelevant()) -    { -        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search"); -        for (auto& other : mProbes) -        { -            if (other != mDefaultProbe && other != probe) -            { -                if (other->isRelevant() && probe->intersects(other)) -                { -                    probe->mNeighbors.push_back(other); -                    other->mNeighbors.push_back(probe); -                } -            } -        } -    } -} -  void LLHeroProbeManager::updateUniforms()  {      if (!LLPipeline::sReflectionProbesEnabled) @@ -892,229 +324,6 @@ void LLHeroProbeManager::updateUniforms()      }      LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - -    // structure for packing uniform buffer object -    // see class3/deferred/reflectionProbeF.glsl -    struct ReflectionProbeData -    { -        // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of  -        // the box probe -        LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];  - -        // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space -        LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];  - -        // extra parameters  -        //  x - irradiance scale -        //  y - radiance scale -        //  z - fade in -        //  w - znear -        LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; - -        // indices used by probe: -        //  [i][0] - cubemap array index for this probe -        //  [i][1] - index into "refNeighbor" for probes that intersect this probe -        //  [i][2] - number of probes  that intersect this probe, or -1 for no neighbors -        //  [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) -        GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];  - -        // list of neighbor indices -        GLint refNeighbor[4096];  - -        GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth -        // numbrer of active refmaps -        GLint refmapCount; -    }; - -    mReflectionMaps.resize(mReflectionProbeCount); -    getReflectionMaps(mReflectionMaps); - -    ReflectionProbeData rpd; - -    F32 minDepth[256]; - -    for (int i = 0; i < 256; ++i) -    { -        rpd.refBucket[i][0] = mReflectionProbeCount; -        rpd.refBucket[i][1] = mReflectionProbeCount; -        rpd.refBucket[i][2] = mReflectionProbeCount; -        rpd.refBucket[i][3] = mReflectionProbeCount; -        minDepth[i] = FLT_MAX; -    } - -    // load modelview matrix into matrix 4a -    LLMatrix4a modelview; -    modelview.loadu(gGLModelView); -    LLVector4a oa; // scratch space for transformed origin - -    S32 count = 0; -    U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors - -    LLEnvironment& environment = LLEnvironment::instance(); -    LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - -    static LLCachedControl<F32> cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); -    static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); -    F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, should_auto_adjust); - -    bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass(); -    F32 ambscale = is_ambiance_pass ? 0.f : 1.f; -    F32 radscale = is_ambiance_pass ? 0.5f : 1.f; -     -    for (auto* refmap : mReflectionMaps) -    { -        if (refmap == nullptr) -        { -            break; -        } - -        if (refmap != mDefaultProbe) -        { -            // bucket search data -            // theory of operation: -            //      1. Determine minimum and maximum depth of each influence volume and store in mDepth (done in getReflectionMaps) -            //      2. Sort by minimum depth -            //      3. Prepare a bucket for each 1m of depth out to 256m -            //      4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket -            //      5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence -            //          the current pixel. -            int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255); -            int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255); -            for (U32 i = depth_min; i <= depth_max; ++i) -            { -                if (refmap->mMinDepth < minDepth[i]) -                { -                    minDepth[i] = refmap->mMinDepth; -                    rpd.refBucket[i][0] = refmap->mProbeIndex; -                } -            } -        } - -        llassert(refmap->mProbeIndex == count); -        llassert(mReflectionMaps[refmap->mProbeIndex] == refmap); - -        llassert(refmap->mCubeIndex >= 0); // should always be  true, if not, getReflectionMaps is bugged - -        { -            if (refmap->mViewerObject) -            { // have active manual probes live-track the object they're associated with -                refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV); -                refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f; - -            } -            modelview.affineTransform(refmap->mOrigin, oa); -            rpd.refSphere[count].set(oa.getF32ptr()); -            rpd.refSphere[count].mV[3] = refmap->mRadius; -        } - -        rpd.refIndex[count][0] = refmap->mCubeIndex; -        llassert(nc % 4 == 0); -        rpd.refIndex[count][1] = nc / 4; -        rpd.refIndex[count][3] = refmap->mPriority; - -        // for objects that are reflection probes, use the volume as the influence volume of the probe -        // only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres -        if (refmap->getBox(rpd.refBox[count])) -        { // negate priority to indicate this probe has a box influence volume -            rpd.refIndex[count][3] = -rpd.refIndex[count][3]; -        } - -        rpd.refParams[count].set( -            llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale -            radscale, // radiance scale -            refmap->mFadeIn, // fade in weight -            oa.getF32ptr()[2] - refmap->mRadius); // z near - -        S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors -        { -            //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors"); -            //pack neghbor list -            const U32 max_neighbors = 64; -            U32 neighbor_count = 0; - -            for (auto& neighbor : refmap->mNeighbors) -            { -                if (ni >= 4096) -                { // out of space -                    break; -                } - -                GLint idx = neighbor->mProbeIndex; -                if (idx == -1 || neighbor->mOccluded || neighbor->mCubeIndex == -1) -                { -                    continue; -                } - -                // this neighbor may be sampled -                rpd.refNeighbor[ni++] = idx; - -                neighbor_count++; -                if (neighbor_count >= max_neighbors) -                { -                    break; -                } -            } -        } - -        if (nc == ni) -        { -            //no neighbors, tag as empty -            rpd.refIndex[count][1] = -1; -        } -        else -        { -            rpd.refIndex[count][2] = ni - nc; - -            // move the cursor forward -            nc = ni; -            if (nc % 4 != 0) -            { // jump to next power of 4 for compatibility with ivec4 -                nc += 4 - (nc % 4); -            } -        } - - -        count++; -    } - -#if 0 -    { -        // fill in gaps in refBucket -        S32 probe_idx = mReflectionProbeCount; -         -        for (int i = 0; i < 256; ++i) -        { -            if (i < count) -            { // for debugging, store depth of mReflectionsMaps[i] -                rpd.refBucket[i][1] = (S32) (mReflectionMaps[i]->mDepth * 10); -            } - -            if (rpd.refBucket[i][0] == mReflectionProbeCount) -            { -                rpd.refBucket[i][0] = probe_idx; -            } -            else -            { -                probe_idx = rpd.refBucket[i][0]; -            } -        } -    } -#endif - -    rpd.refmapCount = count; -     -    //copy rpd into uniform buffer object -    if (mUBO == 0) -    { -        glGenBuffers(1, &mUBO); -    } - -    { -        LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); -        glBindBuffer(GL_UNIFORM_BUFFER, mUBO); -        glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); -        glBindBuffer(GL_UNIFORM_BUFFER, 0); -    }      struct HeroProbeData      { @@ -1124,22 +333,23 @@ void LLHeroProbeManager::updateUniforms()      HeroProbeData hpd; +    LLMatrix4a modelview;      modelview.loadu(gGLModelView); -     +    LLVector4a oa; // scratch space for transformed origin      oa.set(0, 0, 0, 0);      hpd.heroProbeCount = 1; -    modelview.affineTransform(mHeroProbe->mOrigin, oa); +    modelview.affineTransform(mProbes[0]->mOrigin, oa);      hpd.heroPosition[0].set(oa.getF32ptr());      //copy rpd into uniform buffer object      if (mUBO == 0)      { -        glGenBuffers(1, &mHeroUBO); +        glGenBuffers(1, &mUBO);      }      {          LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); -        glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); +        glBindBuffer(GL_UNIFORM_BUFFER, mUBO);          glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW);          glBindBuffer(GL_UNIFORM_BUFFER, 0);      } @@ -1190,11 +400,11 @@ void LLHeroProbeManager::initReflectionMaps()  {      U32 count = LL_MAX_REFLECTION_PROBE_COUNT; -    if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) +    if (mTexture.isNull() || mReflectionProbeCount != count || mReset)      {          mReset = false;          mReflectionProbeCount = count; -        mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); +        mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderHeroProbeResolution"), (U32)128, (U32)1024));          mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1          mTexture = new LLCubeMapArray(); @@ -1205,25 +415,6 @@ void LLHeroProbeManager::initReflectionMaps()          mIrradianceMaps = new LLCubeMapArray();          mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); -        // reset probe state -        mUpdatingFace = 0; -        mUpdatingProbe = nullptr; -        mRadiancePass = false; -        mRealtimeRadiancePass = false; - -        for (auto& probe : mProbes) -        { -            probe->mLastUpdateTime = 0.f; -            probe->mComplete = false; -            probe->mProbeIndex = -1; -            probe->mCubeArray = nullptr; -            probe->mCubeIndex = -1; -            probe->mNeighbors.clear(); -        } - -        mCubeFree.clear(); -        initCubeFree(); -          if (mDefaultProbe.isNull())          {              llassert(mProbes.empty()); // default probe MUST be the first probe created @@ -1233,6 +424,8 @@ void LLHeroProbeManager::initReflectionMaps()          llassert(mProbes[0] == mDefaultProbe); +        // For hero probes, we treat this as the main mirror probe. +                  mDefaultProbe->mCubeIndex = 0;          mDefaultProbe->mCubeArray = mTexture;          mDefaultProbe->mDistance = 64.f; @@ -1240,27 +433,7 @@ void LLHeroProbeManager::initReflectionMaps()          mDefaultProbe->mProbeIndex = 0;          touch_default_probe(mDefaultProbe); -        mHeroProbeResolution = 128; -         -        // Revise when we have both water and mirrors in hero probes. -        mHeroProbeCount = 1; -         -        mHeroArray = new LLCubeMapArray(); -         -        // We use an extra probe for scratch space on these. -        mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); -         -        if (mHeroProbe.isNull()) { -            mHeroProbe = new LLReflectionMap(); -        } -         -        mHeroProbe->mCubeIndex = 0; -        mHeroProbe->mCubeArray = mHeroArray; -        mHeroProbe->mDistance = 64.f; -        mHeroProbe->mRadius = 4096.f; -        mHeroProbe->mProbeIndex = 0; -        touch_default_probe(mHeroProbe); - +        mProbes.push_back(mDefaultProbe);      }      if (mVertexBuffer.isNull()) @@ -1294,28 +467,16 @@ void LLHeroProbeManager::cleanup()      mTexture = nullptr;      mIrradianceMaps = nullptr; -    mHeroArray = nullptr;      mProbes.clear(); -    mKillList.clear(); -    mCreateList.clear();      mReflectionMaps.clear(); -    mUpdatingFace = 0;      mDefaultProbe = nullptr;      mUpdatingProbe = nullptr; -     -    mHeroProbe = nullptr;      glDeleteBuffers(1, &mUBO);      mUBO = 0; -     -    glDeleteBuffers(1, &mHeroUBO); -    mHeroUBO = 0; - -    // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state -    initCubeFree();  }  void LLHeroProbeManager::doOcclusion() diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index be761a680e..95e3963d1a 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -35,13 +35,7 @@ class LLSpatialGroup;  class LLViewerObject;  // number of reflection probes to keep in vram -#define LL_MAX_REFLECTION_PROBE_COUNT 256 - -// reflection probe resolution -#define LL_IRRADIANCE_MAP_RESOLUTION 64 - -// reflection probe mininum scale -#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; +#define LL_MAX_HERO_PROBE_COUNT 2  class alignas(16) LLHeroProbeManager  { @@ -63,30 +57,6 @@ public:      // maintain reflection probes      void update(); -    // add a probe for the given spatial group -    LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr); -     -    // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size() -    // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr. -    //  maps -- presized array of Reflection Map pointers -    void getReflectionMaps(std::vector<LLReflectionMap*>& maps); - -    // called by LLSpatialGroup constructor -    // If spatial group should receive a Reflection Probe, will create one for the specified spatial group -    LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group); - -    // presently hacked into LLViewerObject::setTE -    // Used by LLViewerObjects that are Reflection Probes -    // vobj must not be null -    // Guaranteed to not return null -    LLReflectionMap* registerViewerObject(LLViewerObject* vobj); - -    // reset all state on the next update -    void reset(); - -    // called on region crossing to "shift" probes into new coordinate frame -    void shift(const LLVector4a& offset); -      // debug display, called from llspatialpartition if reflection      // probe debug display is active      void renderDebug(); @@ -94,28 +64,12 @@ public:      // call once at startup to allocate cubemap arrays      void initReflectionMaps(); -    // True if currently updating a radiance map, false if currently updating an irradiance map -    bool isRadiancePass() { return mRadiancePass; } -      // perform occlusion culling on all active reflection probes      void doOcclusion();  private:      friend class LLPipeline; - -    // initialize mCubeFree array to default values -    void initCubeFree(); - -    // delete the probe with the given index in mProbes -    void deleteProbe(U32 i); - -    // get a free cube index -    // returns -1 if allocation failed -    S32 allocateCubeIndex(); - -    // update the neighbors of the given probe  -    void updateNeighbors(LLReflectionMap* probe); - +          // update UBO used for rendering (call only once per render pipe flush)      void updateUniforms(); @@ -132,8 +86,6 @@ private:      // storage for reflection probe radiance maps (plus two scratch space cubemaps)      LLPointer<LLCubeMapArray> mTexture; -     -    LLPointer<LLCubeMapArray> mHeroArray;      // vertex buffer for pushing verts to filter shaders      LLPointer<LLVertexBuffer> mVertexBuffer; @@ -141,61 +93,28 @@ private:      // storage for reflection probe irradiance maps      LLPointer<LLCubeMapArray> mIrradianceMaps; -    // list of free cubemap indices -    std::list<S32> mCubeFree; - -    // perform an update on the currently updating Probe -    void doProbeUpdate(); -      // update the specified face of the specified probe -    void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer<LLCubeMapArray> cubeArray, std::vector<LLRenderTarget> &mipChain, U32 probeCount); +    void updateProbeFace(LLReflectionMap* probe, U32 face);      // list of active reflection maps      std::vector<LLPointer<LLReflectionMap> > mProbes; -    // list of reflection maps to kill -    std::vector<LLPointer<LLReflectionMap> > mKillList; - -    // list of reflection maps to create -    std::vector<LLPointer<LLReflectionMap> > mCreateList; -      // handle to UBO      U32 mUBO = 0; -     -    // Hero UBO -    U32 mHeroUBO = 0;      // list of maps being used for rendering      std::vector<LLReflectionMap*> mReflectionMaps;      LLReflectionMap* mUpdatingProbe = nullptr; -    U32 mUpdatingFace = 0; - -    // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map. -    // Update sequence should be to generate the irradiance map from render of the world that has no irradiance, -    // then generate the radiance map from a render of the world that includes irradiance. -    // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment. -    bool mRadiancePass = false; - -    // same as above, but for the realtime probe. -    // Realtime probes should update all six sides of the irradiance map on "odd" frames and all six sides of the -    // radiance map on "even" frames. -    bool mRealtimeRadiancePass = false;      LLPointer<LLReflectionMap> mDefaultProbe;  // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) -     -    LLPointer<LLReflectionMap> mHeroProbe;      // number of reflection probes to use for rendering      U32 mReflectionProbeCount; -     -    U32 mHeroProbeCount;      // resolution of reflection probes      U32 mProbeResolution = 128; -    U32 mHeroProbeResolution = 512; -      // maximum LoD of reflection probes (mip levels - 1)      F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 909c0f9aaa..4c951a9dea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -642,6 +642,7 @@ void LLPipeline::cleanup()  	mCubeVB = NULL;      mReflectionMapManager.cleanup(); +    mHeroProbeManager.cleanup();  }  //============================================================================ @@ -772,6 +773,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)      { // hacky -- allocate auxillary buffer          gCubeSnapshot = TRUE;          mReflectionMapManager.initReflectionMaps(); +        mHeroProbeManager.initReflectionMaps();          mRT = &mAuxillaryRT;          U32 res = mReflectionMapManager.mProbeResolution * 4;  //multiply by 4 because probes will be 16x super sampled          allocateScreenBuffer(res, res, samples); @@ -2441,6 +2443,26 @@ void LLPipeline::doOcclusion(LLCamera& camera)          gGL.setColorMask(true, true);      } +     +    if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) +    { +        gGL.setColorMask(false, false); +        LLGLDepthTest depth(GL_TRUE, GL_FALSE); +        LLGLDisable cull(GL_CULL_FACE); + +        gOcclusionCubeProgram.bind(); + +        if (mCubeVB.isNull()) +        { //cube VB will be used for issuing occlusion queries +            mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); +        } +        mCubeVB->setBuffer(); + +        mHeroProbeManager.doOcclusion(); +        gOcclusionCubeProgram.unbind(); + +        gGL.setColorMask(true, true); +    }      if (LLPipeline::sUseOcclusion > 1 &&  		(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) @@ -3809,6 +3831,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)          {              //update reflection probe uniform              mReflectionMapManager.updateUniforms(); +            mHeroProbeManager.updateUniforms();          }  		U32 cur_type = 0; @@ -8461,14 +8484,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)          mReflectionMapManager.mIrradianceMaps->bind(channel);          bound = true;      } -    /* +          channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); -    if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) +    if (channel > -1 && mHeroProbeManager.mTexture.notNull())      { -        mReflectionMapManager.mHeroArray->bind(channel); +        mHeroProbeManager.mTexture->bind(channel);          bound = true;      } -     */ +           if (bound)      { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index f3b35e0325..bfb9b95f4d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -39,6 +39,7 @@  #include "lldrawable.h"  #include "llrendertarget.h"  #include "llreflectionmapmanager.h" +#include "llheroprobemanager.h"  #include <stack> @@ -454,6 +455,7 @@ public:      void handleShadowDetailChanged();      LLReflectionMapManager mReflectionMapManager; +    LLHeroProbeManager mHeroProbeManager;  private:  	void unloadShaders();  | 
