diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index e8e4b62934..a8dad89292 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -98,6 +98,29 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs) return *this; } +bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const +{ + return mBaseColorId == rhs.mBaseColorId && + mNormalId == rhs.mNormalId && + mMetallicRoughnessId == rhs.mMetallicRoughnessId && + mEmissiveId == rhs.mEmissiveId && + + mBaseColor == rhs.mBaseColor && + mEmissiveColor == rhs.mEmissiveColor && + + mMetallicFactor == rhs.mMetallicFactor && + mRoughnessFactor == rhs.mRoughnessFactor && + mAlphaCutoff == rhs.mAlphaCutoff && + + mDoubleSided == rhs.mDoubleSided && + mAlphaMode == rhs.mAlphaMode && + + mTextureTransform == rhs.mTextureTransform && + + mOverrideDoubleSided == rhs.mOverrideDoubleSided && + mOverrideAlphaMode == rhs.mOverrideAlphaMode; +} + bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg) { LL_PROFILE_ZONE_SCOPED; @@ -365,6 +388,28 @@ void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, Tex texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map); } +bool LLGLTFMaterial::setBaseMaterial() +{ + const LLGLTFMaterial old_override = *this; + *this = sDefault; + setBaseMaterial(old_override); + return *this != old_override; +} + +bool LLGLTFMaterial::isClearedForBaseMaterial() +{ + LLGLTFMaterial cleared_override = sDefault; + cleared_override.setBaseMaterial(*this); + return *this == cleared_override; +} + +// For material overrides only. Copies transforms from the old override. +void LLGLTFMaterial::setBaseMaterial(const LLGLTFMaterial& old_override_mat) +{ + mTextureTransform = old_override_mat.mTextureTransform; +} + + // static void LLGLTFMaterial::hackOverrideUUID(LLUUID& id) { @@ -646,11 +691,6 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) mTextureTransform[i].mScale = override_mat.mTextureTransform[i].mScale; } - if (override_mat.mTextureTransform[i].mScale != getDefaultTextureScale()) - { - mTextureTransform[i].mScale = override_mat.mTextureTransform[i].mScale; - } - if (override_mat.mTextureTransform[i].mRotation != getDefaultTextureRotation()) { mTextureTransform[i].mRotation = override_mat.mTextureTransform[i].mRotation; diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index aa49a58f0c..dec7b696f8 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -71,6 +71,8 @@ public: LLGLTFMaterial(const LLGLTFMaterial& rhs); LLGLTFMaterial& operator=(const LLGLTFMaterial& rhs); + bool operator==(const LLGLTFMaterial& rhs) const; + bool operator!=(const LLGLTFMaterial& rhs) const { return !(*this == rhs); } LLUUID mBaseColorId; LLUUID mNormalId; @@ -101,7 +103,6 @@ public: md5.finalize(); LLUUID id; md5.raw_digest(id.mData); - // *TODO: Hash the overrides return id; } @@ -181,6 +182,12 @@ public: void applyOverride(const LLGLTFMaterial& override_mat); + // For material overrides only. Clears most properties to + // default/fallthrough, but preserves the transforms. + bool setBaseMaterial(); + // True if setBaseMaterial() was just called + bool isClearedForBaseMaterial(); + private: template @@ -188,5 +195,7 @@ private: template void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const; + + void setBaseMaterial(const LLGLTFMaterial& old_override_mat); }; diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index a0d5793dcc..49f67918f8 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -514,15 +514,15 @@ S32 LLTextureEntry::setBumpShiny(U8 bump_shiny) return TEM_CHANGE_NONE; } -void LLTextureEntry::setGLTFMaterial(LLGLTFMaterial* material) +void LLTextureEntry::setGLTFMaterial(LLGLTFMaterial* material, bool local_origin) { if (material != getGLTFMaterial()) { // assert on precondtion: - // whether or not mGLTFMaterial is null, any existing override should have been nulled out + // whether or not mGLTFMaterial is null, any existing override should have been cleared // before calling setGLTFMaterial // NOTE: if you're hitting this assert, try to make sure calling code is using LLViewerObject::setRenderMaterialID - llassert(getGLTFMaterialOverride() == nullptr); + llassert(!local_origin || getGLTFMaterialOverride() == nullptr || getGLTFMaterialOverride()->isClearedForBaseMaterial()); mGLTFMaterial = material; if (mGLTFMaterial == nullptr) @@ -538,6 +538,27 @@ void LLTextureEntry::setGLTFMaterialOverride(LLGLTFMaterial* mat) mGLTFMaterialOverrides = mat; } +S32 LLTextureEntry::setBaseMaterial() +{ + S32 changed = TEM_CHANGE_NONE; + + if (mGLTFMaterialOverrides) + { + if (mGLTFMaterialOverrides->setBaseMaterial()) + { + changed = TEM_CHANGE_TEXTURE; + } + + if (LLGLTFMaterial::sDefault == *mGLTFMaterialOverrides) + { + mGLTFMaterialOverrides = nullptr; + changed = TEM_CHANGE_TEXTURE; + } + } + + return changed; +} + LLGLTFMaterial* LLTextureEntry::getGLTFRenderMaterial() const { if (mGLTFRenderMaterial.notNull()) @@ -545,7 +566,7 @@ LLGLTFMaterial* LLTextureEntry::getGLTFRenderMaterial() const return mGLTFRenderMaterial; } - llassert(getGLTFMaterialOverride() == nullptr); + llassert(getGLTFMaterialOverride() == nullptr || getGLTFMaterialOverride()->isClearedForBaseMaterial()); return getGLTFMaterial(); } diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index d94e14bd73..9a81181f3a 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -195,12 +195,16 @@ public: enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 }; // GLTF asset - void setGLTFMaterial(LLGLTFMaterial* material); + void setGLTFMaterial(LLGLTFMaterial* material, bool local_origin = true); LLGLTFMaterial* getGLTFMaterial() const { return mGLTFMaterial; } // GLTF override LLGLTFMaterial* getGLTFMaterialOverride() const { return mGLTFMaterialOverrides; } void setGLTFMaterialOverride(LLGLTFMaterial* mat); + // Clear most overrides so the render material better matches the material + // ID (preserve transforms). If the overrides become passthrough, set the + // overrides to nullptr. + S32 setBaseMaterial(); // GLTF render material // nuanced behavior here -- if there is no render material, fall back to getGLTFMaterial, but ONLY for the getter, not the setter diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 87417230ce..0aad5d1dda 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2416,7 +2416,7 @@ void LLGLState::checkStates(const std::string& msg) BOOL error = FALSE; - if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) + /*if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) { if (gDebugSession) { @@ -2427,7 +2427,7 @@ void LLGLState::checkStates(const std::string& msg) { LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; } - } + }*/ for (boost::unordered_map::iterator iter = sStateMap.begin(); iter != sStateMap.end(); ++iter) diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index befd034120..a5740051f5 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llglslshader.cpp * @brief GLSL helper functions and state. * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -37,8 +37,8 @@ #include "OpenGL/OpenGL.h" #endif -// Print-print list of shader included source files that are linked together via glAttachShader() -// i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state. + // Print-print list of shader included source files that are linked together via glAttachShader() + // i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state. #define DEBUG_SHADER_INCLUDES 0 // Lots of STL stuff in here, using namespace std to keep things more readable @@ -55,24 +55,24 @@ std::set LLGLSLShader::sInstances; U64 LLGLSLShader::sTotalTimeElapsed = 0; U32 LLGLSLShader::sTotalTrianglesDrawn = 0; U64 LLGLSLShader::sTotalSamplesDrawn = 0; -U32 LLGLSLShader::sTotalDrawCalls = 0; +U32 LLGLSLShader::sTotalBinds = 0; //UI shader -- declared here so llui_libtest will link properly LLGLSLShader gUIProgram; LLGLSLShader gSolidColorProgram; // NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync! -const std::string gShaderConstsKey[ LLGLSLShader::NUM_SHADER_CONSTS ] = +const std::string gShaderConstsKey[LLGLSLShader::NUM_SHADER_CONSTS] = { - "LL_SHADER_CONST_CLOUD_MOON_DEPTH" - , "LL_SHADER_CONST_STAR_DEPTH" + "LL_SHADER_CONST_CLOUD_MOON_DEPTH" + , "LL_SHADER_CONST_STAR_DEPTH" }; // NOTE: Keep gShaderConsts* and LLGLSLShader::ShaderConsts_e in sync! -const std::string gShaderConstsVal[ LLGLSLShader::NUM_SHADER_CONSTS ] = +const std::string gShaderConstsVal[LLGLSLShader::NUM_SHADER_CONSTS] = { - "0.99998" // SHADER_CONST_CLOUD_MOON_DEPTH // SL-14113 - , "0.99999" // SHADER_CONST_STAR_DEPTH // SL-14113 + "0.99998" // SHADER_CONST_CLOUD_MOON_DEPTH // SL-14113 + , "0.99999" // SHADER_CONST_STAR_DEPTH // SL-14113 }; @@ -121,7 +121,7 @@ void LLGLSLShader::initProfile() sTotalTimeElapsed = 0; sTotalTrianglesDrawn = 0; sTotalSamplesDrawn = 0; - sTotalDrawCalls = 0; + sTotalBinds = 0; for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) { @@ -132,10 +132,10 @@ void LLGLSLShader::initProfile() struct LLGLSLShaderCompareTimeElapsed { - bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) - { - return lhs->mTimeElapsed < rhs->mTimeElapsed; - } + bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) + { + return lhs->mTimeElapsed < rhs->mTimeElapsed; + } }; //static @@ -158,11 +158,11 @@ void LLGLSLShader::finishProfile(bool emit_report) { (*iter)->dumpStats(); } - - LL_INFOS() << "-----------------------------------" << LL_ENDL; - LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL; - LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL; - LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL; + + LL_INFOS() << "-----------------------------------" << LL_ENDL; + LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL; + LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL; + LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL; } } @@ -171,15 +171,12 @@ void LLGLSLShader::clearStats() mTrianglesDrawn = 0; mTimeElapsed = 0; mSamplesDrawn = 0; - mDrawCalls = 0; - mTextureStateFetched = false; - mTextureMagFilter.clear(); - mTextureMinFilter.clear(); + mBinds = 0; } void LLGLSLShader::dumpStats() { - if (mDrawCalls > 0) + if (mBinds > 0) { LL_INFOS() << "=============================================" << LL_ENDL; LL_INFOS() << mName << LL_ENDL; @@ -187,36 +184,25 @@ void LLGLSLShader::dumpStats() { LL_INFOS() << mShaderFiles[i].first << LL_ENDL; } - for (U32 i = 0; i < mTexture.size(); ++i) - { - GLint idx = mTexture[i]; - - if (idx >= 0) - { - GLint uniform_idx = getUniformLocation(i); - LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL; - } - } LL_INFOS() << "=============================================" << LL_ENDL; - - F32 ms = mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; - F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f; - F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0); + F32 ms = mTimeElapsed / 1000000.f; + F32 seconds = ms / 1000.f; + + F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f; + F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0); tris_sec /= seconds; - F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f; - F32 samples_sec = (F32) mSamplesDrawn/1000000000.0; + F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f; + F32 samples_sec = (F32)mSamplesDrawn / 1000000000.0; samples_sec /= seconds; - F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f; - U32 avg_batch = mTrianglesDrawn/mDrawCalls; + F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f; - LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL; - LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL; + LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL; + LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL; LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; - LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL; + LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL; } } @@ -232,111 +218,82 @@ void LLGLSLShader::startProfile() } //static -void LLGLSLShader::stopProfile(U32 count, U32 mode) +void LLGLSLShader::stopProfile() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + if (sProfileEnabled && sCurBoundShaderPtr) { - sCurBoundShaderPtr->readProfileQuery(count, mode); + sCurBoundShaderPtr->unbind(); } } void LLGLSLShader::placeProfileQuery() { - if (mTimerQuery == 0) + if (sProfileEnabled) { - glGenQueries(1, &mSamplesQuery); - glGenQueries(1, &mTimerQuery); - } - - if (!mTextureStateFetched) - { - mTextureStateFetched = true; - mTextureMagFilter.resize(mTexture.size()); - mTextureMinFilter.resize(mTexture.size()); - - U32 cur_active = gGL.getCurrentTexUnitIndex(); - - for (U32 i = 0; i < mTexture.size(); ++i) + if (mTimerQuery == 0) { - GLint idx = mTexture[i]; - - if (idx >= 0) - { - gGL.getTexUnit(idx)->activate(); - - U32 mag = 0xFFFFFFFF; - U32 min = 0xFFFFFFFF; - - U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType()); - - glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag); - glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min); - - mTextureMagFilter[i] = mag; - mTextureMinFilter[i] = min; - } + glGenQueries(1, &mSamplesQuery); + glGenQueries(1, &mTimerQuery); + glGenQueries(1, &mPrimitivesQuery); } - gGL.getTexUnit(cur_active)->activate(); + glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery); + glBeginQuery(GL_TIME_ELAPSED, mTimerQuery); + glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery); } - - - glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery); - glBeginQuery(GL_TIME_ELAPSED, mTimerQuery); } -void LLGLSLShader::readProfileQuery(U32 count, U32 mode) +void LLGLSLShader::readProfileQuery() { - glEndQuery(GL_TIME_ELAPSED); - glEndQuery(GL_SAMPLES_PASSED); - - // U64 and GLuint64 somehow turn out different on x86_64 - //U64 time_elapsed = 0; - GLuint64 time_elapsed = 0; - glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); - - //U64 samples_passed = 0; - GLuint64 samples_passed = 0; - glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); - - sTotalTimeElapsed += time_elapsed; - mTimeElapsed += time_elapsed; - - sTotalSamplesDrawn += samples_passed; - mSamplesDrawn += samples_passed; - - U32 tri_count = 0; - switch (mode) + if (sProfileEnabled) { - case LLRender::TRIANGLES: tri_count = count/3; break; - case LLRender::TRIANGLE_FAN: tri_count = count-2; break; - case LLRender::TRIANGLE_STRIP: tri_count = count-2; break; - default: tri_count = count; break; //points lines etc just use primitive count + glEndQuery(GL_TIME_ELAPSED); + glEndQuery(GL_SAMPLES_PASSED); + glEndQuery(GL_PRIMITIVES_GENERATED); + + // U64 and GLuint64 somehow turn out different on x86_64 + //U64 time_elapsed = 0; + GLuint64 time_elapsed = 0; + glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); + + U64 samples_passed = 0; + glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); + + U64 primitives_generated = 0; + glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); + sTotalTimeElapsed += time_elapsed; + mTimeElapsed += time_elapsed; + + sTotalSamplesDrawn += samples_passed; + mSamplesDrawn += samples_passed; + + U32 tri_count = (U32)primitives_generated / 3; + + mTrianglesDrawn += tri_count; + sTotalTrianglesDrawn += tri_count; + + sTotalBinds++; + mBinds++; } - - mTrianglesDrawn += tri_count; - sTotalTrianglesDrawn += tri_count; - - sTotalDrawCalls++; - mDrawCalls++; } LLGLSLShader::LLGLSLShader() - : mProgramObject(0), - mAttributeMask(0), - mTotalUniformSize(0), - mActiveTextureChannels(0), - mShaderLevel(0), - mShaderGroup(SG_DEFAULT), - mUniformsDirty(FALSE), - mTimerQuery(0), - mSamplesQuery(0) - + : mProgramObject(0), + mAttributeMask(0), + mTotalUniformSize(0), + mActiveTextureChannels(0), + mShaderLevel(0), + mShaderGroup(SG_DEFAULT), + mUniformsDirty(FALSE), + mTimerQuery(0), + mSamplesQuery(0), + mPrimitivesQuery(0) { - + } LLGLSLShader::~LLGLSLShader() @@ -402,10 +359,10 @@ void LLGLSLShader::unloadInternal() stop_glerror(); } -BOOL LLGLSLShader::createShader(std::vector * attributes, - std::vector * uniforms, - U32 varying_count, - const char** varyings) +BOOL LLGLSLShader::createShader(std::vector* attributes, + std::vector* uniforms, + U32 varying_count, + const char** varyings) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -433,19 +390,19 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, } BOOL success = TRUE; - + #if LL_DARWIN // work-around missing mix(vec3,vec3,bvec3) mDefines["OLD_SELECT"] = "1"; #endif - + #if DEBUG_SHADER_INCLUDES fprintf(stderr, "--- %s ---\n", mName.c_str()); #endif // DEBUG_SHADER_INCLUDES //compile new source - vector< pair >::iterator fileIter = mShaderFiles.begin(); - for ( ; fileIter != mShaderFiles.end(); fileIter++ ) + vector< pair >::iterator fileIter = mShaderFiles.begin(); + for (; fileIter != mShaderFiles.end(); fileIter++) { GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; @@ -474,7 +431,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, #ifdef GL_INTERLEAVED_ATTRIBS if (varying_count > 0 && varyings) { - glTransformFeedbackVaryings((GLuint64) mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); + glTransformFeedbackVaryings((GLuint64)mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); } #endif @@ -487,7 +444,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, { success = mapUniforms(uniforms); } - if( !success ) + if (!success) { LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL; @@ -496,7 +453,7 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, { LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; mShaderLevel--; - return createShader(attributes,uniforms); + return createShader(attributes, uniforms); } } else if (mFeatures.mIndexedTextureChannels > 0) @@ -531,22 +488,22 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, } #if DEBUG_SHADER_INCLUDES -void dumpAttachObject( const char *func_name, GLuint program_object, const std::string &object_path ) +void dumpAttachObject(const char* func_name, GLuint program_object, const std::string& object_path) { GLchar* info_log; GLint info_len_expect = 0; GLint info_len_actual = 0; - glGetShaderiv(program_object, GL_INFO_LOG_LENGTH,, &info_len_expect); + glGetShaderiv(program_object, GL_INFO_LOG_LENGTH, , &info_len_expect); fprintf(stderr, " * %-20s(), log size: %d, %s\n", func_name, info_len_expect, object_path.c_str()); if (info_len_expect > 0) { fprintf(stderr, " ========== %s() ========== \n", func_name); - info_log = new GLchar [ info_len_expect ]; - glGetProgramInfoLog(program_object, info_len_expect, &info_len_actual, info_log); - fprintf(stderr, "%s\n", info_log); - delete [] info_log; + info_log = new GLchar[info_len_expect]; + glGetProgramInfoLog(program_object, info_len_expect, &info_len_actual, info_log); + fprintf(stderr, "%s\n", info_log); + delete[] info_log; } } #endif // DEBUG_SHADER_INCLUDES @@ -615,7 +572,7 @@ void LLGLSLShader::attachObjects(GLuint* objects, S32 count) } } -BOOL LLGLSLShader::mapAttributes(const std::vector * attributes) +BOOL LLGLSLShader::mapAttributes(const std::vector* attributes) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -623,9 +580,9 @@ BOOL LLGLSLShader::mapAttributes(const std::vector * attri for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) { const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - glBindAttribLocation(mProgramObject, i, (const GLchar *) name); + glBindAttribLocation(mProgramObject, i, (const GLchar*)name); } - + //link the program BOOL res = link(); @@ -636,7 +593,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector * attri #else mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); #endif - + if (res) { //read back channel locations @@ -646,7 +603,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector * attri for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) { const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - S32 index = glGetAttribLocation(mProgramObject, (const GLchar *)name); + S32 index = glGetAttribLocation(mProgramObject, (const GLchar*)name); if (index != -1) { #if LL_RELEASE_WITH_DEBUG_INFO @@ -674,11 +631,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector * attri return TRUE; } - + return FALSE; } -void LLGLSLShader::mapUniform(GLint index, const vector * uniforms) +void LLGLSLShader::mapUniform(GLint index, const vector* uniforms) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -694,45 +651,45 @@ void LLGLSLShader::mapUniform(GLint index, const vector * name[0] = 0; - glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar *)name); + glGetActiveUniform(mProgramObject, index, 1024, &length, &size, &type, (GLchar*)name); if (size > 0) { - switch(type) + switch (type) { - case GL_FLOAT_VEC2: size *= 2; break; - case GL_FLOAT_VEC3: size *= 3; break; - case GL_FLOAT_VEC4: size *= 4; break; - case GL_DOUBLE: size *= 2; break; - case GL_DOUBLE_VEC2: size *= 2; break; - case GL_DOUBLE_VEC3: size *= 6; break; - case GL_DOUBLE_VEC4: size *= 8; break; - case GL_INT_VEC2: size *= 2; break; - case GL_INT_VEC3: size *= 3; break; - case GL_INT_VEC4: size *= 4; break; - case GL_UNSIGNED_INT_VEC2: size *= 2; break; - case GL_UNSIGNED_INT_VEC3: size *= 3; break; - case GL_UNSIGNED_INT_VEC4: size *= 4; break; - case GL_BOOL_VEC2: size *= 2; break; - case GL_BOOL_VEC3: size *= 3; break; - case GL_BOOL_VEC4: size *= 4; break; - case GL_FLOAT_MAT2: size *= 4; break; - case GL_FLOAT_MAT3: size *= 9; break; - case GL_FLOAT_MAT4: size *= 16; break; - case GL_FLOAT_MAT2x3: size *= 6; break; - case GL_FLOAT_MAT2x4: size *= 8; break; - case GL_FLOAT_MAT3x2: size *= 6; break; - case GL_FLOAT_MAT3x4: size *= 12; break; - case GL_FLOAT_MAT4x2: size *= 8; break; - case GL_FLOAT_MAT4x3: size *= 12; break; - case GL_DOUBLE_MAT2: size *= 8; break; - case GL_DOUBLE_MAT3: size *= 18; break; - case GL_DOUBLE_MAT4: size *= 32; break; - case GL_DOUBLE_MAT2x3: size *= 12; break; - case GL_DOUBLE_MAT2x4: size *= 16; break; - case GL_DOUBLE_MAT3x2: size *= 12; break; - case GL_DOUBLE_MAT3x4: size *= 24; break; - case GL_DOUBLE_MAT4x2: size *= 16; break; - case GL_DOUBLE_MAT4x3: size *= 24; break; + case GL_FLOAT_VEC2: size *= 2; break; + case GL_FLOAT_VEC3: size *= 3; break; + case GL_FLOAT_VEC4: size *= 4; break; + case GL_DOUBLE: size *= 2; break; + case GL_DOUBLE_VEC2: size *= 2; break; + case GL_DOUBLE_VEC3: size *= 6; break; + case GL_DOUBLE_VEC4: size *= 8; break; + case GL_INT_VEC2: size *= 2; break; + case GL_INT_VEC3: size *= 3; break; + case GL_INT_VEC4: size *= 4; break; + case GL_UNSIGNED_INT_VEC2: size *= 2; break; + case GL_UNSIGNED_INT_VEC3: size *= 3; break; + case GL_UNSIGNED_INT_VEC4: size *= 4; break; + case GL_BOOL_VEC2: size *= 2; break; + case GL_BOOL_VEC3: size *= 3; break; + case GL_BOOL_VEC4: size *= 4; break; + case GL_FLOAT_MAT2: size *= 4; break; + case GL_FLOAT_MAT3: size *= 9; break; + case GL_FLOAT_MAT4: size *= 16; break; + case GL_FLOAT_MAT2x3: size *= 6; break; + case GL_FLOAT_MAT2x4: size *= 8; break; + case GL_FLOAT_MAT3x2: size *= 6; break; + case GL_FLOAT_MAT3x4: size *= 12; break; + case GL_FLOAT_MAT4x2: size *= 8; break; + case GL_FLOAT_MAT4x3: size *= 12; break; + case GL_DOUBLE_MAT2: size *= 8; break; + case GL_DOUBLE_MAT3: size *= 18; break; + case GL_DOUBLE_MAT4: size *= 32; break; + case GL_DOUBLE_MAT2x3: size *= 12; break; + case GL_DOUBLE_MAT2x4: size *= 16; break; + case GL_DOUBLE_MAT3x2: size *= 12; break; + case GL_DOUBLE_MAT3x4: size *= 24; break; + case GL_DOUBLE_MAT4x2: size *= 16; break; + case GL_DOUBLE_MAT4x3: size *= 24; break; } mTotalUniformSize += size; } @@ -753,11 +710,11 @@ void LLGLSLShader::mapUniform(GLint index, const vector * mUniformMap[hashedName] = location; LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL; - + //find the index of this uniform - for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++) + for (S32 i = 0; i < (S32)LLShaderMgr::instance()->mReservedUniforms.size(); i++) { - if ( (mUniform[i] == -1) + if ((mUniform[i] == -1) && (LLShaderMgr::instance()->mReservedUniforms[i] == name)) { //found it @@ -771,12 +728,12 @@ void LLGLSLShader::mapUniform(GLint index, const vector * { for (U32 i = 0; i < uniforms->size(); i++) { - if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1) + if ((mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] == -1) && ((*uniforms)[i].String() == name)) { //found it - mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location; - mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size); + mUniform[i + LLShaderMgr::instance()->mReservedUniforms.size()] = location; + mTexture[i + LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size); return; } } @@ -794,9 +751,9 @@ void LLGLSLShader::addPermutation(std::string name, std::string value) mDefines[name] = value; } -void LLGLSLShader::addConstant( const LLGLSLShader::eShaderConsts shader_const ) +void LLGLSLShader::addConstant(const LLGLSLShader::eShaderConsts shader_const) { - addPermutation( gShaderConstsKey[ shader_const ], gShaderConstsVal[ shader_const ] ); + addPermutation(gShaderConstsKey[shader_const], gShaderConstsVal[shader_const]); } void LLGLSLShader::removePermutation(std::string name) @@ -808,7 +765,7 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || + if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || type == GL_SAMPLER_2D_MULTISAMPLE || type == GL_SAMPLER_CUBE_MAP_ARRAY) { //this here is a texture @@ -830,8 +787,8 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint channel[i] = mActiveTextureChannels++; } glUniform1iv(location, size, channel); - LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << - (mActiveTextureChannels-size) << " through " << (mActiveTextureChannels-1) << LL_ENDL; + LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << + (mActiveTextureChannels - size) << " through " << (mActiveTextureChannels - 1) << LL_ENDL; } llassert(mActiveTextureChannels <= 32); // too many textures (probably) @@ -840,102 +797,102 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint return -1; } -BOOL LLGLSLShader::mapUniforms(const vector * uniforms) +BOOL LLGLSLShader::mapUniforms(const vector* uniforms) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; BOOL res = TRUE; - mTotalUniformSize = 0; - mActiveTextureChannels = 0; - mUniform.clear(); - mUniformMap.clear(); - mUniformNameMap.clear(); - mTexture.clear(); - mValue.clear(); - //initialize arrays - U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); - mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTotalUniformSize = 0; + mActiveTextureChannels = 0; + mUniform.clear(); + mUniformMap.clear(); + mUniformNameMap.clear(); + mTexture.clear(); + mValue.clear(); + //initialize arrays + U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size(); + mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); + mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1); - bind(); + bind(); - //get the number of active uniforms - GLint activeCount; + //get the number of active uniforms + GLint activeCount; glGetProgramiv(mProgramObject, GL_ACTIVE_UNIFORMS, &activeCount); - //........................................................................................................................................ - //........................................................................................ + //........................................................................................................................................ + //........................................................................................ - /* - EXPLANATION: - This is part of code is temporary because as the final result the mapUniform() should be rewrited. - But it's a huge a volume of work which is need to be a more carefully performed for avoid possible - regression's (i.e. it should be formalized a separate ticket in JIRA). + /* + EXPLANATION: + This is part of code is temporary because as the final result the mapUniform() should be rewrited. + But it's a huge a volume of work which is need to be a more carefully performed for avoid possible + regression's (i.e. it should be formalized a separate ticket in JIRA). - RESON: - The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear - first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) - it influence to which is texture matrix will be updated during rendering. + RESON: + The reason of this code is that SL engine is very sensitive to fact that "diffuseMap" should be appear + first as uniform parameter which is should get 0-"texture channel" index (see mapUniformTextureChannel() and mActiveTextureChannels) + it influence to which is texture matrix will be updated during rendering. - But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want - , even if the "diffuseMap" will be appear and use first in shader code. + But, order of indexe's of uniform variables is not defined and GLSL compiler can change it as want + , even if the "diffuseMap" will be appear and use first in shader code. - As example where this situation appear see: "Deferred Material Shader 28/29/30/31" - And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437 + As example where this situation appear see: "Deferred Material Shader 28/29/30/31" + And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437 --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel texture channel should follow the uniform VALUE - */ + */ - S32 diffuseMap = glGetUniformLocation(mProgramObject, "diffuseMap"); - S32 specularMap = glGetUniformLocation(mProgramObject, "specularMap"); - S32 bumpMap = glGetUniformLocation(mProgramObject, "bumpMap"); + S32 diffuseMap = glGetUniformLocation(mProgramObject, "diffuseMap"); + S32 specularMap = glGetUniformLocation(mProgramObject, "specularMap"); + S32 bumpMap = glGetUniformLocation(mProgramObject, "bumpMap"); S32 altDiffuseMap = glGetUniformLocation(mProgramObject, "altDiffuseMap"); - S32 environmentMap = glGetUniformLocation(mProgramObject, "environmentMap"); + S32 environmentMap = glGetUniformLocation(mProgramObject, "environmentMap"); S32 reflectionMap = glGetUniformLocation(mProgramObject, "reflectionMap"); - std::set skip_index; + std::set skip_index; - if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap)) - { - GLenum type; - GLsizei length; - GLint size = -1; - char name[1024]; + if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap)) + { + GLenum type; + GLsizei length; + GLint size = -1; + char name[1024]; - diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1; + diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1; - for (S32 i = 0; i < activeCount; i++) - { - name[0] = '\0'; + for (S32 i = 0; i < activeCount; i++) + { + name[0] = '\0'; - glGetActiveUniform(mProgramObject, i, 1024, &length, &size, &type, (GLchar *)name); + glGetActiveUniform(mProgramObject, i, 1024, &length, &size, &type, (GLchar*)name); - if (-1 == diffuseMap && std::string(name) == "diffuseMap") - { - diffuseMap = i; - continue; - } + if (-1 == diffuseMap && std::string(name) == "diffuseMap") + { + diffuseMap = i; + continue; + } - if (-1 == specularMap && std::string(name) == "specularMap") - { - specularMap = i; - continue; - } + if (-1 == specularMap && std::string(name) == "specularMap") + { + specularMap = i; + continue; + } - if (-1 == bumpMap && std::string(name) == "bumpMap") - { - bumpMap = i; - continue; - } + if (-1 == bumpMap && std::string(name) == "bumpMap") + { + bumpMap = i; + continue; + } - if (-1 == environmentMap && std::string(name) == "environmentMap") - { - environmentMap = i; - continue; - } + if (-1 == environmentMap && std::string(name) == "environmentMap") + { + environmentMap = i; + continue; + } if (-1 == reflectionMap && std::string(name) == "reflectionMap") { @@ -944,55 +901,55 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms) } if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap") - { - altDiffuseMap = i; - continue; - } - } + { + altDiffuseMap = i; + continue; + } + } - bool specularDiff = specularMap < diffuseMap && -1 != specularMap; - bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap; - bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; + bool specularDiff = specularMap < diffuseMap && -1 != specularMap; + bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap; + bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap; - if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff) - { - mapUniform(diffuseMap, uniforms); - skip_index.insert(diffuseMap); + if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff) + { + mapUniform(diffuseMap, uniforms); + skip_index.insert(diffuseMap); - if (-1 != specularMap) { - mapUniform(specularMap, uniforms); - skip_index.insert(specularMap); - } + if (-1 != specularMap) { + mapUniform(specularMap, uniforms); + skip_index.insert(specularMap); + } - if (-1 != bumpMap) { - mapUniform(bumpMap, uniforms); - skip_index.insert(bumpMap); - } + if (-1 != bumpMap) { + mapUniform(bumpMap, uniforms); + skip_index.insert(bumpMap); + } - if (-1 != environmentMap) { - mapUniform(environmentMap, uniforms); - skip_index.insert(environmentMap); - } + if (-1 != environmentMap) { + mapUniform(environmentMap, uniforms); + skip_index.insert(environmentMap); + } if (-1 != reflectionMap) { mapUniform(reflectionMap, uniforms); skip_index.insert(reflectionMap); } - } - } + } + } - //........................................................................................ + //........................................................................................ - for (S32 i = 0; i < activeCount; i++) - { - //........................................................................................ - if (skip_index.end() != skip_index.find(i)) continue; - //........................................................................................ + for (S32 i = 0; i < activeCount; i++) + { + //........................................................................................ + if (skip_index.end() != skip_index.find(i)) continue; + //........................................................................................ - mapUniform(i, uniforms); - } - //........................................................................................................................................ + mapUniform(i, uniforms); + } + //........................................................................................................................................ if (mFeatures.hasReflectionProbes) // Set up block binding, in a way supported by Apple (rather than binding = 1 in .glsl). { // See slide 35 and more of https://docs.huihoo.com/apple/wwdc/2011/session_420__advances_in_opengl_for_mac_os_x_lion.pdf @@ -1005,10 +962,10 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms) glUniformBlockBinding(mProgramObject, UBOBlockIndex, BLOCKBINDING); } } - unbind(); + unbind(); - LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; - return res; + LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL; + return res; } @@ -1034,10 +991,15 @@ void LLGLSLShader::bind() if (sCurBoundShader != mProgramObject) // Don't re-bind current shader { + if (sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(); + } LLVertexBuffer::unbind(); glUseProgram(mProgramObject); sCurBoundShader = mProgramObject; sCurBoundShaderPtr = this; + placeProfileQuery(); } if (mUniformsDirty) @@ -1063,8 +1025,11 @@ void LLGLSLShader::bind(bool rigged) void LLGLSLShader::unbind() { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - gGL.flush(); + if (sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(); + } stop_glerror(); LLVertexBuffer::unbind(); glUseProgram(0); @@ -1078,22 +1043,28 @@ void LLGLSLShader::bindNoShader(void) LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; LLVertexBuffer::unbind(); + + if (sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(); + } + glUseProgram(0); sCurBoundShader = 0; sCurBoundShaderPtr = NULL; } -S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) +S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; S32 channel = 0; channel = getUniformLocation(uniform); - + return bindTexture(channel, texture, mode, colorspace); } -S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) +S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; @@ -1102,25 +1073,25 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; return -1; } - + uniform = mTexture[uniform]; - + if (uniform > -1) { gGL.getTexUnit(uniform)->bindFast(texture); gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace); } - + return uniform; } -S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode) +S32 LLGLSLShader::unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; S32 channel = 0; channel = getUniformLocation(uniform); - + return unbindTexture(channel); } @@ -1133,14 +1104,14 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; return -1; } - + uniform = mTexture[uniform]; - + if (uniform > -1) { gGL.getTexUnit(uniform)->unbindFast(mode); } - + return uniform; } @@ -1197,7 +1168,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1210,7 +1181,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1i(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); + mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); } } } @@ -1222,7 +1193,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1235,7 +1206,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x) if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1f(mUniform[index], x); - mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); + mValue[mUniform[index]] = LLVector4(x, 0.f, 0.f, 0.f); } } } @@ -1257,7 +1228,7 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1267,8 +1238,8 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(x,y,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(x, y, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform2f(mUniform[index], x, y); mValue[mUniform[index]] = vec; @@ -1283,7 +1254,7 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1293,8 +1264,8 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(x,y,z,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(x, y, z, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform3f(mUniform[index], x, y, z); mValue[mUniform[index]] = vec; @@ -1309,7 +1280,7 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1319,8 +1290,8 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(x,y,z,w); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(x, y, z, w); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform4f(mUniform[index], x, y, z, w); mValue[mUniform[index]] = vec; @@ -1335,7 +1306,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1345,8 +1316,8 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform1iv(mUniform[index], count, v); mValue[mUniform[index]] = vec; @@ -1388,7 +1359,7 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1398,8 +1369,8 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform1fv(mUniform[index], count, v); mValue[mUniform[index]] = vec; @@ -1414,7 +1385,7 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1424,8 +1395,8 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],v[1],0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], v[1], 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform2fv(mUniform[index], count, v); mValue[mUniform[index]] = vec; @@ -1440,7 +1411,7 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1450,8 +1421,8 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],v[1],v[2],0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], v[1], v[2], 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform3fv(mUniform[index], count, v); mValue[mUniform[index]] = vec; @@ -1466,7 +1437,7 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1476,8 +1447,8 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { const auto& iter = mValue.find(mUniform[index]); - LLVector4 vec(v[0],v[1],v[2],v[3]); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], v[1], v[2], v[3]); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; glUniform4fv(mUniform[index], count, v); @@ -1487,13 +1458,13 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) } } -void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) +void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1507,13 +1478,13 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c } } -void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) +void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1527,33 +1498,33 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c } } -void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - llassert(sCurBoundShaderPtr == this); - - if (mProgramObject) - { - if (mUniform.size() <= index) - { - LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; - return; - } - - if (mUniform[index] >= 0) - { - glUniformMatrix3x4fv(mUniform[index], count, transpose, v); - } - } -} - -void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v) +void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; llassert(sCurBoundShaderPtr == this); if (mProgramObject) - { + { + if (mUniform.size() <= index) + { + LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; + return; + } + + if (mUniform[index] >= 0) + { + glUniformMatrix3x4fv(mUniform[index], count, transpose, v); + } + } +} + +void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; + llassert(sCurBoundShaderPtr == this); + + if (mProgramObject) + { if (mUniform.size() <= index) { LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL; @@ -1629,12 +1600,12 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(v,0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(v, 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform1i(location, v); mValue[location] = vec; @@ -1682,12 +1653,12 @@ void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(i,j,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(i, j, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform2i(location, i, j); mValue[location] = vec; @@ -1700,12 +1671,12 @@ void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(v,0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(v, 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { glUniform1f(location, v); mValue[location] = vec; @@ -1717,14 +1688,14 @@ void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLf { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(x,y,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(x, y, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { - glUniform2f(location, x,y); + glUniform2f(location, x, y); mValue[location] = vec; } } @@ -1735,14 +1706,14 @@ void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLf { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(x,y,z,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec)) + LLVector4 vec(x, y, z, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec)) { - glUniform3f(location, x,y,z); + glUniform3f(location, x, y, z); mValue[location] = vec; } } @@ -1756,8 +1727,8 @@ void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(v[0],0.f,0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], 0.f, 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform1fv(location, count, v); mValue[location] = vec; @@ -1769,12 +1740,12 @@ void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, co { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(v[0],v[1],0.f,0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], v[1], 0.f, 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform2fv(location, count, v); mValue[location] = vec; @@ -1786,12 +1757,12 @@ void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, co { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { const auto& iter = mValue.find(location); - LLVector4 vec(v[0],v[1],v[2],0.f); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + LLVector4 vec(v[0], v[1], v[2], 0.f); + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { glUniform3fv(location, count, v); mValue[location] = vec; @@ -1808,7 +1779,7 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co { LLVector4 vec(v); const auto& iter = mValue.find(location); - if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) + if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; glUniform4fv(location, count, v); @@ -1821,7 +1792,7 @@ void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 cou { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; GLint location = getUniformLocation(uniform); - + if (location >= 0) { stop_glerror(); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 23db1a8549..0522f78614 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -1,25 +1,25 @@ -/** +/** * @file llglslshader.h * @brief GLSL shader wrappers * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -35,36 +35,36 @@ class LLShaderFeatures { public: - bool atmosphericHelpers; - bool calculatesLighting; - bool calculatesAtmospherics; - bool hasLighting; // implies no transport (it's possible to have neither though) - bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions) - bool isShiny; - bool isFullbright; // implies no lighting - bool isSpecular; - bool hasWaterFog; // implies no gamma - bool hasTransport; // implies no lighting (it's possible to have neither though) - bool hasSkinning; - bool hasObjectSkinning; - bool hasAtmospherics; - bool hasGamma; + bool atmosphericHelpers; + bool calculatesLighting; + bool calculatesAtmospherics; + bool hasLighting; // implies no transport (it's possible to have neither though) + bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions) + bool isShiny; + bool isFullbright; // implies no lighting + bool isSpecular; + bool hasWaterFog; // implies no gamma + bool hasTransport; // implies no lighting (it's possible to have neither though) + bool hasSkinning; + bool hasObjectSkinning; + bool hasAtmospherics; + bool hasGamma; bool hasShadows; bool hasAmbientOcclusion; - bool hasSrgb; + bool hasSrgb; bool encodesNormal; // include: shaders\class1\environment\encodeNormF.glsl bool isDeferred; bool hasScreenSpaceReflections; bool hasIndirect; - S32 mIndexedTextureChannels; - bool disableTextureIndex; - bool hasAlphaMask; + S32 mIndexedTextureChannels; + bool disableTextureIndex; + bool hasAlphaMask; bool hasReflectionProbes = false; - bool attachNothing; + bool attachNothing; - // char numLights; - - LLShaderFeatures(); + // char numLights; + + LLShaderFeatures(); }; // ============= Structure for caching shader uniforms =============== @@ -108,7 +108,7 @@ public: { mVectors.push_back({ index, value }); } - + void uniform4fv(S32 index, const F32* value) { mVectors.push_back({ index, LLVector4(value) }); @@ -125,7 +125,7 @@ public: } void apply(LLGLSLShader* shader); - + std::vector mIntegers; std::vector mFloats; @@ -138,184 +138,182 @@ public: // NOTE: Keep gShaderConsts and LLGLSLShader::ShaderConsts_e in sync! enum eShaderConsts { - SHADER_CONST_CLOUD_MOON_DEPTH + SHADER_CONST_CLOUD_MOON_DEPTH , SHADER_CONST_STAR_DEPTH , NUM_SHADER_CONSTS }; // enum primarily used to control application sky settings uniforms - typedef enum - { - SG_DEFAULT = 0, // not sky or water specific - SG_SKY, // - SG_WATER, + typedef enum + { + SG_DEFAULT = 0, // not sky or water specific + SG_SKY, // + SG_WATER, SG_ANY, SG_COUNT - } eGroup; - - static std::set sInstances; - static bool sProfileEnabled; + } eGroup; - LLGLSLShader(); - ~LLGLSLShader(); + static std::set sInstances; + static bool sProfileEnabled; - static GLuint sCurBoundShader; - static LLGLSLShader* sCurBoundShaderPtr; - static S32 sIndexedTextureChannels; + LLGLSLShader(); + ~LLGLSLShader(); - static void initProfile(); - static void finishProfile(bool emit_report = true); + static GLuint sCurBoundShader; + static LLGLSLShader* sCurBoundShaderPtr; + static S32 sIndexedTextureChannels; - static void startProfile(); - static void stopProfile(U32 count, U32 mode); + static void initProfile(); + static void finishProfile(bool emit_report = true); - void unload(); - void clearStats(); - void dumpStats(); - void placeProfileQuery(); - void readProfileQuery(U32 count, U32 mode); + static void startProfile(); + static void stopProfile(); - BOOL createShader(std::vector * attributes, - std::vector * uniforms, - U32 varying_count = 0, - const char** varyings = NULL); + void unload(); + void clearStats(); + void dumpStats(); + void placeProfileQuery(); + void readProfileQuery(); + + BOOL createShader(std::vector* attributes, + std::vector* uniforms, + U32 varying_count = 0, + const char** varyings = NULL); BOOL attachFragmentObject(std::string object); BOOL attachVertexObject(std::string object); - void attachObject(GLuint object); - void attachObjects(GLuint* objects = NULL, S32 count = 0); - BOOL mapAttributes(const std::vector * attributes); - BOOL mapUniforms(const std::vector *); - void mapUniform(GLint index, const std::vector *); - void uniform1i(U32 index, GLint i); - void uniform1f(U32 index, GLfloat v); + void attachObject(GLuint object); + void attachObjects(GLuint* objects = NULL, S32 count = 0); + BOOL mapAttributes(const std::vector* attributes); + BOOL mapUniforms(const std::vector*); + void mapUniform(GLint index, const std::vector*); + void uniform1i(U32 index, GLint i); + void uniform1f(U32 index, GLfloat v); void fastUniform1f(U32 index, GLfloat v); - void uniform2f(U32 index, GLfloat x, GLfloat y); - void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); - void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void uniform1iv(U32 index, U32 count, const GLint* i); + void uniform2f(U32 index, GLfloat x, GLfloat y); + void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); + void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform1iv(U32 index, U32 count, const GLint* i); void uniform4iv(U32 index, U32 count, const GLint* i); - void uniform1fv(U32 index, U32 count, const GLfloat* v); - void uniform2fv(U32 index, U32 count, const GLfloat* v); - void uniform3fv(U32 index, U32 count, const GLfloat* v); - void uniform4fv(U32 index, U32 count, const GLfloat* v); - void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j); - void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); - void uniform1i(const LLStaticHashedString& uniform, GLint i); + void uniform1fv(U32 index, U32 count, const GLfloat* v); + void uniform2fv(U32 index, U32 count, const GLfloat* v); + void uniform3fv(U32 index, U32 count, const GLfloat* v); + void uniform4fv(U32 index, U32 count, const GLfloat* v); + void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j); + void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v); + void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v); + void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v); + void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v); + void uniform1i(const LLStaticHashedString& uniform, GLint i); void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v); void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v); - void uniform1f(const LLStaticHashedString& uniform, GLfloat v); - void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y); - void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z); - void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); - void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v); + void uniform1f(const LLStaticHashedString& uniform, GLfloat v); + void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y); + void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z); + void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); + void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v); - void setMinimumAlpha(F32 minimum); + void setMinimumAlpha(F32 minimum); - void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void vertexAttrib4fv(U32 index, GLfloat* v); - - //GLint getUniformLocation(const std::string& uniform); - GLint getUniformLocation(const LLStaticHashedString& uniform); - GLint getUniformLocation(U32 index); + void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void vertexAttrib4fv(U32 index, GLfloat* v); + + //GLint getUniformLocation(const std::string& uniform); + GLint getUniformLocation(const LLStaticHashedString& uniform); + GLint getUniformLocation(U32 index); + + GLint getAttribLocation(U32 attrib); + GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size); - GLint getAttribLocation(U32 attrib); - GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size); - void clearPermutations(); - void addPermutation(std::string name, std::string value); - void removePermutation(std::string name); - - void addConstant( const LLGLSLShader::eShaderConsts shader_const ); + void addPermutation(std::string name, std::string value); + void removePermutation(std::string name); - //enable/disable texture channel for specified uniform - //if given texture uniform is active in the shader, - //the corresponding channel will be active upon return - //returns channel texture is enabled in from [0-MAX) - S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); + void addConstant(const LLGLSLShader::eShaderConsts shader_const); + + //enable/disable texture channel for specified uniform + //if given texture uniform is active in the shader, + //the corresponding channel will be active upon return + //returns channel texture is enabled in from [0-MAX) + S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); - - // bindTexture returns the texture unit we've bound the texture to. - // You can reuse the return value to unbind a texture when required. - S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); - S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); - S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); - + + // bindTexture returns the texture unit we've bound the texture to. + // You can reuse the return value to unbind a texture when required. + S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); + S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); + S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); + BOOL link(BOOL suppress_errors = FALSE); - void bind(); + void bind(); //helper to conditionally bind mRiggedVariant instead of this void bind(bool rigged); - void unbind(); + void unbind(); - // Unbinds any previously bound shader by explicitly binding no shader. - static void bindNoShader(void); + // Unbinds any previously bound shader by explicitly binding no shader. + static void bindNoShader(void); - U32 mMatHash[LLRender::NUM_MATRIX_MODES]; - U32 mLightHash; + U32 mMatHash[LLRender::NUM_MATRIX_MODES]; + U32 mLightHash; - GLuint mProgramObject; + GLuint mProgramObject; #if LL_RELEASE_WITH_DEBUG_INFO - struct attr_name - { - GLint loc; - const char *name; - void operator = (GLint _loc) { loc = _loc; } - operator GLint () { return loc; } - }; - std::vector mAttribute; //lookup table of attribute enum to attribute channel + struct attr_name + { + GLint loc; + const char* name; + void operator = (GLint _loc) { loc = _loc; } + operator GLint () { return loc; } + }; + std::vector mAttribute; //lookup table of attribute enum to attribute channel #else - std::vector mAttribute; //lookup table of attribute enum to attribute channel + std::vector mAttribute; //lookup table of attribute enum to attribute channel #endif - U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) - std::vector mUniform; //lookup table of uniform enum to uniform location - LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location + U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) + std::vector mUniform; //lookup table of uniform enum to uniform location + LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location typedef std::unordered_map uniform_name_map_t; typedef std::unordered_map uniform_value_map_t; uniform_name_map_t mUniformNameMap; //lookup map of uniform location to uniform name - uniform_value_map_t mValue; //lookup map of uniform location to last known value - std::vector mTexture; - S32 mTotalUniformSize; - S32 mActiveTextureChannels; - S32 mShaderLevel; - S32 mShaderGroup; // see LLGLSLShader::eGroup - BOOL mUniformsDirty; - LLShaderFeatures mFeatures; - std::vector< std::pair< std::string, GLenum > > mShaderFiles; - std::string mName; + uniform_value_map_t mValue; //lookup map of uniform location to last known value + std::vector mTexture; + S32 mTotalUniformSize; + S32 mActiveTextureChannels; + S32 mShaderLevel; + S32 mShaderGroup; // see LLGLSLShader::eGroup + BOOL mUniformsDirty; + LLShaderFeatures mFeatures; + std::vector< std::pair< std::string, GLenum > > mShaderFiles; + std::string mName; typedef std::unordered_map defines_map_t; - defines_map_t mDefines; + defines_map_t mDefines; - //statistcis for profiling shader performance - U32 mTimerQuery; - U32 mSamplesQuery; - U64 mTimeElapsed; - static U64 sTotalTimeElapsed; - U32 mTrianglesDrawn; - static U32 sTotalTrianglesDrawn; - U64 mSamplesDrawn; - static U64 sTotalSamplesDrawn; - U32 mDrawCalls; - static U32 sTotalDrawCalls; + //statistics for profiling shader performance + U32 mTimerQuery; + U32 mSamplesQuery; + U32 mPrimitivesQuery; - bool mTextureStateFetched; - std::vector mTextureMagFilter; - std::vector mTextureMinFilter; + U64 mTimeElapsed; + static U64 sTotalTimeElapsed; + U32 mTrianglesDrawn; + static U32 sTotalTrianglesDrawn; + U64 mSamplesDrawn; + static U64 sTotalSamplesDrawn; + U32 mBinds; + static U32 sTotalBinds; // this pointer should be set to whichever shader represents this shader's rigged variant LLGLSLShader* mRiggedVariant = nullptr; - #ifdef LL_PROFILER_ENABLE_RENDER_DOC +#ifdef LL_PROFILER_ENABLE_RENDER_DOC void setLabel(const char* label); - #endif +#endif private: - void unloadInternal(); + void unloadInternal(); }; //UI shader (declared here so llui_libtest will link properly) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 962dc150c1..a52036a8ee 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -35,6 +35,7 @@ #include "llrendertarget.h" #include "lltexture.h" #include "llshadermgr.h" +#include "llmd5.h" #if LL_WINDOWS extern void APIENTRY gl_debug_callback(GLenum source, @@ -66,6 +67,14 @@ LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f); static const U32 LL_NUM_TEXTURE_LAYERS = 32; static const U32 LL_NUM_LIGHT_UNITS = 8; +struct LLVBCache +{ + LLPointer vb; + std::chrono::steady_clock::time_point touched; +}; + +static std::unordered_map sVBCache; + static const GLenum sGLTextureType[] = { GL_TEXTURE_2D, @@ -370,9 +379,10 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) if (bindDepth) { - if (renderTarget->hasStencil()) + + if (renderTarget->getDepth() && !renderTarget->canSampleDepth()) { - LL_ERRS() << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << LL_ENDL; + LL_ERRS() << "Cannot bind a render buffer for sampling. Allocate render target with depth buffer sampling enabled." << LL_ENDL; } bindManual(renderTarget->getUsage(), renderTarget->getDepth()); @@ -1678,26 +1688,107 @@ void LLRender::flush() if (mBuffer) { - if (mBuffer->useVBOs() && !mBuffer->isLocked()) - { //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata) - mBuffer->getVertexStrider(mVerticesp, 0, count); - mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count); - mBuffer->getColorStrider(mColorsp, 0, count); + + LLMD5 hash; + U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash"); + + hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a)); + if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) + { + hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2)); + } + + if (attribute_mask & LLVertexBuffer::MAP_COLOR) + { + hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U)); + } + + hash.finalize(); + } + + size_t vhash[2]; + hash.raw_digest((unsigned char*) vhash); + + // check the VB cache before making a new vertex buffer + // This is a giant hack to deal with (mostly) our terrible UI rendering code + // that was built on top of OpenGL immediate mode. Huge performance wins + // can be had by not uploading geometry to VRAM unless absolutely necessary. + // Most of our usage of the "immediate mode" style draw calls is actually + // sending the same geometry over and over again. + // To leverage this, we maintain a running hash of the vertex stream being + // built up before a flush, and then check that hash against a VB + // cache just before creating a vertex buffer in VRAM + std::unordered_map::iterator cache = sVBCache.find(vhash[0]); + + LLPointer vb; + + if (cache != sVBCache.end()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit"); + // cache hit, just use the cached buffer + vb = cache->second.vb; + cache->second.touched = std::chrono::steady_clock::now(); + } + else + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); + vb = new LLVertexBuffer(attribute_mask, GL_STATIC_DRAW); + vb->allocateBuffer(count, 0, true); + vb->setPositionData((LLVector4a*) mVerticesp.get()); + + if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) + { + vb->setTexCoordData(mTexcoordsp.get()); + } + + if (attribute_mask & LLVertexBuffer::MAP_COLOR) + { + vb->setColorData(mColorsp.get()); + } + + vb->unbind(); + + sVBCache[vhash[0]] = { vb , std::chrono::steady_clock::now() }; + + static U32 miss_count = 0; + miss_count++; + if (miss_count > 1024) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean"); + miss_count = 0; + auto now = std::chrono::steady_clock::now(); + + using namespace std::chrono_literals; + // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second + for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) + { + if (now - iter->second.touched > 1s) + { + iter = sVBCache.erase(iter); + } + else + { + ++iter; + } + } + } } - mBuffer->flush(); - mBuffer->setBuffer(immediate_mask); + vb->setBuffer(attribute_mask); // Remove QUADS rendering mode //if (mMode == LLRender::QUADS && sGLCoreProfile) //{ - // mBuffer->drawArrays(LLRender::TRIANGLES, 0, count); - // mQuadCycle = 1; + // vb->drawArrays(LLRender::TRIANGLES, 0, count); + // mQuadCycle = 1; //} //else // { - mBuffer->drawArrays(mMode, 0, count); + vb->drawArrays(mMode, 0, count); } } else diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 02c5021796..ca65b9b323 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -67,9 +67,8 @@ LLRenderTarget::LLRenderTarget() : mPreviousResX(0), mPreviousResY(0), mDepth(0), - mStencil(0), mUseDepth(false), - mRenderDepth(false), + mSampleDepth(false), mUsage(LLTexUnit::TT_TEXTURE) { } @@ -98,11 +97,11 @@ void LLRenderTarget::resize(U32 resx, U32 resy) if (mDepth) { //resize depth attachment - if (mStencil) + if (!mSampleDepth) { //use render buffers where stencil buffers are in play glBindRenderbuffer(GL_RENDERBUFFER, mDepth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mResX, mResY); glBindRenderbuffer(GL_RENDERBUFFER, 0); } else @@ -117,7 +116,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy) } -bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) +bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool sample_depth, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize); @@ -130,9 +129,9 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo mResX = resx; mResY = resy; - mStencil = stencil; mUsage = usage; - mUseDepth = depth; + mUseDepth = depth; + mSampleDepth = sample_depth; if ((sUseFBO || use_fbo)) { @@ -150,13 +149,10 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo if (mDepth) { glBindFramebuffer(GL_FRAMEBUFFER, mFBO); - llassert(!mStencil); // use of stencil buffer is deprecated (performance penalty) - if (mStencil) + + if (!canSampleDepth()) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); - stop_glerror(); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); - stop_glerror(); } else { @@ -315,14 +311,12 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) bool LLRenderTarget::allocateDepth() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mStencil) + if (!mSampleDepth) { - //use render buffers where stencil buffers are in play + //use render buffers if depth buffer won't be sampled glGenRenderbuffers(1, (GLuint *) &mDepth); glBindRenderbuffer(GL_RENDERBUFFER, mDepth); - stop_glerror(); - clear_glerror(); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mResX, mResY); glBindRenderbuffer(GL_RENDERBUFFER, 0); } else @@ -367,23 +361,15 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) if (mDepth) { - stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); - stop_glerror(); - - llassert(!mStencil); // deprecated -- performance penalty - if (mStencil) + + if (!mSampleDepth) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); - stop_glerror(); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); - stop_glerror(); - target.mStencil = true; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); } check_framebuffer_status(); @@ -399,15 +385,13 @@ void LLRenderTarget::release() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; if (mDepth) { - if (mStencil) + if (!mSampleDepth) { glDeleteRenderbuffers(1, (GLuint*) &mDepth); - stop_glerror(); } else { LLImageGL::deleteTextures(1, &mDepth); - stop_glerror(); } mDepth = 0; @@ -419,12 +403,10 @@ void LLRenderTarget::release() if (mUseDepth) { //detach shared depth buffer - llassert(!mStencil); //deprecated, performance penalty - if (mStencil) + if (!mSampleDepth) { //attached as a renderbuffer - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - mStencil = false; + mSampleDepth = false; } else { //attached as a texture @@ -624,84 +606,6 @@ void LLRenderTarget::flush(bool fetch_depth) } } -void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, - S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) -{ - LL_PROFILE_GPU_ZONE("LLRenderTarget::copyContents"); - - GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; - - LLGLDepthTest depth(write_depth, write_depth); - - gGL.flush(); - if (!source.mFBO || !mFBO) - { - LL_WARNS() << "Cannot copy framebuffer contents for non FBO render targets." << LL_ENDL; - return; - } - - - if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) - { - stop_glerror(); - - glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO); - check_framebuffer_status(); - gGL.getTexUnit(0)->bind(this, true); - stop_glerror(); - glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); - stop_glerror(); - } - else - { - glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); - stop_glerror(); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO); - stop_glerror(); - check_framebuffer_status(); - stop_glerror(); - glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - stop_glerror(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - stop_glerror(); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); - stop_glerror(); - } -} - -//static -void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, - S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) -{ - if (!source.mFBO) - { - LL_WARNS() << "Cannot copy framebuffer contents for non FBO render targets." << LL_ENDL; - return; - } - - { - LL_PROFILE_GPU_ZONE("copyContentsToFramebuffer"); - GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; - - LLGLDepthTest depth(write_depth, write_depth); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); - stop_glerror(); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - stop_glerror(); - check_framebuffer_status(); - stop_glerror(); - glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); - stop_glerror(); - } -} - bool LLRenderTarget::isComplete() const { return (!mTex.empty() || mDepth) ? true : false; diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 584f224dca..5f3214add3 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -73,7 +73,7 @@ public: //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool sample_depth, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); //resize existing attachments to use new resolution and color format // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined @@ -136,7 +136,7 @@ public: U32 getNumTextures() const; U32 getDepth(void) const { return mDepth; } - bool hasStencil() const { return mStencil; } + bool canSampleDepth() const { return mSampleDepth; } void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR); @@ -148,12 +148,6 @@ public: // the current depth texture. A depth texture will be allocated if needed. void flush(bool fetch_depth = FALSE); - void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, - S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); - - static void copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, - S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); - //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). @@ -172,9 +166,9 @@ protected: U32 mPreviousResY; U32 mDepth; - bool mStencil; - bool mUseDepth; - bool mRenderDepth; + bool mUseDepth; + bool mSampleDepth; + LLTexUnit::eTextureType mUsage; static LLRenderTarget* sBoundTarget; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1a7546d4cd..7fae34a8db 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -62,6 +62,14 @@ U32 wpo2(U32 i) return r; } +struct CompareMappedRegion +{ + bool operator()(const LLVertexBuffer::MappedRegion& lhs, const LLVertexBuffer::MappedRegion& rhs) + { + return lhs.mStart < rhs.mStart; + } +}; + const U32 LL_VBO_BLOCK_SIZE = 2048; const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024; @@ -81,21 +89,374 @@ U32 vbo_block_index(U32 size) const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE) + 1; +#define ENABLE_GL_WORK_QUEUE 0 + +#if ENABLE_GL_WORK_QUEUE + +#define THREAD_COUNT 1 //============================================================================ +// High performance WorkQueue for usage in real-time rendering work +class GLWorkQueue +{ +public: + using Work = std::function; + + GLWorkQueue(); + + void post(const Work& value); + + size_t size(); + + bool done(); + + // Get the next element from the queue + Work pop(); + + void runOne(); + + bool runPending(); + + void runUntilClose(); + + void close(); + + bool isClosed(); + + void syncGL(); + +private: + std::mutex mMutex; + std::condition_variable mCondition; + std::queue mQueue; + bool mClosed = false; +}; + +GLWorkQueue::GLWorkQueue() +{ + +} + +void GLWorkQueue::syncGL() +{ + /*if (mSync) + { + std::lock_guard lock(mMutex); + glWaitSync(mSync, 0, GL_TIMEOUT_IGNORED); + mSync = 0; + }*/ +} + +size_t GLWorkQueue::size() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + std::lock_guard lock(mMutex); + return mQueue.size(); +} + +bool GLWorkQueue::done() +{ + return size() == 0 && isClosed(); +} + +void GLWorkQueue::post(const GLWorkQueue::Work& value) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + { + std::lock_guard lock(mMutex); + mQueue.push(std::move(value)); + } + + mCondition.notify_one(); +} + +// Get the next element from the queue +GLWorkQueue::Work GLWorkQueue::pop() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + // Lock the mutex + { + std::unique_lock lock(mMutex); + + // Wait for a new element to become available or for the queue to close + { + mCondition.wait(lock, [=] { return !mQueue.empty() || mClosed; }); + } + } + + Work ret; + + { + std::lock_guard lock(mMutex); + + // Get the next element from the queue + if (mQueue.size() > 0) + { + ret = mQueue.front(); + mQueue.pop(); + } + else + { + ret = []() {}; + } + } + + return ret; +} + +void GLWorkQueue::runOne() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + Work w = pop(); + w(); + //mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +} + +void GLWorkQueue::runUntilClose() +{ + while (!isClosed()) + { + runOne(); + } +} + +void GLWorkQueue::close() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + { + std::lock_guard lock(mMutex); + mClosed = true; + } + + mCondition.notify_all(); +} + +bool GLWorkQueue::isClosed() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + std::lock_guard lock(mMutex); + return mClosed; +} + +#include "llwindow.h" + +class LLGLWorkerThread : public LLThread +{ +public: + LLGLWorkerThread(const std::string& name, GLWorkQueue* queue, LLWindow* window) + : LLThread(name) + { + mWindow = window; + mContext = mWindow->createSharedContext(); + mQueue = queue; + } + + void run() override + { + mWindow->makeContextCurrent(mContext); + gGL.init(false); + mQueue->runUntilClose(); + gGL.shutdown(); + mWindow->destroySharedContext(mContext); + } + + GLWorkQueue* mQueue; + LLWindow* mWindow; + void* mContext = nullptr; +}; + + +static LLGLWorkerThread* sVBOThread[THREAD_COUNT]; +static GLWorkQueue* sQueue = nullptr; + +#endif + +//============================================================================ +// Pool of reusable VertexBuffer state + +// batch calls to glGenBuffers +static GLuint gen_buffer() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + constexpr U32 pool_size = 4096; + + thread_local static GLuint sNamePool[pool_size]; + thread_local static U32 sIndex = 0; + + if (sIndex == 0) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer"); + sIndex = pool_size; + glGenBuffers(pool_size, sNamePool); + } + + return sNamePool[--sIndex]; +} + +class LLVBOPool +{ +public: + typedef std::chrono::steady_clock::time_point Time; + + struct Entry + { + U8* mData; + GLuint mGLName; + Time mAge; + }; + + ~LLVBOPool() + { + clear(); + } + + typedef std::unordered_map> Pool; + + Pool mVBOPool; + Pool mIBOPool; + + U32 mMissCount = 0; + + void allocate(GLenum type, U32 size, GLuint& name, U8*& data) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + + size = nhpo2(size); + + auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool; + + auto& iter = pool.find(size); + if (iter == pool.end()) + { // cache miss, allocate a new buffer + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo pool miss"); + LL_PROFILE_GPU_ZONE("vbo alloc"); + + ++mMissCount; + if (mMissCount > 1024) + { //clean cache on every 1024 misses + mMissCount = 0; + clean(); + } + + name = gen_buffer(); + glBindBuffer(type, name); + glBufferData(type, size, nullptr, GL_DYNAMIC_DRAW); + if (type == GL_ELEMENT_ARRAY_BUFFER) + { + LLVertexBuffer::sGLRenderIndices = name; + } + else + { + LLVertexBuffer::sGLRenderBuffer = name; + } + + data = (U8*)ll_aligned_malloc_16(size); + } + else + { + std::list& entries = iter->second; + Entry& entry = entries.back(); + name = entry.mGLName; + data = entry.mData; + + entries.pop_back(); + if (entries.empty()) + { + pool.erase(iter); + } + } + } + + void free(GLenum type, U32 size, GLuint name, U8* data) + { + size = nhpo2(size); + + auto& pool = type == GL_ELEMENT_ARRAY_BUFFER ? mIBOPool : mVBOPool; + + auto& iter = pool.find(size); + + if (iter == pool.end()) + { + std::list newlist; + newlist.push_front({ data, name, std::chrono::steady_clock::now() }); + pool[size] = newlist; + } + else + { + iter->second.push_front({ data, name, std::chrono::steady_clock::now() }); + } + } + + void clean() + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + + std::unordered_map>* pools[] = { &mVBOPool, &mIBOPool }; + + using namespace std::chrono_literals; + + Time cutoff = std::chrono::steady_clock::now() - 5s; + + for (auto* pool : pools) + { + for (Pool::iterator iter = pool->begin(); iter != pool->end(); ) + { + auto& entries = iter->second; + + while (!entries.empty() && entries.back().mAge < cutoff) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo cache timeout"); + auto& entry = entries.back(); + ll_aligned_free_16(entry.mData); + glDeleteBuffers(1, &entry.mGLName); + entries.pop_back(); + } + + if (entries.empty()) + { + iter = pool->erase(iter); + } + else + { + ++iter; + } + } + } + } + + void clear() + { + for (auto& entries : mIBOPool) + { + for (auto& entry : entries.second) + { + ll_aligned_free_16(entry.mData); + glDeleteBuffers(1, &entry.mGLName); + } + } + + for (auto& entries : mVBOPool) + { + for (auto& entry : entries.second) + { + ll_aligned_free_16(entry.mData); + glDeleteBuffers(1, &entry.mGLName); + } + } + + mIBOPool.clear(); + mVBOPool.clear(); + } + + +}; + +static LLVBOPool* sVBOPool = nullptr; + +//============================================================================ +// //static -LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW, GL_ARRAY_BUFFER); -LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); -LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY, GL_ARRAY_BUFFER); -LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW, GL_ELEMENT_ARRAY_BUFFER); -LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); - -U32 LLVBOPool::sBytesPooled = 0; -U32 LLVBOPool::sIndexBytesPooled = 0; -U32 LLVBOPool::sNameIdx = 0; -U32 LLVBOPool::sNamePool[1024]; - std::list LLVertexBuffer::sAvailableVAOName; U32 LLVertexBuffer::sCurVAOName = 1; @@ -122,226 +483,6 @@ bool LLVertexBuffer::sUseStreamDraw = true; bool LLVertexBuffer::sUseVAO = false; bool LLVertexBuffer::sPreferStreamDraw = false; -U32 LLVBOPool::genBuffer() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX - - if (sNameIdx == 0) - { - glGenBuffers(1024, sNamePool); - sNameIdx = 1024; - } - - return sNamePool[--sNameIdx]; -} - -void LLVBOPool::deleteBuffer(U32 name) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX - if (gGLManager.mInited) - { - LLVertexBuffer::unbind(); - - glBindBuffer(mType, name); - glBufferData(mType, 0, NULL, mUsage); - glBindBuffer(mType, 0); - - glDeleteBuffers(1, &name); - } -} - - -LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) -: mUsage(vboUsage), mType(vboType), mMissCountDirty(true) -{ - mFreeList.resize(LL_VBO_POOL_SEED_COUNT); - mMissCount.resize(LL_VBO_POOL_SEED_COUNT); - std::fill(mMissCount.begin(), mMissCount.end(), 0); -} - -U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX - llassert(vbo_block_size(size) == size); - - U8* ret = NULL; - - U32 i = vbo_block_index(size); - - if (mFreeList.size() <= i) - { - mFreeList.resize(i+1); - } - - if (mFreeList[i].empty() || for_seed) - { - //make a new buffer - name = genBuffer(); - - glBindBuffer(mType, name); - - if (!for_seed && i < LL_VBO_POOL_SEED_COUNT) - { //record this miss - mMissCount[i]++; - mMissCountDirty = true; // signal to ::seedPool() - } - - if (mType == GL_ARRAY_BUFFER) - { - LLVertexBuffer::sAllocatedBytes += size; - } - else - { - LLVertexBuffer::sAllocatedIndexBytes += size; - } - - if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW) - { - glBufferData(mType, size, 0, mUsage); - if (mUsage != GL_DYNAMIC_COPY) - { //data will be provided by application - ret = (U8*) ll_aligned_malloc<64>(size); - if (!ret) - { - LL_ERRS() - << "Failed to allocate " << size << " bytes for LLVBOPool buffer " << name << "." << LL_NEWLINE - << "Free list size: " - << mFreeList.size() // this happens if we are out of memory so a solution might be to clear some from freelist - << " Allocated Bytes: " << LLVertexBuffer::sAllocatedBytes - << " Allocated Index Bytes: " << LLVertexBuffer::sAllocatedIndexBytes << " Pooled Bytes: " << sBytesPooled - << " Pooled Index Bytes: " << sIndexBytesPooled << LL_ENDL; - } - } - } - else - { //always use a true hint of static draw when allocating non-client-backed buffers - glBufferData(mType, size, 0, GL_STATIC_DRAW); - } - - glBindBuffer(mType, 0); - - if (for_seed) - { //put into pool for future use - llassert(mFreeList.size() > i); - - Record rec; - rec.mGLName = name; - rec.mClientData = ret; - - if (mType == GL_ARRAY_BUFFER) - { - sBytesPooled += size; - } - else - { - sIndexBytesPooled += size; - } - mFreeList[i].push_back(rec); - mMissCountDirty = true; // signal to ::seedPool() - } - } - else - { - name = mFreeList[i].front().mGLName; - ret = mFreeList[i].front().mClientData; - - if (mType == GL_ARRAY_BUFFER) - { - sBytesPooled -= size; - } - else - { - sIndexBytesPooled -= size; - } - - mFreeList[i].pop_front(); - mMissCountDirty = true; // signal to ::seedPool() - } - - return ret; -} - -void LLVBOPool::release(U32 name, U8* buffer, U32 size) -{ - llassert(vbo_block_size(size) == size); - - deleteBuffer(name); - ll_aligned_free_fallback((U8*) buffer); - - if (mType == GL_ARRAY_BUFFER) - { - LLVertexBuffer::sAllocatedBytes -= size; - } - else - { - LLVertexBuffer::sAllocatedIndexBytes -= size; - } -} - -void LLVBOPool::seedPool() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX - if (mMissCountDirty) - { - U32 dummy_name = 0; - U32 size = LL_VBO_BLOCK_SIZE; - - for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++) - { - if (mMissCount[i] > mFreeList[i].size()) - { - S32 count = mMissCount[i] - mFreeList[i].size(); - for (U32 j = 0; j < count; ++j) - { - allocate(dummy_name, size, true); - } - } - size += LL_VBO_BLOCK_SIZE; - } - mMissCountDirty = false; - } -} - -void LLVBOPool::cleanup() -{ - U32 size = LL_VBO_BLOCK_SIZE; - - for (U32 i = 0; i < mFreeList.size(); ++i) - { - record_list_t& l = mFreeList[i]; - - while (!l.empty()) - { - Record& r = l.front(); - - deleteBuffer(r.mGLName); - - if (r.mClientData) - { - ll_aligned_free<64>((void*) r.mClientData); - } - - l.pop_front(); - - if (mType == GL_ARRAY_BUFFER) - { - sBytesPooled -= size; - LLVertexBuffer::sAllocatedBytes -= size; - } - else - { - sIndexBytesPooled -= size; - LLVertexBuffer::sAllocatedIndexBytes -= size; - } - } - - size += LL_VBO_BLOCK_SIZE; - } - - //reset miss counts - std::fill(mMissCount.begin(), mMissCount.end(), 0); -} - //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware const S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = @@ -419,29 +560,12 @@ void LLVertexBuffer::releaseVAOName(U32 name) } -//static -void LLVertexBuffer::seedPools() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX - sStreamVBOPool.seedPool(); - sDynamicVBOPool.seedPool(); - sDynamicCopyVBOPool.seedPool(); - sStreamIBOPool.seedPool(); - sDynamicIBOPool.seedPool(); -} - //static void LLVertexBuffer::setupClientArrays(U32 data_mask) { if (sLastMask != data_mask) { - if (gGLManager.mGLSLVersionMajor < 2 && gGLManager.mGLSLVersionMinor < 30) - { - //make sure texture index is disabled - data_mask = data_mask & ~MAP_TEXTURE_INDEX; - } - for (U32 i = 0; i < TYPE_MAX; ++i) { S32 loc = i; @@ -479,7 +603,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos) } gGL.end(); gGL.flush(); - } +} //static void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp) @@ -600,33 +724,22 @@ void LLVertexBuffer::setLabel(const char* label) { void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { validateRange(start, end, count, indices_offset); - mMappable = false; gGL.syncMatrices(); llassert(mNumVerts >= 0); llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - if (mGLArray) + if (mGLIndices != sGLRenderIndices) { - if (mGLArray != sGLRenderArray) - { - LL_ERRS() << "Wrong vertex array bound." << LL_ENDL; - } - } - else - { - if (mGLIndices != sGLRenderIndices) - { - LL_ERRS() << "Wrong index buffer bound." << LL_ENDL; - } - - if (mGLBuffer != sGLRenderBuffer) - { - LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; - } + LL_ERRS() << "Wrong index buffer bound." << LL_ENDL; } - if (gDebugGL && !mGLArray && useVBOs()) + if (mGLBuffer != sGLRenderBuffer) + { + LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; + } + + if (gDebugGL && useVBOs()) { GLint elem = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem); @@ -645,21 +758,12 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi U16* idx = ((U16*) getIndicesPointer())+indices_offset; - stop_glerror(); - LLGLSLShader::startProfile(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, idx); - LLGLSLShader::stopProfile(count, mode); - stop_glerror(); - - - - placeFence(); } void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { - mMappable = false; gGL.syncMatrices(); U16* idx = ((U16*)getIndicesPointer()) + indices_offset; @@ -671,7 +775,6 @@ void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - mMappable = false; gGL.syncMatrices(); llassert(mNumIndices >= 0); @@ -681,24 +784,15 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL; } - if (mGLArray) + + if (mGLIndices != sGLRenderIndices) { - if (mGLArray != sGLRenderArray) - { - LL_ERRS() << "Wrong vertex array bound." << LL_ENDL; - } + LL_ERRS() << "Wrong index buffer bound." << LL_ENDL; } - else - { - if (mGLIndices != sGLRenderIndices) - { - LL_ERRS() << "Wrong index buffer bound." << LL_ENDL; - } - if (mGLBuffer != sGLRenderBuffer) - { - LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; - } + if (mGLBuffer != sGLRenderBuffer) + { + LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; } if (mode >= LLRender::NUM_MODES) @@ -707,13 +801,8 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const return; } - stop_glerror(); - LLGLSLShader::startProfile(); glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); - LLGLSLShader::stopProfile(count, mode); - stop_glerror(); - placeFence(); } @@ -721,7 +810,6 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); - mMappable = false; gGL.syncMatrices(); #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -732,19 +820,9 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << LL_ENDL; } - if (mGLArray) + if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) { - if (mGLArray != sGLRenderArray) - { - LL_ERRS() << "Wrong vertex array bound." << LL_ENDL; - } - } - else - { - if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) - { - LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; - } + LL_ERRS() << "Wrong vertex buffer bound." << LL_ENDL; } if (mode >= LLRender::NUM_MODES) @@ -754,21 +832,26 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const } #endif - LLGLSLShader::startProfile(); - { - glDrawArrays(sGLMode[mode], first, count); - } - LLGLSLShader::stopProfile(count, mode); - - stop_glerror(); - placeFence(); + glDrawArrays(sGLMode[mode], first, count); } //static -void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) +void LLVertexBuffer::initClass(LLWindow* window) { - sEnableVBOs = use_vbo; - sDisableVBOMapping = sEnableVBOs && no_vbo_mapping; + sEnableVBOs = true; + sDisableVBOMapping = true; + + sVBOPool = new LLVBOPool(); + +#if ENABLE_GL_WORK_QUEUE + sQueue = new GLWorkQueue(); + + for (int i = 0; i < THREAD_COUNT; ++i) + { + sVBOThread[i] = new LLGLWorkerThread("VBO Worker", sQueue, window); + sVBOThread[i]->start(); + } +#endif } //static @@ -804,14 +887,22 @@ void LLVertexBuffer::cleanupClass() { unbind(); - sStreamIBOPool.cleanup(); - sDynamicIBOPool.cleanup(); - sStreamVBOPool.cleanup(); - sDynamicVBOPool.cleanup(); - sDynamicCopyVBOPool.cleanup(); + delete sVBOPool; + sVBOPool = nullptr; + +#if ENABLE_GL_WORK_QUEUE + sQueue->close(); + for (int i = 0; i < THREAD_COUNT; ++i) + { + sVBOThread[i]->shutdown(); + delete sVBOThread[i]; + sVBOThread[i] = nullptr; + } + + delete sQueue; + sQueue = nullptr; +#endif - llassert(0 == LLVBOPool::sBytesPooled); - llassert(0 == LLVBOPool::sIndexBytesPooled); //llassert(0 == sAllocatedBytes); //llassert(0 == sAllocatedIndexBytes); } @@ -832,30 +923,8 @@ S32 LLVertexBuffer::determineUsage(S32 usage) ret_usage = 0; } - if (ret_usage == GL_DYNAMIC_DRAW && sPreferStreamDraw) - { - ret_usage = GL_STREAM_DRAW; - } - - if (ret_usage == 0 && LLRender::sGLCoreProfile) - { //MUST use VBOs for all rendering - ret_usage = GL_STREAM_DRAW; - } - - if (ret_usage && ret_usage != GL_STREAM_DRAW) - { //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default - if (ret_usage != GL_DYNAMIC_COPY) - { - if (sDisableVBOMapping) - { //always use stream draw if VBO mapping is disabled - ret_usage = GL_STREAM_DRAW; - } - else - { - ret_usage = GL_DYNAMIC_DRAW; - } - } - } + // dynamic draw or nothing + ret_usage = GL_DYNAMIC_DRAW; return ret_usage; } @@ -865,15 +934,12 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) mNumVerts(0), mNumIndices(0), - mAlignedOffset(0), - mAlignedIndexOffset(0), mSize(0), mIndicesSize(0), mTypeMask(typemask), mUsage(LLVertexBuffer::determineUsage(usage)), mGLBuffer(0), mGLIndices(0), - mGLArray(0), mMappedData(NULL), mMappedIndexData(NULL), mMappedDataUsingVBOs(false), @@ -881,12 +947,8 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) mVertexLocked(false), mIndexLocked(false), mFinal(false), - mEmpty(true), - mMappable(false), - mFence(NULL) + mEmpty(true) { - mMappable = (mUsage == GL_DYNAMIC_DRAW && !sDisableVBOMapping); - //zero out offsets for (U32 i = 0; i < TYPE_MAX; i++) { @@ -916,7 +978,7 @@ S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_verti offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12; - return offset+16; + return offset; } //static @@ -947,22 +1009,8 @@ LLVertexBuffer::~LLVertexBuffer() destroyGLBuffer(); destroyGLIndices(); - if (mGLArray) - { - releaseVAOName(mGLArray); - } - sCount--; - if (mFence) - { - // Sanity check. We have weird crashes in this destructor (on delete). Yet mFence is disabled. - // TODO: mFence was added in scope of SH-2038, but was never enabled, consider removing mFence. - LL_ERRS() << "LLVertexBuffer destruction failed" << LL_ENDL; - delete mFence; - mFence = NULL; - } - sVertexCount -= mNumVerts; sIndexCount -= mNumIndices; @@ -976,97 +1024,61 @@ LLVertexBuffer::~LLVertexBuffer() } }; -void LLVertexBuffer::placeFence() const -{ - /*if (!mFence && useVBOs()) - { - mFence = new LLGLSyncFence(); - } - - if (mFence) - { - mFence->placeFence(); - }*/ -} - -void LLVertexBuffer::waitFence() const -{ - /*if (mFence) - { - mFence->wait(); - }*/ -} - //---------------------------------------------------------------------------- void LLVertexBuffer::genBuffer(U32 size) { - mSize = vbo_block_size(size); + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - if (mUsage == GL_STREAM_DRAW) - { - mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize); - } - else if (mUsage == GL_DYNAMIC_DRAW) - { - mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize); - } - else - { - mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize); - } - - - sGLCount++; + mSize = size; + + if (sVBOPool) + { + sVBOPool->allocate(GL_ARRAY_BUFFER, size, mGLBuffer, mMappedData); + } + + sGLCount++; } void LLVertexBuffer::genIndices(U32 size) { - mIndicesSize = vbo_block_size(size); + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - if (mUsage == GL_STREAM_DRAW) - { - mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize); - } - else - { - mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize); - } - + mIndicesSize = size; + + if (sVBOPool) + { + sVBOPool->allocate(GL_ELEMENT_ARRAY_BUFFER, size, mGLIndices, mMappedIndexData); + } sGLCount++; } void LLVertexBuffer::releaseBuffer() { - if (mUsage == GL_STREAM_DRAW) - { - sStreamVBOPool.release(mGLBuffer, mMappedData, mSize); - } - else - { - sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize); - } - - mGLBuffer = 0; - mMappedData = NULL; + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + if (sVBOPool) + { + sVBOPool->free(GL_ARRAY_BUFFER, mSize, mGLBuffer, mMappedData); + } + + mGLBuffer = 0; + mMappedData = nullptr; + sGLCount--; } void LLVertexBuffer::releaseIndices() { - if (mUsage == GL_STREAM_DRAW) - { - sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize); - } - else - { - sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize); - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; + + if (sVBOPool) + { + sVBOPool->free(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mGLIndices, mMappedIndexData); + } + + mMappedIndexData = nullptr; - mGLIndices = 0; - mMappedIndexData = NULL; - sGLCount--; } @@ -1255,144 +1267,11 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { //actually allocate space for the vertex buffer if using VBO mapping flush(); //unmap - - if (useVBOs() && sUseVAO) - { - mGLArray = getVAOName(); - setupVertexArray(); - } } return success; } -void LLVertexBuffer::setupVertexArray() -{ - if (!mGLArray) - { - return; - } - - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - glBindVertexArray(mGLArray); - sGLRenderArray = mGLArray; - - static const U32 attrib_size[] = - { - 3, //TYPE_VERTEX, - 3, //TYPE_NORMAL, - 2, //TYPE_TEXCOORD0, - 2, //TYPE_TEXCOORD1, - 2, //TYPE_TEXCOORD2, - 2, //TYPE_TEXCOORD3, - 4, //TYPE_COLOR, - 4, //TYPE_EMISSIVE, - 4, //TYPE_TANGENT, - 1, //TYPE_WEIGHT, - 4, //TYPE_WEIGHT4, - 4, //TYPE_CLOTHWEIGHT, - 1, //TYPE_TEXTURE_INDEX - }; - - static const U32 attrib_type[] = - { - GL_FLOAT, //TYPE_VERTEX, - GL_FLOAT, //TYPE_NORMAL, - GL_FLOAT, //TYPE_TEXCOORD0, - GL_FLOAT, //TYPE_TEXCOORD1, - GL_FLOAT, //TYPE_TEXCOORD2, - GL_FLOAT, //TYPE_TEXCOORD3, - GL_UNSIGNED_BYTE, //TYPE_COLOR, - GL_UNSIGNED_BYTE, //TYPE_EMISSIVE, - GL_FLOAT, //TYPE_TANGENT, - GL_FLOAT, //TYPE_WEIGHT, - GL_FLOAT, //TYPE_WEIGHT4, - GL_FLOAT, //TYPE_CLOTHWEIGHT, - GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX - }; - - static const bool attrib_integer[] = - { - false, //TYPE_VERTEX, - false, //TYPE_NORMAL, - false, //TYPE_TEXCOORD0, - false, //TYPE_TEXCOORD1, - false, //TYPE_TEXCOORD2, - false, //TYPE_TEXCOORD3, - false, //TYPE_COLOR, - false, //TYPE_EMISSIVE, - false, //TYPE_TANGENT, - false, //TYPE_WEIGHT, - false, //TYPE_WEIGHT4, - false, //TYPE_CLOTHWEIGHT, - true, //TYPE_TEXTURE_INDEX - }; - - static const U32 attrib_normalized[] = - { - GL_FALSE, //TYPE_VERTEX, - GL_FALSE, //TYPE_NORMAL, - GL_FALSE, //TYPE_TEXCOORD0, - GL_FALSE, //TYPE_TEXCOORD1, - GL_FALSE, //TYPE_TEXCOORD2, - GL_FALSE, //TYPE_TEXCOORD3, - GL_TRUE, //TYPE_COLOR, - GL_TRUE, //TYPE_EMISSIVE, - GL_FALSE, //TYPE_TANGENT, - GL_FALSE, //TYPE_WEIGHT, - GL_FALSE, //TYPE_WEIGHT4, - GL_FALSE, //TYPE_CLOTHWEIGHT, - GL_FALSE, //TYPE_TEXTURE_INDEX - }; - - bindGLBuffer(true); - bindGLIndices(true); - - for (U32 i = 0; i < TYPE_MAX; ++i) - { - if (mTypeMask & (1 << i)) - { - glEnableVertexAttribArray(i); - - if (attrib_integer[i]) - { - //glVertexattribIPointer requires GLSL 1.30 or later - if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) - { - // nat 2018-10-24: VS 2017 also notices the issue - // described below, and warns even with reinterpret_cast. - // Cast via intptr_t to make it painfully obvious to the - // compiler that we're doing this intentionally. - glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], - reinterpret_cast(intptr_t(mOffsets[i]))); - } - } - else - { - // nat 2016-12-16: With 64-bit clang compile, the compiler - // produces an error if we simply cast mOffsets[i] -- an S32 - // -- to (GLvoid *), the type of the parameter. It correctly - // points out that there's no way an S32 could fit a real - // pointer value. Ruslan asserts that in this case the last - // param is interpreted as an array data offset within the VBO - // rather than as an actual pointer, so it's okay. - glVertexAttribPointer(i, attrib_size[i], attrib_type[i], - attrib_normalized[i], sTypeSize[i], - reinterpret_cast(intptr_t(mOffsets[i]))); - } - } - else - { - glDisableVertexAttribArray(i); - } - } - - //draw a dummy triangle to set index array pointer - //glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, NULL); - - unbind(); -} - bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { llassert(newnverts >= 0); @@ -1406,11 +1285,6 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) if (useVBOs()) { flush(); //unmap - - if (mGLArray) - { //if size changed, offsets changed - setupVertexArray(); - } } return success; @@ -1424,21 +1298,20 @@ bool LLVertexBuffer::useVBOs() const //---------------------------------------------------------------------------- -bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) +// if no gap between region and given range exists, expand region to cover given range and return true +// otherwise return false +bool expand_region(LLVertexBuffer::MappedRegion& region, S32 start, S32 end) { - S32 end = index+count; - S32 region_end = region.mIndex+region.mCount; - if (end < region.mIndex || - index > region_end) + if (end < region.mStart || + start > region.mEnd) { //gap exists, do not merge return false; } - S32 new_end = llmax(end, region_end); - S32 new_index = llmin(index, region.mIndex); - region.mIndex = new_index; - region.mCount = new_end-new_index; + region.mStart = llmin(region.mStart, start); + region.mEnd = llmax(region.mEnd, end); + return true; } @@ -1447,7 +1320,6 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - bindGLBuffer(true); if (mFinal) { LL_ERRS() << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << LL_ENDL; @@ -1456,37 +1328,34 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran { LL_ERRS() << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << LL_ENDL; } - - if (useVBOs()) - { - if (!mMappable) + + + if (useVBOs()) + { + if (count == -1) + { + count = mNumVerts - index; + } + + S32 start = mOffsets[type] + sTypeSize[type] * index; + S32 end = start + sTypeSize[type] * count; + + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { - if (count == -1) - { - count = mNumVerts-index; - } + MappedRegion& region = mMappedVertexRegions[i]; + if (expand_region(region, start, end)) + { + flagged = true; + break; + } + } - bool mapped = false; - //see if range is already mapped - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) - { - MappedRegion& region = mMappedVertexRegions[i]; - if (region.mType == type) - { - if (expand_region(region, index, count)) - { - mapped = true; - break; - } - } - } - - if (!mapped) - { - //not already mapped, map new region - MappedRegion region(type, mMappable && map_range ? -1 : index, count); - mMappedVertexRegions.push_back(region); - } + if (!flagged) + { + //didn't expand an existing region, make a new one + mMappedVertexRegions.push_back({ start, end }); } if (mVertexLocked && map_range) @@ -1500,48 +1369,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran sMappedCount++; stop_glerror(); - if(!mMappable) - { - map_range = false; - } - else - { - U8* src = NULL; - waitFence(); - if (map_range) - { - S32 offset = mOffsets[type] + sTypeSize[type]*index; - S32 length = (sTypeSize[type]*count+0xF) & ~0xF; - src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER, offset, length, - GL_MAP_WRITE_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_INVALIDATE_RANGE_BIT); - } - else - { - if (gDebugGL) - { - GLint size = 0; - glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - - if (size < mSize) - { - LL_ERRS() << "Invalid buffer size." << LL_ENDL; - } - } - - src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER, 0, mSize, - GL_MAP_WRITE_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT); - } - - llassert(src != NULL); - - mMappedData = LL_NEXT_ALIGNED_ADDRESS(src); - mAlignedOffset = mMappedData - src; - - stop_glerror(); - } + map_range = false; if (!mMappedData) { @@ -1549,31 +1377,9 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran //check the availability of memory LLMemory::logMemoryInfo(true); - - if(mMappable) - { - //-------------------- - //print out more debug info before crash - LL_INFOS() << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << LL_ENDL; - GLint size; - glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - LL_INFOS() << "GL_ARRAY_BUFFER size is " << size << LL_ENDL; - //-------------------- + + LL_ERRS() << "memory allocation for vertex data failed." << LL_ENDL; - GLint buff; - glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buff); - if ((GLuint)buff != mGLBuffer) - { - LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL; - } - - - LL_ERRS() << "glMapBuffer returned NULL (no vertex data)" << LL_ENDL; - } - else - { - LL_ERRS() << "memory allocation for vertex data failed." << LL_ENDL; - } } } } @@ -1582,21 +1388,13 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran map_range = false; } - if (map_range && mMappable) - { - return mMappedData; - } - else - { - return mMappedData+mOffsets[type]+sTypeSize[type]*index; - } + return mMappedData+mOffsets[type]+sTypeSize[type]*index; } U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - bindGLIndices(true); if (mFinal) { LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << LL_ENDL; @@ -1608,33 +1406,32 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) if (useVBOs()) { - if (!mMappable) + if (count == -1) { - if (count == -1) - { - count = mNumIndices-index; - } - - bool mapped = false; - //see if range is already mapped - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) - { - MappedRegion& region = mMappedIndexRegions[i]; - if (expand_region(region, index, count)) - { - mapped = true; - break; - } - } - - if (!mapped) - { - //not already mapped, map new region - MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count); - mMappedIndexRegions.push_back(region); - } + count = mNumIndices-index; } + S32 start = sizeof(U16) * index; + S32 end = start + sizeof(U16) * count; + + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + { + MappedRegion& region = mMappedIndexRegions[i]; + if (expand_region(region, start, end)) + { + flagged = true; + break; + } + } + + if (!flagged) + { + //didn't expand an existing region, make a new one + mMappedIndexRegions.push_back({ start, end }); + } + if (mIndexLocked && map_range) { LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL; @@ -1646,47 +1443,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) sMappedCount++; stop_glerror(); - if (gDebugGL && useVBOs()) - { - GLint elem = 0; - glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elem); - - if (elem != mGLIndices) - { - LL_ERRS() << "Wrong index buffer bound!" << LL_ENDL; - } - } - - if(!mMappable) - { - map_range = false; - } - else - { - U8* src = NULL; - waitFence(); - if (map_range) - { - S32 offset = sizeof(U16)*index; - S32 length = sizeof(U16)*count; - src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length, - GL_MAP_WRITE_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_INVALIDATE_RANGE_BIT); - } - else - { - src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16)*mNumIndices, - GL_MAP_WRITE_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT); - } - - llassert(src != NULL); - - mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS(src); - mAlignedIndexOffset = mMappedIndexData - src; - stop_glerror(); - } + map_range = false; } if (!mMappedIndexData) @@ -1694,21 +1451,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) log_glerror(); LLMemory::logMemoryInfo(true); - if(mMappable) - { - GLint buff; - glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buff); - if ((GLuint)buff != mGLIndices) - { - LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL; - } - - LL_ERRS() << "glMapBuffer returned NULL (no index data)" << LL_ENDL; - } - else - { - LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL; - } + LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL; } } else @@ -1716,14 +1459,28 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) map_range = false; } - if (map_range && mMappable) - { - return mMappedIndexData; - } - else - { - return mMappedIndexData + sizeof(U16)*index; - } + return mMappedIndexData + sizeof(U16)*index; +} + +static void flush_vbo(GLenum target, S32 start, S32 end, void* data) +{ + if (end != 0) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData"); + LL_PROFILE_ZONE_NUM(start); + LL_PROFILE_ZONE_NUM(end); + LL_PROFILE_ZONE_NUM(end-start); + + constexpr S32 block_size = 65536; + + for (S32 i = start; i < end; i += block_size) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block"); + LL_PROFILE_GPU_ZONE("glBufferSubData"); + S32 tend = llmin(i + block_size, end); + glBufferSubData(target, i, tend - i, (U8*) data + (i-start)); + } + } } void LLVertexBuffer::unmapBuffer() @@ -1741,66 +1498,35 @@ void LLVertexBuffer::unmapBuffer() bindGLBuffer(true); updated_all = mIndexLocked; //both vertex and index buffers done updating - if(!mMappable) + if (!mMappedVertexRegions.empty()) { - if (!mMappedVertexRegions.empty()) - { - stop_glerror(); - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) - { - const MappedRegion& region = mMappedVertexRegions[i]; - S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; - S32 length = sTypeSize[region.mType]*region.mCount; - if (mSize >= length + offset) - { - glBufferSubData(GL_ARRAY_BUFFER, offset, length, (U8*)mMappedData + offset); - } - else - { - GLint size = 0; - glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - LL_WARNS() << "Attempted to map regions to a buffer that is too small, " - << "mapped size: " << mSize - << ", gl buffer size: " << size - << ", length: " << length - << ", offset: " << offset - << LL_ENDL; - } - stop_glerror(); - } + S32 start = 0; + S32 end = 0; - mMappedVertexRegions.clear(); - } - else + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { - stop_glerror(); - glBufferSubData(GL_ARRAY_BUFFER, 0, getSize(), (U8*) mMappedData); - stop_glerror(); + const MappedRegion& region = mMappedVertexRegions[i]; + if (region.mStart == end + 1) + { + end = region.mEnd; + } + else + { + flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start); + start = region.mStart; + end = region.mEnd; + } } + + flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start); + + mMappedVertexRegions.clear(); } else { - if (!mMappedVertexRegions.empty()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush vertex"); - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) - { - const MappedRegion& region = mMappedVertexRegions[i]; - S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; - S32 length = sTypeSize[region.mType]*region.mCount; - glFlushMappedBufferRange(GL_ARRAY_BUFFER, offset, length); - } - - mMappedVertexRegions.clear(); - } - - stop_glerror(); - glUnmapBuffer(GL_ARRAY_BUFFER); - stop_glerror(); - - mMappedData = NULL; + llassert(false); // this shouldn't happen -- a buffer must always be explicitly mapped } - + mVertexLocked = false; sMappedCount--; } @@ -1809,64 +1535,36 @@ void LLVertexBuffer::unmapBuffer() { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index"); bindGLIndices(); - if(!mMappable) + + if (!mMappedIndexRegions.empty()) { - if (!mMappedIndexRegions.empty()) - { - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) - { - const MappedRegion& region = mMappedIndexRegions[i]; - S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; - S32 length = sizeof(U16)*region.mCount; - if (mIndicesSize >= length + offset) - { - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, length, (U8*) mMappedIndexData+offset); - } - else - { - GLint size = 0; - glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); - LL_WARNS() << "Attempted to map regions to a buffer that is too small, " - << "mapped size: " << mIndicesSize - << ", gl buffer size: " << size - << ", length: " << length - << ", offset: " << offset - << LL_ENDL; - } - stop_glerror(); - } + S32 start = 0; + S32 end = 0; - mMappedIndexRegions.clear(); - } - else - { - stop_glerror(); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, getIndicesSize(), (U8*) mMappedIndexData); - stop_glerror(); - } + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + { + const MappedRegion& region = mMappedIndexRegions[i]; + if (region.mStart == end + 1) + { + end = region.mEnd; + } + else + { + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start); + start = region.mStart; + end = region.mEnd; + } + } + + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start); + + mMappedIndexRegions.clear(); } else { - if (!mMappedIndexRegions.empty()) - { - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush index"); - const MappedRegion& region = mMappedIndexRegions[i]; - S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; - S32 length = sizeof(U16)*region.mCount; - glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length); - stop_glerror(); - } - - mMappedIndexRegions.clear(); - } - - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - mMappedIndexData = NULL; + llassert(false); // this shouldn't happen -- a buffer must always be explicitly mapped } - + mIndexLocked = false; sMappedCount--; } @@ -1996,30 +1694,8 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 i //---------------------------------------------------------------------------- -bool LLVertexBuffer::bindGLArray() -{ - if (mGLArray && sGLRenderArray != mGLArray) - { - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - glBindVertexArray(mGLArray); - sGLRenderArray = mGLArray; - } - - //really shouldn't be necessary, but some drivers don't properly restore the - //state of GL_ELEMENT_ARRAY_BUFFER_BINDING - bindGLIndices(); - - return true; - } - - return false; -} - bool LLVertexBuffer::bindGLBuffer(bool force_bind) { - bindGLArray(); - bool ret = false; if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)))) @@ -2029,9 +1705,6 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind) sGLRenderBuffer = mGLBuffer; sBindCount++; sVBOActive = true; - - llassert(!mGLArray || sGLRenderArray == mGLArray); - ret = true; } @@ -2056,9 +1729,8 @@ bool LLVertexBuffer::bindGLBufferFast() bool LLVertexBuffer::bindGLIndices(bool force_bind) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - bindGLArray(); - bool ret = false; + bool ret = false; if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)))) { /*if (sMapped) @@ -2091,11 +1763,11 @@ bool LLVertexBuffer::bindGLIndicesFast() return false; } -void LLVertexBuffer::flush() +void LLVertexBuffer::flush(bool discard) { if (useVBOs()) { - unmapBuffer(); + unmapBuffer(); } } @@ -2178,20 +1850,12 @@ void LLVertexBuffer::setBuffer(U32 data_mask) if (useVBOs()) { - if (mGLArray) - { - bindGLArray(); - setup = false; //do NOT perform pointer setup if using VAO - } - else - { - const bool bindBuffer = bindGLBuffer(); - const bool bindIndices = bindGLIndices(); + const bool bindBuffer = bindGLBuffer(); + const bool bindIndices = bindGLIndices(); - setup = setup || bindBuffer || bindIndices; - } + setup = setup || bindBuffer || bindIndices; - if (gDebugGL && !mGLArray) + if (gDebugGL) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buff); @@ -2263,14 +1927,9 @@ void LLVertexBuffer::setBuffer(U32 data_mask) sGLRenderIndices = mGLIndices; } } - // Need to setup (activate/deactivate) client arrays with VAOs too - // if( !mGLArray ) - if (!sUseVAO && !mGLArray) - // - { - setupClientArrays(data_mask); - } - + + setupClientArrays(data_mask); + if (mGLBuffer) { if (data_mask && setup) @@ -2313,7 +1972,7 @@ void LLVertexBuffer::setBufferFast(U32 data_mask) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { stop_glerror(); - U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + U8* base = useVBOs() ? nullptr: mMappedData; if (gDebugGL && ((data_mask & mTypeMask) != data_mask)) { @@ -2419,8 +2078,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) } void LLVertexBuffer::setupVertexBufferFast(U32 data_mask) - { - U8* base = (U8*)mAlignedOffset; +{ + U8* base = nullptr; if (data_mask & MAP_NORMAL) { @@ -2507,12 +2166,24 @@ void LLVertexBuffer::setupVertexBufferFast(U32 data_mask) void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); } - } +} -LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count) -: mType(type), mIndex(index), mCount(count) -{ - mEnd = mIndex+mCount; -} +void LLVertexBuffer::setPositionData(const LLVector4a* data) +{ + bindGLBuffer(); + flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts(), (U8*) data); +} + +void LLVertexBuffer::setTexCoordData(const LLVector2* data) +{ + bindGLBuffer(); + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts(), (U8*)data); +} + +void LLVertexBuffer::setColorData(const LLColor4U* data) +{ + bindGLBuffer(); + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts(), (U8*) data); +} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 38e290e501..130bcdc2ee 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -50,67 +50,16 @@ // called from the main (i.e OpenGL) thread) -//============================================================================ -// gl name pools for dynamic and streaming buffers -class LLVBOPool -{ -public: - static U32 sBytesPooled; - static U32 sIndexBytesPooled; - - LLVBOPool(U32 vboUsage, U32 vboType); - - const U32 mUsage; - const U32 mType; - - //size MUST be a power of 2 - U8* allocate(U32& name, U32 size, bool for_seed = false); - - //size MUST be the size provided to allocate that returned the given name - void release(U32 name, U8* buffer, U32 size); - - //batch allocate buffers to be provided to the application on demand - void seedPool(); - - //destroy all records in mFreeList - void cleanup(); - - U32 genBuffer(); - void deleteBuffer(U32 name); - - class Record - { - public: - U32 mGLName; - U8* mClientData; - }; - - typedef std::list record_list_t; - std::vector mFreeList; - std::vector mMissCount; - bool mMissCountDirty; // flag any changes to mFreeList or mMissCount - - //used to avoid calling glGenBuffers for every VBO creation - static U32 sNamePool[1024]; - static U32 sNameIdx; -}; - - //============================================================================ // base class class LLPrivateMemoryPool; class LLVertexBuffer : public LLRefCount { public: - class MappedRegion + struct MappedRegion { - public: - S32 mType; - S32 mIndex; - S32 mCount; - S32 mEnd; - - MappedRegion(S32 type, S32 index, S32 count); + S32 mStart; + S32 mEnd; }; LLVertexBuffer(const LLVertexBuffer& rhs) @@ -125,12 +74,6 @@ public: return *this; } - static LLVBOPool sStreamVBOPool; - static LLVBOPool sDynamicVBOPool; - static LLVBOPool sDynamicCopyVBOPool; - static LLVBOPool sStreamIBOPool; - static LLVBOPool sDynamicIBOPool; - static std::list sAvailableVAOName; static U32 sCurVAOName; @@ -138,12 +81,10 @@ public: static bool sUseVAO; static bool sPreferStreamDraw; - static void seedPools(); - static U32 getVAOName(); static void releaseVAOName(U32 name); - static void initClass(bool use_vbo, bool no_vbo_mapping); + static void initClass(LLWindow* window); static void cleanupClass(); static void setupClientArrays(U32 data_mask); static void drawArrays(U32 mode, const std::vector& pos); @@ -166,8 +107,7 @@ public: // 4 - modify LLVertexBuffer::setupVertexBuffer // 5 - modify LLVertexBuffer::setupVertexBufferFast // 6 - modify LLViewerShaderMgr::mReservedAttribs - // 7 - update LLVertexBuffer::setupVertexArray - + // clang-format off enum { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms() TYPE_VERTEX = 0, // "position" @@ -212,15 +152,12 @@ protected: virtual void setupVertexBuffer(U32 data_mask); void setupVertexBufferFast(U32 data_mask); - void setupVertexArray(); - void genBuffer(U32 size); void genIndices(U32 size); bool bindGLBuffer(bool force_bind = false); bool bindGLBufferFast(); bool bindGLIndices(bool force_bind = false); bool bindGLIndicesFast(); - bool bindGLArray(); void releaseBuffer(); void releaseIndices(); bool createGLBuffer(U32 size); @@ -244,7 +181,7 @@ public: virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 void setBufferFast(U32 data_mask); // calls setupVertexBufferFast(), assumes data_mask is not 0 among other assumptions - void flush(); //flush pending data to GL memory + void flush(bool discard = false); //flush pending data to GL memory, if discard is true, discard previous VBO // allocate buffer bool allocateBuffer(S32 nverts, S32 nindices, bool create); virtual bool resizeBuffer(S32 newnverts, S32 newnindices); @@ -279,6 +216,10 @@ public: bool getMetallicRoughnessTexcoordStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); bool getEmissiveTexcoordStrider(LLStrider& strider, S32 index=0, S32 count = -1, bool map_range = false); + void setPositionData(const LLVector4a* data); + void setTexCoordData(const LLVector2* data); + void setColorData(const LLColor4U* data); + bool useVBOs() const; bool isEmpty() const { return mEmpty; } @@ -286,8 +227,8 @@ public: S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } - U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } - U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + U8* getIndicesPointer() const { return useVBOs() ? nullptr : mMappedIndexData; } + U8* getVerticesPointer() const { return useVBOs() ? nullptr : mMappedData; } U32 getTypeMask() const { return mTypeMask; } bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } S32 getSize() const; @@ -296,7 +237,7 @@ public: U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } - bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW) ? true : false; } + bool isWriteable() const { return (mUsage == GL_STREAM_DRAW) ? true : false; } void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; @@ -314,21 +255,19 @@ public: protected: + U32 mGLBuffer; // GL VBO handle + U32 mGLIndices; // GL IBO handle + + U32 mTypeMask; + S32 mNumVerts; // Number of vertices allocated S32 mNumIndices; // Number of indices allocated - - ptrdiff_t mAlignedOffset; - ptrdiff_t mAlignedIndexOffset; + S32 mSize; S32 mIndicesSize; - U32 mTypeMask; const S32 mUsage; // GL usage - - U32 mGLBuffer; // GL VBO handle - U32 mGLIndices; // GL IBO handle - U32 mGLArray; // GL VAO handle - + U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) @@ -339,18 +278,11 @@ protected: U32 mFinal : 1; // if true, buffer can not be mapped again U32 mEmpty : 1; // if true, client buffer is empty (or NULL). Old values have been discarded. - mutable bool mMappable; // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) - S32 mOffsets[TYPE_MAX]; std::vector mMappedVertexRegions; std::vector mMappedIndexRegions; - mutable LLGLFence* mFence; - - void placeFence() const; - void waitFence() const; - static S32 determineUsage(S32 usage); private: diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl deleted file mode 100644 index c2372fcbc0..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file attachmentAlphaMaskShadowF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform float minimum_alpha; - -uniform sampler2D diffuseMap; - -VARYING vec4 post_pos; -VARYING vec2 vary_texcoord0; -VARYING float pos_w; -VARYING float target_pos_x; -VARYING vec4 vertex_color; - -void main() -{ - float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a; - - if (alpha < 0.05) // treat as totally transparent - { - discard; - } - - if (alpha < minimum_alpha) // treat as semi-transparent - { - //if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25) - { - discard; - } - } - - frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl deleted file mode 100644 index d0a049d372..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file attachmentAlphaShadowF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform float minimum_alpha; -uniform sampler2D diffuseMap; - -VARYING float pos_w; -VARYING float target_pos_x; - -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif - -VARYING vec2 vary_texcoord0; -VARYING vec4 vertex_color; - -void main() -{ - float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a; - - if (alpha < 0.05) // treat as totally transparent - { - discard; - } - - if (alpha < minimum_alpha) - { - if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25) - { - discard; - } - } - - frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif - -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl deleted file mode 100644 index a7bf4d7780..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file attachmentAlphaShadowV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 projection_matrix; -uniform mat4 modelview_matrix; -uniform mat4 texture_matrix0; -uniform float shadow_target_width; - -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec2 texcoord0; - -mat4 getObjectSkinnedTransform(); -void passTextureIndex(); - -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif -VARYING vec2 vary_texcoord0; -VARYING float pos_w; -VARYING float target_pos_x; -VARYING vec4 vertex_color; - -void main() -{ - //transform vertex - mat4 mat = getObjectSkinnedTransform(); - - mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - vec4 p = projection_matrix * vec4(pos, 1.0); - - pos_w = p.w; - - target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x; - - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - vertex_color = diffuse_color; - -#if !defined(DEPTH_CLAMP) - p.z = max(p.z, -p.w+0.01); - post_pos = p; - gl_Position = p; -#else - gl_Position = p; -#endif - - passTextureIndex(); -} - diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl index f231213ac8..44f67899e4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl @@ -32,10 +32,6 @@ out vec4 frag_color; uniform float minimum_alpha; uniform sampler2D diffuseMap; -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif - VARYING float target_pos_x; VARYING float pos_w; VARYING vec2 vary_texcoord0; @@ -58,8 +54,4 @@ void main() } frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl index 0e66c722b6..9a0024ede9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl @@ -33,10 +33,6 @@ uniform float minimum_alpha; uniform sampler2D diffuseMap; -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif - VARYING float pos_w; VARYING float target_pos_x; VARYING vec2 vary_texcoord0; @@ -60,9 +56,4 @@ void main() } frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl index 40ac7b1f95..dfe7077db5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl @@ -34,9 +34,6 @@ ATTRIBUTE vec3 position; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif VARYING float pos_w; VARYING float target_pos_x; VARYING vec2 vary_texcoord0; @@ -66,13 +63,7 @@ void main() vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; -#if !defined(DEPTH_CLAMP) - post_pos = pos; - - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else gl_Position = pos; -#endif passTextureIndex(); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 50020a50d8..0c386ade6c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -25,24 +25,12 @@ /*[EXTRA_CODE_HERE]*/ -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif uniform sampler2D diffuseMap; -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif - void main() { frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl index 91b25613e0..ac8a483a6a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -31,10 +31,6 @@ ATTRIBUTE vec3 position; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif - void main() { vec4 pos; @@ -53,13 +49,7 @@ void main() norm = normalize(norm); pos = projection_matrix * pos; -#if !defined(DEPTH_CLAMP) - post_pos = pos; - - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else gl_Position = pos; -#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl index 06ebeb8281..68e9addc1b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -69,8 +69,4 @@ void main() #endif frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl index 2b17aea75a..61c9e60744 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl @@ -57,11 +57,7 @@ void main() post_pos = pos; -#if !defined(DEPTH_CLAMP) - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else gl_Position = pos; -#endif passTextureIndex(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl index b6a0f0b165..40f8fc9894 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl @@ -47,11 +47,7 @@ void main() post_pos = pos; -#if !defined(DEPTH_CLAMP) - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else gl_Position = pos; -#endif passTextureIndex(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl index 0e74d2eb8a..9608e89169 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl @@ -27,10 +27,6 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; -#if !defined(DEPTH_CLAMP) -VARYING vec4 post_pos; -#endif - uniform vec3 box_center; uniform vec3 box_size; @@ -40,11 +36,5 @@ void main() vec3 p = position*box_size+box_center; vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0); -#if !defined(DEPTH_CLAMP) - post_pos = pos; - - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else gl_Position = pos; -#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index 1ea96918bb..406a7ef3b3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -25,20 +25,9 @@ /*[EXTRA_CODE_HERE]*/ -#ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -VARYING vec4 post_pos; void main() { frag_color = vec4(1,1,1,1); - -#if !defined(DEPTH_CLAMP) - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); -#endif - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl index bdf8e0854d..186ba49969 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl @@ -28,8 +28,6 @@ uniform mat4 projection_matrix; ATTRIBUTE vec3 position; -VARYING vec4 post_pos; - mat4 getObjectSkinnedTransform(); void main() @@ -41,12 +39,5 @@ void main() vec4 pos = (mat*vec4(position.xyz, 1.0)); pos = projection_matrix*pos; - post_pos = pos; - -#if !defined(DEPTH_CLAMP) - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else gl_Position = pos; -#endif - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index 72bd0f0f34..bd62954ff8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -25,21 +25,10 @@ uniform mat4 modelview_projection_matrix; -ATTRIBUTE vec3 position; - -VARYING vec4 post_pos; +in vec3 position; void main() { //transform vertex - vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0); - - post_pos = pos; - -#if !defined(DEPTH_CLAMP) - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); -#else - gl_Position = pos; -#endif - + gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl index e34d75ba1d..c850a39d6f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl @@ -25,18 +25,14 @@ /*[EXTRA_CODE_HERE]*/ -#ifdef DEFINE_GL_FRAGCOLOR + out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif uniform float minimum_alpha; uniform sampler2D diffuseMap; -VARYING vec4 post_pos; -VARYING vec2 vary_texcoord0; +in vec2 vary_texcoord0; void main() { @@ -48,6 +44,4 @@ void main() } frag_color = vec4(1,1,1,1); - - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl index d9ca6d3a46..5a7cf369b5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl @@ -30,8 +30,7 @@ uniform mat4 projection_matrix; ATTRIBUTE vec3 position; ATTRIBUTE vec2 texcoord0; -VARYING vec4 post_pos; -VARYING vec2 vary_texcoord0; +out vec2 vary_texcoord0; mat4 getObjectSkinnedTransform(); @@ -43,11 +42,7 @@ void main() mat = modelview_matrix * mat; vec4 pos = mat * vec4(position.xyz, 1.0); - pos = projection_matrix * pos; - - post_pos = pos; - - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); + gl_Position = projection_matrix * pos; vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl index e472a75304..3102c870fc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowV.glsl @@ -26,20 +26,15 @@ uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; -ATTRIBUTE vec3 position; -ATTRIBUTE vec2 texcoord0; +in vec3 position; +in vec2 texcoord0; -VARYING vec4 post_pos; -VARYING vec2 vary_texcoord0; +out vec2 vary_texcoord0; void main() { //transform vertex - vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0); - - post_pos = pos; - - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); + gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/interface/copyF.glsl similarity index 77% rename from indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl rename to indra/newview/app_settings/shaders/class1/interface/copyF.glsl index 8e9a5fcd41..65d3c20091 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/copyF.glsl @@ -1,8 +1,9 @@ /** - * @file avatarShadowF.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * @file copyF.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. + * Copyright (C) 2023, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,20 +23,18 @@ * $/LicenseInfo$ */ -/*[EXTRA_CODE_HERE]*/ - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif +in vec2 tc; +uniform sampler2D depthMap; uniform sampler2D diffuseMap; -VARYING vec2 vary_texcoord0; +out vec4 frag_color; void main() { - frag_color = vec4(1,1,1,1); + frag_color = texture(diffuseMap, tc); +#if defined(COPY_DEPTH) + gl_FragDepth = texture(depthMap, tc).r; +#endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/interface/copyV.glsl similarity index 58% rename from indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl rename to indra/newview/app_settings/shaders/class1/interface/copyV.glsl index 0fa0edfd67..ace5da6578 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/copyV.glsl @@ -1,8 +1,9 @@ /** - * @file attachmentShadowV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * @file copyV.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. + * Copyright (C) 2023, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,29 +23,12 @@ * $/LicenseInfo$ */ -uniform mat4 projection_matrix; -uniform mat4 modelview_matrix; -uniform mat4 texture_matrix0; -ATTRIBUTE vec3 position; -ATTRIBUTE vec2 texcoord0; +in vec3 position; +out vec2 tc; -mat4 getObjectSkinnedTransform(); - -void main() +void main() { - //transform vertex - mat4 mat = getObjectSkinnedTransform(); - - mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - - vec4 p = projection_matrix * vec4(pos, 1.0); -#if !defined(DEPTH_CLAMP) - p.z = max(p.z, -p.w+0.01); - gl_Position = p; -#else - gl_Position = p; -#endif + tc = position.xy * 0.5 + 0.5; + gl_Position = vec4(position, 1.0); } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index a50982e8c4..159efebc29 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -398,12 +398,12 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL t if (pparams) { // Capture render times - if(pparams->mFace) + if (pparams->mFace) { LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) + if (vobj->isAttachment()) { - trackAttachments( vobj, false,&ratPtr); + trackAttachments(vobj, false,&ratPtr); } } // @@ -420,22 +420,22 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, U64 lastMeshId = 0; mask |= LLVertexBuffer::MAP_WEIGHT4; - std::unique_ptr ratPtr{}; // Perf stats + std::unique_ptr ratPtr{}; // Perf stats for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo* pparams = *k; if (pparams) { - // Capture render times - if(pparams->mFace) - { - LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) - { - trackAttachments( vobj, true ,&ratPtr); - } - } - // + // Capture render times + if (pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if (vobj->isAttachment()) + { + trackAttachments(vobj, true ,&ratPtr); + } + } + // if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) { uploadMatrixPalette(*pparams); @@ -472,10 +472,14 @@ void teardown_texture_matrix(LLDrawInfo& params) void LLRenderPass::pushGLTFBatches(U32 type, U32 mask) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushGLTFBatch"); LLDrawInfo& params = **i; + LLCullResult::increment_iterator(i, end); + auto& mat = params.mGLTFMaterial; mat->bind(); @@ -499,10 +503,14 @@ void LLRenderPass::pushRiggedGLTFBatches(U32 type, U32 mask) LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; mask |= LLVertexBuffer::MAP_WEIGHT4; - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("pushRiggedGLTFBatch"); LLDrawInfo& params = **i; + LLCullResult::increment_iterator(i, end); + auto& mat = params.mGLTFMaterial; mat->bind(); @@ -530,24 +538,25 @@ void LLRenderPass::pushRiggedGLTFBatches(U32 type, U32 mask) void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - std::unique_ptr ratPtr{}; - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) - { - LLDrawInfo* pparams = *i; - if (pparams) - { - // Capture render times - if(pparams->mFace) - { - LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) - { - trackAttachments( vobj, false, &ratPtr); - } - } - // - pushBatch(*pparams, mask, texture, batch_textures); - } + std::unique_ptr ratPtr{}; + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) + { + LLDrawInfo* pparams = *i; + LLCullResult::increment_iterator(i, end); + // Capture render times + if (pparams && pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if (vobj->isAttachment()) + { + trackAttachments(vobj, false, &ratPtr); + } + } + // + + pushBatch(*pparams, mask, texture, batch_textures); } } @@ -557,56 +566,58 @@ void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batc LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; mask |= LLVertexBuffer::MAP_WEIGHT4; - std::unique_ptr ratPtr{}; // Perf stats - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + std::unique_ptr ratPtr{}; // Perf stats + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LLDrawInfo* pparams = *i; - if (pparams) - { - // Capture render times - if(pparams->mFace) - { - LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) - { - trackAttachments( vobj, true, &ratPtr); - } - } - // - if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)) - { - uploadMatrixPalette(*pparams); - lastAvatar = pparams->mAvatar; - lastMeshId = pparams->mSkinInfo->mHash; - } + LLCullResult::increment_iterator(i, end); - pushBatch(*pparams, mask, texture, batch_textures); + // Capture render times + if (pparams && pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if (vobj->isAttachment()) + { + trackAttachments(vobj, true, &ratPtr); + } } + // + + if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)) + { + uploadMatrixPalette(*pparams); + lastAvatar = pparams->mAvatar; + lastMeshId = pparams->mSkinInfo->mHash; + } + + pushBatch(*pparams, mask, texture, batch_textures); } } void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - std::unique_ptr ratPtr{}; - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + std::unique_ptr ratPtr{}; + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { - LLDrawInfo* pparams = *i; - if (pparams) - { - // Capture render times - if((*pparams).mFace) - { - LLViewerObject* vobj = (*pparams).mFace->getViewerObject(); - if(vobj->isAttachment()) - { - trackAttachments( vobj, false, &ratPtr); - } - } - // - LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); - pushBatch(*pparams, mask, texture, batch_textures); - } + LLDrawInfo* pparams = *i; + LLCullResult::increment_iterator(i, end); + // Capture render times + if (pparams && pparams->mFace) + { + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if (vobj->isAttachment()) + { + trackAttachments(vobj, false, &ratPtr); + } + } + // + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); + pushBatch(*pparams, mask, texture, batch_textures); } } @@ -615,40 +626,43 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture, BOOL LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; - std::unique_ptr ratPtr{}; - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + std::unique_ptr ratPtr{}; + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LLDrawInfo* pparams = *i; - if (pparams) + + LLCullResult::increment_iterator(i, end); + + // Capture render times + if (pparams && pparams->mFace) { - // Capture render times - if((*pparams).mFace) - { - LLViewerObject* vobj = (*pparams).mFace->getViewerObject(); - if(vobj->isAttachment()) - { - trackAttachments( vobj, true, &ratPtr); - } - } - // - if (LLGLSLShader::sCurBoundShaderPtr) + LLViewerObject* vobj = pparams->mFace->getViewerObject(); + if (vobj->isAttachment()) { - LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); + trackAttachments(vobj, true, &ratPtr); } - else - { - gGL.flush(); - } - - if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) - { - uploadMatrixPalette(*pparams); - lastAvatar = pparams->mAvatar; - lastMeshId = pparams->mSkinInfo->mHash; - } - - pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_textures); } + // + + if (LLGLSLShader::sCurBoundShaderPtr) + { + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); + } + else + { + gGL.flush(); + } + + if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) + { + uploadMatrixPalette(*pparams); + lastAvatar = pparams->mAvatar; + lastMeshId = pparams->mSkinInfo->mHash; + } + + pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_textures); } } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index da13cf31c1..2e302e8e49 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -642,6 +642,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) begin = gPipeline.beginAlphaGroups(); end = gPipeline.endAlphaGroups(); } + + LLEnvironment& env = LLEnvironment::instance(); + F32 water_height = env.getWaterHeight(); + + bool above_water = getType() == LLDrawPool::POOL_ALPHA_POST_WATER; + if (LLPipeline::sUnderWaterRender) + { + above_water = !above_water; + } + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { @@ -653,6 +663,25 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { + + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); + const LLVector4a* ext = bridge ? bridge->getSpatialExtents() : group->getExtents(); + + if (above_water) + { // reject any spatial groups that have no part above water + if (ext[1].getF32ptr()[2] < water_height) + { + continue; + } + } + else + { // reject any spatial groups that he no part below water + if (ext[0].getF32ptr()[2] > water_height) + { + continue; + } + } + static std::vector emissives; static std::vector rigged_emissives; emissives.resize(0); @@ -686,7 +715,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) continue; } - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch") + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("ra - push batch"); U32 have_mask = params.mVertexBuffer->getTypeMask() & mask; if (have_mask != mask) diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 5cef9dd34b..4124de67df 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -742,22 +742,22 @@ void LLDrawPoolBump::renderDeferred(S32 pass) U64 skin = 0; std::unique_ptr ratPtr{}; // render time capture - for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LLDrawInfo& params = **i; + LLCullResult::increment_iterator(i, end); // Capture render times - if(params.mFace) + if (params.mFace) { LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); - if(vobj && vobj->isAttachment()) + if (vobj && vobj->isAttachment()) { - trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + trackAttachments(vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); } } // - LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff); LLDrawPoolBump::bindBumpMap(params, bump_channel); diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 32c22ad9ca..240f134107 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -205,23 +205,25 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) LLVOAvatar* lastAvatar = nullptr; std::unique_ptr ratPtr{}; // render time capture - for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LL_PROFILE_ZONE_NAMED_CATEGORY_MATERIAL("materials draw loop"); LLDrawInfo& params = **i; // Capture render times - if(params.mFace) + if (params.mFace) { LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); - if( vobj && vobj->isAttachment() ) + if (vobj && vobj->isAttachment() ) { - trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); + trackAttachments(vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr); } } // + LLCullResult::increment_iterator(i, end); + if (specular > -1 && params.mSpecColor != lastSpecular) { lastSpecular = params.mSpecColor; diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index e558ab39f1..eb0ad0b758 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -137,11 +137,28 @@ void LLDrawPoolWater::beginPostDeferredPass(S32 pass) // reflections and refractions LLRenderTarget& src = gPipeline.mRT->screen; LLRenderTarget& dst = gPipeline.mWaterDis; + +#if 0 dst.copyContents(src, 0, 0, src.getWidth(), src.getHeight(), 0, 0, dst.getWidth(), dst.getHeight(), GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); +#else + dst.bindTarget(); + gCopyDepthProgram.bind(); + + S32 diff_map = gCopyDepthProgram.enableTexture(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH); + + gGL.getTexUnit(diff_map)->bind(&src); + gGL.getTexUnit(depth_map)->bind(&src, true); + + gPipeline.mScreenTriangleVB->setBuffer(LLVertexBuffer::MAP_VERTEX); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + dst.flush(); +#endif } } diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index a4cfa6f22e..132117943e 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -665,6 +665,8 @@ std::vector* LLFilePicker::navOpenFilterProc(ELoadFilter filter) // allowedv->push_back("dic"); allowedv->push_back("xcu"); allowedv->push_back("gif"); + allowedv->push_back("gltf"); + allowedv->push_back("glb"); allowedv->push_back("xml"); // Import filter allowedv->push_back("oxp"); diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp index 95d6a2d652..4d11399867 100644 --- a/indra/newview/llfloaterenvironmentadjust.cpp +++ b/indra/newview/llfloaterenvironmentadjust.cpp @@ -62,6 +62,7 @@ namespace const std::string FIELD_SKY_MOON_ROTATION("moon_rotation"); const std::string FIELD_SKY_MOON_AZIMUTH("moon_azimuth"); const std::string FIELD_SKY_MOON_ELEVATION("moon_elevation"); + const std::string FIELD_REFLECTION_PROBE_AMBIANCE("probe_ambiance"); const std::string BTN_RESET("btn_reset"); const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f); @@ -117,6 +118,8 @@ BOOL LLFloaterEnvironmentAdjust::postBuild() getChild(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(LLUUID(gSavedSettings.getString("DefaultBlankNormalTexture"))); getChild(FIELD_WATER_NORMAL_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onWaterMapChanged(); }); + getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); }); + refresh(); return TRUE; } @@ -171,6 +174,8 @@ void LLFloaterEnvironmentAdjust::refresh() getChild(FIELD_SKY_CLOUD_MAP)->setValue(mLiveSky->getCloudNoiseTextureId()); getChild(FIELD_WATER_NORMAL_MAP)->setValue(mLiveWater->getNormalMapID()); + getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->setValue(mLiveSky->getReflectionProbeAmbiance()); + LLColor3 glow(mLiveSky->getGlow()); // takes 40 - 0.2 range -> 0 - 1.99 UI range @@ -468,6 +473,13 @@ void LLFloaterEnvironmentAdjust::onSunColorChanged() mLiveSky->update(); } +void LLFloaterEnvironmentAdjust::onReflectionProbeAmbianceChanged() +{ + if (!mLiveSky) return; + F32 ambiance = getChild(FIELD_REFLECTION_PROBE_AMBIANCE)->getValue().asReal(); + mLiveSky->setReflectionProbeAmbiance(ambiance); + mLiveSky->update(); +} void LLFloaterEnvironmentAdjust::onEnvironmentUpdated(LLEnvironment::EnvSelection_t env, S32 version) { diff --git a/indra/newview/llfloaterenvironmentadjust.h b/indra/newview/llfloaterenvironmentadjust.h index 05ff011be5..43c0ba0495 100644 --- a/indra/newview/llfloaterenvironmentadjust.h +++ b/indra/newview/llfloaterenvironmentadjust.h @@ -82,6 +82,8 @@ private: void onCloudMapChanged(); void onWaterMapChanged(); + void onReflectionProbeAmbianceChanged(); + void onButtonReset(); void onEnvironmentUpdated(LLEnvironment::EnvSelection_t env, S32 version); diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index d04a674e91..9399342a61 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -297,7 +297,7 @@ public: // object not ready to receive override data, queue for later gGLTFMaterialList.queueOverrideUpdate(object_override.mObjectId, results[i].mSide, results[i].mMaterial); } - else if (obj && obj->getTE(i) && obj->getTE(i)->isSelected()) + else if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected()) { doSelectionCallbacks(object_override.mObjectId, results[i].mSide); } @@ -305,7 +305,7 @@ public: else { // unblock material editor - if (obj && obj->getTE(i) && obj->getTE(i)->isSelected()) + if (obj && obj->getTE(results[i].mSide) && obj->getTE(results[i].mSide)->isSelected()) { doSelectionCallbacks(object_override.mObjectId, results[i].mSide); } @@ -404,9 +404,19 @@ void LLGLTFMaterialList::queueModify(const LLUUID& id, S32 side, const LLGLTFMat } } -void LLGLTFMaterialList::queueApply(const LLUUID& object_id, S32 side, const LLUUID& asset_id) +void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id) { - sApplyQueue.push_back({ object_id, side, asset_id}); + const LLGLTFMaterial* material_override = obj->getTE(side)->getGLTFMaterialOverride(); + if (material_override) + { + LLGLTFMaterial* cleared_override = new LLGLTFMaterial(*material_override); + cleared_override->setBaseMaterial(); + sApplyQueue.push_back({ obj->getID(), side, asset_id, cleared_override }); + } + else + { + sApplyQueue.push_back({ obj->getID(), side, asset_id, nullptr }); + } } void LLGLTFMaterialList::queueUpdate(const LLSD& data) @@ -436,6 +446,11 @@ void LLGLTFMaterialList::flushUpdates(void(*done_callback)(bool)) { data[i]["gltf_json"] = e.override_data.asJSON(); } + else + { + // Clear all overrides + data[i]["gltf_json"] = ""; + } llassert(is_valid_update(data[i])); ++i; @@ -447,7 +462,15 @@ void LLGLTFMaterialList::flushUpdates(void(*done_callback)(bool)) data[i]["object_id"] = e.object_id; data[i]["side"] = e.side; data[i]["asset_id"] = e.asset_id; - data[i]["gltf_json"] = ""; // null out any existing overrides when applying a material asset + if (e.override_data) + { + data[i]["gltf_json"] = e.override_data->asJSON(); + } + else + { + // Clear all overrides + data[i]["gltf_json"] = ""; + } llassert(is_valid_update(data[i])); ++i; diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index abbb755599..70540e5e01 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -59,7 +59,7 @@ public: // side - TexureEntry index to modify, or -1 for all sides // mat - material to apply as override, or nullptr to remove existing overrides and revert to asset // - // NOTE: do not use to revert to asset when applying a new asset id, use queueApplyMaterialAsset below + // NOTE: do not use to revert to asset when applying a new asset id, use queueApply below static void queueModify(const LLUUID& id, S32 side, const LLGLTFMaterial* mat); // Queue an application of a material asset we want to send to the simulator. Call "flushUpdates" to flush pending updates. @@ -67,8 +67,8 @@ public: // side - TextureEntry index to apply material to, or -1 for all sides // asset_id - ID of material asset to apply, or LLUUID::null to disassociate current material asset // - // NOTE: implicitly removes any override data if present - static void queueApply(const LLUUID& object_id, S32 side, const LLUUID& asset_id); + // NOTE: Implicitly clears most override data if present + static void queueApply(const LLViewerObject* obj, S32 side, const LLUUID& asset_id); // flush pending material updates to the simulator // Automatically called once per frame, but may be called explicitly @@ -136,6 +136,7 @@ protected: LLUUID object_id; S32 side = -1; LLUUID asset_id; + LLPointer override_data; }; typedef std::list apply_queue_t; diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 2e57c35326..dbbd6edb7d 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1324,7 +1324,16 @@ bool LLMaterialEditor::updateInventoryItem(const std::string &buffer, const LLUU // done callback LLMaterialEditor::finishInventoryUpload(itemId, newAssetId, newItemId); }, - nullptr // failure callback + [](LLUUID itemId, LLUUID taskId, LLSD response, std::string reason) + { + // failure callback + LLMaterialEditor* me = LLFloaterReg::findTypedInstance("material_editor", LLSD(itemId)); + if (me) + { + me->setEnabled(true); + } + return true; + } ); url = agent_url; } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7c6596e7a4..181d43c116 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -4685,8 +4685,8 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) tep->setGLTFRenderMaterial(nullptr); tep->setGLTFMaterialOverride(nullptr); - // blank out any override data on the server - LLGLTFMaterialList::queueApply(objectp->getID(), te, LLUUID::null); + // blank out most override data on the server + LLGLTFMaterialList::queueApply(objectp, te, LLUUID::null); } // Texture map diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 4da89ff182..399b4a1dc0 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1892,11 +1892,9 @@ void LLObjectSelection::applyNoCopyPbrMaterialToTEs(LLViewerInventoryItem* item) } // apply texture for the selected faces + // blank out most override data on the server //add(LLStatViewer::EDIT_TEXTURE, 1); - object->setRenderMaterialID(te, asset_id, false /*will be sent later*/); - - // blank out any override data on the server - LLGLTFMaterialList::queueApply(object->getID(), te, asset_id); + object->setRenderMaterialID(te, asset_id); } } } @@ -2035,10 +2033,8 @@ void LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) objectp->setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, TRUE, false /*prevent an update*/); } - objectp->setRenderMaterialID(te, asset_id, false /*prevent an update to prevent a race condition*/); - - // blank out any override data on the server - LLGLTFMaterialList::queueApply(objectp->getID(), te, asset_id); + // Blank out most override data on the object and send to server + objectp->setRenderMaterialID(te, asset_id); return true; } @@ -2309,17 +2305,12 @@ void LLSelectMgr::selectionRevertGLTFMaterials() && asset_id.notNull()) { // Restore overrides - LLSD overrides; - overrides["object_id"] = objectp->getID(); - overrides["side"] = te; - - overrides["gltf_json"] = nodep->mSavedGLTFOverrideMaterials[te]->asJSON(); - LLGLTFMaterialList::queueUpdate(overrides); + LLGLTFMaterialList::queueModify(objectp->getID(), te, nodep->mSavedGLTFOverrideMaterials[te]); } else { //blank override out - LLGLTFMaterialList::queueApply(objectp->getID(), te, asset_id); + LLGLTFMaterialList::queueApply(objectp, te, asset_id); } } @@ -6056,7 +6047,6 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data if (can_copy && can_transfer) { - // this should be the only place that saved textures is called node->saveTextures(texture_ids); } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 371679cf2c..15f73ed056 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2924,42 +2924,6 @@ void renderBatchSize(LLDrawInfo* params) } } -void renderShadowFrusta(LLDrawInfo* params) -{ - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLVector4a center; - center.setAdd(params->mExtents[1], params->mExtents[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(params->mExtents[1],params->mExtents[0]); - size.mul(0.5f); - - if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(1,0,0); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(0,1,0); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(0,0,1); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size)) - { - gGL.diffuseColor3f(1,0,1); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - - gGL.setSceneBlendType(LLRender::BT_ALPHA); -} - void renderTexelDensity(LLDrawable* drawable) { if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF @@ -3548,10 +3512,6 @@ public: { renderBatchSize(draw_info); } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) - { - renderShadowFrusta(draw_info); - } } } } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 8cfccfd21b..639c7061bf 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -98,8 +98,6 @@ public: // return mSkinHash->mHash, or 0 if mSkinHash is null U64 getSkinHash(); - LLVector4a mExtents[2]; - LLPointer mVertexBuffer; LLPointer mTexture; std::vector > mTextureList; @@ -516,6 +514,23 @@ public: typedef LLDrawInfo** drawinfo_iterator; typedef LLDrawable** drawable_iterator; + // Helper function for taking advantage of _mm_prefetch when iterating over cull results + static inline void increment_iterator(LLCullResult::drawinfo_iterator& i, const LLCullResult::drawinfo_iterator& end) + { + ++i; + + if (i != end) + { + _mm_prefetch((char*)(*i)->mVertexBuffer.get(), _MM_HINT_NTA); + + auto* ni = i + 1; + if (ni != end) + { + _mm_prefetch((char*)*ni, _MM_HINT_NTA); + } + } + } + void clear(); sg_iterator beginVisibleGroups(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index edb643ccc0..6071077bc9 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2164,24 +2164,101 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject( { if (cargo_type == DAD_TEXTURE) { + LLSelectNode *nodep = nullptr; + if (obj->isSelected()) + { + // update object's saved textures + nodep = LLSelectMgr::getInstance()->getSelection()->findNode(obj); + } + if((mask & MASK_SHIFT)) { dropTextureAllFaces(obj, item, mSource, mSourceID); + + // If user dropped a texture onto face it implies + // applying texture now without cancel, save to selection + if (nodep) + { + uuid_vec_t texture_ids; + S32 num_faces = obj->getNumTEs(); + for (S32 face = 0; face < num_faces; face++) + { + LLViewerTexture *tex = obj->getTEImage(face); + if (tex != nullptr) + { + texture_ids.push_back(tex->getID()); + } + else + { + texture_ids.push_back(LLUUID::null); + } + } + nodep->saveTextures(texture_ids); + } } else { dropTextureOneFace(obj, face, item, mSource, mSourceID); + + // If user dropped a texture onto face it implies + // applying texture now without cancel, save to selection + LLPanelFace* panel_face = gFloaterTools->getPanelFace(); + if (nodep + && gFloaterTools->getVisible() + && panel_face + && panel_face->getTextureDropChannel() == 0 /*texture*/ + && nodep->mSavedGLTFMaterialIds.size() > face) + { + LLViewerTexture *tex = obj->getTEImage(face); + if (tex != nullptr) + { + nodep->mSavedTextures[face] = tex->getID(); + } + else + { + nodep->mSavedTextures[face] = LLUUID::null; + } + } } } else if (cargo_type == DAD_MATERIAL) { + LLSelectNode *nodep = nullptr; + if (obj->isSelected()) + { + // update object's saved materials + nodep = LLSelectMgr::getInstance()->getSelection()->findNode(obj); + } + + // If user dropped a material onto face it implies + // applying texture now without cancel, save to selection if ((mask & MASK_SHIFT)) { dropMaterialAllFaces(obj, item, mSource, mSourceID); + + if (nodep) + { + uuid_vec_t material_ids; + S32 num_faces = obj->getNumTEs(); + for (S32 face = 0; face < num_faces; face++) + { + material_ids.push_back(obj->getRenderMaterialID(face)); + } + nodep->saveGLTFMaterialIds(material_ids); + } } else { dropMaterialOneFace(obj, face, item, mSource, mSourceID); + + // If user dropped a material onto face it implies + // applying texture now without cancel, save to selection + if (nodep + && gFloaterTools->getVisible() + && nodep->mSavedGLTFMaterialIds.size() > face) + { + nodep->mSavedGLTFMaterialIds[face] = obj->getRenderMaterialID(face); + } } } else if (cargo_type == DAD_MESH) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index eb0a13abb2..7a69d4eb8f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -844,11 +844,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (!for_snapshot) { - if (gFrameCount > 1) - { //for some reason, ATI 4800 series will error out if you - //try to generate a shadow before the first frame is through - gPipeline.generateSunShadow(camera); // Factor out calls to getInstance - } + if (gFrameCount > 1 && !for_snapshot) + { //for some reason, ATI 4800 series will error out if you + //try to generate a shadow before the first frame is through + gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); + } LLVertexBuffer::unbind(); @@ -1080,8 +1080,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) else { gPipeline.renderGeom(camera, TRUE); // Factor out calls to getInstance - } - + } gGL.setColorMask(true, true); //store this frame's modelview matrix for use @@ -1111,13 +1110,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mRT->deferredScreen : gPipeline.mRT->screen); rt.flush(); - /*if (rt.sUseFBO) - { - LLRenderTarget::copyContentsToFramebuffer(rt, 0, 0, rt.getWidth(), rt.getHeight(), 0, 0, rt.getWidth(), - rt.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, - GL_NEAREST); - }*/ - if (LLPipeline::sRenderDeferred) { gPipeline.renderDeferredLighting(); @@ -1340,7 +1332,7 @@ void render_hud_attachments() LLSpatialGroup::sNoDelete = TRUE; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - gPipeline.updateCull(hud_cam, result, NULL, true); + gPipeline.updateCull(hud_cam, result, true); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); @@ -1533,6 +1525,8 @@ void render_ui(F32 zoom_factor, int subfield) // [/RLVa:KB] render_hud_attachments(); + LLGLState::checkStates(); + LLGLSDefault gls_default; LLGLSUIDefault gls_ui; { @@ -1547,6 +1541,7 @@ void render_ui(F32 zoom_factor, int subfield) if (!gDisconnected) { LL_PROFILE_ZONE_NAMED_CATEGORY_UI("UI 3D"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D); + LLGLState::checkStates(); render_ui_3d(); LLGLState::checkStates(); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 88646f8c5d..57b332734c 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7350,11 +7350,11 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat { // implementation is delicate - // if update is bound for server, should always null out GLTFRenderMaterial and GLTFMaterialOverride even if ids haven't changed + // if update is bound for server, should always null out GLTFRenderMaterial and clear GLTFMaterialOverride even if ids haven't changed // (the case where ids haven't changed indicates the user has reapplied the original material, in which case overrides should be dropped) - // otherwise, should only null out where ids have changed + // otherwise, should only null out the render material where ids or overrides have changed // (the case where ids have changed but overrides are still present is from unsynchronized updates from the simulator) - + S32 start_idx = 0; S32 end_idx = getNumTEs(); @@ -7367,6 +7367,13 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat start_idx = llmax(start_idx, 0); end_idx = llmin(end_idx, (S32) getNumTEs()); + LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); + if (!param_block && id.notNull()) + { // block doesn't exist, but it will need to + param_block = (LLRenderMaterialParams*)createNewParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL)->data; + } + + // update local state for (S32 te = start_idx; te < end_idx; ++te) { @@ -7379,17 +7386,27 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat new_material = gGLTFMaterialList.getMaterial(id); } - bool material_changed = tep->getGLTFMaterial() != new_material; + bool material_changed = !param_block || id != param_block->getMaterial(te); + + if (update_server) + { + // Clear most overrides so the render material better matches the material + // ID (preserve transforms). If overrides become passthrough, set the overrides + // to nullptr. + if (tep->setBaseMaterial()) + { + material_changed = true; + } + } if (update_server || material_changed) { tep->setGLTFRenderMaterial(nullptr); - tep->setGLTFMaterialOverride(nullptr); } if (new_material != tep->getGLTFMaterial()) { - tep->setGLTFMaterial(new_material); + tep->setGLTFMaterial(new_material, !update_server); } } @@ -7402,17 +7419,14 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat // update via ModifyMaterialParams cap (server will echo back changes) for (S32 te = start_idx; te < end_idx; ++te) { - LLGLTFMaterialList::queueApply(getID(), te, id); + // This sends a cleared version of this object's current material + // override, but the override should already be cleared due to + // calling setBaseMaterial above. + LLGLTFMaterialList::queueApply(this, te, id); } } // predictively update LLRenderMaterialParams (don't wait for server) - LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); - if (!param_block && id.notNull()) - { // block doesn't exist, but it will need to - param_block = (LLRenderMaterialParams*)createNewParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL)->data; - } - if (param_block) { // update existing parameter block for (S32 te = start_idx; te < end_idx; ++te) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3a18253dbc..cc2debe967 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -190,7 +190,7 @@ public: // set the RenderMaterialID for the given TextureEntry // te - TextureEntry index to set, or -1 for all TEs // id - asset id of material asset - // update_server - if true, will send updates to server + // update_server - if true, will send updates to server and clear most overrides void setRenderMaterialID(S32 te, const LLUUID& id, bool update_server = true); void setRenderMaterialIDs(const LLUUID& id); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index eef457a560..1ee453c02a 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -93,6 +93,8 @@ LLGLSLShader gDownsampleDepthRectProgram; LLGLSLShader gAlphaMaskProgram; LLGLSLShader gBenchmarkProgram; LLGLSLShader gReflectionProbeDisplayProgram; +LLGLSLShader gCopyProgram; +LLGLSLShader gCopyDepthProgram; //object shaders LLGLSLShader gObjectSimpleProgram; @@ -223,9 +225,6 @@ LLGLSLShader gDeferredSkinnedShadowFullbrightAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAvatarAlphaShadowProgram; LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; -LLGLSLShader gDeferredAttachmentShadowProgram; -LLGLSLShader gDeferredAttachmentAlphaShadowProgram; -LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram; LLGLSLShader gDeferredAlphaProgram; LLGLSLShader gDeferredSkinnedAlphaProgram; LLGLSLShader gDeferredAlphaImpostorProgram; @@ -1292,9 +1291,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarShadowProgram.unload(); gDeferredAvatarAlphaShadowProgram.unload(); gDeferredAvatarAlphaMaskShadowProgram.unload(); - gDeferredAttachmentShadowProgram.unload(); - gDeferredAttachmentAlphaShadowProgram.unload(); - gDeferredAttachmentAlphaMaskShadowProgram.unload(); gDeferredAvatarProgram.unload(); gDeferredAvatarAlphaProgram.unload(); gDeferredAlphaProgram.unload(); @@ -2661,7 +2657,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL); llassert(success); } - if (success) { gDeferredAvatarAlphaMaskShadowProgram.mName = "Deferred Avatar Alpha Mask Shadow Shader"; @@ -2674,43 +2669,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader"; - gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true; - - gDeferredAttachmentShadowProgram.mShaderFiles.clear(); - gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAttachmentShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredAttachmentAlphaShadowProgram.mName = "Deferred Attachment Alpha Shadow Shader"; - gDeferredAttachmentAlphaShadowProgram.mFeatures.hasObjectSkinning = true; - gDeferredAttachmentAlphaShadowProgram.mShaderFiles.clear(); - gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAttachmentAlphaShadowProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredAttachmentAlphaMaskShadowProgram.mName = "Deferred Attachment Alpha Mask Shadow Shader"; - gDeferredAttachmentAlphaMaskShadowProgram.mFeatures.hasObjectSkinning = true; - gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.clear(); - gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAttachmentAlphaMaskShadowProgram.createShader(NULL, NULL); - llassert(success); - } - if (success) { gDeferredTerrainProgram.mName = "Deferred Terrain Shader"; @@ -3938,6 +3896,27 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gReflectionProbeDisplayProgram.createShader(NULL, NULL); } + if (success) + { + gCopyProgram.mName = "Copy Shader"; + gCopyProgram.mShaderFiles.clear(); + gCopyProgram.mShaderFiles.push_back(make_pair("interface/copyV.glsl", GL_VERTEX_SHADER)); + gCopyProgram.mShaderFiles.push_back(make_pair("interface/copyF.glsl", GL_FRAGMENT_SHADER)); + gCopyProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gCopyProgram.createShader(NULL, NULL); + } + + if (success) + { + gCopyDepthProgram.mName = "Copy Depth Shader"; + gCopyDepthProgram.mShaderFiles.clear(); + gCopyDepthProgram.mShaderFiles.push_back(make_pair("interface/copyV.glsl", GL_VERTEX_SHADER)); + gCopyDepthProgram.mShaderFiles.push_back(make_pair("interface/copyF.glsl", GL_FRAGMENT_SHADER)); + gCopyDepthProgram.clearPermutations(); + gCopyDepthProgram.addPermutation("COPY_DEPTH", "1"); + gCopyDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gCopyDepthProgram.createShader(NULL, NULL); + } if (success) { diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 525df2a1ff..bb14017d38 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -164,6 +164,8 @@ extern LLGLSLShader gDownsampleDepthProgram; extern LLGLSLShader gDownsampleDepthRectProgram; extern LLGLSLShader gBenchmarkProgram; extern LLGLSLShader gReflectionProbeDisplayProgram; +extern LLGLSLShader gCopyProgram; +extern LLGLSLShader gCopyDepthProgram; //output tex0[tc0] + tex1[tc1] extern LLGLSLShader gTwoTextureAddProgram; @@ -288,9 +290,6 @@ extern LLGLSLShader gFXAAProgram; extern LLGLSLShader gDeferredPostNoDoFProgram; extern LLGLSLShader gDeferredPostGammaCorrectProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; -extern LLGLSLShader gDeferredAttachmentShadowProgram; -extern LLGLSLShader gDeferredAttachmentAlphaShadowProgram; -extern LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram; extern LLGLSLShader gDeferredAvatarAlphaShadowProgram; extern LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; extern LLGLSLShader gDeferredAlphaProgram; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 0f3e1ff791..3fb5d2b3a8 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -707,12 +707,6 @@ public: } - addText(xpos, ypos, llformat("%d MB Index Data (%d MB Pooled, %d KIndices)", LLVertexBuffer::sAllocatedIndexBytes/(1024*1024), LLVBOPool::sIndexBytesPooled/(1024*1024), LLVertexBuffer::sIndexCount/1024)); - ypos += y_inc; - - addText(xpos, ypos, llformat("%d MB Vertex Data (%d MB Pooled, %d KVerts)", LLVertexBuffer::sAllocatedBytes/(1024*1024), LLVBOPool::sBytesPooled/(1024*1024), LLVertexBuffer::sVertexCount/1024)); - ypos += y_inc; - addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount)); ypos += y_inc; @@ -2084,7 +2078,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL; // Initialize OpenGL Renderer - LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable")); + LLVertexBuffer::initClass(mWindow); LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; gGL.init(true); // Exodus vignette @@ -5307,14 +5301,11 @@ void LLViewerWindow::pickAsync( S32 x, { // "Show Debug Alpha" means no object actually transparent BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); - if (LLDrawPoolAlpha::sShowDebugAlpha) + if (LLDrawPoolAlpha::sShowDebugAlpha + || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects"))) { pick_transparent = TRUE; } - else if (in_build_mode && !gSavedSettings.getBOOL("SelectInvisibleObjects")) - { - pick_transparent = FALSE; - } LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, TRUE, pick_unselectable, callback); schedulePick(pick_info); diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 753baf0570..b2166836de 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -776,9 +776,6 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group) //facep->getTexture(), buffer, object->isSelected(), fullbright); - const LLVector4a* exts = group->getObjectExtents(); - info->mExtents[0] = exts[0]; - info->mExtents[1] = exts[1]; info->mVSize = vsize; draw_vec.push_back(info); //for alpha sorting diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index dccaf03a17..bd05e3a8a3 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -977,9 +977,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, object->isSelected(), fullbright); - const LLVector4a* exts = group->getObjectExtents(); - info->mExtents[0] = exts[0]; - info->mExtents[1] = exts[1]; info->mVSize = vsize; info->mBlendFuncDst = bf_dst; info->mBlendFuncSrc = bf_src; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 04e239b219..a5a8b99a5f 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5596,8 +5596,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mTextureListVSize[index] = vsize; } draw_vec[idx]->validate(); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); - update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); } else { @@ -5676,8 +5674,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, { //for alpha sorting facep->setDrawInfo(draw_info); } - draw_info->mExtents[0] = facep->mExtents[0]; - draw_info->mExtents[1] = facep->mExtents[1]; if (index < FACE_DO_NOT_BATCH_TEXTURES) { //initialize texture list for texture batching diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index baf1d7b00d..64f43e70ff 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -952,17 +952,13 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) S32 shadow_detail = RenderShadowDetail; bool ssao = RenderDeferredSSAO; - const U32 occlusion_divisor = 3; - //allocate deferred rendering color buffers - if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; - //if (!mRT->deferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; - if (!mRT->occlusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true, true, LLTexUnit::TT_TEXTURE, false, samples)) return false; if (!addDeferredAttachments(mRT->deferredScreen)) return false; GLuint screenFormat = GL_RGBA16; - if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, true, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; mRT->deferredScreen.shareDepthBuffer(mRT->screen); @@ -1005,23 +1001,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mRT->fxaaBuffer.release(); mRT->screen.release(); mRT->deferredScreen.release(); //make sure to release any render targets that share a depth buffer with mRT->deferredScreen first -// [RLVa:KB] - @setsphere - if (!LLRenderTarget::sUseFBO || !LLPipeline::sUseDepthTexture) - { - //mRT->deferredDepth.release(); - mRT->occlusionDepth.release(); - } - else - { - const U32 occlusion_divisor = 3; - //if (!mRT->deferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; - if (!mRT->occlusionDepth.allocate(resX / occlusion_divisor, resY / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; - if (RlvActions::isRlvEnabled() && !!mRT->deferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; - } -// [/RLVa:KB] -// //mRT->deferredDepth.release(); -// mRT->occlusionDepth.release(); - + if (!mRT->screen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_TEXTURE, FALSE)) return false; } @@ -1040,8 +1020,6 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; S32 shadow_detail = RenderShadowDetail; - const U32 occlusion_divisor = 3; - F32 scale = llmax(0.f, RenderShadowResolutionScale); U32 sun_shadow_map_width = BlurHappySize(resX, scale); U32 sun_shadow_map_height = BlurHappySize(resY, scale); @@ -1050,12 +1028,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) { //allocate 4 sun shadow maps for (U32 i = 0; i < 4; i++) { - if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) - { - return false; - } - - if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width / occlusion_divisor, sun_shadow_map_height / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) + if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, true, true, LLTexUnit::TT_TEXTURE)) { return false; } @@ -1080,11 +1053,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) U32 spot_shadow_map_height = height; for (U32 i = 0; i < 2; i++) { - if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE)) - { - return false; - } - if (!mSpotShadowOcclusion[i].allocate(spot_shadow_map_width / occlusion_divisor, height / occlusion_divisor, 0, TRUE, FALSE)) + if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, true, true)) { return false; } @@ -1115,7 +1084,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) } } - if (shadow_detail > 1) + if (shadow_detail > 1 && !gCubeSnapshot) { for (U32 i = 0; i < 2; i++) { @@ -1339,7 +1308,6 @@ void LLPipeline::releaseScreenBuffers() mRT->deferredScreen.release(); mRT->deferredDepth.release(); mRT->deferredLight.release(); - mRT->occlusionDepth.release(); } @@ -1347,7 +1315,6 @@ void LLPipeline::releaseSunShadowTarget(U32 index) { llassert(index < 4); mRT->shadow[index].release(); - mRT->shadowOcclusion[index].release(); } void LLPipeline::releaseSunShadowTargets() @@ -1365,7 +1332,6 @@ void LLPipeline::releaseSpotShadowTargets() for (U32 i = 0; i < 2; i++) { mSpotShadow[i].release(); - mSpotShadowOcclusion[i].release(); } } } @@ -1380,7 +1346,7 @@ void LLPipeline::createGLBuffers() if (LLPipeline::sRenderTransparentWater) { //water reflection texture U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512); - mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE); + mWaterDis.allocate(res,res,GL_RGBA,true,true,LLTexUnit::TT_TEXTURE); } // Use FBO for bake tex @@ -2506,19 +2472,35 @@ bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); -void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* planep, bool hud_attachments) +void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, bool hud_attachments) { - static LLCachedControl use_occlusion(gSavedSettings,"UseOcclusion"); - static bool can_use_occlusion = LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion"); - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL); + LL_PROFILE_GPU_ZONE("updateCull"); // should always be zero GPU time, but drop a timer to flush stuff out - // Factor out instance() call - LLWorld& world = LLWorld::instance(); + bool water_clip = !sRenderTransparentWater; - if (planep != nullptr) + if (water_clip) { - camera.setUserClipPlane(*planep); + + LLVector3 pnorm; + + F32 water_height = LLEnvironment::instance().getWaterHeight(); + + if (sUnderWaterRender) + { + //camera is below water, cull above water + pnorm.setVec(0, 0, 1); + } + else + { + //camera is above water, cull below water + pnorm = LLVector3(0, 0, -1); + } + + LLPlane plane; + plane.setVec(LLVector3(0, 0, water_height), pnorm); + + camera.setUserClipPlane(plane); } else { @@ -2529,58 +2511,8 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla sCull->clear(); - bool to_texture = LLPipeline::sUseOcclusion > 1 && gPipeline.shadersLoaded(); - - if (to_texture) - { - if (LLPipeline::sRenderDeferred && can_use_occlusion) - { - mRT->occlusionDepth.bindTarget(); - } - else - { - mRT->screen.bindTarget(); - } - } - - if (sUseOcclusion > 1) - { - gGL.setColorMask(false, false); - } - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadMatrix(gGLLastProjection); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLLastModelView); - - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - - bool bound_shader = false; - if (gPipeline.shadersLoaded() && LLGLSLShader::sCurBoundShader == 0) - { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can - // (shadow render uses a special shader that clamps to clip planes) - bound_shader = true; - gOcclusionCubeProgram.bind(); - } - - if (sUseOcclusion > 1) - { - if (mCubeVB.isNull()) - { //cube VB will be used for issuing occlusion queries - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW); - } - mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - } - - for (LLWorld::region_list_t::const_iterator iter = world.getRegionList().begin(); // Factor out instance() call - iter != world.getRegionList().end(); ++iter) + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -2600,16 +2532,10 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla LLVOCachePartition* vo_part = region->getVOCachePartition(); if(vo_part) { - bool do_occlusion_cull = can_use_occlusion && use_occlusion && !gUseWireframe; - vo_part->cull(camera, do_occlusion_cull); + vo_part->cull(camera, sUseOcclusion > 0); } } - if (bound_shader) - { - gOcclusionCubeProgram.unbind(); - } - if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull()) @@ -2633,30 +2559,8 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla if (render_water) { - world.precullWaterObjects(camera, sCull, render_water); // Factor out instance() call + LLWorld::getInstance()->precullWaterObjects(camera, sCull, render_water); } - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - - if (sUseOcclusion > 1) - { - gGL.setColorMask(true, false); - } - - if (to_texture) - { - if (LLPipeline::sRenderDeferred && can_use_occlusion) - { - mRT->occlusionDepth.flush(); - } - else - { - mRT->screen.flush(); - } - } } void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) @@ -2719,19 +2623,22 @@ void LLPipeline::markOccluder(LLSpatialGroup* group) void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + LL_PROFILE_GPU_ZONE("downsampleDepthBuffer"); + LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; LLGLSLShader* shader = NULL; if (scratch_space) { +#if 0 // TODO -- restore occlusion culling functionality GLint bits = 0; - llassert(!source.hasStencil()); // stencil buffer usage is deprecated - bits |= (source.hasStencil() && dest.hasStencil()) ? GL_STENCIL_BUFFER_BIT : 0; - bits |= GL_DEPTH_BUFFER_BIT; - scratch_space->copyContents(source, + bits = GL_DEPTH_BUFFER_BIT; + scratch_space->copyContents(source, 0, 0, source.getWidth(), source.getHeight(), 0, 0, scratch_space->getWidth(), scratch_space->getHeight(), bits, GL_NEAREST); +#endif } dest.bindTarget(); @@ -2780,23 +2687,6 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d } } -void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - llassert(!gCubeSnapshot); -#if 0 - downsampleDepthBuffer(source, dest, scratch_space); - dest.bindTarget(); - doOcclusion(camera); - dest.flush(); -#else - // none of the above shenanigans should matter (enough) because we've preserved hierarchical Z before issuing occlusion queries - //source.bindTarget(); - doOcclusion(camera); - //source.flush(); -#endif -} - void LLPipeline::doOcclusion(LLCamera& camera) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -2897,10 +2787,6 @@ void LLPipeline::updateGL() LLGLUpdate::sGLQ.pop_front(); } } - - { //seed VBO Pools - LLVertexBuffer::seedPools(); - } } void LLPipeline::clearRebuildGroups() @@ -3019,6 +2905,8 @@ void LLPipeline::clearRebuildDrawables() void LLPipeline::rebuildPriorityGroups() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + LL_PROFILE_GPU_ZONE("rebuildPriorityGroups"); + LLTimer update_timer; assertInitialized(); @@ -3487,6 +3375,7 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + LL_PROFILE_GPU_ZONE("stateSort"); if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, @@ -4112,6 +4001,7 @@ void LLPipeline::postSort(LLCamera &camera) // flush particle VB if (LLVOPartGroup::sVB) { + LL_PROFILE_GPU_ZONE("flush particle vb"); LLVOPartGroup::sVB->flush(); } else @@ -4136,9 +4026,12 @@ void LLPipeline::postSort(LLCamera &camera) { LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rebuild delayed upd groups"); // pack vertex buffers for groups that chose to delay their updates - for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) { - (*iter)->rebuildMesh(); + LL_PROFILE_GPU_ZONE("rebuildMesh"); + for (LLSpatialGroup::sg_vector_t::iterator iter = mMeshDirtyGroup.begin(); iter != mMeshDirtyGroup.end(); ++iter) + { + (*iter)->rebuildMesh(); + } } } @@ -7555,8 +7448,6 @@ void LLPipeline::doResetVertexBuffers(bool forced) LLVOPartGroup::destroyGL(); gGL.resetVertexBuffer(); - SUBSYSTEM_CLEANUP(LLVertexBuffer); - if (LLVertexBuffer::sGLCount != 0) { LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; @@ -7579,7 +7470,6 @@ void LLPipeline::doResetVertexBuffers(bool forced) sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha"); LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind"); - LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping); gGL.initVertexBuffer(); // Reset VB during TP @@ -7612,6 +7502,38 @@ void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_text gGLLastMatrix = NULL; } +void LLPipeline::renderShadowSimple(U32 type) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + + LLVertexBuffer* last_vb = nullptr; + + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); + + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) + { + LLDrawInfo& params = **i; + + LLCullResult::increment_iterator(i, end); + + LLVertexBuffer* vb = params.mVertexBuffer; + if (vb != last_vb) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("push shadow simple"); + mSimplePool->applyModelMatrix(params); + vb->setBufferFast(LLVertexBuffer::MAP_VERTEX); + vb->drawRangeFast(LLRender::TRIANGLES, 0, vb->getNumVerts()-1, vb->getNumIndices(), 0); + last_vb = vb; + } + } + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; +} + void LLPipeline::renderAlphaObjects(U32 mask, bool texture, bool batch_texture, bool rigged) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -7621,31 +7543,34 @@ void LLPipeline::renderAlphaObjects(U32 mask, bool texture, bool batch_texture, U32 type = LLRenderPass::PASS_ALPHA; LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; - for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + auto* begin = gPipeline.beginRenderMap(type); + auto* end = gPipeline.endRenderMap(type); + + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) { LLDrawInfo* pparams = *i; - if (pparams) - { - if (rigged) - { - if (pparams->mAvatar != nullptr) - { - if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) - { - mSimplePool->uploadMatrixPalette(*pparams); - lastAvatar = pparams->mAvatar; - lastMeshId = pparams->mSkinInfo->mHash; - } + LLCullResult::increment_iterator(i, end); - mSimplePool->pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_texture); - } - } - else if (pparams->mAvatar == nullptr) + if (rigged) + { + if (pparams->mAvatar != nullptr) { - mSimplePool->pushBatch(*pparams, mask, texture, batch_texture); + if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) + { + mSimplePool->uploadMatrixPalette(*pparams); + lastAvatar = pparams->mAvatar; + lastMeshId = pparams->mSkinInfo->mHash; + } + + mSimplePool->pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_texture); } } + else if (pparams->mAvatar == nullptr) + { + mSimplePool->pushBatch(*pparams, mask, texture, batch_texture); + } } + gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; } @@ -9837,20 +9762,17 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLGLEnable cull(GL_CULL_FACE); //enable depth clamping if available - //LLGLEnable depth_clamp(GL_DEPTH_CLAMP); + LLGLEnable depth_clamp(GL_DEPTH_CLAMP); + + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_LESS); if (use_shader) { gDeferredShadowCubeProgram.bind(); } - LLRenderTarget& occlusion_target = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ? - mSpotShadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] : - mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0]; - - occlusion_target.bindTarget(); + updateCull(shadow_cam, result); - occlusion_target.flush(); stateSort(shadow_cam, result); @@ -9872,20 +9794,21 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLEnvironment& environment = LLEnvironment::instance(); - LLVertexBuffer::unbind(); + struct CompareVertexBuffer + { + bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs) + { + return lhs->mVertexBuffer > rhs->mVertexBuffer; + } + }; + + LLVertexBuffer::unbind(); for (int j = 0; j < 2; ++j) // 0 -- static, 1 -- rigged { bool rigged = j == 1; - if (!use_shader) - { //occlusion program is general purpose depth-only no-textures - gOcclusionProgram.bind(rigged); - } - else - { - gDeferredShadowProgram.bind(rigged); - LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - } + gDeferredShadowProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); gGL.diffuseColor4f(1, 1, 1, 1); @@ -9900,19 +9823,28 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow simple"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); LL_PROFILE_GPU_ZONE("shadow simple"); gGL.getTexUnit(0)->disable(); - for (U32 i = 0; i < sizeof(types) / sizeof(U32); ++i) + + for (U32 type : types) { - renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE, FALSE, rigged); + if (rigged) + { + renderObjects(type, LLVertexBuffer::MAP_VERTEX, FALSE, FALSE, rigged); + } + else + { + renderShadowSimple(type); + } } + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - if (!use_shader) - { - gOcclusionProgram.unbind(); - } - - } + if (occlude > 1) + { // do occlusion culling against non-masked only to take advantage of hierarchical Z + doOcclusion(shadow_cam); + } + + if (use_shader) { LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow geom"); @@ -10012,15 +9944,6 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGLLastMatrix = NULL; gGL.loadMatrix(gGLModelView); - LLRenderTarget& occlusion_source = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ? - mSpotShadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] : - mRT->shadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0]; - - if (occlude > 1) - { - doOcclusion(shadow_cam, occlusion_source, occlusion_target); - } - if (use_shader) { gDeferredShadowProgram.unbind(); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fb87f72ef4..8a826b410a 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -173,7 +173,6 @@ public: // if source's depth buffer cannot be bound for reading, a scratch space depth buffer must be provided void downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); - void doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space = NULL); void doOcclusion(LLCamera& camera); void markNotCulled(LLSpatialGroup* group, LLCamera &camera); void markMoved(LLDrawable *drawablep, bool damped_motion = false); @@ -244,7 +243,9 @@ public: bool visibleObjectsInFrustum(LLCamera& camera); bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); - void updateCull(LLCamera& camera, LLCullResult& result, LLPlane* plane = NULL, bool hud_attachments = false); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane; different because SL-11614 + + // Populate given LLCullResult with results of a frustum cull of the entire scene against the given LLCamera + void updateCull(LLCamera& camera, LLCullResult& result, bool hud_attachments = false); void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void processPartitionQ(); @@ -272,6 +273,8 @@ public: void forAllVisibleDrawables(void (*func)(LLDrawable*)); void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false); + void renderShadowSimple(U32 type); + void renderAlphaObjects(U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false); void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false); void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false); @@ -686,12 +689,10 @@ public: LLRenderTarget fxaaBuffer; LLRenderTarget edgeMap; LLRenderTarget deferredDepth; - LLRenderTarget occlusionDepth; LLRenderTarget deferredLight; //sun shadow map LLRenderTarget shadow[4]; - LLRenderTarget shadowOcclusion[4]; }; // main full resoltuion render target @@ -704,7 +705,6 @@ public: RenderTargetPack* mRT; LLRenderTarget mSpotShadow[2]; - LLRenderTarget mSpotShadowOcclusion[2]; LLRenderTarget mPbrBrdfLut; diff --git a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml index 2bdd797899..0d82ba0a34 100644 --- a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml +++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml @@ -264,6 +264,25 @@ top_pad="5" width="185" can_edit_text="true"/> + Reflection Probe Ambiance: +