diff options
Diffstat (limited to 'indra')
372 files changed, 12892 insertions, 17822 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index f4071793d5..bb5dd8f847 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -42,8 +42,8 @@ if(NON_RELEASE_CRASH_REPORTING) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1") endif() -# Don't bother with a MinSizeRel build. -set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING +# Don't bother with MinSizeRel or Debug builds. +set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release" CACHE STRING "Supported build types." FORCE) @@ -66,16 +66,21 @@ if (WINDOWS) # CP changed to only append the flag for 32bit builds - on 64bit builds, # locally at least, the build output is spammed with 1000s of 'D9002' # warnings about this switch being ignored. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") if( ADDRESS_SIZE EQUAL 32 ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64") endif() + # Preserve first-pass-through versions (ie no FORCE overwrite). Prevents recursive addition of /Zo (04/2021) + set(OG_CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} CACHE STRING "OG_CXX_FLAGS_RELEASE") + set(OG_CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} CACHE STRING "OG_CXX_FLAGS_RELWITHDEBINFO") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo" + "${OG_CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo" CACHE STRING "C++ compiler release-with-debug options" FORCE) set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /Zo" + "${OG_CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /Zo" CACHE STRING "C++ compiler release options" FORCE) + # zlib has assembly-language object files incompatible with SAFESEH set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE /SAFESEH:NO /NODEFAULTLIB:LIBCMT /IGNORE:4099") diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 336896ed01..b408702f04 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -103,6 +103,8 @@ if(WINDOWS) set(MSVC_VER 120) elseif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1920) # Visual Studio 2017 set(MSVC_VER 140) + elseif (MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019 + set(MSVC_VER 140) else (MSVC80) MESSAGE(WARNING "New MSVC_VERSION ${MSVC_VERSION} of MSVC: adapt Copy3rdPartyLibs.cmake") endif (MSVC80) diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index 8900419f9b..34499aaa36 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -3,12 +3,14 @@ include(APR) include(Boost) include(EXPAT) +include(Tracy) include(ZLIB) set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llcommon ${APRUTIL_INCLUDE_DIR} ${APR_INCLUDE_DIR} + ${TRACY_INCLUDE_DIR} ) set(LLCOMMON_SYSTEM_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} @@ -30,7 +32,8 @@ else (LINUX) ${BOOST_FIBER_LIBRARY} ${BOOST_CONTEXT_LIBRARY} ${BOOST_THREAD_LIBRARY} - ${BOOST_SYSTEM_LIBRARY} ) + ${BOOST_SYSTEM_LIBRARY} + ) endif (LINUX) set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a static library.") diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake new file mode 100644 index 0000000000..cfff956bcf --- /dev/null +++ b/indra/cmake/Tracy.cmake @@ -0,0 +1,29 @@ +# -*- cmake -*- +include(Prebuilt) + +set(USE_TRACY OFF CACHE BOOL "Use Tracy profiler.") + +if (USE_TRACY) + set(TRACY_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tracy) + +# See: indra/llcommon/llprofiler.h + add_definitions(-DLL_PROFILER_CONFIGURATION=3) + use_prebuilt_binary(tracy) + + if (WINDOWS) + MESSAGE(STATUS "Including Tracy for Windows: '${TRACY_INCLUDE_DIR}'") + endif (WINDOWS) + + if (DARWIN) + MESSAGE(STATUS "Including Tracy for Darwin: '${TRACY_INCLUDE_DIR}'") + endif (DARWIN) + + if (LINUX) + MESSAGE(STATUS "Including Tracy for Linux: '${TRACY_INCLUDE_DIR}'") + endif (LINUX) +else (USE_TRACY) + # Tracy.cmake should not set LLCOMMON_INCLUDE_DIRS, let LLCommon.cmake do that + set(TRACY_INCLUDE_DIR "") + set(TRACY_LIBRARY "") +endif (USE_TRACY) + diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index ade83202cf..eab7c17b71 100644 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -1,3 +1,4 @@ euclid 5/29/2020 euclid 7/23/2020 euclid 4/29/2021 +euclid 10/5/2021 DRTVWR-546 diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 90dfa04f28..2d6d2a10d2 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -1590,7 +1590,7 @@ BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num ) delete_and_clear_array(mCollisionVolumes); mNumCollisionVolumes = 0; - mCollisionVolumes = new(std::nothrow) LLAvatarJointCollisionVolume[num]; + mCollisionVolumes = new LLAvatarJointCollisionVolume[num]; if (!mCollisionVolumes) { LL_WARNS() << "Failed to allocate collision volumes" << LL_ENDL; diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index f278dcc2e2..a6261b507b 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -77,73 +77,63 @@ protected: //----------------------------------------------------------------------------- -LL_ALIGN_PREFIX(16) -class LLDriverParam : public LLViewerVisualParam +class alignas(16) LLDriverParam : public LLViewerVisualParam { + LL_ALIGN_NEW private: - // Hide the default constructor. Force construction with LLAvatarAppearance. - LLDriverParam() {} + // Hide the default constructor. Force construction with LLAvatarAppearance. + LLDriverParam() {} public: - LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable = NULL); - ~LLDriverParam(); - - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - - // Special: These functions are overridden by child classes - LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } - // This sets mInfo and calls initialization functions - BOOL setInfo(LLDriverParamInfo *info); - - LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } - const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } - - void updateCrossDrivenParams(LLWearableType::EType driven_type); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - /*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param. - /*virtual*/ void setWeight(F32 weight); - /*virtual*/ void setAnimationTarget( F32 target_value); - /*virtual*/ void stopAnimating(); - /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); - /*virtual*/ void resetDrivenParams(); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector4a& getAvgDistortion(); - /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); - - S32 getDrivenParamsCount() const; - const LLViewerVisualParam* getDrivenParam(S32 index) const; - - typedef std::vector<LLDrivenEntry> entry_list_t; - entry_list_t& getDrivenList() { return mDriven; } + LLDriverParam(LLAvatarAppearance* appearance, LLWearable* wearable = NULL); + ~LLDriverParam(); + + // Special: These functions are overridden by child classes + LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } + // This sets mInfo and calls initialization functions + BOOL setInfo(LLDriverParamInfo* info); + + LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } + const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + + void updateCrossDrivenParams(LLWearableType::EType driven_type); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + /*virtual*/ void apply(ESex sex) {} // apply is called separately for each driven param. + /*virtual*/ void setWeight(F32 weight); + /*virtual*/ void setAnimationTarget(F32 target_value); + /*virtual*/ void stopAnimating(); + /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); + /*virtual*/ void resetDrivenParams(); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); + /*virtual*/ F32 getMaxDistortion(); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh* poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32* index, LLPolyMesh** poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32* index, LLPolyMesh** poly_mesh); + + S32 getDrivenParamsCount() const; + const LLViewerVisualParam* getDrivenParam(S32 index) const; + + typedef std::vector<LLDrivenEntry> entry_list_t; + entry_list_t& getDrivenList() { return mDriven; } void setDrivenList(entry_list_t& driven_list) { mDriven = driven_list; } protected: - LLDriverParam(const LLDriverParam& pOther); - F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); - void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight); - - - LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder - entry_list_t mDriven; - LLViewerVisualParam* mCurrentDistortionParam; - // Backlink only; don't make this an LLPointer. - LLAvatarAppearance* mAvatarAppearance; - LLWearable* mWearablep; -} LL_ALIGN_POSTFIX(16); + LLDriverParam(const LLDriverParam& pOther); + F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); + void setDrivenWeight(LLDrivenEntry* driven, F32 driven_weight); + + + LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder + entry_list_t mDriven; + LLViewerVisualParam* mCurrentDistortionParam; + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance* mAvatarAppearance; + LLWearable* mWearablep; +}; #endif // LL_LLDRIVERPARAM_H diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index ce7010984a..16b5f1e204 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -539,8 +539,6 @@ F32 LLPolyMorphTarget::getMaxDistortion() //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_APPLY_MORPH_TARGET("Apply Morph"); - void LLPolyMorphTarget::apply( ESex avatar_sex ) { if (!mMorphData || mNumMorphMasksPending > 0) @@ -548,7 +546,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) return; } - LL_RECORD_BLOCK_TIME(FTM_APPLY_MORPH_TARGET); + LL_PROFILE_ZONE_SCOPED; mLastSex = avatar_sex; diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index c6133cd831..29cd373636 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -41,24 +41,14 @@ class LLWearable; //----------------------------------------------------------------------------- // LLPolyMorphData() //----------------------------------------------------------------------------- -LL_ALIGN_PREFIX(16) -class LLPolyMorphData +class alignas(16) LLPolyMorphData { + LL_ALIGN_NEW public: LLPolyMorphData(const std::string& morph_name); ~LLPolyMorphData(); LLPolyMorphData(const LLPolyMorphData &rhs); - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); const std::string& getName() { return mName; } @@ -76,7 +66,7 @@ public: F32 mTotalDistortion; // vertex distortion summed over entire morph F32 mMaxDistortion; // maximum single vertex distortion in a given morph - LL_ALIGN_16(LLVector4a mAvgDistortion); // average vertex distortion, to infer directionality of the morph + LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph LLPolyMeshSharedData* mMesh; private: @@ -154,8 +144,9 @@ protected: // These morph targets must be topologically consistent with a given Polymesh // (share face sets) //----------------------------------------------------------------------------- -class LLPolyMorphTarget : public LLViewerVisualParam +class alignas(16) LLPolyMorphTarget : public LLViewerVisualParam { + LL_ALIGN_NEW public: LLPolyMorphTarget(LLPolyMesh *poly_mesh); ~LLPolyMorphTarget(); @@ -184,16 +175,6 @@ public: void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - protected: LLPolyMorphTarget(const LLPolyMorphTarget& pOther); diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index ae38c25dbf..360f17508f 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -188,11 +188,9 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) //----------------------------------------------------------------------------- // apply() //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_POLYSKELETAL_DISTORTION_APPLY("Skeletal Distortion"); - void LLPolySkeletalDistortion::apply( ESex avatar_sex ) { - LL_RECORD_BLOCK_TIME(FTM_POLYSKELETAL_DISTORTION_APPLY); + LL_PROFILE_ZONE_SCOPED; F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index ab1a132d19..585d85f055 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -62,9 +62,9 @@ struct LLPolySkeletalBoneInfo BOOL mHasPositionDeformation; }; -LL_ALIGN_PREFIX(16) -class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo +class alignas(16) LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo { + LL_ALIGN_NEW friend class LLPolySkeletalDistortion; public: @@ -73,19 +73,6 @@ public: /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); - - - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - - protected: typedef std::vector<LLPolySkeletalBoneInfo> bone_info_list_t; bone_info_list_t mBoneInfoList; @@ -95,19 +82,10 @@ protected: // LLPolySkeletalDeformation // A set of joint scale data for deforming the avatar mesh //----------------------------------------------------------------------------- -class LLPolySkeletalDistortion : public LLViewerVisualParam +class alignas(16) LLPolySkeletalDistortion : public LLViewerVisualParam { + LL_ALIGN_NEW public: - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - LLPolySkeletalDistortion(LLAvatarAppearance *avatarp); ~LLPolySkeletalDistortion(); diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index a4600069ce..234f5c3007 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -142,17 +142,8 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) BOOL success = TRUE; - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - if (use_shaders) - { - gAlphaMaskProgram.bind(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.00f); - } + gAlphaMaskProgram.bind(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); LLVertexBuffer::unbind(); @@ -164,10 +155,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) midRenderTexLayerSet(success); - if (use_shaders) - { - gAlphaMaskProgram.unbind(); - } + gAlphaMaskProgram.unbind(); LLVertexBuffer::unbind(); @@ -390,8 +378,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* } } - bool use_shaders = LLGLSLShader::sNoFixedFunction; - LLGLSUIDefault gls_ui; LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); gGL.setColorMask(true, true); @@ -400,20 +386,14 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* { gGL.flush(); LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.0f); - } + gAlphaMaskProgram.setMinimumAlpha(0.0f); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f( 0.f, 0.f, 0.f, 1.f ); gl_rect_2d_simple( width, height ); gGL.flush(); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } if (mIsVisible) @@ -440,10 +420,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* gGL.setSceneBlendType(LLRender::BT_REPLACE); LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } + gAlphaMaskProgram.setMinimumAlpha(0.f); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f( 0.f, 0.f, 0.f, 0.f ); @@ -452,10 +429,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.flush(); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } return success; @@ -520,10 +494,9 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const return mComposite; } -static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha"); void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target) { - LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA); + LL_PROFILE_ZONE_SCOPED; memset(data, 255, width * height); for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) @@ -536,14 +509,11 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true); } -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures"); void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES); + LL_PROFILE_ZONE_SCOPED; const LLTexLayerSetInfo *info = getInfo(); - bool use_shaders = LLGLSLShader::sNoFixedFunction; - gGL.setColorMask(false, true); gGL.setSceneBlendType(LLRender::BT_REPLACE); @@ -557,7 +527,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->bind(tex); - gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); gl_rect_2d_simple_tex( width, height ); } } @@ -568,20 +537,14 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, // Set the alpha channel to one (clean up after previous blending) gGL.flush(); LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } + gAlphaMaskProgram.setMinimumAlpha(0.f); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4f( 0.f, 0.f, 0.f, 1.f ); gl_rect_2d_simple( width, height ); gGL.flush(); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } // (Optional) Mask out part of the baked texture with alpha masks @@ -589,7 +552,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, if (mMaskLayerList.size() > 0) { gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); - gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++) { LLTexLayerInterface* layer = *iter; @@ -602,7 +564,6 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); gGL.setColorMask(true, true); gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -1128,13 +1089,6 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou // *TODO: Is this correct? //gPipeline.disableLights(); stop_glerror(); - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } - stop_glerror(); - - bool use_shaders = LLGLSLShader::sNoFixedFunction; LLColor4 net_color; BOOL color_specified = findNetColor(&net_color); @@ -1221,10 +1175,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou LLGLDisable alpha_test(no_alpha_test ? GL_ALPHA_TEST : 0); if (no_alpha_test) { - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } + gAlphaMaskProgram.setMinimumAlpha(0.f); } LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); @@ -1238,10 +1189,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); if (no_alpha_test) { - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } } } @@ -1275,18 +1223,12 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou color_specified ) { LLGLDisable no_alpha(GL_ALPHA_TEST); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.000f); - } + gAlphaMaskProgram.setMinimumAlpha(0.000f); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4fv( net_color.mV ); gl_rect_2d_simple( width, height ); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } if( alpha_mask_specified || getInfo()->mWriteAllChannels ) @@ -1374,25 +1316,17 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) gGL.flush(); - bool use_shaders = LLGLSLShader::sNoFixedFunction; - if( !getInfo()->mStaticImageFileName.empty() ) { LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); if( tex ) { LLGLSNoAlphaTest gls_no_alpha_test; - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } + gAlphaMaskProgram.setMinimumAlpha(0.f); gGL.getTexUnit(0)->bind(tex, TRUE); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } else { @@ -1407,18 +1341,11 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) if (tex) { LLGLSNoAlphaTest gls_no_alpha_test; - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } + gAlphaMaskProgram.setMinimumAlpha(0.f); gGL.getTexUnit(0)->bind(tex); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - success = TRUE; - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); } } } @@ -1431,7 +1358,6 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) addAlphaMask(data, originX, originY, width, height, bound_target); } -static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks"); void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render) { if (!force_render && !hasMorph()) @@ -1439,18 +1365,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; return; } - LL_RECORD_BLOCK_TIME(FTM_RENDER_MORPH_MASKS); + LL_PROFILE_ZONE_SCOPED; BOOL success = TRUE; llassert( !mParamAlphaList.empty() ); - bool use_shaders = LLGLSLShader::sNoFixedFunction; - - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - + gAlphaMaskProgram.setMinimumAlpha(0.f); gGL.setColorMask(false, true); LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin(); @@ -1535,10 +1455,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC gl_rect_2d_simple( width, height ); } - if (use_shaders) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } + gAlphaMaskProgram.setMinimumAlpha(0.004f); LLGLSUIDefault gls_ui; @@ -1637,10 +1554,9 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } } -static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask"); void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) { - LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK); + LL_PROFILE_ZONE_SCOPED; S32 size = width * height; const U8* alphaData = getAlphaData(); if (!alphaData && hasAlphaParams()) @@ -1981,10 +1897,9 @@ void LLTexLayerStaticImageList::deleteCachedImages() // Returns an LLImageTGA that contains the encoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -static LLTrace::BlockTimerStatHandle FTM_LOAD_STATIC_TGA("getImageTGA"); LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) { - LL_RECORD_BLOCK_TIME(FTM_LOAD_STATIC_TGA); + LL_PROFILE_ZONE_SCOPED; const char *namekey = mImageNames.addString(file_name); image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); if( iter != mStaticImageListTGA.end() ) @@ -2011,10 +1926,9 @@ LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -static LLTrace::BlockTimerStatHandle FTM_LOAD_STATIC_TEXTURE("getTexture"); LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) { - LL_RECORD_BLOCK_TIME(FTM_LOAD_STATIC_TEXTURE); + LL_PROFILE_ZONE_SCOPED; LLPointer<LLGLTexture> tex; const char *namekey = mImageNames.addString(file_name); @@ -2061,10 +1975,9 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, // Reads a .tga file, decodes it, and puts the decoded data in image_raw. // Returns TRUE if successful. -static LLTrace::BlockTimerStatHandle FTM_LOAD_IMAGE_RAW("loadImageRaw"); BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) { - LL_RECORD_BLOCK_TIME(FTM_LOAD_IMAGE_RAW); + LL_PROFILE_ZONE_SCOPED; BOOL success = FALSE; std::string path; path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index ff682d6906..ce5c7142d5 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -261,10 +261,9 @@ BOOL LLTexLayerParamAlpha::getSkip() const } -static LLTrace::BlockTimerStatHandle FTM_TEX_LAYER_PARAM_ALPHA("alpha render"); BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) { - LL_RECORD_BLOCK_TIME(FTM_TEX_LAYER_PARAM_ALPHA); + LL_PROFILE_ZONE_SCOPED; BOOL success = TRUE; if (!mTexLayer) diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index 0cb2dedbff..e2440998b3 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -63,23 +63,14 @@ protected: // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL_ALIGN_PREFIX(16) -class LLTexLayerParamAlpha : public LLTexLayerParam +class alignas(16) LLTexLayerParamAlpha : public LLTexLayerParam { + LL_ALIGN_NEW public: LLTexLayerParamAlpha( LLTexLayerInterface* layer ); LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); /*virtual*/ ~LLTexLayerParamAlpha(); - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions @@ -146,9 +137,9 @@ private: // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL_ALIGN_PREFIX(16) -class LLTexLayerParamColor : public LLTexLayerParam +class alignas(16) LLTexLayerParamColor : public LLTexLayerParam { + LL_ALIGN_NEW public: enum EColorOperation { @@ -161,16 +152,6 @@ public: LLTexLayerParamColor( LLTexLayerInterface* layer ); LLTexLayerParamColor( LLAvatarAppearance* appearance ); - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - /* virtual */ ~LLTexLayerParamColor(); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; @@ -198,8 +179,8 @@ protected: virtual void onGlobalColorChanged() {} private: - LL_ALIGN_16(LLVector4a mAvgDistortionVec); -} LL_ALIGN_POSTFIX(16); + LLVector4a mAvgDistortionVec; +}; class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo { diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index b764ef0c7e..8874df32f5 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -188,20 +188,15 @@ void LLCharacter::requestStopMotion( LLMotion* motion) //----------------------------------------------------------------------------- // updateMotions() //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_UPDATE_ANIMATION("Update Animation"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_MOTIONS("Update Motions"); - void LLCharacter::updateMotions(e_update_t update_type) { + LL_PROFILE_ZONE_SCOPED; if (update_type == HIDDEN_UPDATE) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_HIDDEN_ANIMATION); mMotionController.updateMotionsMinimal(); } else { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_ANIMATION); // unpause if the number of outstanding pause requests has dropped to the initial one if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1) { @@ -209,7 +204,6 @@ void LLCharacter::updateMotions(e_update_t update_type) } bool force_update = (update_type == FORCE_UPDATE); { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOTIONS); mMotionController.updateMotions(force_update); } } diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index ddf89f30f2..c5757163d9 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -163,6 +163,7 @@ BOOL LLEditingMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; LLVector3 focus_pt; LLVector3* pointAtPt = (LLVector3*)mCharacter->getAnimationData("PointAtPoint"); diff --git a/indra/llcharacter/lleditingmotion.h b/indra/llcharacter/lleditingmotion.h index 7b1c8bb059..80c1717a70 100644 --- a/indra/llcharacter/lleditingmotion.h +++ b/indra/llcharacter/lleditingmotion.h @@ -42,9 +42,11 @@ //----------------------------------------------------------------------------- // class LLEditingMotion //----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) class LLEditingMotion : public LLMotion { + LL_ALIGN_NEW public: // Constructor LLEditingMotion(const LLUUID &id); @@ -108,6 +110,13 @@ public: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- + LL_ALIGN_16(LLJoint mParentJoint); + LL_ALIGN_16(LLJoint mShoulderJoint); + LL_ALIGN_16(LLJoint mElbowJoint); + LL_ALIGN_16(LLJoint mWristJoint); + LL_ALIGN_16(LLJoint mTarget); + LLJointSolverRP3 mIKSolver; + LLCharacter *mCharacter; LLVector3 mWristOffset; @@ -117,17 +126,10 @@ public: LLPointer<LLJointState> mWristState; LLPointer<LLJointState> mTorsoState; - LLJoint mParentJoint; - LLJoint mShoulderJoint; - LLJoint mElbowJoint; - LLJoint mWristJoint; - LLJoint mTarget; - LLJointSolverRP3 mIKSolver; - static S32 sHandPose; static S32 sHandPosePriority; LLVector3 mLastSelectPt; -}; +} LL_ALIGN_POSTFIX(16); #endif // LL_LLKEYFRAMEMOTION_H diff --git a/indra/llcharacter/llhandmotion.cpp b/indra/llcharacter/llhandmotion.cpp index b3bf5a9a91..ceba956214 100644 --- a/indra/llcharacter/llhandmotion.cpp +++ b/indra/llcharacter/llhandmotion.cpp @@ -121,6 +121,7 @@ BOOL LLHandMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLHandMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; eHandPose *requestedHandPose; F32 timeDelta = time - mLastTime; diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index e91de7a11d..fdf97266a3 100644 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -175,6 +175,7 @@ BOOL LLHeadRotMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; LLQuaternion targetHeadRotWorld; LLQuaternion currentRootRotWorld = mRootJoint->getWorldRotation(); LLQuaternion currentInvRootRotWorld = ~currentRootRotWorld; @@ -458,6 +459,7 @@ void LLEyeMotion::adjustEyeTarget(LLVector3* targetPos, LLJointState& left_eye_s //----------------------------------------------------------------------------- BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; //calculate jitter if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime) { diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index dee642310e..d72282ab42 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -922,6 +922,13 @@ const LLMatrix4 &LLJoint::getWorldMatrix() return mXform.getWorldMatrix(); } +const LLMatrix4a& LLJoint::getWorldMatrix4a() +{ + updateWorldMatrixParent(); + + return mWorldMatrix; +} + //-------------------------------------------------------------------- // setWorldMatrix() @@ -1003,6 +1010,7 @@ void LLJoint::updateWorldMatrix() { sNumUpdates++; mXform.updateMatrix(FALSE); + mWorldMatrix.loadu(mXform.getWorldMatrix()); mDirtyFlags = 0x0; } } diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 1b646b641f..63d99b9209 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -38,6 +38,7 @@ #include "m4math.h" #include "llquaternion.h" #include "xform.h" +#include "llmatrix4a.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; // Need to set this to count of animate-able joints, @@ -85,8 +86,10 @@ inline bool operator!=(const LLVector3OverrideMap& a, const LLVector3OverrideMap //----------------------------------------------------------------------------- // class LLJoint //----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) class LLJoint { + LL_ALIGN_NEW public: // priority levels, from highest to lowest enum JointPriority @@ -114,16 +117,17 @@ public: SUPPORT_EXTENDED }; protected: - std::string mName; + // explicit transformation members + LL_ALIGN_16(LLMatrix4a mWorldMatrix); + LLXformMatrix mXform; + + std::string mName; SupportCategory mSupport; // parent joint LLJoint *mParent; - // explicit transformation members - LLXformMatrix mXform; - LLVector3 mDefaultPosition; LLVector3 mDefaultScale; @@ -259,6 +263,8 @@ public: const LLMatrix4 &getWorldMatrix(); void setWorldMatrix( const LLMatrix4& mat ); + const LLMatrix4a& getWorldMatrix4a(); + void updateWorldMatrixChildren(); void updateWorldMatrixParent(); @@ -296,6 +302,6 @@ public: // These are used in checks of whether a pos/scale override is considered significant. bool aboveJointPosThreshold(const LLVector3& pos) const; bool aboveJointScaleThreshold(const LLVector3& scale) const; -}; +} LL_ALIGN_POSTFIX(16); #endif // LL_LLJOINT_H diff --git a/indra/llcharacter/llkeyframefallmotion.cpp b/indra/llcharacter/llkeyframefallmotion.cpp index 7842f0e5fb..9a41ba4d3d 100644 --- a/indra/llcharacter/llkeyframefallmotion.cpp +++ b/indra/llcharacter/llkeyframefallmotion.cpp @@ -121,6 +121,7 @@ BOOL LLKeyframeFallMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLKeyframeFallMotion::onUpdate(F32 activeTime, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; BOOL result = LLKeyframeMotion::onUpdate(activeTime, joint_mask); F32 slerp_amt = clamp_rescale(activeTime / getDuration(), 0.5f, 0.75f, 0.f, 1.f); diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index fe9de30f0a..5a5aa2c83e 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -677,6 +677,7 @@ BOOL LLKeyframeMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLKeyframeMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; // llassert(time >= 0.f); // This will fire time = llmax(0.f, time); diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp index 6ed18bc445..aba1c5db39 100644 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ b/indra/llcharacter/llkeyframemotionparam.cpp @@ -158,6 +158,7 @@ BOOL LLKeyframeMotionParam::onActivate() //----------------------------------------------------------------------------- BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; F32 weightFactor = 1.f / (F32)mParameterizedMotions.size(); // zero out all pose weights diff --git a/indra/llcharacter/llkeyframestandmotion.h b/indra/llcharacter/llkeyframestandmotion.h index c2634ecd6d..1aa5b187ba 100644 --- a/indra/llcharacter/llkeyframestandmotion.h +++ b/indra/llcharacter/llkeyframestandmotion.h @@ -37,9 +37,11 @@ //----------------------------------------------------------------------------- // class LLKeyframeStandMotion //----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) class LLKeyframeStandMotion : public LLKeyframeMotion { + LL_ALIGN_NEW public: // Constructor LLKeyframeStandMotion(const LLUUID &id); @@ -69,6 +71,18 @@ public: //------------------------------------------------------------------------- // Member Data //------------------------------------------------------------------------- + LLJoint mPelvisJoint; + + LLJoint mHipLeftJoint; + LLJoint mKneeLeftJoint; + LLJoint mAnkleLeftJoint; + LLJoint mTargetLeft; + + LLJoint mHipRightJoint; + LLJoint mKneeRightJoint; + LLJoint mAnkleRightJoint; + LLJoint mTargetRight; + LLCharacter *mCharacter; BOOL mFlipFeet; @@ -83,18 +97,6 @@ public: LLPointer<LLJointState> mKneeRightState; LLPointer<LLJointState> mAnkleRightState; - LLJoint mPelvisJoint; - - LLJoint mHipLeftJoint; - LLJoint mKneeLeftJoint; - LLJoint mAnkleLeftJoint; - LLJoint mTargetLeft; - - LLJoint mHipRightJoint; - LLJoint mKneeRightJoint; - LLJoint mAnkleRightJoint; - LLJoint mTargetRight; - LLJointSolverRP3 mIKLeft; LLJointSolverRP3 mIKRight; @@ -110,7 +112,7 @@ public: BOOL mTrackAnkles; S32 mFrameNum; -}; +} LL_ALIGN_POSTFIX(16); #endif // LL_LLKEYFRAMESTANDMOTION_H diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp index f180702385..298b37e60c 100644 --- a/indra/llcharacter/llkeyframewalkmotion.cpp +++ b/indra/llcharacter/llkeyframewalkmotion.cpp @@ -105,6 +105,7 @@ void LLKeyframeWalkMotion::onDeactivate() //----------------------------------------------------------------------------- BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; // compute time since last update F32 deltaTime = time - mRealTimeLast; @@ -198,6 +199,7 @@ BOOL LLWalkAdjustMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; // delta_time is guaranteed to be non zero F32 delta_time = llclamp(time - mLastTime, TIME_EPSILON, MAX_TIME_DELTA); mLastTime = time; @@ -373,6 +375,7 @@ BOOL LLFlyAdjustMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation(); F32 speed = mCharacter->getCharacterVelocity().magVec(); diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index c48d02b652..d4546ce901 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -503,6 +503,7 @@ void LLMotionController::resetJointSignatures() //----------------------------------------------------------------------------- void LLMotionController::updateIdleMotion(LLMotion* motionp) { + LL_PROFILE_ZONE_SCOPED; if (motionp->isStopped() && mAnimTime > motionp->getStopTime() + motionp->getEaseOutDuration()) { deactivateMotionInstance(motionp); @@ -541,6 +542,7 @@ void LLMotionController::updateIdleMotion(LLMotion* motionp) //----------------------------------------------------------------------------- void LLMotionController::updateIdleActiveMotions() { + LL_PROFILE_ZONE_SCOPED; for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ) { @@ -553,10 +555,9 @@ void LLMotionController::updateIdleActiveMotions() //----------------------------------------------------------------------------- // updateMotionsByType() //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_MOTION_ON_UPDATE("Motion onUpdate"); - void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type) { + LL_PROFILE_ZONE_SCOPED; BOOL update_result = TRUE; U8 last_joint_signature[LL_CHARACTER_MAX_ANIMATED_JOINTS]; @@ -712,7 +713,6 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty // perform motion update { - LL_RECORD_BLOCK_TIME(FTM_MOTION_ON_UPDATE); update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); } } @@ -768,6 +768,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty //----------------------------------------------------------------------------- void LLMotionController::updateLoadingMotions() { + LL_PROFILE_ZONE_SCOPED; // query pending motions for completion for (motion_set_t::iterator iter = mLoadingMotions.begin(); iter != mLoadingMotions.end(); ) @@ -815,6 +816,7 @@ void LLMotionController::updateLoadingMotions() //----------------------------------------------------------------------------- void LLMotionController::updateMotions(bool force_update) { + LL_PROFILE_ZONE_SCOPED; // SL-763: "Distant animated objects run at super fast speed" // The use_quantum optimization or possibly the associated code in setTimeStamp() // does not work as implemented. @@ -907,6 +909,7 @@ void LLMotionController::updateMotions(bool force_update) //----------------------------------------------------------------------------- void LLMotionController::updateMotionsMinimal() { + LL_PROFILE_ZONE_SCOPED; // Always update mPrevTimerElapsed mPrevTimerElapsed = mTimer.getElapsedTimeF32(); @@ -924,6 +927,7 @@ void LLMotionController::updateMotionsMinimal() //----------------------------------------------------------------------------- BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time) { + LL_PROFILE_ZONE_SCOPED; // It's not clear why the getWeight() line seems to be crashing this, but // hopefully this fixes it. if (motion == NULL || motion->getPose() == NULL) diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index c004a0f3b7..1405f1e053 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -80,8 +80,10 @@ public: const S32 JSB_NUM_JOINT_STATES = 6; +LL_ALIGN_PREFIX(16) class LLJointStateBlender { + LL_ALIGN_NEW protected: LLPointer<LLJointState> mJointStates[JSB_NUM_JOINT_STATES]; S32 mPriorities[JSB_NUM_JOINT_STATES]; @@ -96,8 +98,8 @@ public: void resetCachedJoint(); public: - LLJoint mJointCache; -}; + LL_ALIGN_16(LLJoint mJointCache); +} LL_ALIGN_POSTFIX(16); class LLMotion; diff --git a/indra/llcharacter/lltargetingmotion.cpp b/indra/llcharacter/lltargetingmotion.cpp index 69681e4197..ec75212a40 100644 --- a/indra/llcharacter/lltargetingmotion.cpp +++ b/indra/llcharacter/lltargetingmotion.cpp @@ -103,6 +103,7 @@ BOOL LLTargetingMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; F32 slerp_amt = LLSmoothInterpolation::getInterpolant(TORSO_TARGET_HALF_LIFE); LLVector3 target; diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 766a1849f9..782f656406 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -12,6 +12,7 @@ include(JsonCpp) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) +include(Tracy) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -19,6 +20,7 @@ include_directories( ${JSONCPP_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ${URIPARSER_INCLUDE_DIRS} + ${TRACY_INCLUDE_DIR} ) # add_executable(lltreeiterators lltreeiterators.cpp) @@ -117,14 +119,16 @@ set(llcommon_SOURCE_FILES lluriparser.cpp lluuid.cpp llworkerthread.cpp - timing.cpp u64.cpp + threadpool.cpp + workqueue.cpp StackWalker.cpp ) set(llcommon_HEADER_FILES CMakeLists.txt + chrono.h ctype_workaround.h fix_macros.h indra_constants.h @@ -197,6 +201,7 @@ set(llcommon_HEADER_FILES llmortician.h llnametable.h llpointer.h + llprofiler.h llpounceable.h llpredicate.h llpreprocessor.h @@ -251,8 +256,12 @@ set(llcommon_HEADER_FILES lockstatic.h stdtypes.h stringize.h + threadpool.h + threadsafeschedule.h timer.h + tuple.h u64.h + workqueue.h StackWalker.h ) @@ -299,6 +308,7 @@ target_link_libraries( ${BOOST_SYSTEM_LIBRARY} ${GOOGLE_PERFTOOLS_LIBRARIES} ${URIPARSER_LIBRARIES} + ${TRACY_LIBRARY} ) if (DARWIN) @@ -355,6 +365,9 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}") LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(threadsafeschedule "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(tuple "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(workqueue "" "${test_libs}") ## llexception_test.cpp isn't a regression test, and doesn't need to be run ## every build. It's to help a developer make implementation choices about diff --git a/indra/llcommon/chrono.h b/indra/llcommon/chrono.h new file mode 100644 index 0000000000..806e871892 --- /dev/null +++ b/indra/llcommon/chrono.h @@ -0,0 +1,65 @@ +/** + * @file chrono.h + * @author Nat Goodspeed + * @date 2021-10-05 + * @brief supplement <chrono> with utility functions + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_CHRONO_H) +#define LL_CHRONO_H + +#include <chrono> +#include <type_traits> // std::enable_if + +namespace LL +{ + +// time_point_cast() is derived from https://stackoverflow.com/a/35293183 +// without the iteration: we think errors in the ~1 microsecond range are +// probably acceptable. + +// This variant is for the optimal case when the source and dest use the same +// clock: that case is handled by std::chrono. +template <typename DestTimePoint, typename SrcTimePoint, + typename std::enable_if<std::is_same<typename DestTimePoint::clock, + typename SrcTimePoint::clock>::value, + bool>::type = true> +DestTimePoint time_point_cast(const SrcTimePoint& time) +{ + return std::chrono::time_point_cast<typename DestTimePoint::duration>(time); +} + +// This variant is for when the source and dest use different clocks -- see +// the linked StackOverflow answer, also Howard Hinnant's, for more context. +template <typename DestTimePoint, typename SrcTimePoint, + typename std::enable_if<! std::is_same<typename DestTimePoint::clock, + typename SrcTimePoint::clock>::value, + bool>::type = true> +DestTimePoint time_point_cast(const SrcTimePoint& time) +{ + // The basic idea is that we must adjust the passed time_point by the + // difference between the clocks' epochs. But since time_point doesn't + // expose its epoch, we fall back on what each of them thinks is now(). + // However, since we necessarily make sequential calls to those now() + // functions, the answers differ not only by the cycles spent executing + // those calls, but by potential OS interruptions between them. Try to + // reduce that error by capturing the source clock time both before and + // after the dest clock, and splitting the difference. Of course an + // interruption between two of these now() calls without a comparable + // interruption between the other two will skew the result, but better is + // more expensive. + const auto src_before = typename SrcTimePoint::clock::now(); + const auto dest_now = typename DestTimePoint::clock::now(); + const auto src_after = typename SrcTimePoint::clock::now(); + const auto src_diff = src_after - src_before; + const auto src_now = src_before + src_diff / 2; + return dest_now + (time - src_now); +} + +} // namespace LL + +#endif /* ! defined(LL_CHRONO_H) */ diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index e5a913a6a9..a228fd22be 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -27,6 +27,14 @@ #ifndef LL_LINDEN_COMMON_H #define LL_LINDEN_COMMON_H +#include "llprofiler.h" +#if TRACY_ENABLE && !defined(LL_PROFILER_ENABLE_TRACY_OPENGL) // hooks for memory profiling +void *tracy_aligned_malloc(size_t size, size_t alignment); +void tracy_aligned_free(void *memblock); +#define _aligned_malloc(X, Y) tracy_aligned_malloc((X), (Y)) +#define _aligned_free(X) tracy_aligned_free((X)) +#endif + // *NOTE: Please keep includes here to a minimum! // // Files included here are included in every library .cpp file and diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 96be913d17..25a809dad2 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -33,6 +33,66 @@ #include "lltracethreadrecorder.h" #include "llcleanup.h" +thread_local bool gProfilerEnabled = false; + +#if (TRACY_ENABLE) +// Override new/delete for tracy memory profiling +void *operator new(size_t size) +{ + void* ptr; + if (gProfilerEnabled) + { + LL_PROFILE_ZONE_SCOPED; + ptr = (malloc)(size); + } + else + { + ptr = (malloc)(size); + } + if (!ptr) + { + throw std::bad_alloc(); + } + TracyAlloc(ptr, size); + return ptr; +} + +void operator delete(void *ptr) noexcept +{ + TracyFree(ptr); + if (gProfilerEnabled) + { + LL_PROFILE_ZONE_SCOPED; + (free)(ptr); + } + else + { + (free)(ptr); + } +} + +// C-style malloc/free can't be so easily overridden, so we define tracy versions and use +// a pre-processor #define in linden_common.h to redirect to them. The parens around the native +// functions below prevents recursive substitution by the preprocessor. +// +// Unaligned mallocs are rare in LL code but hooking them causes problems in 3p lib code (looking at +// you, Havok), so we'll only capture the aligned version. + +void *tracy_aligned_malloc(size_t size, size_t alignment) +{ + auto ptr = ll_aligned_malloc_fallback(size, alignment); + if (ptr) TracyAlloc(ptr, size); + return ptr; +} + +void tracy_aligned_free(void *memblock) +{ + TracyFree(memblock); + ll_aligned_free_fallback(memblock); +} + +#endif + //static BOOL LLCommon::sAprInitialized = FALSE; diff --git a/indra/llcommon/llcond.h b/indra/llcommon/llcond.h index e31b67d893..da6e6affe1 100644 --- a/indra/llcommon/llcond.h +++ b/indra/llcommon/llcond.h @@ -53,6 +53,8 @@ private: LLCoros::Mutex mMutex; // Use LLCoros::ConditionVariable for the same reason. LLCoros::ConditionVariable mCond; + using LockType = LLCoros::LockType; + using cv_status = LLCoros::cv_status; public: /// LLCond can be explicitly initialized with a specific value for mData if @@ -65,10 +67,29 @@ public: LLCond(const LLCond&) = delete; LLCond& operator=(const LLCond&) = delete; - /// get() returns a const reference to the stored DATA. The only way to - /// get a non-const reference -- to modify the stored DATA -- is via - /// update_one() or update_all(). - const value_type& get() const { return mData; } + /** + * get() returns the stored DATA by value -- so to use get(), DATA must + * be copyable. The only way to get a non-const reference -- to modify + * the stored DATA -- is via update_one() or update_all(). + */ + value_type get() + { + LockType lk(mMutex); + return mData; + } + + /** + * get(functor) returns whatever the functor returns. It allows us to peek + * at the stored DATA without copying the whole thing. The functor must + * accept a const reference to DATA. If you want to modify DATA, call + * update_one() or update_all() instead. + */ + template <typename FUNC> + auto get(FUNC&& func) + { + LockType lk(mMutex); + return std::forward<FUNC>(func)(const_data()); + } /** * Pass update_one() an invocable accepting non-const (DATA&). The @@ -80,11 +101,11 @@ public: * update_one() when DATA is a struct or class. */ template <typename MODIFY> - void update_one(MODIFY modify) + void update_one(MODIFY&& modify) { { // scope of lock can/should end before notify_one() - LLCoros::LockType lk(mMutex); - modify(mData); + LockType lk(mMutex); + std::forward<MODIFY>(modify)(mData); } mCond.notify_one(); } @@ -99,11 +120,11 @@ public: * update_all() when DATA is a struct or class. */ template <typename MODIFY> - void update_all(MODIFY modify) + void update_all(MODIFY&& modify) { { // scope of lock can/should end before notify_all() - LLCoros::LockType lk(mMutex); - modify(mData); + LockType lk(mMutex); + std::forward<MODIFY>(modify)(mData); } mCond.notify_all(); } @@ -116,9 +137,9 @@ public: * wait() on the condition_variable. */ template <typename Pred> - void wait(Pred pred) + void wait(Pred&& pred) { - LLCoros::LockType lk(mMutex); + LockType lk(mMutex); // We must iterate explicitly since the predicate accepted by // condition_variable::wait() requires a different signature: // condition_variable::wait() calls its predicate with no arguments. @@ -127,7 +148,7 @@ public: // But what if they instead pass a predicate accepting non-const // (DATA&)? Such a predicate could modify mData, which would be Bad. // Forbid that. - while (! pred(const_cast<const value_type&>(mData))) + while (! std::forward<Pred>(pred)(const_data())) { mCond.wait(lk); } @@ -144,7 +165,7 @@ public: * returning true. */ template <typename Rep, typename Period, typename Pred> - bool wait_for(const std::chrono::duration<Rep, Period>& timeout_duration, Pred pred) + bool wait_for(const std::chrono::duration<Rep, Period>& timeout_duration, Pred&& pred) { // Instead of replicating wait_until() logic, convert duration to // time_point and just call wait_until(). @@ -153,7 +174,8 @@ public: // wrong! We'd keep pushing the timeout time farther and farther into // the future. This way, we establish a definite timeout time and // stick to it. - return wait_until(std::chrono::steady_clock::now() + timeout_duration, pred); + return wait_until(std::chrono::steady_clock::now() + timeout_duration, + std::forward<Pred>(pred)); } /** @@ -163,9 +185,9 @@ public: * generic wait_for() method. */ template <typename Pred> - bool wait_for(F32Milliseconds timeout_duration, Pred pred) + bool wait_for(F32Milliseconds timeout_duration, Pred&& pred) { - return wait_for(convert(timeout_duration), pred); + return wait_for(convert(timeout_duration), std::forward<Pred>(pred)); } protected: @@ -183,6 +205,10 @@ protected: } private: + // It's important to pass a const ref to certain user-specified functors + // that aren't supposed to be able to modify mData. + const value_type& const_data() const { return mData; } + /** * Pass wait_until() a chrono::time_point, indicating the time at which we * should stop waiting, and a predicate accepting (const DATA&), returning @@ -203,21 +229,21 @@ private: * honoring a fixed timeout. */ template <typename Clock, typename Duration, typename Pred> - bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, Pred pred) + bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, Pred&& pred) { - LLCoros::LockType lk(mMutex); + LockType lk(mMutex); // We advise the caller to pass a predicate accepting (const DATA&). // But what if they instead pass a predicate accepting non-const // (DATA&)? Such a predicate could modify mData, which would be Bad. // Forbid that. - while (! pred(const_cast<const value_type&>(mData))) + while (! std::forward<Pred>(pred)(const_data())) { - if (LLCoros::cv_status::timeout == mCond.wait_until(lk, timeout_time)) + if (cv_status::timeout == mCond.wait_until(lk, timeout_time)) { // It's possible that wait_until() timed out AND the predicate // became true more or less simultaneously. Even though // wait_until() timed out, check the predicate one more time. - return pred(const_cast<const value_type&>(mData)); + return std::forward<Pred>(pred)(const_data()); } } return true; diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 7a2a0869f4..2ddcf40895 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -86,11 +86,9 @@ std::string LLDate::asRFC1123() const return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } -LLTrace::BlockTimerStatHandle FT_DATE_FORMAT("Date Format"); - std::string LLDate::toHTTPDateString (std::string fmt) const { - LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT); + LL_PROFILE_ZONE_SCOPED; time_t locSeconds = (time_t) mSecondsSinceEpoch; struct tm * gmt = gmtime (&locSeconds); @@ -99,7 +97,7 @@ std::string LLDate::toHTTPDateString (std::string fmt) const std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) { - LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT); + LL_PROFILE_ZONE_SCOPED; // avoid calling setlocale() unnecessarily - it's expensive. static std::string prev_locale = ""; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 3fe8ce5f0e..17a5ec5776 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -109,6 +109,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { + LL_PROFILE_ZONE_SCOPED int syslogPriority = LOG_CRIT; switch (level) { case LLError::LEVEL_DEBUG: syslogPriority = LOG_DEBUG; break; @@ -166,6 +167,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { + LL_PROFILE_ZONE_SCOPED if (LLError::getAlwaysFlush()) { mFile << message << std::endl; @@ -194,7 +196,7 @@ namespace { { return LLError::getEnabledLogTypesMask() & 0x04; } - + LL_FORCE_INLINE std::string createBoldANSI() { std::string ansi_code; @@ -220,10 +222,10 @@ namespace { LL_FORCE_INLINE std::string createANSI(const std::string& color) { std::string ansi_code; - ansi_code += '\033'; - ansi_code += "["; + ansi_code += '\033'; + ansi_code += "["; ansi_code += "38;5;"; - ansi_code += color; + ansi_code += color; ansi_code += "m"; return ansi_code; @@ -232,6 +234,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { + LL_PROFILE_ZONE_SCOPED // The default colors for error, warn and debug are now a bit more pastel // and easier to read on the default (black) terminal background but you // now have the option to set the color of each via an environment variables: @@ -261,6 +264,7 @@ namespace { } else { + LL_PROFILE_ZONE_NAMED("fprintf"); fprintf(stderr, "%s\n", message.c_str()); } } @@ -270,6 +274,7 @@ namespace { LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message) { + LL_PROFILE_ZONE_SCOPED static std::string s_ansi_bold = createBoldANSI(); // bold text static std::string s_ansi_reset = createResetANSI(); // reset // ANSI color code escape sequence, message, and reset in one fprintf call @@ -306,6 +311,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { + LL_PROFILE_ZONE_SCOPED mBuffer->addLine(message); } @@ -332,6 +338,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { + LL_PROFILE_ZONE_SCOPED debugger_print(message); } }; @@ -1213,6 +1220,7 @@ namespace void writeToRecorders(const LLError::CallSite& site, const std::string& message) { + LL_PROFILE_ZONE_SCOPED LLError::ELevel level = site.mLevel; SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); @@ -1347,6 +1355,7 @@ namespace LLError bool Log::shouldLog(CallSite& site) { + LL_PROFILE_ZONE_SCOPED LLMutexTrylock lock(getMutex<LOG_MUTEX>(), 5); if (!lock.isLocked()) { @@ -1391,6 +1400,7 @@ namespace LLError void Log::flush(const std::ostringstream& out, const CallSite& site) { + LL_PROFILE_ZONE_SCOPED LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5); if (!lock.isLocked()) { diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index d439136ca8..d06c0e2132 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -35,7 +35,9 @@ #include "stdtypes.h" +#include "llprofiler.h" #include "llpreprocessor.h" + #include <boost/static_assert.hpp> const int LL_ERR_NOERR = 0; @@ -348,7 +350,8 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; // if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL; #define lllog(level, once, ...) \ - do { \ + do { \ + LL_PROFILE_ZONE_NAMED("lllog"); \ const char* tags[] = {"", ##__VA_ARGS__}; \ static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \ lllog_test_() diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index e87bb7bf35..57f10b7895 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -190,6 +190,7 @@ namespace LLError {} void recordMessage(LLError::ELevel level, const std::string& message) override { + LL_PROFILE_ZONE_SCOPED mCallable(level, message); } private: diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h index 48c2570732..7613850fb2 100644 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h @@ -429,6 +429,8 @@ public: // path, then stores it to mTarget. virtual bool post(const LLSD& event) { + LL_PROFILE_ZONE_SCOPED + // Extract the element specified by 'mPath' from 'event'. To perform a // generic type-appropriate store through mTarget, construct an // LLSDParam<T> and store that, thus engaging LLSDParam's custom diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 5b6a7b82f8..d38946004f 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -191,29 +191,30 @@ TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const } + void BlockTimer::bootstrapTimerTree() { - for (auto& base : BlockTimerStatHandle::instance_snapshot()) - { - // because of indirect derivation from LLInstanceTracker, have to downcast - BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(base); - if (&timer == &BlockTimer::getRootTimeBlock()) continue; - - // bootstrap tree construction by attaching to last timer to be on stack - // when this timer was called - if (timer.getParent() == &BlockTimer::getRootTimeBlock()) - { - TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator(); - - if (accumulator.mLastCaller) - { - timer.setParent(accumulator.mLastCaller); - accumulator.mParent = accumulator.mLastCaller; - } - // no need to push up tree on first use, flag can be set spuriously - accumulator.mMoveUpTree = false; - } - } + for (auto& base : BlockTimerStatHandle::instance_snapshot()) + { + // because of indirect derivation from LLInstanceTracker, have to downcast + BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(base); + if (&timer == &BlockTimer::getRootTimeBlock()) continue; + + // bootstrap tree construction by attaching to last timer to be on stack + // when this timer was called + if (timer.getParent() == &BlockTimer::getRootTimeBlock()) + { + TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator(); + + if (accumulator.mLastCaller) + { + timer.setParent(accumulator.mLastCaller); + accumulator.mParent = accumulator.mLastCaller; + } + // no need to push up tree on first use, flag can be set spuriously + accumulator.mMoveUpTree = false; + } + } } // bump timers up tree if they have been flagged as being in the wrong place @@ -221,6 +222,7 @@ void BlockTimer::bootstrapTimerTree() // this preserves partial order derived from current frame's observations void BlockTimer::incrementalUpdateTimerTree() { + LL_PROFILE_ZONE_SCOPED; for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimer::getRootTimeBlock()); it != end_block_timer_tree_df_post(); ++it) @@ -260,7 +262,8 @@ void BlockTimer::incrementalUpdateTimerTree() void BlockTimer::updateTimes() - { +{ + LL_PROFILE_ZONE_SCOPED; // walk up stack of active timers and accumulate current time while leaving timing structures active BlockTimerStackRecord* stack_record = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance(); if (!stack_record) return; @@ -271,7 +274,7 @@ void BlockTimer::updateTimes() while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self - { + { U64 cumulative_time_delta = cur_time - cur_timer->mStartTime; cur_timer->mStartTime = cur_time; diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index dfc63d08a2..9bd93d7240 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -38,7 +38,10 @@ #define LL_FAST_TIMER_ON 1 #define LL_FASTTIMER_USE_RDTSC 1 +// NOTE: Also see llprofiler.h +#if !defined(LL_PROFILER_CONFIGURATION) #define LL_RECORD_BLOCK_TIME(timer_stat) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__); +#endif // LL_PROFILER_CONFIGURATION namespace LLTrace { diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index 1e9920746b..c54029e8b4 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -29,6 +29,11 @@ #include "llframetimer.h" +// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support +#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER + #include "TracyClient.cpp" +#endif // LL_PROFILER_CONFIGURATION + // Static members //LLTimer LLFrameTimer::sInternalTimer; U64 LLFrameTimer::sStartTotalTime = totalTime(); diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 402333cca7..02535a59e7 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -83,13 +83,34 @@ class LLInstanceTracker typedef llthread::LockStatic<StaticData> LockStatic; public: + using ptr_t = std::shared_ptr<T>; + using weak_t = std::weak_ptr<T>; + + /** + * Storing a dumb T* somewhere external is a bad idea, since + * LLInstanceTracker subclasses are explicitly destroyed rather than + * managed by smart pointers. It's legal to declare stack instances of an + * LLInstanceTracker subclass. But it's reasonable to store a + * std::weak_ptr<T>, which will become invalid when the T instance is + * destroyed. + */ + weak_t getWeak() + { + return mSelf; + } + + static S32 instanceCount() + { + return LockStatic()->mMap.size(); + } + // snapshot of std::pair<const KEY, std::shared_ptr<T>> pairs class snapshot { // It's very important that what we store in this snapshot are // weak_ptrs, NOT shared_ptrs. That's how we discover whether any // instance has been deleted during the lifespan of a snapshot. - typedef std::vector<std::pair<const KEY, std::weak_ptr<T>>> VectorType; + typedef std::vector<std::pair<const KEY, weak_t>> VectorType; // Dereferencing our iterator produces a std::shared_ptr for each // instance that still exists. Since we store weak_ptrs, that involves // two chained transformations: @@ -98,7 +119,7 @@ public: // It is very important that we filter lazily, that is, during // traversal. Any one of our stored weak_ptrs might expire during // traversal. - typedef std::pair<const KEY, std::shared_ptr<T>> strong_pair; + typedef std::pair<const KEY, ptr_t> strong_pair; // Note for future reference: nat has not yet had any luck (up to // Boost 1.67) trying to use boost::transform_iterator with a hand- // coded functor, only with actual functions. In my experience, an @@ -202,17 +223,12 @@ public: iterator end() { return iterator(snapshot::end(), key_getter); } }; - static T* getInstance(const KEY& k) + static ptr_t getInstance(const KEY& k) { LockStatic lock; const InstanceMap& map(lock->mMap); typename InstanceMap::const_iterator found = map.find(k); - return (found == map.end()) ? NULL : found->second.get(); - } - - static S32 instanceCount() - { - return LockStatic()->mMap.size(); + return (found == map.end()) ? NULL : found->second; } protected: @@ -222,7 +238,9 @@ protected: // shared_ptr, so give it a no-op deleter. We store shared_ptrs in our // InstanceMap specifically so snapshot can store weak_ptrs so we can // detect deletions during traversals. - std::shared_ptr<T> ptr(static_cast<T*>(this), [](T*){}); + ptr_t ptr(static_cast<T*>(this), [](T*){}); + // save corresponding weak_ptr for future reference + mSelf = ptr; LockStatic lock; add_(lock, key, ptr); } @@ -257,7 +275,7 @@ private: static std::string report(const char* key) { return report(std::string(key)); } // caller must instantiate LockStatic - void add_(LockStatic& lock, const KEY& key, const std::shared_ptr<T>& ptr) + void add_(LockStatic& lock, const KEY& key, const ptr_t& ptr) { mInstanceKey = key; InstanceMap& map = lock->mMap; @@ -281,7 +299,7 @@ private: break; } } - std::shared_ptr<T> remove_(LockStatic& lock) + ptr_t remove_(LockStatic& lock) { InstanceMap& map = lock->mMap; typename InstanceMap::iterator iter = map.find(mInstanceKey); @@ -295,6 +313,9 @@ private: } private: + // Storing a weak_ptr to self is a bit like deriving from + // std::enable_shared_from_this(), except more explicit. + weak_t mSelf; KEY mInstanceKey; }; @@ -326,6 +347,9 @@ class LLInstanceTracker<T, void, KEY_COLLISION_BEHAVIOR> typedef llthread::LockStatic<StaticData> LockStatic; public: + using ptr_t = std::shared_ptr<T>; + using weak_t = std::weak_ptr<T>; + /** * Storing a dumb T* somewhere external is a bad idea, since * LLInstanceTracker subclasses are explicitly destroyed rather than @@ -334,12 +358,15 @@ public: * std::weak_ptr<T>, which will become invalid when the T instance is * destroyed. */ - std::weak_ptr<T> getWeak() + weak_t getWeak() { return mSelf; } - static S32 instanceCount() { return LockStatic()->mSet.size(); } + static S32 instanceCount() + { + return LockStatic()->mSet.size(); + } // snapshot of std::shared_ptr<T> pointers class snapshot @@ -347,7 +374,7 @@ public: // It's very important that what we store in this snapshot are // weak_ptrs, NOT shared_ptrs. That's how we discover whether any // instance has been deleted during the lifespan of a snapshot. - typedef std::vector<std::weak_ptr<T>> VectorType; + typedef std::vector<weak_t> VectorType; // Dereferencing our iterator produces a std::shared_ptr for each // instance that still exists. Since we store weak_ptrs, that involves // two chained transformations: @@ -453,7 +480,7 @@ protected: private: // Storing a weak_ptr to self is a bit like deriving from // std::enable_shared_from_this(), except more explicit. - std::weak_ptr<T> mSelf; + weak_t mSelf; }; #endif diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp index 3e6ce9092c..11bfec1b31 100644 --- a/indra/llcommon/llleaplistener.cpp +++ b/indra/llcommon/llleaplistener.cpp @@ -220,7 +220,7 @@ void LLLeapListener::getAPI(const LLSD& request) const { Response reply(LLSD(), request); - LLEventAPI* found = LLEventAPI::getInstance(request["api"]); + auto found = LLEventAPI::getInstance(request["api"]); if (found) { reply["name"] = found->getName(); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index ea84e4c1ea..849867586a 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -82,6 +82,7 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size) //static void LLMemory::updateMemoryInfo() { + LL_PROFILE_ZONE_SCOPED #if LL_WINDOWS PROCESS_MEMORY_COUNTERS counters; @@ -145,6 +146,7 @@ void* LLMemory::tryToAlloc(void* address, U32 size) //static void LLMemory::logMemoryInfo(BOOL update) { + LL_PROFILE_ZONE_SCOPED if(update) { updateMemoryInfo() ; diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 24f86cc11e..41023b4ba4 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -101,6 +101,29 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) #define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) +#define LL_ALIGN_NEW \ +public: \ + void* operator new(size_t size) \ + { \ + return ll_aligned_malloc_16(size); \ + } \ + \ + void operator delete(void* ptr) \ + { \ + ll_aligned_free_16(ptr); \ + } \ + \ + void* operator new[](size_t size) \ + { \ + return ll_aligned_malloc_16(size); \ + } \ + \ + void operator delete[](void* ptr) \ + { \ + ll_aligned_free_16(ptr); \ + } + + //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library @@ -113,8 +136,9 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) #else inline void* ll_aligned_malloc_fallback( size_t size, int align ) { + LL_PROFILE_ZONE_SCOPED; #if defined(LL_WINDOWS) - return _aligned_malloc(size, align); + void* ret = _aligned_malloc(size, align); #else char* aligned = NULL; void* mem = malloc( size + (align - 1) + sizeof(void*) ); @@ -125,12 +149,16 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) ((void**)aligned)[-1] = mem; } - return aligned; + void* ret = aligned; #endif + LL_PROFILE_ALLOC(ret, size); + return ret; } inline void ll_aligned_free_fallback( void* ptr ) { + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_FREE(ptr); #if defined(LL_WINDOWS) _aligned_free(ptr); #else @@ -146,21 +174,24 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { + LL_PROFILE_ZONE_SCOPED; #if defined(LL_WINDOWS) - return _aligned_malloc(size, 16); + void* ret = _aligned_malloc(size, 16); #elif defined(LL_DARWIN) - return malloc(size); // default osx malloc is 16 byte aligned. + void* ret = malloc(size); // default osx malloc is 16 byte aligned. #else - void *rtn; - if (LL_LIKELY(0 == posix_memalign(&rtn, 16, size))) - return rtn; - else // bad alignment requested, or out of memory - return NULL; + void *ret; + if (0 != posix_memalign(&ret, 16, size)) + return nullptr; #endif + LL_PROFILE_ALLOC(ret, size); + return ret; } inline void ll_aligned_free_16(void *p) { + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_FREE(p); #if defined(LL_WINDOWS) _aligned_free(p); #elif defined(LL_DARWIN) @@ -172,10 +203,12 @@ inline void ll_aligned_free_16(void *p) inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // returned hunk MUST be freed with ll_aligned_free_16(). { + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_FREE(ptr); #if defined(LL_WINDOWS) - return _aligned_realloc(ptr, size, 16); + void* ret = _aligned_realloc(ptr, size, 16); #elif defined(LL_DARWIN) - return realloc(ptr,size); // default osx malloc is 16 byte aligned. + void* ret = realloc(ptr,size); // default osx malloc is 16 byte aligned. #else //FIXME: memcpy is SLOW void* ret = ll_aligned_malloc_16(size); @@ -188,27 +221,31 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r } ll_aligned_free_16(ptr); } - return ret; #endif + LL_PROFILE_ALLOC(ptr, size); + return ret; } inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { + LL_PROFILE_ZONE_SCOPED; #if defined(LL_WINDOWS) - return _aligned_malloc(size, 32); + void* ret = _aligned_malloc(size, 32); #elif defined(LL_DARWIN) - return ll_aligned_malloc_fallback( size, 32 ); + void* ret = ll_aligned_malloc_fallback( size, 32 ); #else - void *rtn; - if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size))) - return rtn; - else // bad alignment requested, or out of memory - return NULL; + void *ret; + if (0 != posix_memalign(&ret, 32, size)) + return nullptr; #endif + LL_PROFILE_ALLOC(ret, size); + return ret; } inline void ll_aligned_free_32(void *p) { + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_FREE(p); #if defined(LL_WINDOWS) _aligned_free(p); #elif defined(LL_DARWIN) @@ -222,29 +259,35 @@ inline void ll_aligned_free_32(void *p) template<size_t ALIGNMENT> LL_FORCE_INLINE void* ll_aligned_malloc(size_t size) { + LL_PROFILE_ZONE_SCOPED; + void* ret; if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0) { - return malloc(size); + ret = malloc(size); + LL_PROFILE_ALLOC(ret, size); } else if (ALIGNMENT == 16) { - return ll_aligned_malloc_16(size); + ret = ll_aligned_malloc_16(size); } else if (ALIGNMENT == 32) { - return ll_aligned_malloc_32(size); + ret = ll_aligned_malloc_32(size); } else { - return ll_aligned_malloc_fallback(size, ALIGNMENT); + ret = ll_aligned_malloc_fallback(size, ALIGNMENT); } + return ret; } template<size_t ALIGNMENT> LL_FORCE_INLINE void ll_aligned_free(void* ptr) { + LL_PROFILE_ZONE_SCOPED; if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN) { + LL_PROFILE_FREE(ptr); free(ptr); } else if (ALIGNMENT == 16) @@ -266,6 +309,7 @@ LL_FORCE_INLINE void ll_aligned_free(void* ptr) // inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes) { + LL_PROFILE_ZONE_SCOPED; assert(src != NULL); assert(dst != NULL); assert(bytes > 0); diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp index 4d73c04d07..a49002b5dc 100644 --- a/indra/llcommon/llmutex.cpp +++ b/indra/llcommon/llmutex.cpp @@ -44,6 +44,7 @@ LLMutex::~LLMutex() void LLMutex::lock() { + LL_PROFILE_ZONE_SCOPED if(isSelfLocked()) { //redundant lock mCount++; @@ -65,6 +66,7 @@ void LLMutex::lock() void LLMutex::unlock() { + LL_PROFILE_ZONE_SCOPED if (mCount > 0) { //not the root unlock mCount--; @@ -85,6 +87,7 @@ void LLMutex::unlock() bool LLMutex::isLocked() { + LL_PROFILE_ZONE_SCOPED if (!mMutex.try_lock()) { return true; @@ -108,6 +111,7 @@ LLThread::id_t LLMutex::lockingThread() const bool LLMutex::trylock() { + LL_PROFILE_ZONE_SCOPED if(isSelfLocked()) { //redundant lock mCount++; @@ -146,17 +150,20 @@ LLCondition::~LLCondition() void LLCondition::wait() { + LL_PROFILE_ZONE_SCOPED std::unique_lock< std::mutex > lock(mMutex); mCond.wait(lock); } void LLCondition::signal() { + LL_PROFILE_ZONE_SCOPED mCond.notify_one(); } void LLCondition::broadcast() { + LL_PROFILE_ZONE_SCOPED mCond.notify_all(); } @@ -166,6 +173,7 @@ LLMutexTrylock::LLMutexTrylock(LLMutex* mutex) : mMutex(mutex), mLocked(false) { + LL_PROFILE_ZONE_SCOPED if (mMutex) mLocked = mMutex->trylock(); } @@ -174,6 +182,7 @@ LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms) : mMutex(mutex), mLocked(false) { + LL_PROFILE_ZONE_SCOPED if (!mMutex) return; @@ -188,6 +197,7 @@ LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms) LLMutexTrylock::~LLMutexTrylock() { + LL_PROFILE_ZONE_SCOPED if (mMutex && mLocked) mMutex->unlock(); } @@ -199,6 +209,7 @@ LLMutexTrylock::~LLMutexTrylock() // LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex) { + LL_PROFILE_ZONE_SCOPED if(mutex) { mutex->lock(); @@ -217,6 +228,7 @@ LLScopedLock::~LLScopedLock() void LLScopedLock::unlock() { + LL_PROFILE_ZONE_SCOPED if(mLocked) { mMutex->unlock(); diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index b17a8e761a..dc586b0008 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -171,7 +171,9 @@ #define LL_DLLIMPORT #endif // LL_WINDOWS -#if ! defined(LL_WINDOWS) +#if __clang__ || ! defined(LL_WINDOWS) +// Only on Windows, and only with the Microsoft compiler (vs. clang) is +// wchar_t potentially not a distinct type. #define LL_WCHAR_T_NATIVE 1 #else // LL_WINDOWS // https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h new file mode 100644 index 0000000000..ca60d23248 --- /dev/null +++ b/indra/llcommon/llprofiler.h @@ -0,0 +1,111 @@ +/** + * @file llprofiler.h + * @brief Wrapper for Tracy and/or other profilers + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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$ + */ + +#ifndef LL_PROFILER_H +#define LL_PROFILER_H + +#define LL_PROFILER_CONFIG_NONE 0 // No profiling +#define LL_PROFILER_CONFIG_FAST_TIMER 1 // Profiling on: Only Fast Timers +#define LL_PROFILER_CONFIG_TRACY 2 // Profiling on: Only Tracy +#define LL_PROFILER_CONFIG_TRACY_FAST_TIMER 3 // Profiling on: Fast Timers + Tracy + +#ifndef LL_PROFILER_CONFIGURATION +#define LL_PROFILER_CONFIGURATION LL_PROFILER_CONFIG_FAST_TIMER +#endif + +extern thread_local bool gProfilerEnabled; + +#if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE) + #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER + #define TRACY_ENABLE 1 +// Normally these would be enabled but we want to be able to build any viewer with Tracy enabled and run the Tracy server on another machine +// They must be undefined in order to work across multiple machines +// #define TRACY_NO_BROADCAST 1 +// #define TRACY_ONLY_LOCALHOST 1 + #define TRACY_ONLY_IPV4 1 + #include "Tracy.hpp" + + // Mutually exclusive with detailed memory tracing + #define LL_PROFILER_ENABLE_TRACY_OPENGL 0 + #endif + + #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY + #define LL_PROFILER_FRAME_END FrameMark + #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true; + #define LL_RECORD_BLOCK_TIME(name) ZoneScoped // Want descriptive names; was: ZoneNamedN( ___tracy_scoped_zone, #name, true ); + #define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, name, true ); + #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB + #define LL_PROFILE_ZONE_SCOPED ZoneScoped + + #define LL_PROFILE_ZONE_NUM( val ) ZoneValue( val ) + #define LL_PROFILE_ZONE_TEXT( text, size ) ZoneText( text, size ) + + #define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow + #define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan + #define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red + #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) + #define LL_PROFILE_FREE(ptr) TracyFree(ptr) + #endif + #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER + #define LL_PROFILER_FRAME_END + #define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name) + #define LL_RECORD_BLOCK_TIME(name) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__); + #define LL_PROFILE_ZONE_NAMED(name) // LL_PROFILE_ZONE_NAMED is a no-op when Tracy is disabled + #define LL_PROFILE_ZONE_SCOPED // LL_PROFILE_ZONE_SCOPED is a no-op when Tracy is disabled + #define LL_PROFILE_ZONE_COLOR(name,color) // LL_RECORD_BLOCK_TIME(name) + + #define LL_PROFILE_ZONE_NUM( val ) (void)( val ); // Not supported + #define LL_PROFILE_ZONE_TEXT( text, size ) (void)( text ); void( size ); // Not supported + + #define LL_PROFILE_ZONE_ERR(name) (void)(name); // Not supported + #define LL_PROFILE_ZONE_INFO(name) (void)(name); // Not supported + #define LL_PROFILE_ZONE_WARN(name) (void)(name); // Not supported + #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size); + #define LL_PROFILE_FREE(ptr) (void)(ptr); + #endif + #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER + #define LL_PROFILER_FRAME_END FrameMark + #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true; + #define LL_RECORD_BLOCK_TIME(name) ZoneNamedN(___tracy_scoped_zone, #name, true); const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__); + #define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, #name, true ); + #define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB + #define LL_PROFILE_ZONE_SCOPED ZoneScoped + + #define LL_PROFILE_ZONE_NUM( val ) ZoneValue( val ) + #define LL_PROFILE_ZONE_TEXT( text, size ) ZoneText( text, size ) + + #define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow + #define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan + #define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red + #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) + #define LL_PROFILE_FREE(ptr) TracyFree(ptr) + #endif +#else + #define LL_PROFILER_FRAME_END + #define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name) +#endif // LL_PROFILER + +#endif // LL_PROFILER_H diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 57b746889d..605f6bf0e3 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -400,6 +400,7 @@ namespace ImplMap& ImplMap::makeMap(LLSD::Impl*& var) { + LL_PROFILE_ZONE_SCOPED; if (shared()) { ImplMap* i = new ImplMap(mData); @@ -414,18 +415,21 @@ namespace bool ImplMap::has(const LLSD::String& k) const { + LL_PROFILE_ZONE_SCOPED; DataMap::const_iterator i = mData.find(k); return i != mData.end(); } LLSD ImplMap::get(const LLSD::String& k) const { + LL_PROFILE_ZONE_SCOPED; DataMap::const_iterator i = mData.find(k); return (i != mData.end()) ? i->second : LLSD(); } LLSD ImplMap::getKeys() const { + LL_PROFILE_ZONE_SCOPED; LLSD keys = LLSD::emptyArray(); DataMap::const_iterator iter = mData.begin(); while (iter != mData.end()) @@ -438,11 +442,13 @@ namespace void ImplMap::insert(const LLSD::String& k, const LLSD& v) { + LL_PROFILE_ZONE_SCOPED; mData.insert(DataMap::value_type(k, v)); } void ImplMap::erase(const LLSD::String& k) { + LL_PROFILE_ZONE_SCOPED; mData.erase(k); } @@ -684,6 +690,7 @@ const LLSD::Impl& LLSD::Impl::safe(const Impl* impl) ImplMap& LLSD::Impl::makeMap(Impl*& var) { + LL_PROFILE_ZONE_SCOPED; ImplMap* im = new ImplMap; reset(var, im); return *im; @@ -887,11 +894,16 @@ LLSD& LLSD::with(const String& k, const LLSD& v) } void LLSD::erase(const String& k) { makeMap(impl).erase(k); } -LLSD& LLSD::operator[](const String& k) - { return makeMap(impl).ref(k); } +LLSD& LLSD::operator[](const String& k) +{ + LL_PROFILE_ZONE_SCOPED; + return makeMap(impl).ref(k); +} const LLSD& LLSD::operator[](const String& k) const - { return safe(impl).ref(k); } - +{ + LL_PROFILE_ZONE_SCOPED; + return safe(impl).ref(k); +} LLSD LLSD::emptyArray() { @@ -914,10 +926,16 @@ LLSD& LLSD::with(Integer i, const LLSD& v) LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); } void LLSD::erase(Integer i) { makeArray(impl).erase(i); } -LLSD& LLSD::operator[](Integer i) - { return makeArray(impl).ref(i); } +LLSD& LLSD::operator[](Integer i) +{ + LL_PROFILE_ZONE_SCOPED; + return makeArray(impl).ref(i); +} const LLSD& LLSD::operator[](Integer i) const - { return safe(impl).ref(i); } +{ + LL_PROFILE_ZONE_SCOPED; + return safe(impl).ref(i); +} static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat) { diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 5b6d5545af..b8ddf21596 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -290,9 +290,17 @@ public: LLSD& with(const String&, const LLSD&); LLSD& operator[](const String&); - LLSD& operator[](const char* c) { return (*this)[String(c)]; } + LLSD& operator[](const char* c) + { + LL_PROFILE_ZONE_SCOPED; + return (*this)[String(c)]; + } const LLSD& operator[](const String&) const; - const LLSD& operator[](const char* c) const { return (*this)[String(c)]; } + const LLSD& operator[](const char* c) const + { + LL_PROFILE_ZONE_SCOPED; + return (*this)[String(c)]; + } //@} /** @name Array Values */ diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 2e7b46f885..af4ccf25fd 100644 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -37,8 +37,6 @@ static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs; static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs; static const LLSD NO_VALUE_MARKER; -LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion"); - // // LLParamSDParser // diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h index 93910b70ae..82a623a8a0 100644 --- a/indra/llcommon/llsdparam.h +++ b/indra/llcommon/llsdparam.h @@ -110,7 +110,6 @@ private: }; -extern LL_COMMON_API LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR; template<typename T> class LLSDParamAdapter : public T { @@ -118,7 +117,7 @@ public: LLSDParamAdapter() {} LLSDParamAdapter(const LLSD& sd) { - LL_RECORD_BLOCK_TIME(FTM_SD_PARAM_ADAPTOR); + LL_PROFILE_ZONE_SCOPED; LLParamSDParser parser; // don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it bool parse_silently = true; diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index eb3a96b133..c2fe15e9b7 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -214,6 +214,8 @@ BOOL compare_llsd_with_template( const LLSD& template_llsd, LLSD& resultant_llsd) { + LL_PROFILE_ZONE_SCOPED + if ( llsd_to_test.isUndefined() && template_llsd.isDefined() ) @@ -335,6 +337,8 @@ bool filter_llsd_with_template( const LLSD & template_llsd, LLSD & resultant_llsd) { + LL_PROFILE_ZONE_SCOPED + if (llsd_to_test.isUndefined() && template_llsd.isDefined()) { resultant_llsd = template_llsd; @@ -529,6 +533,8 @@ class TypeLookup public: TypeLookup() { + LL_PROFILE_ZONE_SCOPED + for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di) { mMap[di->type] = di->name; @@ -537,6 +543,8 @@ public: std::string lookup(LLSD::Type type) const { + LL_PROFILE_ZONE_SCOPED + MapType::const_iterator found = mMap.find(type); if (found != mMap.end()) { @@ -587,6 +595,8 @@ static std::string match_types(LLSD::Type expect, // prototype.type() LLSD::Type actual, // type we're checking const std::string& pfx) // as for llsd_matches { + LL_PROFILE_ZONE_SCOPED + // Trivial case: if the actual type is exactly what we expect, we're good. if (actual == expect) return ""; @@ -624,6 +634,8 @@ static std::string match_types(LLSD::Type expect, // prototype.type() // see docstring in .h file std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx) { + LL_PROFILE_ZONE_SCOPED + // An undefined prototype means that any data is valid. // An undefined slot in an array or map prototype means that any data // may fill that slot. @@ -756,6 +768,8 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits) { + LL_PROFILE_ZONE_SCOPED + // We're comparing strict equality of LLSD representation rather than // performing any conversions. So if the types aren't equal, the LLSD // values aren't equal. @@ -864,6 +878,8 @@ namespace llsd LLSD& drill(LLSD& blob, const LLSD& rawPath) { + LL_PROFILE_ZONE_SCOPED + // Treat rawPath uniformly as an array. If it's not already an array, // store it as the only entry in one. (But let's say Undefined means an // empty array.) @@ -889,6 +905,8 @@ LLSD& drill(LLSD& blob, const LLSD& rawPath) // path entry that's bad. for (LLSD::Integer i = 0; i < path.size(); ++i) { + LL_PROFILE_ZONE_NUM( i ) + const LLSD& key{path[i]}; if (key.isString()) { @@ -917,6 +935,8 @@ LLSD& drill(LLSD& blob, const LLSD& rawPath) LLSD drill(const LLSD& blob, const LLSD& path) { + LL_PROFILE_ZONE_SCOPED + // non-const drill() does exactly what we want. Temporarily cast away // const-ness and use that. return drill(const_cast<LLSD&>(blob), path); @@ -929,6 +949,8 @@ LLSD drill(const LLSD& blob, const LLSD& path) // filter may be include to exclude/include keys in a map. LLSD llsd_clone(LLSD value, LLSD filter) { + LL_PROFILE_ZONE_SCOPED + LLSD clone; bool has_filter(filter.isMap()); diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 7c81d65a8b..6042c0906c 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -455,6 +455,7 @@ public: static DERIVED_TYPE* getInstance() { + LL_PROFILE_ZONE_SCOPED; // We know the viewer has LLSingleton dependency circularities. If you // feel strongly motivated to eliminate them, cheers and good luck. // (At that point we could consider a much simpler locking mechanism.) @@ -838,4 +839,36 @@ private: \ /* LLSINGLETON() is carefully implemented to permit exactly this */ \ LLSINGLETON_C11(DERIVED_CLASS) {} +// Relatively unsafe singleton implementation that is much faster +// and simpler than LLSingleton, but has no dependency tracking +// or inherent thread safety and requires manual invocation of +// createInstance before first use. +template<class T> +class LLSimpleton +{ +public: + template <typename... ARGS> + static void createInstance(ARGS&&... args) + { + llassert(sInstance == nullptr); + sInstance = new T(std::forward<ARGS>(args)...); + } + + static inline T* getInstance() { return sInstance; } + static inline T& instance() { return *getInstance(); } + static inline bool instanceExists() { return sInstance != nullptr; } + + static void deleteSingleton() + { + delete sInstance; + sInstance = nullptr; + } + +private: + static T* sInstance; +}; + +template <class T> +T* LLSimpleton<T>::sInstance{ nullptr }; + #endif diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 0290eea143..bdea1e76ea 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -37,9 +37,6 @@ #include <winnls.h> // for WideCharToMultiByte #endif -LLTrace::BlockTimerStatHandle FT_STRING_FORMAT("String Format"); - - std::string ll_safe_string(const char* in) { if(in) return std::string(in); @@ -215,7 +212,7 @@ S32 utf16chars_to_wchar(const U16* inchars, llwchar* outchar) return inchars - base; } -llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len) +llutf16string wstring_to_utf16str(const llwchar* utf32str, size_t len) { llutf16string out; @@ -237,27 +234,19 @@ llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len) return out; } -llutf16string wstring_to_utf16str(const LLWString &utf32str) -{ - const S32 len = (S32)utf32str.length(); - return wstring_to_utf16str(utf32str, len); -} - -llutf16string utf8str_to_utf16str ( const std::string& utf8str ) +llutf16string utf8str_to_utf16str( const char* utf8str, size_t len ) { - LLWString wstr = utf8str_to_wstring ( utf8str ); + LLWString wstr = utf8str_to_wstring ( utf8str, len ); return wstring_to_utf16str ( wstr ); } - -LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len) +LLWString utf16str_to_wstring(const U16* utf16str, size_t len) { LLWString wout; - if((len <= 0) || utf16str.empty()) return wout; + if (len == 0) return wout; S32 i = 0; - // craziness to make gcc happy (llutf16string.c_str() is tweaked on linux): - const U16* chars16 = &(*(utf16str.begin())); + const U16* chars16 = utf16str; while (i < len) { llwchar cur_char; @@ -267,12 +256,6 @@ LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len) return wout; } -LLWString utf16str_to_wstring(const llutf16string &utf16str) -{ - const S32 len = (S32)utf16str.length(); - return utf16str_to_wstring(utf16str, len); -} - // Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string. S32 utf16str_wstring_length(const llutf16string &utf16str, const S32 utf16_len) { @@ -392,8 +375,7 @@ S32 wstring_utf8_length(const LLWString& wstr) return len; } - -LLWString utf8str_to_wstring(const std::string& utf8str, S32 len) +LLWString utf8str_to_wstring(const char* utf8str, size_t len) { LLWString wout; @@ -481,13 +463,7 @@ LLWString utf8str_to_wstring(const std::string& utf8str, S32 len) return wout; } -LLWString utf8str_to_wstring(const std::string& utf8str) -{ - const S32 len = (S32)utf8str.length(); - return utf8str_to_wstring(utf8str, len); -} - -std::string wstring_to_utf8str(const LLWString& utf32str, S32 len) +std::string wstring_to_utf8str(const llwchar* utf32str, size_t len) { std::string out; @@ -503,20 +479,9 @@ std::string wstring_to_utf8str(const LLWString& utf32str, S32 len) return out; } -std::string wstring_to_utf8str(const LLWString& utf32str) -{ - const S32 len = (S32)utf32str.length(); - return wstring_to_utf8str(utf32str, len); -} - -std::string utf16str_to_utf8str(const llutf16string& utf16str) -{ - return wstring_to_utf8str(utf16str_to_wstring(utf16str)); -} - -std::string utf16str_to_utf8str(const llutf16string& utf16str, S32 len) +std::string utf16str_to_utf8str(const U16* utf16str, size_t len) { - return wstring_to_utf8str(utf16str_to_wstring(utf16str, len), len); + return wstring_to_utf8str(utf16str_to_wstring(utf16str, len)); } std::string utf8str_trim(const std::string& utf8str) @@ -657,17 +622,16 @@ std::string utf8str_removeCRLF(const std::string& utf8str) } #if LL_WINDOWS -std::string ll_convert_wide_to_string(const wchar_t* in) +unsigned int ll_wstring_default_code_page() { - return ll_convert_wide_to_string(in, CP_UTF8); + return CP_UTF8; } -std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) +std::string ll_convert_wide_to_string(const wchar_t* in, size_t len_in, unsigned int code_page) { std::string out; if(in) { - int len_in = wcslen(in); int len_out = WideCharToMultiByte( code_page, 0, @@ -699,12 +663,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) return out; } -std::wstring ll_convert_string_to_wide(const std::string& in) -{ - return ll_convert_string_to_wide(in, CP_UTF8); -} - -std::wstring ll_convert_string_to_wide(const std::string& in, unsigned int code_page) +std::wstring ll_convert_string_to_wide(const char* in, size_t len, unsigned int code_page) { // From review: // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input, @@ -716,10 +675,10 @@ std::wstring ll_convert_string_to_wide(const std::string& in, unsigned int code_ // reserve an output buffer that will be destroyed on exit, with a place // to put NULL terminator - std::vector<wchar_t> w_out(in.length() + 1); + std::vector<wchar_t> w_out(len + 1); memset(&w_out[0], 0, w_out.size()); - int real_output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), + int real_output_str_len = MultiByteToWideChar(code_page, 0, in, len, &w_out[0], w_out.size() - 1); //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. @@ -729,30 +688,32 @@ std::wstring ll_convert_string_to_wide(const std::string& in, unsigned int code_ return {&w_out[0]}; } -LLWString ll_convert_wide_to_wstring(const std::wstring& in) +LLWString ll_convert_wide_to_wstring(const wchar_t* in, size_t len) { - // This function, like its converse, is a placeholder, encapsulating a - // guilty little hack: the only "official" way nat has found to convert - // between std::wstring (16 bits on Windows) and LLWString (UTF-32) is - // by using iconv, which we've avoided so far. It kinda sorta works to - // just copy individual characters... - // The point is that if/when we DO introduce some more official way to - // perform such conversions, we should only have to call it here. - return { in.begin(), in.end() }; + // Whether or not std::wstring and llutf16string are distinct types, they + // both hold UTF-16LE characters. (See header file comments.) Pretend this + // wchar_t* sequence is really a U16* sequence and use the conversion we + // define above. + return utf16str_to_wstring(reinterpret_cast<const U16*>(in), len); } -std::wstring ll_convert_wstring_to_wide(const LLWString& in) +std::wstring ll_convert_wstring_to_wide(const llwchar* in, size_t len) { - // See comments in ll_convert_wide_to_wstring() - return { in.begin(), in.end() }; + // first, convert to llutf16string, for which we have a real implementation + auto utf16str{ wstring_to_utf16str(in, len) }; + // then, because each U16 char must be UTF-16LE encoded, pretend the U16* + // string pointer is a wchar_t* and instantiate a std::wstring of the same + // length. + return { reinterpret_cast<const wchar_t*>(utf16str.c_str()), utf16str.length() }; } std::string ll_convert_string_to_utf8_string(const std::string& in) { - auto w_mesg = ll_convert_string_to_wide(in, CP_ACP); - std::string out_utf8(ll_convert_wide_to_string(w_mesg.c_str(), CP_UTF8)); - - return out_utf8; + // If you pass code_page, you must also pass length, otherwise the code + // page parameter will be mistaken for length. + auto w_mesg = ll_convert_string_to_wide(in, in.length(), CP_ACP); + // CP_UTF8 is default -- see ll_wstring_default_code_page() above. + return ll_convert_wide_to_string(w_mesg); } namespace @@ -1356,7 +1317,7 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, template<> S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) { - LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT); + LL_PROFILE_ZONE_SCOPED; S32 res = 0; std::string output; @@ -1429,7 +1390,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) template<> S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) { - LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT); + LL_PROFILE_ZONE_SCOPED; S32 res = 0; if (!substitutions.isMap()) diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 4263122f36..d94f549480 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -27,9 +27,11 @@ #ifndef LL_LLSTRING_H #define LL_LLSTRING_H +#include <boost/call_traits.hpp> #include <boost/optional/optional.hpp> #include <string> #include <cstdio> +#include <cwchar> // std::wcslen() //#include <locale> #include <iomanip> #include <algorithm> @@ -527,14 +529,71 @@ struct ll_convert_impl<T, T> T operator()(const T& in) const { return in; } }; +// simple construction from char* +template<typename T> +struct ll_convert_impl<T, const typename T::value_type*> +{ + T operator()(const typename T::value_type* in) const { return { in }; } +}; + // specialize ll_convert_impl<TO, FROM> to return EXPR #define ll_convert_alias(TO, FROM, EXPR) \ template<> \ struct ll_convert_impl<TO, FROM> \ { \ - TO operator()(const FROM& in) const { return EXPR; } \ + /* param_type optimally passes both char* and string */ \ + TO operator()(typename boost::call_traits<FROM>::param_type in) const { return EXPR; } \ +} + +// If all we're doing is copying characters, pass this to ll_convert_alias as +// EXPR. Since it expands into the 'return EXPR' slot in the ll_convert_impl +// specialization above, it implies TO{ in.begin(), in.end() }. +#define LL_CONVERT_COPY_CHARS { in.begin(), in.end() } + +// Generic name for strlen() / wcslen() - the default implementation should +// (!) work with U16 and llwchar, but we don't intend to engage it. +template <typename CHARTYPE> +size_t ll_convert_length(const CHARTYPE* zstr) +{ + const CHARTYPE* zp; + // classic C string scan + for (zp = zstr; *zp; ++zp) + ; + return (zp - zstr); } +// specialize where we have a library function; may use intrinsic operations +template <> +inline size_t ll_convert_length<wchar_t>(const wchar_t* zstr) { return std::wcslen(zstr); } +template <> +inline size_t ll_convert_length<char> (const char* zstr) { return std::strlen(zstr); } + +// ll_convert_forms() is short for a bunch of boilerplate. It defines +// longname(const char*, len), longname(const char*), longname(const string&) +// and longname(const string&, len) so calls written pre-ll_convert() will +// work. Most of these overloads will be unified once we turn on C++17 and can +// use std::string_view. +// It also uses aliasmacro to ensure that both ll_convert<OUTSTR>(const char*) +// and ll_convert<OUTSTR>(const string&) will work. +#define ll_convert_forms(aliasmacro, OUTSTR, INSTR, longname) \ +LL_COMMON_API OUTSTR longname(const INSTR::value_type* in, size_t len); \ +inline auto longname(const INSTR& in, size_t len) \ +{ \ + return longname(in.c_str(), len); \ +} \ +inline auto longname(const INSTR::value_type* in) \ +{ \ + return longname(in, ll_convert_length(in)); \ +} \ +inline auto longname(const INSTR& in) \ +{ \ + return longname(in.c_str(), in.length()); \ +} \ +/* string param */ \ +aliasmacro(OUTSTR, INSTR, longname(in)); \ +/* char* param */ \ +aliasmacro(OUTSTR, const INSTR::value_type*, longname(in)) + // Make the incoming string a utf8 string. Replaces any unknown glyph // with the UNKNOWN_CHARACTER. Once any unknown glyph is found, the rest // of the data may not be recovered. @@ -571,63 +630,47 @@ LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw); // LL_WCHAR_T_NATIVE. typedef std::basic_string<U16> llutf16string; -#if ! defined(LL_WCHAR_T_NATIVE) -// wchar_t is identical to U16, and std::wstring is identical to llutf16string. -// Defining an ll_convert alias involving llutf16string would collide with the -// comparable preferred alias involving std::wstring. (In this scenario, if -// you pass llutf16string, it will engage the std::wstring specialization.) -#define ll_convert_u16_alias(TO, FROM, EXPR) // nothing -#else // defined(LL_WCHAR_T_NATIVE) -// wchar_t is a distinct native type, so llutf16string is also a distinct -// type, and there IS a point to converting separately to/from llutf16string. -// (But why? Windows APIs are still defined in terms of wchar_t, and -// in this scenario llutf16string won't work for them!) -#define ll_convert_u16_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) +// Considering wchar_t, llwchar and U16, there are three relevant cases: +#if LLWCHAR_IS_WCHAR_T // every which way but Windows +// llwchar is identical to wchar_t, LLWString is identical to std::wstring. +// U16 is distinct, llutf16string is distinct (though pretty useless). +// Given conversions to/from LLWString and to/from llutf16string, conversions +// involving std::wstring would collide. +#define ll_convert_wstr_alias(TO, FROM, EXPR) // nothing +// but we can define conversions involving llutf16string without collisions +#define ll_convert_u16_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) + +#elif defined(LL_WCHAR_T_NATIVE) // Windows, either clang or MS /Zc:wchar_t +// llwchar (32-bit), wchar_t (16-bit) and U16 are all different types. +// Conversions to/from LLWString, to/from std::wstring and to/from llutf16string +// can all be defined. +#define ll_convert_wstr_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) +#define ll_convert_u16_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) + +#else // ! LL_WCHAR_T_NATIVE: Windows with MS /Zc:wchar_t- +// wchar_t is identical to U16, std::wstring is identical to llutf16string. +// Given conversions to/from LLWString and to/from std::wstring, conversions +// involving llutf16string would collide. +#define ll_convert_u16_alias(TO, FROM, EXPR) // nothing +// but we can define conversions involving std::wstring without collisions +#define ll_convert_wstr_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) +#endif + +ll_convert_forms(ll_convert_u16_alias, LLWString, llutf16string, utf16str_to_wstring); +ll_convert_forms(ll_convert_u16_alias, llutf16string, LLWString, wstring_to_utf16str); +ll_convert_forms(ll_convert_u16_alias, llutf16string, std::string, utf8str_to_utf16str); +ll_convert_forms(ll_convert_alias, LLWString, std::string, utf8str_to_wstring); -#if LL_WINDOWS -// LL_WCHAR_T_NATIVE is defined on non-Windows systems because, in fact, -// wchar_t is native. Everywhere but Windows, we use it for llwchar (see -// stdtypes.h). That makes LLWString identical to std::wstring, so these -// aliases for std::wstring would collide with those for LLWString. Only -// define on Windows, where converting between std::wstring and llutf16string -// means copying chars. -ll_convert_alias(llutf16string, std::wstring, llutf16string(in.begin(), in.end())); -ll_convert_alias(std::wstring, llutf16string, std::wstring(in.begin(), in.end())); -#endif // LL_WINDOWS -#endif // defined(LL_WCHAR_T_NATIVE) - -LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); -LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); -ll_convert_u16_alias(LLWString, llutf16string, utf16str_to_wstring(in)); - -LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); -LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str); -ll_convert_u16_alias(llutf16string, LLWString, wstring_to_utf16str(in)); - -LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); -LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str ); -ll_convert_u16_alias(llutf16string, std::string, utf8str_to_utf16str(in)); - -LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); -LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str); // Same function, better name. JC inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } -// best name of all -ll_convert_alias(LLWString, std::string, utf8string_to_wstring(in)); -// LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars); -LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); -LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str); -ll_convert_alias(std::string, LLWString, wstring_to_utf8str(in)); -LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); -LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str); -ll_convert_u16_alias(std::string, llutf16string, utf16str_to_utf8str(in)); +ll_convert_forms(ll_convert_alias, std::string, LLWString, wstring_to_utf8str); +ll_convert_forms(ll_convert_u16_alias, std::string, llutf16string, utf16str_to_utf8str); -#if LL_WINDOWS +// an older alias for utf16str_to_utf8str(llutf16string) inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);} -#endif // Length of this UTF32 string in bytes when transformed to UTF8 LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); @@ -701,42 +744,48 @@ LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str); //@{ /** - * @brief Convert a wide string to std::string + * @brief Convert a wide string to/from std::string + * Convert a Windows wide string to/from our LLWString * * This replaces the unsafe W2A macro from ATL. */ -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page); -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); // default CP_UTF8 -inline std::string ll_convert_wide_to_string(const std::wstring& in, unsigned int code_page) -{ - return ll_convert_wide_to_string(in.c_str(), code_page); -} -inline std::string ll_convert_wide_to_string(const std::wstring& in) -{ - return ll_convert_wide_to_string(in.c_str()); -} -ll_convert_alias(std::string, std::wstring, ll_convert_wide_to_string(in)); - -/** - * Converts a string to wide string. - */ -LL_COMMON_API std::wstring ll_convert_string_to_wide(const std::string& in, - unsigned int code_page); -LL_COMMON_API std::wstring ll_convert_string_to_wide(const std::string& in); - // default CP_UTF8 -ll_convert_alias(std::wstring, std::string, ll_convert_string_to_wide(in)); - -/** - * Convert a Windows wide string to our LLWString - */ -LL_COMMON_API LLWString ll_convert_wide_to_wstring(const std::wstring& in); -ll_convert_alias(LLWString, std::wstring, ll_convert_wide_to_wstring(in)); - -/** - * Convert LLWString to Windows wide string - */ -LL_COMMON_API std::wstring ll_convert_wstring_to_wide(const LLWString& in); -ll_convert_alias(std::wstring, LLWString, ll_convert_wstring_to_wide(in)); +// Avoid requiring this header to #include the Windows header file declaring +// our actual default code_page by delegating this function to our .cpp file. +LL_COMMON_API unsigned int ll_wstring_default_code_page(); + +// This is like ll_convert_forms(), with the added complexity of a code page +// parameter that may or may not be passed. +#define ll_convert_cp_forms(aliasmacro, OUTSTR, INSTR, longname) \ +/* declare the only nontrivial implementation (in .cpp file) */ \ +LL_COMMON_API OUTSTR longname( \ + const INSTR::value_type* in, \ + size_t len, \ + unsigned int code_page=ll_wstring_default_code_page()); \ +/* if passed only a char pointer, scan for nul terminator */ \ +inline auto longname(const INSTR::value_type* in) \ +{ \ + return longname(in, ll_convert_length(in)); \ +} \ +/* if passed string and length, extract its char pointer */ \ +inline auto longname( \ + const INSTR& in, \ + size_t len, \ + unsigned int code_page=ll_wstring_default_code_page()) \ +{ \ + return longname(in.c_str(), len, code_page); \ +} \ +/* if passed only a string object, no scan, pass known length */ \ +inline auto longname(const INSTR& in) \ +{ \ + return longname(in.c_str(), in.length()); \ +} \ +aliasmacro(OUTSTR, INSTR, longname(in)); \ +aliasmacro(OUTSTR, const INSTR::value_type*, longname(in)) + +ll_convert_cp_forms(ll_convert_wstr_alias, std::string, std::wstring, ll_convert_wide_to_string); +ll_convert_cp_forms(ll_convert_wstr_alias, std::wstring, std::string, ll_convert_string_to_wide); + ll_convert_forms(ll_convert_wstr_alias, LLWString, std::wstring, ll_convert_wide_to_wstring); + ll_convert_forms(ll_convert_wstr_alias, std::wstring, LLWString, ll_convert_wstring_to_wide); /** * Converts incoming string into utf8 string @@ -1937,4 +1986,14 @@ void LLStringUtilBase<T>::truncate(string_type& string, size_type count) string.resize(count < cur_size ? count : cur_size); } +// The good thing about *declaration* macros, vs. usage macros, is that now +// we're done with them: we don't need them to bleed into the consuming source +// file. +#undef ll_convert_alias +#undef ll_convert_u16_alias +#undef ll_convert_wstr_alias +#undef LL_CONVERT_COPY_CHARS +#undef ll_convert_forms +#undef ll_convert_cp_forms + #endif // LL_STRING_H diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 2ca15a31c6..18f4684b49 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -828,6 +828,7 @@ LLSD LLMemoryInfo::getStatsMap() const LLMemoryInfo& LLMemoryInfo::refresh() { + LL_PROFILE_ZONE_SCOPED mStatsMap = loadStatsMap(); LL_DEBUGS("LLMemoryInfo") << "Populated mStatsMap:\n"; @@ -837,11 +838,9 @@ LLMemoryInfo& LLMemoryInfo::refresh() return *this; } -static LLTrace::BlockTimerStatHandle FTM_MEMINFO_LOAD_STATS("MemInfo Load Stats"); - LLSD LLMemoryInfo::loadStatsMap() { - LL_RECORD_BLOCK_TIME(FTM_MEMINFO_LOAD_STATS); + LL_PROFILE_ZONE_SCOPED; // This implementation is derived from stream() code (as of 2011-06-29). Stats stats; diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 6d531d842d..11f5a015f1 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -135,6 +135,8 @@ void LLThread::threadRun() set_thread_name(-1, mName.c_str()); #endif + LL_PROFILER_SET_THREAD_NAME( mName.c_str() ); + // this is the first point at which we're actually running in the new thread mID = currentID(); @@ -331,6 +333,7 @@ bool LLThread::runCondition(void) // Stop thread execution if requested until unpaused. void LLThread::checkPause() { + LL_PROFILE_ZONE_SCOPED mDataLock->lock(); // This is in a while loop because the pthread API allows for spurious wakeups. @@ -362,17 +365,20 @@ void LLThread::setQuitting() // static LLThread::id_t LLThread::currentID() { + LL_PROFILE_ZONE_SCOPED return std::this_thread::get_id(); } // static void LLThread::yield() { + LL_PROFILE_ZONE_SCOPED std::this_thread::yield(); } void LLThread::wake() { + LL_PROFILE_ZONE_SCOPED mDataLock->lock(); if(!shouldSleep()) { @@ -383,6 +389,7 @@ void LLThread::wake() void LLThread::wakeLocked() { + LL_PROFILE_ZONE_SCOPED if(!shouldSleep()) { mRunCondition->signal(); @@ -391,11 +398,13 @@ void LLThread::wakeLocked() void LLThread::lockData() { + LL_PROFILE_ZONE_SCOPED mDataLock->lock(); } void LLThread::unlockData() { + LL_PROFILE_ZONE_SCOPED mDataLock->unlock(); } diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 26e0d71d31..2806506550 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -1,6 +1,6 @@ /** * @file llthreadsafequeue.h - * @brief Base classes for thread, mutex and condition handling. + * @brief Queue protected with mutexes for cross-thread use * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code @@ -27,16 +27,19 @@ #ifndef LL_LLTHREADSAFEQUEUE_H #define LL_LLTHREADSAFEQUEUE_H -#include "llexception.h" -#include <deque> -#include <string> -#include <chrono> -#include "mutex.h" #include "llcoros.h" #include LLCOROS_MUTEX_HEADER #include <boost/fiber/timed_mutex.hpp> #include LLCOROS_CONDVAR_HEADER +#include "llexception.h" +#include "mutex.h" +#include <chrono> +#include <queue> +#include <string> +/***************************************************************************** +* LLThreadSafeQueue +*****************************************************************************/ // // A general queue exception. // @@ -66,70 +69,116 @@ public: } }; -// -// Implements a thread safe FIFO. -// -template<typename ElementT> +/** + * Implements a thread safe FIFO. + */ +// Let the default std::queue default to underlying std::deque. Override if +// desired. +template<typename ElementT, typename QueueT=std::queue<ElementT>> class LLThreadSafeQueue { public: typedef ElementT value_type; - - // If the pool is set to NULL one will be allocated and managed by this - // queue. + + // Limiting the number of pending items prevents unbounded growth of the + // underlying queue. LLThreadSafeQueue(U32 capacity = 1024); - - // Add an element to the front of queue (will block if the queue has - // reached capacity). + virtual ~LLThreadSafeQueue() {} + + // Add an element to the queue (will block if the queue has reached + // capacity). // // This call will raise an interrupt error if the queue is closed while // the caller is blocked. - void pushFront(ElementT const & element); - - // Try to add an element to the front of queue without blocking. Returns + template <typename T> + void push(T&& element); + // legacy name + void pushFront(ElementT const & element) { return push(element); } + + // Add an element to the queue (will block if the queue has reached + // capacity). Return false if the queue is closed before push is possible. + template <typename T> + bool pushIfOpen(T&& element); + + // Try to add an element to the queue without blocking. Returns // true only if the element was actually added. - bool tryPushFront(ElementT const & element); + template <typename T> + bool tryPush(T&& element); + // legacy name + bool tryPushFront(ElementT const & element) { return tryPush(element); } - // Try to add an element to the front of queue, blocking if full but with - // timeout. Returns true if the element was added. + // Try to add an element to the queue, blocking if full but with timeout + // after specified duration. Returns true if the element was added. // There are potentially two different timeouts involved: how long to try // to lock the mutex, versus how long to wait for the queue to stop being // full. Careful settings for each timeout might be orders of magnitude // apart. However, this method conflates them. + template <typename Rep, typename Period, typename T> + bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout, + T&& element); + // legacy name template <typename Rep, typename Period> bool tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout, - ElementT const & element); + ElementT const & element) { return tryPushFor(timeout, element); } + + // Try to add an element to the queue, blocking if full but with + // timeout at specified time_point. Returns true if the element was added. + template <typename Clock, typename Duration, typename T> + bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until, + T&& element); + // no legacy name because this is a newer method - // Pop the element at the end of the queue (will block if the queue is + // Pop the element at the head of the queue (will block if the queue is // empty). // // This call will raise an interrupt error if the queue is closed while // the caller is blocked. - ElementT popBack(void); - - // Pop an element from the end of the queue if there is one available. + ElementT pop(void); + // legacy name + ElementT popBack(void) { return pop(); } + + // Pop an element from the head of the queue if there is one available. // Returns true only if an element was popped. - bool tryPopBack(ElementT & element); - + bool tryPop(ElementT & element); + // legacy name + bool tryPopBack(ElementT & element) { return tryPop(element); } + + // Pop the element at the head of the queue, blocking if empty, with + // timeout after specified duration. Returns true if an element was popped. + template <typename Rep, typename Period> + bool tryPopFor(const std::chrono::duration<Rep, Period>& timeout, ElementT& element); + // no legacy name because this is a newer method + + // Pop the element at the head of the queue, blocking if empty, with + // timeout at specified time_point. Returns true if an element was popped. + template <typename Clock, typename Duration> + bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until, + ElementT& element); + // no legacy name because this is a newer method + // Returns the size of the queue. size_t size(); + //Returns the capacity of the queue. + U32 capacity() { return mCapacity; } + // closes the queue: - // - every subsequent pushFront() call will throw LLThreadSafeQueueInterrupt - // - every subsequent tryPushFront() call will return false - // - popBack() calls will return normally until the queue is drained, then - // every subsequent popBack() will throw LLThreadSafeQueueInterrupt - // - tryPopBack() calls will return normally until the queue is drained, - // then every subsequent tryPopBack() call will return false + // - every subsequent push() call will throw LLThreadSafeQueueInterrupt + // - every subsequent tryPush() call will return false + // - pop() calls will return normally until the queue is drained, then + // every subsequent pop() will throw LLThreadSafeQueueInterrupt + // - tryPop() calls will return normally until the queue is drained, + // then every subsequent tryPop() call will return false void close(); - // detect closed state + // producer end: are we prevented from pushing any additional items? bool isClosed(); - // inverse of isClosed() - explicit operator bool(); + // consumer end: are we done, is the queue entirely drained? + bool done(); -private: - std::deque< ElementT > mStorage; +protected: + typedef QueueT queue_type; + QueueT mStorage; U32 mCapacity; bool mClosed; @@ -137,37 +186,154 @@ private: typedef std::unique_lock<decltype(mLock)> lock_t; boost::fibers::condition_variable_any mCapacityCond; boost::fibers::condition_variable_any mEmptyCond; -}; -// LLThreadSafeQueue -//----------------------------------------------------------------------------- + enum pop_result { EMPTY, DONE, WAITING, POPPED }; + // implementation logic, suitable for passing to tryLockUntil() + template <typename Clock, typename Duration> + pop_result tryPopUntil_(lock_t& lock, + const std::chrono::time_point<Clock, Duration>& until, + ElementT& element); + // if we're able to lock immediately, do so and run the passed callable, + // which must accept lock_t& and return bool + template <typename CALLABLE> + bool tryLock(CALLABLE&& callable); + // if we're able to lock before the passed time_point, do so and run the + // passed callable, which must accept lock_t& and return bool + template <typename Clock, typename Duration, typename CALLABLE> + bool tryLockUntil(const std::chrono::time_point<Clock, Duration>& until, + CALLABLE&& callable); + // while lock is locked, really push the passed element, if we can + template <typename T> + bool push_(lock_t& lock, T&& element); + // while lock is locked, really pop the head element, if we can + pop_result pop_(lock_t& lock, ElementT& element); + // Is the current head element ready to pop? We say yes; subclass can + // override as needed. + virtual bool canPop(const ElementT& head) const { return true; } +}; -template<typename ElementT> -LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(U32 capacity) : +/***************************************************************************** +* PriorityQueueAdapter +*****************************************************************************/ +namespace LL +{ + /** + * std::priority_queue's API is almost like std::queue, intentionally of + * course, but you must access the element about to pop() as top() rather + * than as front(). Make an adapter for use with LLThreadSafeQueue. + */ + template <typename T, typename Container=std::vector<T>, + typename Compare=std::less<typename Container::value_type>> + class PriorityQueueAdapter + { + public: + // publish all the same types + typedef std::priority_queue<T, Container, Compare> queue_type; + typedef typename queue_type::container_type container_type; + typedef typename queue_type::value_compare value_compare; + typedef typename queue_type::value_type value_type; + typedef typename queue_type::size_type size_type; + typedef typename queue_type::reference reference; + typedef typename queue_type::const_reference const_reference; + + // Although std::queue defines both const and non-const front() + // methods, std::priority_queue defines only const top(). + const_reference front() const { return mQ.top(); } + // std::priority_queue has no equivalent to back(), so it's good that + // LLThreadSafeQueue doesn't use it. + + // All the rest of these merely forward to the corresponding + // queue_type methods. + bool empty() const { return mQ.empty(); } + size_type size() const { return mQ.size(); } + void push(const value_type& value) { mQ.push(value); } + void push(value_type&& value) { mQ.push(std::move(value)); } + template <typename... Args> + void emplace(Args&&... args) { mQ.emplace(std::forward<Args>(args)...); } + void pop() { mQ.pop(); } + + private: + queue_type mQ; + }; +} // namespace LL + + +/***************************************************************************** +* LLThreadSafeQueue implementation +*****************************************************************************/ +template<typename ElementT, typename QueueT> +LLThreadSafeQueue<ElementT, QueueT>::LLThreadSafeQueue(U32 capacity) : mCapacity(capacity), mClosed(false) { } -template<typename ElementT> -void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element) +// if we're able to lock immediately, do so and run the passed callable, which +// must accept lock_t& and return bool +template <typename ElementT, typename QueueT> +template <typename CALLABLE> +bool LLThreadSafeQueue<ElementT, QueueT>::tryLock(CALLABLE&& callable) +{ + LL_PROFILE_ZONE_SCOPED; + lock_t lock1(mLock, std::defer_lock); + if (!lock1.try_lock()) + return false; + + return std::forward<CALLABLE>(callable)(lock1); +} + + +// if we're able to lock before the passed time_point, do so and run the +// passed callable, which must accept lock_t& and return bool +template <typename ElementT, typename QueueT> +template <typename Clock, typename Duration, typename CALLABLE> +bool LLThreadSafeQueue<ElementT, QueueT>::tryLockUntil( + const std::chrono::time_point<Clock, Duration>& until, + CALLABLE&& callable) { + LL_PROFILE_ZONE_SCOPED; + lock_t lock1(mLock, std::defer_lock); + if (!lock1.try_lock_until(until)) + return false; + + return std::forward<CALLABLE>(callable)(lock1); +} + + +// while lock is locked, really push the passed element, if we can +template <typename ElementT, typename QueueT> +template <typename T> +bool LLThreadSafeQueue<ElementT, QueueT>::push_(lock_t& lock, T&& element) +{ + LL_PROFILE_ZONE_SCOPED; + if (mStorage.size() >= mCapacity) + return false; + + mStorage.push(std::forward<T>(element)); + lock.unlock(); + // now that we've pushed, if somebody's been waiting to pop, signal them + mEmptyCond.notify_one(); + return true; +} + + +template <typename ElementT, typename QueueT> +template <typename T> +bool LLThreadSafeQueue<ElementT, QueueT>::pushIfOpen(T&& element) +{ + LL_PROFILE_ZONE_SCOPED; lock_t lock1(mLock); while (true) { + // On the producer side, it doesn't matter whether the queue has been + // drained or not: the moment either end calls close(), further push() + // operations will fail. if (mClosed) - { - LLTHROW(LLThreadSafeQueueInterrupt()); - } + return false; - if (mStorage.size() < mCapacity) - { - mStorage.push_front(element); - lock1.unlock(); - mEmptyCond.notify_one(); - return; - } + if (push_(lock1, std::forward<T>(element))) + return true; // Storage Full. Wait for signal. mCapacityCond.wait(lock1); @@ -175,142 +341,250 @@ void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element) } -template <typename ElementT> -template <typename Rep, typename Period> -bool LLThreadSafeQueue<ElementT>::tryPushFrontFor(const std::chrono::duration<Rep, Period>& timeout, - ElementT const & element) +template <typename ElementT, typename QueueT> +template<typename T> +void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element) { - // Convert duration to time_point: passing the same timeout duration to - // each of multiple calls is wrong. - auto endpoint = std::chrono::steady_clock::now() + timeout; + LL_PROFILE_ZONE_SCOPED; + if (! pushIfOpen(std::forward<T>(element))) + { + LLTHROW(LLThreadSafeQueueInterrupt()); + } +} - lock_t lock1(mLock, std::defer_lock); - if (!lock1.try_lock_until(endpoint)) - return false; - while (true) - { - if (mClosed) +template<typename ElementT, typename QueueT> +template<typename T> +bool LLThreadSafeQueue<ElementT, QueueT>::tryPush(T&& element) +{ + LL_PROFILE_ZONE_SCOPED; + return tryLock( + [this, element=std::move(element)](lock_t& lock) { - return false; - } + if (mClosed) + return false; + return push_(lock, std::move(element)); + }); +} - if (mStorage.size() < mCapacity) - { - mStorage.push_front(element); - lock1.unlock(); - mEmptyCond.notify_one(); - return true; - } - // Storage Full. Wait for signal. - if (LLCoros::cv_status::timeout == mCapacityCond.wait_until(lock1, endpoint)) - { - // timed out -- formally we might recheck both conditions above - return false; - } - // If we didn't time out, we were notified for some reason. Loop back - // to check. - } +template <typename ElementT, typename QueueT> +template <typename Rep, typename Period, typename T> +bool LLThreadSafeQueue<ElementT, QueueT>::tryPushFor( + const std::chrono::duration<Rep, Period>& timeout, + T&& element) +{ + LL_PROFILE_ZONE_SCOPED; + // Convert duration to time_point: passing the same timeout duration to + // each of multiple calls is wrong. + return tryPushUntil(std::chrono::steady_clock::now() + timeout, + std::forward<T>(element)); } -template<typename ElementT> -bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element) +template <typename ElementT, typename QueueT> +template <typename Clock, typename Duration, typename T> +bool LLThreadSafeQueue<ElementT, QueueT>::tryPushUntil( + const std::chrono::time_point<Clock, Duration>& until, + T&& element) { - lock_t lock1(mLock, std::defer_lock); - if (!lock1.try_lock()) - return false; + LL_PROFILE_ZONE_SCOPED; + return tryLockUntil( + until, + [this, until, element=std::move(element)](lock_t& lock) + { + while (true) + { + if (mClosed) + { + return false; + } + + if (push_(lock, std::move(element))) + return true; + + // Storage Full. Wait for signal. + if (LLCoros::cv_status::timeout == mCapacityCond.wait_until(lock, until)) + { + // timed out -- formally we might recheck both conditions above + return false; + } + // If we didn't time out, we were notified for some reason. Loop back + // to check. + } + }); +} - if (mClosed) - return false; - if (mStorage.size() >= mCapacity) - return false; +// while lock is locked, really pop the head element, if we can +template <typename ElementT, typename QueueT> +typename LLThreadSafeQueue<ElementT, QueueT>::pop_result +LLThreadSafeQueue<ElementT, QueueT>::pop_(lock_t& lock, ElementT& element) +{ + LL_PROFILE_ZONE_SCOPED; + // If mStorage is empty, there's no head element. + if (mStorage.empty()) + return mClosed? DONE : EMPTY; - mStorage.push_front(element); - lock1.unlock(); - mEmptyCond.notify_one(); - return true; + // If there's a head element, pass it to canPop() to see if it's ready to pop. + if (! canPop(mStorage.front())) + return WAITING; + + // std::queue::front() is the element about to pop() + element = mStorage.front(); + mStorage.pop(); + lock.unlock(); + // now that we've popped, if somebody's been waiting to push, signal them + mCapacityCond.notify_one(); + return POPPED; } -template<typename ElementT> -ElementT LLThreadSafeQueue<ElementT>::popBack(void) +template<typename ElementT, typename QueueT> +ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void) { + LL_PROFILE_ZONE_SCOPED; lock_t lock1(mLock); + ElementT value; while (true) { - if (!mStorage.empty()) - { - ElementT value = mStorage.back(); - mStorage.pop_back(); - lock1.unlock(); - mCapacityCond.notify_one(); - return value; - } - - if (mClosed) + // On the consumer side, we always try to pop before checking mClosed + // so we can finish draining the queue. + pop_result popped = pop_(lock1, value); + if (popped == POPPED) + return std::move(value); + + // Once the queue is DONE, there will never be any more coming. + if (popped == DONE) { LLTHROW(LLThreadSafeQueueInterrupt()); } - // Storage empty. Wait for signal. + // If we didn't pop because WAITING, i.e. canPop() returned false, + // then even if the producer end has been closed, there's still at + // least one item to drain: wait for it. Or we might be EMPTY, with + // the queue still open. Either way, wait for signal. mEmptyCond.wait(lock1); } } -template<typename ElementT> -bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element) +template<typename ElementT, typename QueueT> +bool LLThreadSafeQueue<ElementT, QueueT>::tryPop(ElementT & element) { - lock_t lock1(mLock, std::defer_lock); - if (!lock1.try_lock()) - return false; + LL_PROFILE_ZONE_SCOPED; + return tryLock( + [this, &element](lock_t& lock) + { + // conflate EMPTY, DONE, WAITING: tryPop() behavior when the queue + // is closed is implemented by simple inability to push any new + // elements + return pop_(lock, element) == POPPED; + }); +} - // no need to check mClosed: tryPopBack() behavior when the queue is - // closed is implemented by simple inability to push any new elements - if (mStorage.empty()) - return false; - element = mStorage.back(); - mStorage.pop_back(); - lock1.unlock(); - mCapacityCond.notify_one(); - return true; +template <typename ElementT, typename QueueT> +template <typename Rep, typename Period> +bool LLThreadSafeQueue<ElementT, QueueT>::tryPopFor( + const std::chrono::duration<Rep, Period>& timeout, + ElementT& element) +{ + LL_PROFILE_ZONE_SCOPED; + // Convert duration to time_point: passing the same timeout duration to + // each of multiple calls is wrong. + return tryPopUntil(std::chrono::steady_clock::now() + timeout, element); } -template<typename ElementT> -size_t LLThreadSafeQueue<ElementT>::size(void) +template <typename ElementT, typename QueueT> +template <typename Clock, typename Duration> +bool LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil( + const std::chrono::time_point<Clock, Duration>& until, + ElementT& element) { + LL_PROFILE_ZONE_SCOPED; + return tryLockUntil( + until, + [this, until, &element](lock_t& lock) + { + // conflate EMPTY, DONE, WAITING + return tryPopUntil_(lock, until, element) == POPPED; + }); +} + + +// body of tryPopUntil(), called once we have the lock +template <typename ElementT, typename QueueT> +template <typename Clock, typename Duration> +typename LLThreadSafeQueue<ElementT, QueueT>::pop_result +LLThreadSafeQueue<ElementT, QueueT>::tryPopUntil_( + lock_t& lock, + const std::chrono::time_point<Clock, Duration>& until, + ElementT& element) +{ + LL_PROFILE_ZONE_SCOPED; + while (true) + { + pop_result popped = pop_(lock, element); + if (popped == POPPED || popped == DONE) + { + // If we succeeded, great! If we've drained the last item, so be + // it. Either way, break the loop and tell caller. + return popped; + } + + // EMPTY or WAITING: wait for signal. + if (LLCoros::cv_status::timeout == mEmptyCond.wait_until(lock, until)) + { + // timed out -- formally we might recheck + // as it is, break loop + return popped; + } + // If we didn't time out, we were notified for some reason. Loop back + // to check. + } +} + + +template<typename ElementT, typename QueueT> +size_t LLThreadSafeQueue<ElementT, QueueT>::size(void) +{ + LL_PROFILE_ZONE_SCOPED; lock_t lock(mLock); return mStorage.size(); } -template<typename ElementT> -void LLThreadSafeQueue<ElementT>::close() + +template<typename ElementT, typename QueueT> +void LLThreadSafeQueue<ElementT, QueueT>::close() { + LL_PROFILE_ZONE_SCOPED; lock_t lock(mLock); mClosed = true; lock.unlock(); - // wake up any blocked popBack() calls + // wake up any blocked pop() calls mEmptyCond.notify_all(); - // wake up any blocked pushFront() calls + // wake up any blocked push() calls mCapacityCond.notify_all(); } -template<typename ElementT> -bool LLThreadSafeQueue<ElementT>::isClosed() + +template<typename ElementT, typename QueueT> +bool LLThreadSafeQueue<ElementT, QueueT>::isClosed() { + LL_PROFILE_ZONE_SCOPED; lock_t lock(mLock); - return mClosed && mStorage.size() == 0; + return mClosed; } -template<typename ElementT> -LLThreadSafeQueue<ElementT>::operator bool() + +template<typename ElementT, typename QueueT> +bool LLThreadSafeQueue<ElementT, QueueT>::done() { - return ! isClosed(); + LL_PROFILE_ZONE_SCOPED; + lock_t lock(mLock); + return mClosed && mStorage.empty(); } #endif diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index 54079a4689..f59b207ded 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -61,6 +61,7 @@ TimeBlockTreeNode::TimeBlockTreeNode() void TimeBlockTreeNode::setParent( BlockTimerStatHandle* parent ) { + LL_PROFILE_ZONE_SCOPED; llassert_always(parent != mBlock); llassert_always(parent != NULL); diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 0d0cd6f581..4051c558a4 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -227,6 +227,7 @@ public: void setName(const char* name) { + LL_PROFILE_ZONE_SCOPED; mName = name; setKey(name); } @@ -234,12 +235,14 @@ public: /*virtual*/ const char* getUnitLabel() const { return "KB"; } StatType<MemAccumulator::AllocationFacet>& allocations() - { + { + LL_PROFILE_ZONE_SCOPED; return static_cast<StatType<MemAccumulator::AllocationFacet>&>(*(StatType<MemAccumulator>*)this); } StatType<MemAccumulator::DeallocationFacet>& deallocations() - { + { + LL_PROFILE_ZONE_SCOPED; return static_cast<StatType<MemAccumulator::DeallocationFacet>&>(*(StatType<MemAccumulator>*)this); } }; @@ -261,6 +264,7 @@ struct MeasureMem<T, typename T::mem_trackable_tag_t, IS_BYTES> { static size_t measureFootprint(const T& value) { + LL_PROFILE_ZONE_SCOPED; return sizeof(T) + value.getMemFootprint(); } }; @@ -270,6 +274,7 @@ struct MeasureMem<T, IS_MEM_TRACKABLE, typename T::is_unit_t> { static size_t measureFootprint(const T& value) { + LL_PROFILE_ZONE_SCOPED; return U32Bytes(value).value(); } }; @@ -279,6 +284,7 @@ struct MeasureMem<T*, IS_MEM_TRACKABLE, IS_BYTES> { static size_t measureFootprint(const T* value) { + LL_PROFILE_ZONE_SCOPED; if (!value) { return 0; @@ -323,6 +329,7 @@ struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES> { static size_t measureFootprint(const std::basic_string<T>& value) { + LL_PROFILE_ZONE_SCOPED; return value.capacity() * sizeof(T); } }; @@ -331,6 +338,7 @@ struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES> template<typename T> inline void claim_alloc(MemStatHandle& measurement, const T& value) { + LL_PROFILE_ZONE_SCOPED; #if LL_TRACE_ENABLED S32 size = MeasureMem<T>::measureFootprint(value); if(size == 0) return; @@ -343,6 +351,7 @@ inline void claim_alloc(MemStatHandle& measurement, const T& value) template<typename T> inline void disclaim_alloc(MemStatHandle& measurement, const T& value) { + LL_PROFILE_ZONE_SCOPED; #if LL_TRACE_ENABLED S32 size = MeasureMem<T>::measureFootprint(value); if(size == 0) return; @@ -352,141 +361,6 @@ inline void disclaim_alloc(MemStatHandle& measurement, const T& value) #endif } -template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN> -class MemTrackableNonVirtual -{ -public: - typedef void mem_trackable_tag_t; - - MemTrackableNonVirtual(const char* name) -#if LL_TRACE_ENABLED - : mMemFootprint(0) -#endif - { -#if LL_TRACE_ENABLED - static bool name_initialized = false; - if (!name_initialized) - { - name_initialized = true; - sMemStat.setName(name); - } -#endif - } - -#if LL_TRACE_ENABLED - ~MemTrackableNonVirtual() - { - disclaimMem(mMemFootprint); - } - - static MemStatHandle& getMemStatHandle() - { - return sMemStat; - } - - S32 getMemFootprint() const { return mMemFootprint; } -#endif - - void* operator new(size_t size) - { -#if LL_TRACE_ENABLED - claim_alloc(sMemStat, size); -#endif - return ll_aligned_malloc<ALIGNMENT>(size); - } - - template<int CUSTOM_ALIGNMENT> - static void* aligned_new(size_t size) - { -#if LL_TRACE_ENABLED - claim_alloc(sMemStat, size); -#endif - return ll_aligned_malloc<CUSTOM_ALIGNMENT>(size); - } - - void operator delete(void* ptr, size_t size) - { -#if LL_TRACE_ENABLED - disclaim_alloc(sMemStat, size); -#endif - ll_aligned_free<ALIGNMENT>(ptr); - } - - template<int CUSTOM_ALIGNMENT> - static void aligned_delete(void* ptr, size_t size) - { -#if LL_TRACE_ENABLED - disclaim_alloc(sMemStat, size); -#endif - ll_aligned_free<CUSTOM_ALIGNMENT>(ptr); - } - - void* operator new [](size_t size) - { -#if LL_TRACE_ENABLED - claim_alloc(sMemStat, size); -#endif - return ll_aligned_malloc<ALIGNMENT>(size); - } - - void operator delete[](void* ptr, size_t size) - { -#if LL_TRACE_ENABLED - disclaim_alloc(sMemStat, size); -#endif - ll_aligned_free<ALIGNMENT>(ptr); - } - - // claim memory associated with other objects/data as our own, adding to our calculated footprint - template<typename CLAIM_T> - void claimMem(const CLAIM_T& value) const - { -#if LL_TRACE_ENABLED - S32 size = MeasureMem<CLAIM_T>::measureFootprint(value); - claim_alloc(sMemStat, size); - mMemFootprint += size; -#endif - } - - // remove memory we had claimed from our calculated footprint - template<typename CLAIM_T> - void disclaimMem(const CLAIM_T& value) const - { -#if LL_TRACE_ENABLED - S32 size = MeasureMem<CLAIM_T>::measureFootprint(value); - disclaim_alloc(sMemStat, size); - mMemFootprint -= size; -#endif - } - -private: -#if LL_TRACE_ENABLED - // use signed values so that we can temporarily go negative - // and reconcile in destructor - // NB: this assumes that no single class is responsible for > 2GB of allocations - mutable S32 mMemFootprint; - - static MemStatHandle sMemStat; -#endif - -}; - -#if LL_TRACE_ENABLED -template<typename DERIVED, size_t ALIGNMENT> -MemStatHandle MemTrackableNonVirtual<DERIVED, ALIGNMENT>::sMemStat(typeid(MemTrackableNonVirtual<DERIVED, ALIGNMENT>).name()); -#endif - -template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN> -class MemTrackable : public MemTrackableNonVirtual<DERIVED, ALIGNMENT> -{ -public: - MemTrackable(const char* name) - : MemTrackableNonVirtual<DERIVED, ALIGNMENT>(name) - {} - - virtual ~MemTrackable() - {} -}; } #endif // LL_LLTRACE_H diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp index b1c23c6fb7..8e9aaee0e6 100644 --- a/indra/llcommon/lltraceaccumulators.cpp +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -41,6 +41,7 @@ extern MemStatHandle gTraceMemStat; AccumulatorBufferGroup::AccumulatorBufferGroup() { + LL_PROFILE_ZONE_SCOPED; claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator)); claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator)); claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); @@ -55,6 +56,7 @@ AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& oth mStackTimers(other.mStackTimers), mMemStats(other.mMemStats) { + LL_PROFILE_ZONE_SCOPED; claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator)); claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator)); claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); @@ -64,6 +66,7 @@ AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& oth AccumulatorBufferGroup::~AccumulatorBufferGroup() { + LL_PROFILE_ZONE_SCOPED; disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator)); disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator)); disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); @@ -73,6 +76,7 @@ AccumulatorBufferGroup::~AccumulatorBufferGroup() void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other) { + LL_PROFILE_ZONE_SCOPED; other.mCounts.reset(&mCounts); other.mSamples.reset(&mSamples); other.mEvents.reset(&mEvents); @@ -82,6 +86,7 @@ void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other) void AccumulatorBufferGroup::makeCurrent() { + LL_PROFILE_ZONE_SCOPED; mCounts.makeCurrent(); mSamples.makeCurrent(); mEvents.makeCurrent(); @@ -104,6 +109,7 @@ void AccumulatorBufferGroup::makeCurrent() //static void AccumulatorBufferGroup::clearCurrent() { + LL_PROFILE_ZONE_SCOPED; AccumulatorBuffer<CountAccumulator>::clearCurrent(); AccumulatorBuffer<SampleAccumulator>::clearCurrent(); AccumulatorBuffer<EventAccumulator>::clearCurrent(); @@ -118,6 +124,7 @@ bool AccumulatorBufferGroup::isCurrent() const void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) { + LL_PROFILE_ZONE_SCOPED; mCounts.addSamples(other.mCounts, SEQUENTIAL); mSamples.addSamples(other.mSamples, SEQUENTIAL); mEvents.addSamples(other.mEvents, SEQUENTIAL); @@ -127,6 +134,7 @@ void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other) { + LL_PROFILE_ZONE_SCOPED; mCounts.addSamples(other.mCounts, NON_SEQUENTIAL); mSamples.addSamples(other.mSamples, NON_SEQUENTIAL); mEvents.addSamples(other.mEvents, NON_SEQUENTIAL); @@ -137,6 +145,7 @@ void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other) void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other) { + LL_PROFILE_ZONE_SCOPED; mCounts.reset(other ? &other->mCounts : NULL); mSamples.reset(other ? &other->mSamples : NULL); mEvents.reset(other ? &other->mEvents : NULL); @@ -146,6 +155,7 @@ void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other) void AccumulatorBufferGroup::sync() { + LL_PROFILE_ZONE_SCOPED; if (isCurrent()) { F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); @@ -190,7 +200,7 @@ F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const Samp void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type ) { - if (append_type == NON_SEQUENTIAL) + if (append_type == NON_SEQUENTIAL) { return; } @@ -289,7 +299,7 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT void EventAccumulator::reset( const EventAccumulator* other ) { - mNumSamples = 0; + mNumSamples = 0; mSum = 0; mMin = F32(NaN); mMax = F32(NaN); diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index 8eb5338a2a..b183fcd14a 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -66,6 +66,7 @@ namespace LLTrace : mStorageSize(0), mStorage(NULL) { + LL_PROFILE_ZONE_SCOPED; const AccumulatorBuffer& other = *getDefaultBuffer(); resize(sNextStorageSlot); for (S32 i = 0; i < sNextStorageSlot; i++) @@ -76,6 +77,7 @@ namespace LLTrace ~AccumulatorBuffer() { + LL_PROFILE_ZONE_SCOPED; if (isCurrent()) { LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); @@ -98,6 +100,7 @@ namespace LLTrace : mStorageSize(0), mStorage(NULL) { + LL_PROFILE_ZONE_SCOPED; resize(sNextStorageSlot); for (S32 i = 0; i < sNextStorageSlot; i++) { @@ -107,6 +110,7 @@ namespace LLTrace void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type) { + LL_PROFILE_ZONE_SCOPED; llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -116,6 +120,7 @@ namespace LLTrace void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other) { + LL_PROFILE_ZONE_SCOPED; llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -125,6 +130,7 @@ namespace LLTrace void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL) { + LL_PROFILE_ZONE_SCOPED; llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -134,6 +140,7 @@ namespace LLTrace void sync(F64SecondsImplicit time_stamp) { + LL_PROFILE_ZONE_SCOPED; llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -153,12 +160,13 @@ namespace LLTrace static void clearCurrent() { - LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); + LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); } // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned size_t reserveSlot() { + LL_PROFILE_ZONE_SCOPED; size_t next_slot = sNextStorageSlot++; if (next_slot >= mStorageSize) { @@ -172,6 +180,7 @@ namespace LLTrace void resize(size_t new_size) { + LL_PROFILE_ZONE_SCOPED; if (new_size <= mStorageSize) return; ACCUMULATOR* old_storage = mStorage; @@ -212,6 +221,7 @@ namespace LLTrace static self_t* getDefaultBuffer() { + LL_PROFILE_ZONE_SCOPED; static bool sInitialized = false; if (!sInitialized) { @@ -326,6 +336,7 @@ namespace LLTrace void sample(F64 value) { + LL_PROFILE_ZONE_SCOPED; F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); // store effect of last value @@ -444,9 +455,9 @@ namespace LLTrace S32 mNumSamples; }; - class TimeBlockAccumulator + class alignas(32) TimeBlockAccumulator { - public: + public: typedef F64Seconds value_t; static F64Seconds getDefaultValue() { return F64Seconds(0); } @@ -539,6 +550,7 @@ namespace LLTrace void addSamples(const MemAccumulator& other, EBufferAppendType append_type) { + LL_PROFILE_ZONE_SCOPED; mAllocations.addSamples(other.mAllocations, append_type); mDeallocations.addSamples(other.mDeallocations, append_type); @@ -557,6 +569,7 @@ namespace LLTrace void reset(const MemAccumulator* other) { + LL_PROFILE_ZONE_SCOPED; mSize.reset(other ? &other->mSize : NULL); mAllocations.reset(other ? &other->mAllocations : NULL); mDeallocations.reset(other ? &other->mDeallocations : NULL); diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 3094b627a2..5ce1b337fe 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -50,6 +50,7 @@ Recording::Recording(EPlayState state) : mElapsedSeconds(0), mActiveBuffers(NULL) { + LL_PROFILE_ZONE_SCOPED; claim_alloc(gTraceMemStat, this); mBuffers = new AccumulatorBufferGroup(); claim_alloc(gTraceMemStat, mBuffers); @@ -59,12 +60,14 @@ Recording::Recording(EPlayState state) Recording::Recording( const Recording& other ) : mActiveBuffers(NULL) { + LL_PROFILE_ZONE_SCOPED; claim_alloc(gTraceMemStat, this); *this = other; } Recording& Recording::operator = (const Recording& other) { + LL_PROFILE_ZONE_SCOPED; // this will allow us to seamlessly start without affecting any data we've acquired from other setPlayState(PAUSED); @@ -85,6 +88,7 @@ Recording& Recording::operator = (const Recording& other) Recording::~Recording() { + LL_PROFILE_ZONE_SCOPED; disclaim_alloc(gTraceMemStat, this); disclaim_alloc(gTraceMemStat, mBuffers); @@ -103,6 +107,7 @@ void Recording::update() #if LL_TRACE_ENABLED if (isStarted()) { + LL_PROFILE_ZONE_SCOPED; mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); // must have @@ -123,6 +128,7 @@ void Recording::update() void Recording::handleReset() { + LL_PROFILE_ZONE_SCOPED; #if LL_TRACE_ENABLED mBuffers.write()->reset(); @@ -133,6 +139,7 @@ void Recording::handleReset() void Recording::handleStart() { + LL_PROFILE_ZONE_SCOPED; #if LL_TRACE_ENABLED mSamplingTimer.reset(); mBuffers.setStayUnique(true); @@ -144,6 +151,7 @@ void Recording::handleStart() void Recording::handleStop() { + LL_PROFILE_ZONE_SCOPED; #if LL_TRACE_ENABLED mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); // must have thread recorder running on this thread @@ -273,7 +281,7 @@ F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat) F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return F64Bytes(llmax(accumulator.mSize.getMax(), active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMax() : F32_MIN)); @@ -281,7 +289,7 @@ F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat) F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) @@ -297,7 +305,7 @@ F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& sta F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return F64Bytes(active_accumulator ? active_accumulator->mSize.getLastValue() : accumulator.mSize.getLastValue()); @@ -305,7 +313,7 @@ F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat) bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return accumulator.mAllocations.hasValue() || (active_accumulator ? active_accumulator->mAllocations.hasValue() : false); @@ -313,7 +321,7 @@ bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat) F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return F64Bytes(accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)); @@ -321,7 +329,7 @@ F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return F64Bytes((accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)) / mElapsedSeconds.value()); @@ -329,7 +337,7 @@ F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return accumulator.mAllocations.getSampleCount() + (active_accumulator ? active_accumulator->mAllocations.getSampleCount() : 0); @@ -337,7 +345,7 @@ S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& s bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return accumulator.mDeallocations.hasValue() || (active_accumulator ? active_accumulator->mDeallocations.hasValue() : false); @@ -346,7 +354,7 @@ bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return F64Bytes(accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)); @@ -354,7 +362,7 @@ F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet> F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return F64Bytes((accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)) / mElapsedSeconds.value()); @@ -362,7 +370,7 @@ F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFac S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat) { - update(); + update(); const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; return accumulator.mDeallocations.getSampleCount() + (active_accumulator ? active_accumulator->mDeallocations.getSampleCount() : 0); @@ -370,7 +378,7 @@ S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& bool Recording::hasValue(const StatType<CountAccumulator>& stat) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false); @@ -378,7 +386,7 @@ bool Recording::hasValue(const StatType<CountAccumulator>& stat) F64 Recording::getSum(const StatType<CountAccumulator>& stat) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0); @@ -386,7 +394,7 @@ F64 Recording::getSum(const StatType<CountAccumulator>& stat) F64 Recording::getPerSec( const StatType<CountAccumulator>& stat ) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0); @@ -395,7 +403,7 @@ F64 Recording::getPerSec( const StatType<CountAccumulator>& stat ) S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat ) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0); @@ -403,7 +411,7 @@ S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat ) bool Recording::hasValue(const StatType<SampleAccumulator>& stat) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue()); @@ -411,7 +419,7 @@ bool Recording::hasValue(const StatType<SampleAccumulator>& stat) F64 Recording::getMin( const StatType<SampleAccumulator>& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX); @@ -419,7 +427,7 @@ F64 Recording::getMin( const StatType<SampleAccumulator>& stat ) F64 Recording::getMax( const StatType<SampleAccumulator>& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN); @@ -427,7 +435,7 @@ F64 Recording::getMax( const StatType<SampleAccumulator>& stat ) F64 Recording::getMean( const StatType<SampleAccumulator>& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) @@ -448,7 +456,7 @@ F64 Recording::getMean( const StatType<SampleAccumulator>& stat ) F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; @@ -465,7 +473,7 @@ F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat ) F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue()); @@ -473,7 +481,7 @@ F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat ) S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0); @@ -481,7 +489,7 @@ S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat ) bool Recording::hasValue(const StatType<EventAccumulator>& stat) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue()); @@ -489,7 +497,7 @@ bool Recording::hasValue(const StatType<EventAccumulator>& stat) F64 Recording::getSum( const StatType<EventAccumulator>& stat) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0)); @@ -497,7 +505,7 @@ F64 Recording::getSum( const StatType<EventAccumulator>& stat) F64 Recording::getMin( const StatType<EventAccumulator>& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX); @@ -505,7 +513,7 @@ F64 Recording::getMin( const StatType<EventAccumulator>& stat ) F64 Recording::getMax( const StatType<EventAccumulator>& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN); @@ -513,7 +521,7 @@ F64 Recording::getMax( const StatType<EventAccumulator>& stat ) F64 Recording::getMean( const StatType<EventAccumulator>& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) @@ -534,7 +542,7 @@ F64 Recording::getMean( const StatType<EventAccumulator>& stat ) F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; @@ -551,7 +559,7 @@ F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat ) F64 Recording::getLastValue( const StatType<EventAccumulator>& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue(); @@ -559,7 +567,7 @@ F64 Recording::getLastValue( const StatType<EventAccumulator>& stat ) S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0); @@ -575,17 +583,20 @@ PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) mNumRecordedPeriods(0), mRecordingPeriods(num_periods ? num_periods : 1) { + LL_PROFILE_ZONE_SCOPED; setPlayState(state); claim_alloc(gTraceMemStat, this); } PeriodicRecording::~PeriodicRecording() { + LL_PROFILE_ZONE_SCOPED; disclaim_alloc(gTraceMemStat, this); } void PeriodicRecording::nextPeriod() { + LL_PROFILE_ZONE_SCOPED; if (mAutoResize) { mRecordingPeriods.push_back(Recording()); @@ -600,6 +611,7 @@ void PeriodicRecording::nextPeriod() void PeriodicRecording::appendRecording(Recording& recording) { + LL_PROFILE_ZONE_SCOPED; getCurRecording().appendRecording(recording); nextPeriod(); } @@ -607,6 +619,7 @@ void PeriodicRecording::appendRecording(Recording& recording) void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) { + LL_PROFILE_ZONE_SCOPED; if (other.mRecordingPeriods.empty()) return; getCurRecording().update(); @@ -680,6 +693,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) F64Seconds PeriodicRecording::getDuration() const { + LL_PROFILE_ZONE_SCOPED; F64Seconds duration; S32 num_periods = mRecordingPeriods.size(); for (S32 i = 1; i <= num_periods; i++) @@ -693,6 +707,7 @@ F64Seconds PeriodicRecording::getDuration() const LLTrace::Recording PeriodicRecording::snapshotCurRecording() const { + LL_PROFILE_ZONE_SCOPED; Recording recording_copy(getCurRecording()); recording_copy.stop(); return recording_copy; @@ -735,16 +750,19 @@ const Recording& PeriodicRecording::getPrevRecording( S32 offset ) const void PeriodicRecording::handleStart() { + LL_PROFILE_ZONE_SCOPED; getCurRecording().start(); } void PeriodicRecording::handleStop() { + LL_PROFILE_ZONE_SCOPED; getCurRecording().pause(); } void PeriodicRecording::handleReset() { + LL_PROFILE_ZONE_SCOPED; getCurRecording().stop(); if (mAutoResize) @@ -768,11 +786,13 @@ void PeriodicRecording::handleReset() void PeriodicRecording::handleSplitTo(PeriodicRecording& other) { + LL_PROFILE_ZONE_SCOPED; getCurRecording().splitTo(other.getCurRecording()); } F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -794,6 +814,7 @@ F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -816,6 +837,7 @@ F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 // calculates means using aggregates per period F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 mean = 0; @@ -836,9 +858,9 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S3 : NaN; } - F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 period_mean = getPeriodMean(stat, num_periods); @@ -863,6 +885,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -884,6 +907,7 @@ F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S3 F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -906,6 +930,7 @@ F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); S32 valid_period_count = 0; @@ -926,8 +951,35 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S : NaN; } +F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ + LL_PROFILE_ZONE_SCOPED; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + std::vector<F64> buf; + for (S32 i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > (F32Seconds)0.f) + { + if (recording.hasValue(stat)) + { + buf.push_back(recording.getMean(stat)); + } + } + } + if (buf.size()==0) + { + return 0.0f; + } + std::sort(buf.begin(), buf.end()); + + return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); +} + F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 period_mean = getPeriodMean(stat, num_periods); @@ -953,6 +1005,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes min_val(std::numeric_limits<F64>::max()); @@ -972,6 +1025,7 @@ F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_ F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes max_val(0.0); @@ -991,6 +1045,7 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_ F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes mean(0); @@ -1011,6 +1066,7 @@ F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes period_mean = getPeriodMean(stat, num_periods); @@ -1044,6 +1100,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& void ExtendableRecording::extend() { + LL_PROFILE_ZONE_SCOPED; // push the data back to accepted recording mAcceptedRecording.appendRecording(mPotentialRecording); // flush data, so we can start from scratch @@ -1052,22 +1109,26 @@ void ExtendableRecording::extend() void ExtendableRecording::handleStart() { + LL_PROFILE_ZONE_SCOPED; mPotentialRecording.start(); } void ExtendableRecording::handleStop() { + LL_PROFILE_ZONE_SCOPED; mPotentialRecording.pause(); } void ExtendableRecording::handleReset() { + LL_PROFILE_ZONE_SCOPED; mAcceptedRecording.reset(); mPotentialRecording.reset(); } void ExtendableRecording::handleSplitTo(ExtendableRecording& other) { + LL_PROFILE_ZONE_SCOPED; mPotentialRecording.splitTo(other.mPotentialRecording); } @@ -1084,6 +1145,7 @@ ExtendablePeriodicRecording::ExtendablePeriodicRecording() void ExtendablePeriodicRecording::extend() { + LL_PROFILE_ZONE_SCOPED; // push the data back to accepted recording mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); // flush data, so we can start from scratch @@ -1093,22 +1155,26 @@ void ExtendablePeriodicRecording::extend() void ExtendablePeriodicRecording::handleStart() { + LL_PROFILE_ZONE_SCOPED; mPotentialRecording.start(); } void ExtendablePeriodicRecording::handleStop() { + LL_PROFILE_ZONE_SCOPED; mPotentialRecording.pause(); } void ExtendablePeriodicRecording::handleReset() { + LL_PROFILE_ZONE_SCOPED; mAcceptedRecording.reset(); mPotentialRecording.reset(); } void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other) { + LL_PROFILE_ZONE_SCOPED; mPotentialRecording.splitTo(other.mPotentialRecording); } @@ -1123,6 +1189,7 @@ PeriodicRecording& get_frame_recording() void LLStopWatchControlsMixinCommon::start() { + LL_PROFILE_ZONE_SCOPED; switch (mPlayState) { case STOPPED: @@ -1144,6 +1211,7 @@ void LLStopWatchControlsMixinCommon::start() void LLStopWatchControlsMixinCommon::stop() { + LL_PROFILE_ZONE_SCOPED; switch (mPlayState) { case STOPPED: @@ -1163,6 +1231,7 @@ void LLStopWatchControlsMixinCommon::stop() void LLStopWatchControlsMixinCommon::pause() { + LL_PROFILE_ZONE_SCOPED; switch (mPlayState) { case STOPPED: @@ -1182,6 +1251,7 @@ void LLStopWatchControlsMixinCommon::pause() void LLStopWatchControlsMixinCommon::unpause() { + LL_PROFILE_ZONE_SCOPED; switch (mPlayState) { case STOPPED: @@ -1201,6 +1271,7 @@ void LLStopWatchControlsMixinCommon::unpause() void LLStopWatchControlsMixinCommon::resume() { + LL_PROFILE_ZONE_SCOPED; switch (mPlayState) { case STOPPED: @@ -1221,6 +1292,7 @@ void LLStopWatchControlsMixinCommon::resume() void LLStopWatchControlsMixinCommon::restart() { + LL_PROFILE_ZONE_SCOPED; switch (mPlayState) { case STOPPED: @@ -1244,11 +1316,13 @@ void LLStopWatchControlsMixinCommon::restart() void LLStopWatchControlsMixinCommon::reset() { + LL_PROFILE_ZONE_SCOPED; handleReset(); } void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state ) { + LL_PROFILE_ZONE_SCOPED; switch(state) { case STOPPED: diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index d0b4a842a6..1f3d37336a 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -355,6 +355,7 @@ namespace LLTrace template <typename T> S32 getSampleCount(const StatType<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); S32 num_samples = 0; @@ -374,6 +375,7 @@ namespace LLTrace template <typename T> typename T::value_t getPeriodMin(const StatType<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -396,6 +398,7 @@ namespace LLTrace template<typename T> T getPeriodMin(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); } @@ -403,6 +406,7 @@ namespace LLTrace template<typename T> T getPeriodMin(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); } @@ -410,6 +414,7 @@ namespace LLTrace template<typename T> T getPeriodMin(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); } @@ -419,6 +424,7 @@ namespace LLTrace template <typename T> typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max()); @@ -433,6 +439,7 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); } @@ -444,6 +451,7 @@ namespace LLTrace template <typename T> typename T::value_t getPeriodMax(const StatType<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -466,6 +474,7 @@ namespace LLTrace template<typename T> T getPeriodMax(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); } @@ -473,6 +482,7 @@ namespace LLTrace template<typename T> T getPeriodMax(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); } @@ -480,6 +490,7 @@ namespace LLTrace template<typename T> T getPeriodMax(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); } @@ -489,6 +500,7 @@ namespace LLTrace template <typename T> typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 max_val = std::numeric_limits<F64>::min(); @@ -503,6 +515,7 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); } @@ -514,6 +527,7 @@ namespace LLTrace template <typename T> typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes<typename T::value_t>::fractional_t mean(0); @@ -534,12 +548,14 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); } F64 getPeriodMean(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX); template<typename T> typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); } @@ -547,6 +563,7 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); } @@ -556,6 +573,7 @@ namespace LLTrace template <typename T> typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes<typename T::value_t>::fractional_t mean = 0; @@ -577,9 +595,39 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); } + F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX); + + template <typename T> + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX) + { + LL_PROFILE_ZONE_SCOPED; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf; + for (S32 i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > (F32Seconds)0.f) + { + buf.push_back(recording.getPerSec(stat)); + } + } + std::sort(buf.begin(), buf.end()); + + return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); + } + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) + { + LL_PROFILE_ZONE_SCOPED; + return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + // // PERIODIC STANDARD DEVIATION // @@ -589,6 +637,7 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); } @@ -596,6 +645,7 @@ namespace LLTrace template<typename T> typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX) { + LL_PROFILE_ZONE_SCOPED; return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); } diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 025dc57044..7ae1e72784 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -274,12 +274,10 @@ void ThreadRecorder::pushToParent() } -static LLTrace::BlockTimerStatHandle FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data"); - void ThreadRecorder::pullFromChildren() { #if LL_TRACE_ENABLED - LL_RECORD_BLOCK_TIME(FTM_PULL_TRACE_DATA_FROM_CHILDREN); + LL_PROFILE_ZONE_SCOPED; if (mActiveRecordings.empty()) return; { LLMutexLock lock(&mChildListMutex); diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index fe7482ba29..86a396ab06 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -184,6 +184,17 @@ struct boost::hash<LLUUID> } }; +// Adapt boost hash to std hash +namespace std +{ + template<> struct hash<LLUUID> + { + std::size_t operator()(LLUUID const& s) const noexcept + { + return boost::hash<LLUUID>()(s); + } + }; +} #endif diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index 887f6ab733..b07805b628 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -42,10 +42,17 @@ typedef unsigned int U32; // Windows wchar_t is 16-bit, whichever way /Zc:wchar_t is set. In effect, // Windows wchar_t is always a typedef, either for unsigned short or __wchar_t. // (__wchar_t, available either way, is Microsoft's native 2-byte wchar_t type.) +// The version of clang available with VS 2019 also defines wchar_t as __wchar_t +// which is also 16 bits. // In any case, llwchar should be a UTF-32 type. typedef U32 llwchar; #else typedef wchar_t llwchar; +// What we'd actually want is a simple module-scope 'if constexpr' to test +// std::is_same<wchar_t, llwchar>::value and use that to define, or not +// define, string conversion specializations. Since we don't have that, we'll +// have to rely on #if instead. Sorry, Dr. Stroustrup. +#define LLWCHAR_IS_WCHAR_T 1 #endif #if LL_WINDOWS diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index 38dd198ad3..12df693910 100644 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h @@ -31,58 +31,109 @@ #include <sstream> #include <llstring.h> +#include <boost/call_traits.hpp> /** - * gstringize(item) encapsulates an idiom we use constantly, using - * operator<<(std::ostringstream&, TYPE) followed by std::ostringstream::str() - * or their wstring equivalents - * to render a string expressing some item. + * stream_to(std::ostream&, items, ...) streams each item in the parameter list + * to the passed std::ostream using the insertion operator <<. This can be + * used, for instance, to make a simple print() function, e.g.: + * + * @code + * template <typename... Items> + * void print(Items&&... items) + * { + * stream_to(std::cout, std::forward<Items>(items)...); + * } + * @endcode */ -template <typename CHARTYPE, typename T> -std::basic_string<CHARTYPE> gstringize(const T& item) +// recursion tail +template <typename CHARTYPE> +void stream_to(std::basic_ostream<CHARTYPE>& out) {} +// stream one or more items +template <typename CHARTYPE, typename T, typename... Items> +void stream_to(std::basic_ostream<CHARTYPE>& out, T&& item, Items&&... items) { - std::basic_ostringstream<CHARTYPE> out; - out << item; - return out.str(); + out << std::forward<T>(item); + stream_to(out, std::forward<Items>(items)...); } +// why we use function overloads, not function template specializations: +// http://www.gotw.ca/publications/mill17.htm + /** - *partial specialization of stringize for handling wstring - *TODO: we should have similar specializations for wchar_t[] but not until it is needed. + * gstringize(item, ...) encapsulates an idiom we use constantly, using + * operator<<(std::ostringstream&, TYPE) followed by std::ostringstream::str() + * or their wstring equivalents to render a string expressing one or more items. */ -inline std::string stringize(const std::wstring& item) +// two or more args - the case of a single argument is handled separately +template <typename CHARTYPE, typename T0, typename T1, typename... Items> +auto gstringize(T0&& item0, T1&& item1, Items&&... items) { - return wstring_to_utf8str(item); + std::basic_ostringstream<CHARTYPE> out; + stream_to(out, std::forward<T0>(item0), std::forward<T1>(item1), + std::forward<Items>(items)...); + return out.str(); } -/** - * Specialization of gstringize for std::string return types - */ -template <typename T> -std::string stringize(const T& item) +// generic single argument: stream to out, as above +template <typename CHARTYPE, typename T> +struct gstringize_impl { - return gstringize<char>(item); + auto operator()(typename boost::call_traits<T>::param_type arg) + { + std::basic_ostringstream<CHARTYPE> out; + out << arg; + return out.str(); + } +}; + +// partially specialize for a single STRING argument - +// note that ll_convert<T>(T) already handles the trivial case +template <typename OUTCHAR, typename INCHAR> +struct gstringize_impl<OUTCHAR, std::basic_string<INCHAR>> +{ + auto operator()(const std::basic_string<INCHAR>& arg) + { + return ll_convert<std::basic_string<OUTCHAR>>(arg); + } +}; + +// partially specialize for a single CHARTYPE* argument - +// since it's not a basic_string and we do want to optimize this common case +template <typename OUTCHAR, typename INCHAR> +struct gstringize_impl<OUTCHAR, INCHAR*> +{ + auto operator()(const INCHAR* arg) + { + return ll_convert<std::basic_string<OUTCHAR>>(arg); + } +}; + +// gstringize(single argument) +template <typename CHARTYPE, typename T> +auto gstringize(T&& item) +{ + // use decay<T> so we don't require separate specializations + // for T, const T, T&, const T& ... + return gstringize_impl<CHARTYPE, std::decay_t<T>>()(std::forward<T>(item)); } /** - * Specialization for generating wstring from string. - * Both a convenience function and saves a miniscule amount of overhead. + * Specialization of gstringize for std::string return types */ -inline std::wstring wstringize(const std::string& item) +template <typename... Items> +auto stringize(Items&&... items) { - // utf8str_to_wstring() returns LLWString, which isn't necessarily the - // same as std::wstring - LLWString s(utf8str_to_wstring(item)); - return std::wstring(s.begin(), s.end()); + return gstringize<char>(std::forward<Items>(items)...); } /** * Specialization of gstringize for std::wstring return types */ -template <typename T> -std::wstring wstringize(const T& item) +template <typename... Items> +auto wstringize(Items&&... items) { - return gstringize<wchar_t>(item); + return gstringize<wchar_t>(std::forward<Items>(items)...); } /** @@ -146,11 +197,9 @@ void destringize_f(std::basic_string<CHARTYPE> const & str, Functor const & f) * std::istringstream in(str); * in >> item1 >> item2 >> item3 ... ; * @endcode - * @NOTE - once we get generic lambdas, we shouldn't need DEWSTRINGIZE() any - * more since DESTRINGIZE() should do the right thing with a std::wstring. But - * until then, the lambda we pass must accept the right std::basic_istream. */ -#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::istream& in){in >> EXPRESSION;})) -#define DEWSTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::wistream& in){in >> EXPRESSION;})) +#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](auto& in){in >> EXPRESSION;})) +// legacy name, just use DESTRINGIZE() going forward +#define DEWSTRINGIZE(STR, EXPRESSION) DESTRINGIZE(STR, EXPRESSION) #endif /* ! defined(LL_STRINGIZE_H) */ diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 9b89159625..5daa29adf4 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -90,19 +90,19 @@ namespace tut { Keyed one("one"); ensure_equals(Keyed::instanceCount(), 1); - Keyed* found = Keyed::getInstance("one"); - ensure("couldn't find stack Keyed", found); - ensure_equals("found wrong Keyed instance", found, &one); + auto found = Keyed::getInstance("one"); + ensure("couldn't find stack Keyed", bool(found)); + ensure_equals("found wrong Keyed instance", found.get(), &one); { boost::scoped_ptr<Keyed> two(new Keyed("two")); ensure_equals(Keyed::instanceCount(), 2); - Keyed* found = Keyed::getInstance("two"); - ensure("couldn't find heap Keyed", found); - ensure_equals("found wrong Keyed instance", found, two.get()); + auto found = Keyed::getInstance("two"); + ensure("couldn't find heap Keyed", bool(found)); + ensure_equals("found wrong Keyed instance", found.get(), two.get()); } ensure_equals(Keyed::instanceCount(), 1); } - Keyed* found = Keyed::getInstance("one"); + auto found = Keyed::getInstance("one"); ensure("Keyed key lives too long", ! found); ensure_equals(Keyed::instanceCount(), 0); } diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index f0eafa8201..447c7f50f2 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -356,14 +356,15 @@ namespace tut // Create a script file in a temporary place. NamedTempFile script("py", + "from __future__ import print_function" EOL "import sys" EOL "import time" EOL EOL "time.sleep(2)" EOL - "print >>sys.stdout, 'stdout after wait'" EOL + "print('stdout after wait',file=sys.stdout)" EOL "sys.stdout.flush()" EOL "time.sleep(2)" EOL - "print >>sys.stderr, 'stderr after wait'" EOL + "print('stderr after wait',file=sys.stderr)" EOL "sys.stderr.flush()" EOL ); @@ -568,12 +569,12 @@ namespace tut { set_test_name("arguments"); PythonProcessLauncher py(get_test_name(), - "from __future__ import with_statement\n" + "from __future__ import with_statement, print_function\n" "import sys\n" // note nonstandard output-file arg! "with open(sys.argv[3], 'w') as f:\n" " for arg in sys.argv[1:]:\n" - " print >>f, arg\n"); + " print(arg,file=f)\n"); // We expect that PythonProcessLauncher has already appended // its own NamedTempFile to mParams.args (sys.argv[0]). py.mParams.args.add("first arg"); // sys.argv[1] @@ -857,7 +858,8 @@ namespace tut set_test_name("'bogus' test"); CaptureLog recorder; PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam("bogus")); py.mPy = LLProcess::create(py.mParams); ensure("should have rejected 'bogus'", ! py.mPy); @@ -872,7 +874,8 @@ namespace tut // Replace this test with one or more real 'file' tests when we // implement 'file' support PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam("file")); py.mPy = LLProcess::create(py.mParams); @@ -887,7 +890,8 @@ namespace tut // implement 'tpipe' support CaptureLog recorder; PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam("tpipe")); py.mPy = LLProcess::create(py.mParams); @@ -904,7 +908,8 @@ namespace tut // implement 'npipe' support CaptureLog recorder; PythonProcessLauncher py(get_test_name(), - "print 'Hello world'\n"); + "from __future__ import print_function\n" + "print('Hello world')\n"); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam()); py.mParams.files.add(LLProcess::FileParam("npipe")); @@ -980,7 +985,8 @@ namespace tut { set_test_name("get*Pipe() validation"); PythonProcessLauncher py(get_test_name(), - "print 'this output is expected'\n"); + "from __future__ import print_function\n" + "print('this output is expected')\n"); py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stdin py.mParams.files.add(LLProcess::FileParam()); // inherit stdout py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr @@ -1000,14 +1006,15 @@ namespace tut { set_test_name("talk to stdin/stdout"); PythonProcessLauncher py(get_test_name(), + "from __future__ import print_function\n" "import sys, time\n" - "print 'ok'\n" + "print('ok')\n" "sys.stdout.flush()\n" "# wait for 'go' from test program\n" "go = sys.stdin.readline()\n" "if go != 'go\\n':\n" " sys.exit('expected \"go\", saw %r' % go)\n" - "print 'ack'\n"); + "print('ack')\n"); py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout py.launch(); @@ -1118,7 +1125,8 @@ namespace tut { set_test_name("ReadPipe \"eof\" event"); PythonProcessLauncher py(get_test_name(), - "print 'Hello from Python!'\n"); + "from __future__ import print_function\n" + "print('Hello from Python!')\n"); py.mParams.files.add(LLProcess::FileParam()); // stdin py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout py.launch(); diff --git a/indra/llcommon/tests/threadsafeschedule_test.cpp b/indra/llcommon/tests/threadsafeschedule_test.cpp new file mode 100644 index 0000000000..c421cc7b1c --- /dev/null +++ b/indra/llcommon/tests/threadsafeschedule_test.cpp @@ -0,0 +1,69 @@ +/** + * @file threadsafeschedule_test.cpp + * @author Nat Goodspeed + * @date 2021-10-04 + * @brief Test for threadsafeschedule. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "threadsafeschedule.h" +// STL headers +// std headers +#include <chrono> +// external library headers +// other Linden headers +#include "../test/lltut.h" + +using namespace std::literals::chrono_literals; // ms suffix +using namespace std::literals::string_literals; // s suffix +using Queue = LL::ThreadSafeSchedule<std::string>; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct threadsafeschedule_data + { + Queue queue; + }; + typedef test_group<threadsafeschedule_data> threadsafeschedule_group; + typedef threadsafeschedule_group::object object; + threadsafeschedule_group threadsafeschedulegrp("threadsafeschedule"); + + template<> template<> + void object::test<1>() + { + set_test_name("push"); + // Simply calling push() a few times might result in indeterminate + // delivery order if the resolution of steady_clock is coarser than + // the real time required for each push() call. Explicitly increment + // the timestamp for each one -- but since we're passing explicit + // timestamps, make the queue reorder them. + queue.push(Queue::TimeTuple(Queue::Clock::now() + 200ms, "ghi")); + // Given the various push() overloads, you have to match the type + // exactly: conversions are ambiguous. + queue.push("abc"s); + queue.push(Queue::Clock::now() + 100ms, "def"); + queue.close(); + auto entry = queue.pop(); + ensure_equals("failed to pop first", std::get<0>(entry), "abc"s); + entry = queue.pop(); + ensure_equals("failed to pop second", std::get<0>(entry), "def"s); + ensure("queue not closed", queue.isClosed()); + ensure("queue prematurely done", ! queue.done()); + std::string s; + bool popped = queue.tryPopFor(1s, s); + ensure("failed to pop third", popped); + ensure_equals("third is wrong", s, "ghi"s); + popped = queue.tryPop(s); + ensure("queue not empty", ! popped); + ensure("queue not done", queue.done()); + } +} // namespace tut diff --git a/indra/llcommon/tests/tuple_test.cpp b/indra/llcommon/tests/tuple_test.cpp new file mode 100644 index 0000000000..af94e2086c --- /dev/null +++ b/indra/llcommon/tests/tuple_test.cpp @@ -0,0 +1,47 @@ +/** + * @file tuple_test.cpp + * @author Nat Goodspeed + * @date 2021-10-04 + * @brief Test for tuple. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "tuple.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "../test/lltut.h" + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct tuple_data + { + }; + typedef test_group<tuple_data> tuple_group; + typedef tuple_group::object object; + tuple_group tuplegrp("tuple"); + + template<> template<> + void object::test<1>() + { + set_test_name("tuple"); + std::tuple<std::string, int> tup{ "abc", 17 }; + std::tuple<int, std::string, int> ptup{ tuple_cons(34, tup) }; + std::tuple<std::string, int> tup2; + int i; + std::tie(i, tup2) = tuple_split(ptup); + ensure_equals("tuple_car() fail", i, 34); + ensure_equals("tuple_cdr() (0) fail", std::get<0>(tup2), "abc"); + ensure_equals("tuple_cdr() (1) fail", std::get<1>(tup2), 17); + } +} // namespace tut diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp new file mode 100644 index 0000000000..1d73f7aa0d --- /dev/null +++ b/indra/llcommon/tests/workqueue_test.cpp @@ -0,0 +1,235 @@ +/** + * @file workqueue_test.cpp + * @author Nat Goodspeed + * @date 2021-10-07 + * @brief Test for workqueue. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "workqueue.h" +// STL headers +// std headers +#include <chrono> +#include <deque> +// external library headers +// other Linden headers +#include "../test/lltut.h" +#include "../test/catch_and_store_what_in.h" +#include "llcond.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "llstring.h" +#include "stringize.h" + +using namespace LL; +using namespace std::literals::chrono_literals; // ms suffix +using namespace std::literals::string_literals; // s suffix + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct workqueue_data + { + WorkQueue queue{"queue"}; + }; + typedef test_group<workqueue_data> workqueue_group; + typedef workqueue_group::object object; + workqueue_group workqueuegrp("workqueue"); + + template<> template<> + void object::test<1>() + { + set_test_name("name"); + ensure_equals("didn't capture name", queue.getKey(), "queue"); + ensure("not findable", WorkQueue::getInstance("queue") == queue.getWeak().lock()); + WorkQueue q2; + ensure("has no name", LLStringUtil::startsWith(q2.getKey(), "WorkQueue")); + } + + template<> template<> + void object::test<2>() + { + set_test_name("post"); + bool wasRun{ false }; + // We only get away with binding a simple bool because we're running + // the work on the same thread. + queue.post([&wasRun](){ wasRun = true; }); + queue.close(); + ensure("ran too soon", ! wasRun); + queue.runUntilClose(); + ensure("didn't run", wasRun); + } + + template<> template<> + void object::test<3>() + { + set_test_name("postEvery"); + // record of runs + using Shared = std::deque<WorkQueue::TimePoint>; + // This is an example of how to share data between the originator of + // postEvery(work) and the work item itself, since usually a WorkQueue + // is used to dispatch work to a different thread. Neither of them + // should call any of LLCond's wait methods: you don't want to stall + // either the worker thread or the originating thread (conventionally + // main). Use LLCond or a subclass even if all you want to do is + // signal the work item that it can quit; consider LLOneShotCond. + LLCond<Shared> data; + auto start = WorkQueue::TimePoint::clock::now(); + auto interval = 100ms; + queue.postEvery( + interval, + [&data, count = 0] + () mutable + { + // record the timestamp at which this instance is running + data.update_one( + [](Shared& data) + { + data.push_back(WorkQueue::TimePoint::clock::now()); + }); + // by the 3rd call, return false to stop + return (++count < 3); + }); + // no convenient way to close() our queue while we've got a + // postEvery() running, so run until we have exhausted the iterations + // or we time out waiting + for (auto finish = start + 10*interval; + WorkQueue::TimePoint::clock::now() < finish && + data.get([](const Shared& data){ return data.size(); }) < 3; ) + { + queue.runPending(); + std::this_thread::sleep_for(interval/10); + } + // Take a copy of the captured deque. + Shared result = data.get(); + ensure_equals("called wrong number of times", result.size(), 3); + // postEvery() assumes you want the first call to happen right away. + // Pretend our start time was (interval) earlier than that, to make + // our too early/too late tests uniform for all entries. + start -= interval; + for (size_t i = 0; i < result.size(); ++i) + { + auto diff = result[i] - start; + start += interval; + try + { + ensure(STRINGIZE("call " << i << " too soon"), diff >= interval); + ensure(STRINGIZE("call " << i << " too late"), diff < interval*1.5); + } + catch (const tut::failure&) + { + auto interval_ms = interval / 1ms; + auto diff_ms = diff / 1ms; + std::cerr << "interval " << interval_ms + << "ms; diff " << diff_ms << "ms" << std::endl; + throw; + } + } + } + + template<> template<> + void object::test<4>() + { + set_test_name("postTo"); + WorkQueue main("main"); + auto qptr = WorkQueue::getInstance("queue"); + int result = 0; + main.postTo( + qptr, + [](){ return 17; }, + // Note that a postTo() *callback* can safely bind a reference to + // a variable on the invoking thread, because the callback is run + // on the invoking thread. (Of course the bound variable must + // survive until the callback is called.) + [&result](int i){ result = i; }); + // this should post the callback to main + qptr->runOne(); + // this should run the callback + main.runOne(); + ensure_equals("failed to run int callback", result, 17); + + std::string alpha; + // postTo() handles arbitrary return types + main.postTo( + qptr, + [](){ return "abc"s; }, + [&alpha](const std::string& s){ alpha = s; }); + qptr->runPending(); + main.runPending(); + ensure_equals("failed to run string callback", alpha, "abc"); + } + + template<> template<> + void object::test<5>() + { + set_test_name("postTo with void return"); + WorkQueue main("main"); + auto qptr = WorkQueue::getInstance("queue"); + std::string observe; + main.postTo( + qptr, + // The ONLY reason we can get away with binding a reference to + // 'observe' in our work callable is because we're directly + // calling qptr->runOne() on this same thread. It would be a + // mistake to do that if some other thread were servicing 'queue'. + [&observe](){ observe = "queue"; }, + [&observe](){ observe.append(";main"); }); + qptr->runOne(); + main.runOne(); + ensure_equals("failed to run both lambdas", observe, "queue;main"); + } + + template<> template<> + void object::test<6>() + { + set_test_name("waitForResult"); + std::string stored; + // Try to call waitForResult() on this thread's main coroutine. It + // should throw because the main coroutine must service the queue. + auto what{ catch_what<WorkQueue::Error>( + [this, &stored](){ stored = queue.waitForResult( + [](){ return "should throw"; }); }) }; + ensure("lambda should not have run", stored.empty()); + ensure_not("waitForResult() should have thrown", what.empty()); + ensure(STRINGIZE("should mention waitForResult: " << what), + what.find("waitForResult") != std::string::npos); + + // Call waitForResult() on a coroutine, with a string result. + LLCoros::instance().launch( + "waitForResult string", + [this, &stored]() + { stored = queue.waitForResult( + [](){ return "string result"; }); }); + llcoro::suspend(); + // Nothing will have happened yet because, even if the coroutine did + // run immediately, all it did was to queue the inner lambda on + // 'queue'. Service it. + queue.runOne(); + llcoro::suspend(); + ensure_equals("bad waitForResult return", stored, "string result"); + + // Call waitForResult() on a coroutine, with a void callable. + stored.clear(); + bool done = false; + LLCoros::instance().launch( + "waitForResult void", + [this, &stored, &done]() + { + queue.waitForResult([&stored](){ stored = "ran"; }); + done = true; + }); + llcoro::suspend(); + queue.runOne(); + llcoro::suspend(); + ensure_equals("didn't run coroutine", stored, "ran"); + ensure("void waitForResult() didn't return", done); + } +} // namespace tut diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp new file mode 100644 index 0000000000..ba914035e2 --- /dev/null +++ b/indra/llcommon/threadpool.cpp @@ -0,0 +1,88 @@ +/** + * @file threadpool.cpp + * @author Nat Goodspeed + * @date 2021-10-21 + * @brief Implementation for threadpool. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "threadpool.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" +#include "llevents.h" +#include "stringize.h" + +LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): + mQueue(name, capacity), + mName("ThreadPool:" + name), + mThreadCount(threads) +{} + +void LL::ThreadPool::start() +{ + for (size_t i = 0; i < mThreadCount; ++i) + { + std::string tname{ stringize(mName, ':', (i+1), '/', mThreadCount) }; + mThreads.emplace_back(tname, [this, tname]() + { + LL_PROFILER_SET_THREAD_NAME(tname.c_str()); + run(tname); + }); + } + // Listen on "LLApp", and when the app is shutting down, close the queue + // and join the workers. + LLEventPumps::instance().obtain("LLApp").listen( + mName, + [this](const LLSD& stat) + { + std::string status(stat["status"]); + if (status != "running") + { + // viewer is starting shutdown -- proclaim the end is nigh! + LL_DEBUGS("ThreadPool") << mName << " saw " << status << LL_ENDL; + close(); + } + return false; + }); +} + +LL::ThreadPool::~ThreadPool() +{ + close(); +} + +void LL::ThreadPool::close() +{ + if (! mQueue.isClosed()) + { + LL_DEBUGS("ThreadPool") << mName << " closing queue and joining threads" << LL_ENDL; + mQueue.close(); + for (auto& pair: mThreads) + { + LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL; + pair.second.join(); + } + LL_DEBUGS("ThreadPool") << mName << " shutdown complete" << LL_ENDL; + } +} + +void LL::ThreadPool::run(const std::string& name) +{ + LL_DEBUGS("ThreadPool") << name << " starting" << LL_ENDL; + run(); + LL_DEBUGS("ThreadPool") << name << " stopping" << LL_ENDL; +} + +void LL::ThreadPool::run() +{ + mQueue.runUntilClose(); +} diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h new file mode 100644 index 0000000000..b79c9b9090 --- /dev/null +++ b/indra/llcommon/threadpool.h @@ -0,0 +1,71 @@ +/** + * @file threadpool.h + * @author Nat Goodspeed + * @date 2021-10-21 + * @brief ThreadPool configures a WorkQueue along with a pool of threads to + * service it. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_THREADPOOL_H) +#define LL_THREADPOOL_H + +#include "workqueue.h" +#include <string> +#include <thread> +#include <utility> // std::pair +#include <vector> + +namespace LL +{ + + class ThreadPool + { + public: + /** + * Pass ThreadPool a string name. This can be used to look up the + * relevant WorkQueue. + */ + ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024); + virtual ~ThreadPool(); + + /** + * Launch the ThreadPool. Until this call, a constructed ThreadPool + * launches no threads. That permits coders to derive from ThreadPool, + * or store it as a member of some other class, but refrain from + * launching it until all other construction is complete. + */ + void start(); + + /** + * ThreadPool listens for application shutdown messages on the "LLApp" + * LLEventPump. Call close() to shut down this ThreadPool early. + */ + void close(); + + std::string getName() const { return mName; } + size_t getWidth() const { return mThreads.size(); } + /// obtain a non-const reference to the WorkQueue to post work to it + WorkQueue& getQueue() { return mQueue; } + + /** + * Override run() if you need special processing. The default run() + * implementation simply calls WorkQueue::runUntilClose(). + */ + virtual void run(); + + private: + void run(const std::string& name); + + WorkQueue mQueue; + std::string mName; + size_t mThreadCount; + std::vector<std::pair<std::string, std::thread>> mThreads; + }; + +} // namespace LL + +#endif /* ! defined(LL_THREADPOOL_H) */ diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h new file mode 100644 index 0000000000..601681d550 --- /dev/null +++ b/indra/llcommon/threadsafeschedule.h @@ -0,0 +1,399 @@ +/** + * @file threadsafeschedule.h + * @author Nat Goodspeed + * @date 2021-10-02 + * @brief ThreadSafeSchedule is an ordered queue in which every item has an + * associated timestamp. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_THREADSAFESCHEDULE_H) +#define LL_THREADSAFESCHEDULE_H + +#include "chrono.h" +#include "llexception.h" +#include "llthreadsafequeue.h" +#include "tuple.h" +#include <chrono> +#include <tuple> + +namespace LL +{ + namespace ThreadSafeSchedulePrivate + { + using TimePoint = std::chrono::steady_clock::time_point; + // Bundle consumer's data with a TimePoint to order items by timestamp. + template <typename... Args> + using TimestampedTuple = std::tuple<TimePoint, Args...>; + + // comparison functor for TimedTuples -- see TimedQueue comments + struct ReverseTupleOrder + { + template <typename Tuple> + bool operator()(const Tuple& left, const Tuple& right) const + { + return std::get<0>(left) > std::get<0>(right); + } + }; + + template <typename... Args> + using TimedQueue = PriorityQueueAdapter< + TimestampedTuple<Args...>, + // std::vector is the default storage for std::priority_queue, + // have to restate to specify comparison template parameter + std::vector<TimestampedTuple<Args...>>, + // std::priority_queue uses a counterintuitive comparison + // behavior: the default std::less comparator is used to present + // the *highest* value as top(). So to sort by earliest timestamp, + // we must invert by using >. + ReverseTupleOrder>; + } // namespace ThreadSafeSchedulePrivate + + /** + * ThreadSafeSchedule is an ordered LLThreadSafeQueue in which every item + * is given an associated timestamp. That is, TimePoint is implicitly + * prepended to the std::tuple with the specified types. + * + * Items are popped in increasing chronological order. Moreover, any item + * with a timestamp in the future is held back until + * std::chrono::steady_clock reaches that timestamp. + */ + template <typename... Args> + class ThreadSafeSchedule: + public LLThreadSafeQueue<ThreadSafeSchedulePrivate::TimestampedTuple<Args...>, + ThreadSafeSchedulePrivate::TimedQueue<Args...>> + { + public: + using DataTuple = std::tuple<Args...>; + using TimeTuple = ThreadSafeSchedulePrivate::TimestampedTuple<Args...>; + + private: + using super = LLThreadSafeQueue<TimeTuple, ThreadSafeSchedulePrivate::TimedQueue<Args...>>; + using lock_t = typename super::lock_t; + // VS 2017 needs this due to a bug: + // https://developercommunity.visualstudio.com/t/cannot-access-protected-enumerator-of-enclosing-cl/203430 + enum pop_result { EMPTY=super::EMPTY, DONE=super::DONE, WAITING=super::WAITING, POPPED=super::POPPED }; + + public: + using Closed = LLThreadSafeQueueInterrupt; + using TimePoint = ThreadSafeSchedulePrivate::TimePoint; + using Clock = TimePoint::clock; + + ThreadSafeSchedule(U32 capacity=1024): + super(capacity) + {} + + /*----------------------------- push() -----------------------------*/ + /// explicitly pass TimeTuple + using super::push; + + /// pass DataTuple with implicit now + // This could be ambiguous for Args with a single type. Unfortunately + // we can't enable_if an individual method with a condition based on + // the *class* template arguments, only on that method's template + // arguments. We could specialize this class for the single-Args case; + // we could minimize redundancy by breaking out a common base class... + void push(const DataTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + push(tuple_cons(Clock::now(), tuple)); + } + + /// individually pass each component of the TimeTuple + void push(const TimePoint& time, Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + push(TimeTuple(time, std::forward<Args>(args)...)); + } + + /// individually pass every component except the TimePoint (implies now) + // This could be ambiguous if the first specified template parameter + // type is also TimePoint. We could try to disambiguate, but a simpler + // approach would be for the caller to explicitly construct DataTuple + // and call that overload. + void push(Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + push(Clock::now(), std::forward<Args>(args)...); + } + + /*--------------------------- tryPush() ----------------------------*/ + /// explicit TimeTuple + using super::tryPush; + + /// DataTuple with implicit now + bool tryPush(const DataTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + return tryPush(tuple_cons(Clock::now(), tuple)); + } + + /// individually pass components + bool tryPush(const TimePoint& time, Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + return tryPush(TimeTuple(time, std::forward<Args>(args)...)); + } + + /// individually pass components with implicit now + bool tryPush(Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + return tryPush(Clock::now(), std::forward<Args>(args)...); + } + + /*-------------------------- tryPushFor() --------------------------*/ + /// explicit TimeTuple + using super::tryPushFor; + + /// DataTuple with implicit now + template <typename Rep, typename Period> + bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout, + const DataTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + return tryPushFor(timeout, tuple_cons(Clock::now(), tuple)); + } + + /// individually pass components + template <typename Rep, typename Period> + bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout, + const TimePoint& time, Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + return tryPushFor(TimeTuple(time, std::forward<Args>(args)...)); + } + + /// individually pass components with implicit now + template <typename Rep, typename Period> + bool tryPushFor(const std::chrono::duration<Rep, Period>& timeout, + Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + return tryPushFor(Clock::now(), std::forward<Args>(args)...); + } + + /*------------------------- tryPushUntil() -------------------------*/ + /// explicit TimeTuple + using super::tryPushUntil; + + /// DataTuple with implicit now + template <typename Clock, typename Duration> + bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until, + const DataTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + return tryPushUntil(until, tuple_cons(Clock::now(), tuple)); + } + + /// individually pass components + template <typename Clock, typename Duration> + bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until, + const TimePoint& time, Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + return tryPushUntil(until, TimeTuple(time, std::forward<Args>(args)...)); + } + + /// individually pass components with implicit now + template <typename Clock, typename Duration> + bool tryPushUntil(const std::chrono::time_point<Clock, Duration>& until, + Args&&... args) + { + LL_PROFILE_ZONE_SCOPED; + return tryPushUntil(until, Clock::now(), std::forward<Args>(args)...); + } + + /*----------------------------- pop() ------------------------------*/ + // Our consumer may or may not care about the timestamp associated + // with each popped item, so we allow retrieving either DataTuple or + // TimeTuple. One potential use would be to observe, and possibly + // adjust for, the time lag between the item time and the actual + // current time. + + /// pop DataTuple by value + // It would be great to notice when sizeof...(Args) == 1 and directly + // return the first (only) value, instead of making pop()'s caller + // call std::get<0>(value). See push(DataTuple) remarks for why we + // haven't yet jumped through those hoops. + DataTuple pop() + { + LL_PROFILE_ZONE_SCOPED; + return tuple_cdr(popWithTime()); + } + + /// pop TimeTuple by value + TimeTuple popWithTime() + { + LL_PROFILE_ZONE_SCOPED; + lock_t lock(super::mLock); + // We can't just sit around waiting forever, given that there may + // be items in the queue that are not yet ready but will *become* + // ready in the near future. So in fact, with this class, every + // pop() becomes a tryPopUntil(), constrained to the timestamp of + // the head item. It almost doesn't matter what we specify for the + // caller's time constraint -- all we really care about is the + // head item's timestamp. Since pop() and popWithTime() are + // defined to wait until either an item becomes available or the + // queue is closed, loop until one of those things happens. The + // constraint we pass just determines how often we'll loop while + // waiting. + TimeTuple tt; + while (true) + { + // Pick a point suitably far into the future. + TimePoint until = TimePoint::clock::now() + std::chrono::hours(24); + pop_result popped = tryPopUntil_(lock, until, tt); + if (popped == POPPED) + return std::move(tt); + + // DONE: throw, just as super::pop() does + if (popped == DONE) + { + LLTHROW(LLThreadSafeQueueInterrupt()); + } + // WAITING: we've still got items to drain. + // EMPTY: not closed, so it's worth waiting for more items. + // Either way, loop back to wait. + } + } + + // We can use tryPop(TimeTuple&) just as it stands; the only behavior + // difference is in our canPop() override method. + using super::tryPop; + + /// tryPop(DataTuple&) + bool tryPop(DataTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + TimeTuple tt; + if (! super::tryPop(tt)) + return false; + tuple = tuple_cdr(std::move(tt)); + return true; + } + + /// for when Args has exactly one type + bool tryPop(typename std::tuple_element<1, TimeTuple>::type& value) + { + LL_PROFILE_ZONE_SCOPED; + TimeTuple tt; + if (! super::tryPop(tt)) + return false; + value = std::get<1>(std::move(tt)); + return true; + } + + /// tryPopFor() + template <typename Rep, typename Period, typename Tuple> + bool tryPopFor(const std::chrono::duration<Rep, Period>& timeout, Tuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + // It's important to use OUR tryPopUntil() implementation, rather + // than delegating immediately to our base class. + return tryPopUntil(Clock::now() + timeout, tuple); + } + + /// tryPopUntil(TimeTuple&) + template <typename Clock, typename Duration> + bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until, + TimeTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + // super::tryPopUntil() wakes up when an item becomes available or + // we hit 'until', whichever comes first. Thing is, the current + // head of the queue could become ready sooner than either of + // those events, and we need to deliver it as soon as it does. + // Don't wait past the TimePoint of the head item. + // Naturally, lock the queue before peeking at mStorage. + return super::tryLockUntil( + until, + [this, until, &tuple](lock_t& lock) + { + // Use our time_point_cast to allow for 'until' that's a + // time_point type other than TimePoint. + return POPPED == + tryPopUntil_(lock, LL::time_point_cast<TimePoint>(until), tuple); + }); + } + + pop_result tryPopUntil_(lock_t& lock, const TimePoint& until, TimeTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + TimePoint adjusted = until; + if (! super::mStorage.empty()) + { + LL_PROFILE_ZONE_NAMED("tpu - adjust"); + // use whichever is earlier: the head item's timestamp, or + // the caller's limit + adjusted = min(std::get<0>(super::mStorage.front()), adjusted); + } + // now delegate to base-class tryPopUntil_() + pop_result popped; + { + LL_PROFILE_ZONE_NAMED("tpu - super"); + while ((popped = pop_result(super::tryPopUntil_(lock, adjusted, tuple))) == WAITING) + { + // If super::tryPopUntil_() returns WAITING, it means there's + // a head item, but it's not yet time. But it's worth looping + // back to recheck. + } + } + return popped; + } + + /// tryPopUntil(DataTuple&) + template <typename Clock, typename Duration> + bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until, + DataTuple& tuple) + { + LL_PROFILE_ZONE_SCOPED; + TimeTuple tt; + if (! tryPopUntil(until, tt)) + return false; + tuple = tuple_cdr(std::move(tt)); + return true; + } + + /// for when Args has exactly one type + template <typename Clock, typename Duration> + bool tryPopUntil(const std::chrono::time_point<Clock, Duration>& until, + typename std::tuple_element<1, TimeTuple>::type& value) + { + LL_PROFILE_ZONE_SCOPED; + TimeTuple tt; + if (! tryPopUntil(until, tt)) + return false; + value = std::get<1>(std::move(tt)); + return true; + } + + /*------------------------------ etc. ------------------------------*/ + // We can't hide items that aren't yet ready because we can't traverse + // the underlying priority_queue: it has no iterators, only top(). So + // a consumer could observe size() > 0 and yet tryPop() returns false. + // Shrug, in a multi-consumer scenario that would be expected behavior. + using super::size; + // open/closed state + using super::close; + using super::isClosed; + using super::done; + + private: + // this method is called by base class pop_() every time we're + // considering whether to deliver the current head element + bool canPop(const TimeTuple& head) const override + { + LL_PROFILE_ZONE_SCOPED; + // an item with a future timestamp isn't yet ready to pop + // (should we add some slop for overhead?) + return std::get<0>(head) <= Clock::now(); + } + }; + +} // namespace LL + +#endif /* ! defined(LL_THREADSAFESCHEDULE_H) */ diff --git a/indra/llcommon/timing.cpp b/indra/llcommon/timing.cpp deleted file mode 100644 index c2dc695ef3..0000000000 --- a/indra/llcommon/timing.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file timing.cpp - * @brief This file will be deprecated in the future. - * - * $LicenseInfo:firstyear=2000&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$ - */ diff --git a/indra/llcommon/tuple.h b/indra/llcommon/tuple.h new file mode 100644 index 0000000000..bfe7e3c2ba --- /dev/null +++ b/indra/llcommon/tuple.h @@ -0,0 +1,84 @@ +/** + * @file tuple.h + * @author Nat Goodspeed + * @date 2021-10-04 + * @brief A couple tuple utilities + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_TUPLE_H) +#define LL_TUPLE_H + +#include <tuple> +#include <type_traits> // std::remove_reference +#include <utility> // std::pair + +/** + * tuple_cons() behaves like LISP cons: it uses std::tuple_cat() to prepend a + * new item of arbitrary type to an existing std::tuple. + */ +template <typename First, typename... Rest, typename Tuple_=std::tuple<Rest...>> +auto tuple_cons(First&& first, Tuple_&& rest) +{ + // All we need to do is make a tuple containing 'first', and let + // tuple_cat() do the hard part. + return std::tuple_cat(std::tuple<First>(std::forward<First>(first)), + std::forward<Tuple_>(rest)); +} + +/** + * tuple_car() behaves like LISP car: it extracts the first item from a + * std::tuple. + */ +template <typename... Args, typename Tuple_=std::tuple<Args...>> +auto tuple_car(Tuple_&& tuple) +{ + return std::get<0>(std::forward<Tuple_>(tuple)); +} + +/** + * tuple_cdr() behaves like LISP cdr: it returns a new tuple containing + * everything BUT the first item. + */ +// derived from https://stackoverflow.com/a/24046437 +template <typename Tuple, std::size_t... Indices> +auto tuple_cdr_(Tuple&& tuple, const std::index_sequence<Indices...>) +{ + // Given an index sequence from [0..N-1), extract tuple items [1..N) + return std::make_tuple(std::get<Indices+1u>(std::forward<Tuple>(tuple))...); +} + +template <typename Tuple> +auto tuple_cdr(Tuple&& tuple) +{ + return tuple_cdr_( + std::forward<Tuple>(tuple), + // Pass helper function an index sequence one item shorter than tuple + std::make_index_sequence< + std::tuple_size< + // tuple_size doesn't like reference types + typename std::remove_reference<Tuple>::type + >::value - 1u> + ()); +} + +/** + * tuple_split(), the opposite of tuple_cons(), has no direct analog in LISP. + * It returns a std::pair of tuple_car(), tuple_cdr(). We could call this + * function tuple_car_cdr(), or tuple_slice() or some such. But tuple_split() + * feels more descriptive. + */ +template <typename... Args, typename Tuple_=std::tuple<Args...>> +auto tuple_split(Tuple_&& tuple) +{ + // We're not really worried about forwarding multiple times a tuple that + // might contain move-only items, because the implementation above only + // applies std::get() exactly once to each item. + return std::make_pair(tuple_car(std::forward<Tuple_>(tuple)), + tuple_cdr(std::forward<Tuple_>(tuple))); +} + +#endif /* ! defined(LL_TUPLE_H) */ diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp new file mode 100644 index 0000000000..c74dada2e4 --- /dev/null +++ b/indra/llcommon/workqueue.cpp @@ -0,0 +1,158 @@ +/** + * @file workqueue.cpp + * @author Nat Goodspeed + * @date 2021-10-06 + * @brief Implementation for WorkQueue. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "workqueue.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llcoros.h" +#include LLCOROS_MUTEX_HEADER +#include "llerror.h" +#include "llexception.h" +#include "stringize.h" + +using Mutex = LLCoros::Mutex; +using Lock = LLCoros::LockType; + +LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity): + super(makeName(name)), + mQueue(capacity) +{ + // TODO: register for "LLApp" events so we can implicitly close() on + // viewer shutdown. +} + +void LL::WorkQueue::close() +{ + mQueue.close(); +} + +size_t LL::WorkQueue::size() +{ + return mQueue.size(); +} + +bool LL::WorkQueue::isClosed() +{ + return mQueue.isClosed(); +} + +bool LL::WorkQueue::done() +{ + return mQueue.done(); +} + +void LL::WorkQueue::runUntilClose() +{ + try + { + for (;;) + { + LL_PROFILE_ZONE_SCOPED; + callWork(mQueue.pop()); + } + } + catch (const Queue::Closed&) + { + } +} + +bool LL::WorkQueue::runPending() +{ + LL_PROFILE_ZONE_SCOPED; + for (Work work; mQueue.tryPop(work); ) + { + callWork(work); + } + return ! mQueue.done(); +} + +bool LL::WorkQueue::runOne() +{ + Work work; + if (mQueue.tryPop(work)) + { + callWork(work); + } + return ! mQueue.done(); +} + +bool LL::WorkQueue::runUntil(const TimePoint& until) +{ + LL_PROFILE_ZONE_SCOPED; + // Should we subtract some slop to allow for typical Work execution time? + // How much slop? + // runUntil() is simply a time-bounded runPending(). + for (Work work; TimePoint::clock::now() < until && mQueue.tryPop(work); ) + { + callWork(work); + } + return ! mQueue.done(); +} + +std::string LL::WorkQueue::makeName(const std::string& name) +{ + if (! name.empty()) + return name; + + static U32 discriminator = 0; + static Mutex mutex; + U32 num; + { + // Protect discriminator from concurrent access by different threads. + // It can't be thread_local, else two racing threads will come up with + // the same name. + Lock lk(mutex); + num = discriminator++; + } + return STRINGIZE("WorkQueue" << num); +} + +void LL::WorkQueue::callWork(const Queue::DataTuple& work) +{ + // ThreadSafeSchedule::pop() always delivers a tuple, even when + // there's only one data field per item, as for us. + callWork(std::get<0>(work)); +} + +void LL::WorkQueue::callWork(const Work& work) +{ + LL_PROFILE_ZONE_SCOPED; + try + { + work(); + } + catch (...) + { + // No matter what goes wrong with any individual work item, the worker + // thread must go on! Log our own instance name with the exception. + LOG_UNHANDLED_EXCEPTION(getKey()); + } +} + +void LL::WorkQueue::error(const std::string& msg) +{ + LL_ERRS("WorkQueue") << msg << LL_ENDL; +} + +void LL::WorkQueue::checkCoroutine(const std::string& method) +{ + // By convention, the default coroutine on each thread has an empty name + // string. See also LLCoros::logname(). + if (LLCoros::getName().empty()) + { + LLTHROW(Error("Do not call " + method + " from a thread's default coroutine")); + } +} diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h new file mode 100644 index 0000000000..96574a18b9 --- /dev/null +++ b/indra/llcommon/workqueue.h @@ -0,0 +1,574 @@ +/** + * @file workqueue.h + * @author Nat Goodspeed + * @date 2021-09-30 + * @brief Queue used for inter-thread work passing. + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Copyright (c) 2021, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_WORKQUEUE_H) +#define LL_WORKQUEUE_H + +#include "llcoros.h" +#include "llexception.h" +#include "llinstancetracker.h" +#include "threadsafeschedule.h" +#include <chrono> +#include <exception> // std::current_exception +#include <functional> // std::function +#include <string> + +namespace LL +{ + /** + * A typical WorkQueue has a string name that can be used to find it. + */ + class WorkQueue: public LLInstanceTracker<WorkQueue, std::string> + { + private: + using super = LLInstanceTracker<WorkQueue, std::string>; + + public: + using Work = std::function<void()>; + + private: + using Queue = ThreadSafeSchedule<Work>; + // helper for postEvery() + template <typename Rep, typename Period, typename CALLABLE> + class BackJack; + + public: + using TimePoint = Queue::TimePoint; + using TimedWork = Queue::TimeTuple; + using Closed = Queue::Closed; + + struct Error: public LLException + { + Error(const std::string& what): LLException(what) {} + }; + + /** + * You may omit the WorkQueue name, in which case a unique name is + * synthesized; for practical purposes that makes it anonymous. + */ + WorkQueue(const std::string& name = std::string(), size_t capacity=1024); + + /** + * Since the point of WorkQueue is to pass work to some other worker + * thread(s) asynchronously, it's important that the WorkQueue continue + * to exist until the worker thread(s) have drained it. To communicate + * that it's time for them to quit, close() the queue. + */ + void close(); + + /** + * WorkQueue supports multiple producers and multiple consumers. In + * the general case it's misleading to test size(), since any other + * thread might change it the nanosecond the lock is released. On that + * basis, some might argue against publishing a size() method at all. + * + * But there are two specific cases in which a test based on size() + * might be reasonable: + * + * * If you're the only producer, noticing that size() == 0 is + * meaningful. + * * If you're the only consumer, noticing that size() > 0 is + * meaningful. + */ + size_t size(); + /// producer end: are we prevented from pushing any additional items? + bool isClosed(); + /// consumer end: are we done, is the queue entirely drained? + bool done(); + + /*---------------------- fire and forget API -----------------------*/ + + /// fire-and-forget, but at a particular (future?) time + template <typename CALLABLE> + void post(const TimePoint& time, CALLABLE&& callable) + { + // Defer reifying an arbitrary CALLABLE until we hit this or + // postIfOpen(). All other methods should accept CALLABLEs of + // arbitrary type to avoid multiple levels of std::function + // indirection. + mQueue.push(TimedWork(time, std::move(callable))); + } + + /// fire-and-forget + template <typename CALLABLE> + void post(CALLABLE&& callable) + { + // We use TimePoint::clock::now() instead of TimePoint's + // representation of the epoch because this WorkQueue may contain + // a mix of past-due TimedWork items and TimedWork items scheduled + // for the future. Sift this new item into the correct place. + post(TimePoint::clock::now(), std::move(callable)); + } + + /** + * post work for a particular time, unless the queue is closed before + * we can post + */ + template <typename CALLABLE> + bool postIfOpen(const TimePoint& time, CALLABLE&& callable) + { + // Defer reifying an arbitrary CALLABLE until we hit this or + // post(). All other methods should accept CALLABLEs of arbitrary + // type to avoid multiple levels of std::function indirection. + return mQueue.pushIfOpen(TimedWork(time, std::move(callable))); + } + + /** + * post work, unless the queue is closed before we can post + */ + template <typename CALLABLE> + bool postIfOpen(CALLABLE&& callable) + { + return postIfOpen(TimePoint::clock::now(), std::move(callable)); + } + + /** + * Post work to be run at a specified time to another WorkQueue, which + * may or may not still exist and be open. Return true if we were able + * to post. + */ + template <typename CALLABLE> + static bool postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable); + + /** + * Post work to another WorkQueue, which may or may not still exist + * and be open. Return true if we were able to post. + */ + template <typename CALLABLE> + static bool postMaybe(weak_t target, CALLABLE&& callable) + { + return postMaybe(target, TimePoint::clock::now(), + std::forward<CALLABLE>(callable)); + } + + /** + * Launch a callable returning bool that will trigger repeatedly at + * specified interval, until the callable returns false. + * + * If you need to signal that callable from outside, DO NOT bind a + * reference to a simple bool! That's not thread-safe. Instead, bind + * an LLCond variant, e.g. LLOneShotCond or LLBoolCond. + */ + template <typename Rep, typename Period, typename CALLABLE> + void postEvery(const std::chrono::duration<Rep, Period>& interval, + CALLABLE&& callable); + + template <typename CALLABLE> + bool tryPost(CALLABLE&& callable) + { + return mQueue.tryPush(TimedWork(TimePoint::clock::now(), std::move(callable))); + } + + /*------------------------- handshake API --------------------------*/ + + /** + * Post work to another WorkQueue to be run at a specified time, + * requesting a specific callback to be run on this WorkQueue on + * completion. + * + * Returns true if able to post, false if the other WorkQueue is + * inaccessible. + */ + // Apparently some Microsoft header file defines a macro CALLBACK? The + // natural template argument name CALLBACK produces very weird Visual + // Studio compile errors that seem utterly unrelated to this source + // code. + template <typename CALLABLE, typename FOLLOWUP> + bool postTo(weak_t target, + const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback); + + /** + * Post work to another WorkQueue, requesting a specific callback to + * be run on this WorkQueue on completion. + * + * Returns true if able to post, false if the other WorkQueue is + * inaccessible. + */ + template <typename CALLABLE, typename FOLLOWUP> + bool postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback) + { + return postTo(target, TimePoint::clock::now(), + std::move(callable), std::move(callback)); + } + + /** + * Post work to another WorkQueue to be run at a specified time, + * blocking the calling coroutine until then, returning the result to + * caller on completion. + * + * In general, we assume that each thread's default coroutine is busy + * servicing its WorkQueue or whatever. To try to prevent mistakes, we + * forbid calling waitForResult() from a thread's default coroutine. + */ + template <typename CALLABLE> + auto waitForResult(const TimePoint& time, CALLABLE&& callable); + + /** + * Post work to another WorkQueue, blocking the calling coroutine + * until then, returning the result to caller on completion. + * + * In general, we assume that each thread's default coroutine is busy + * servicing its WorkQueue or whatever. To try to prevent mistakes, we + * forbid calling waitForResult() from a thread's default coroutine. + */ + template <typename CALLABLE> + auto waitForResult(CALLABLE&& callable) + { + return waitForResult(TimePoint::clock::now(), std::move(callable)); + } + + /*--------------------------- worker API ---------------------------*/ + + /** + * runUntilClose() pulls TimedWork items off this WorkQueue until the + * queue is closed, at which point it returns. This would be the + * typical entry point for a simple worker thread. + */ + void runUntilClose(); + + /** + * runPending() runs all TimedWork items that are ready to run. It + * returns true if the queue remains open, false if the queue has been + * closed. This could be used by a thread whose primary purpose is to + * serve the queue, but also wants to do other things with its idle time. + */ + bool runPending(); + + /** + * runOne() runs at most one ready TimedWork item -- zero if none are + * ready. It returns true if the queue remains open, false if the + * queue has been closed. + */ + bool runOne(); + + /** + * runFor() runs a subset of ready TimedWork items, until the + * timeslice has been exceeded. It returns true if the queue remains + * open, false if the queue has been closed. This could be used by a + * busy main thread to lend a bounded few CPU cycles to this WorkQueue + * without risking the WorkQueue blowing out the length of any one + * frame. + */ + template <typename Rep, typename Period> + bool runFor(const std::chrono::duration<Rep, Period>& timeslice) + { + LL_PROFILE_ZONE_SCOPED; + return runUntil(TimePoint::clock::now() + timeslice); + } + + /** + * runUntil() is just like runFor(), only with a specific end time + * instead of a timeslice duration. + */ + bool runUntil(const TimePoint& until); + + private: + template <typename CALLABLE, typename FOLLOWUP> + static auto makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback); + /// general case: arbitrary C++ return type + template <typename CALLABLE, typename FOLLOWUP, typename RETURNTYPE> + struct MakeReplyLambda; + /// specialize for CALLABLE returning void + template <typename CALLABLE, typename FOLLOWUP> + struct MakeReplyLambda<CALLABLE, FOLLOWUP, void>; + + /// general case: arbitrary C++ return type + template <typename CALLABLE, typename RETURNTYPE> + struct WaitForResult; + /// specialize for CALLABLE returning void + template <typename CALLABLE> + struct WaitForResult<CALLABLE, void>; + + static void checkCoroutine(const std::string& method); + static void error(const std::string& msg); + static std::string makeName(const std::string& name); + void callWork(const Queue::DataTuple& work); + void callWork(const Work& work); + Queue mQueue; + }; + + /** + * BackJack is, in effect, a hand-rolled lambda, binding a WorkQueue, a + * CALLABLE that returns bool, a TimePoint and an interval at which to + * relaunch it. As long as the callable continues returning true, BackJack + * keeps resubmitting it to the target WorkQueue. + */ + // Why is BackJack a class and not a lambda? Because, unlike a lambda, a + // class method gets its own 'this' pointer -- which we need to resubmit + // the whole BackJack callable. + template <typename Rep, typename Period, typename CALLABLE> + class WorkQueue::BackJack + { + public: + // bind the desired data + BackJack(weak_t target, + const TimePoint& start, + const std::chrono::duration<Rep, Period>& interval, + CALLABLE&& callable): + mTarget(target), + mStart(start), + mInterval(interval), + mCallable(std::move(callable)) + {} + + // Call by target WorkQueue -- note that although WE require a + // callable returning bool, WorkQueue wants a void callable. We + // consume the bool. + void operator()() + { + // If mCallable() throws an exception, don't catch it here: if it + // throws once, it's likely to throw every time, so it's a waste + // of time to arrange to call it again. + if (mCallable()) + { + // Modify mStart to the new start time we desire. If we simply + // added mInterval to now, we'd get actual timings of + // (mInterval + slop), where 'slop' is the latency between the + // previous mStart and the WorkQueue actually calling us. + // Instead, add mInterval to mStart so that at least we + // register our intent to fire at exact mIntervals. + mStart += mInterval; + + // We're being called at this moment by the target WorkQueue. + // Assume it still exists, rather than checking the result of + // lock(). + // Resubmit the whole *this callable: that's why we're a class + // rather than a lambda. Allow moving *this so we can carry a + // move-only callable; but naturally this statement must be + // the last time we reference this instance, which may become + // moved-from. + try + { + mTarget.lock()->post(mStart, std::move(*this)); + } + catch (const Closed&) + { + // Once this queue is closed, oh well, just stop + } + } + } + + private: + weak_t mTarget; + TimePoint mStart; + std::chrono::duration<Rep, Period> mInterval; + CALLABLE mCallable; + }; + + template <typename Rep, typename Period, typename CALLABLE> + void WorkQueue::postEvery(const std::chrono::duration<Rep, Period>& interval, + CALLABLE&& callable) + { + if (interval.count() <= 0) + { + // It's essential that postEvery() be called with a positive + // interval, since each call to BackJack posts another instance of + // itself at (start + interval) and we order by target time. A + // zero or negative interval would result in that BackJack + // instance going to the head of the queue every time, immediately + // ready to run. Effectively that would produce an infinite loop, + // a denial of service on this WorkQueue. + error("postEvery(interval) may not be 0"); + } + // Instantiate and post a suitable BackJack, binding a weak_ptr to + // self, the current time, the desired interval and the desired + // callable. + post( + BackJack<Rep, Period, CALLABLE>( + getWeak(), TimePoint::clock::now(), interval, std::move(callable))); + } + + /// general case: arbitrary C++ return type + template <typename CALLABLE, typename FOLLOWUP, typename RETURNTYPE> + struct WorkQueue::MakeReplyLambda + { + auto operator()(CALLABLE&& callable, FOLLOWUP&& callback) + { + // Call the callable in any case -- but to minimize + // copying the result, immediately bind it into the reply + // lambda. The reply lambda also binds the original + // callback, so that when we, the originating WorkQueue, + // finally receive and process the reply lambda, we'll + // call the bound callback with the bound result -- on the + // same thread that originally called postTo(). + return + [result = std::forward<CALLABLE>(callable)(), + callback = std::move(callback)] + () + { callback(std::move(result)); }; + } + }; + + /// specialize for CALLABLE returning void + template <typename CALLABLE, typename FOLLOWUP> + struct WorkQueue::MakeReplyLambda<CALLABLE, FOLLOWUP, void> + { + auto operator()(CALLABLE&& callable, FOLLOWUP&& callback) + { + // Call the callable, which produces no result. + std::forward<CALLABLE>(callable)(); + // Our completion callback is simply the caller's callback. + return std::move(callback); + } + }; + + template <typename CALLABLE, typename FOLLOWUP> + auto WorkQueue::makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback) + { + return MakeReplyLambda<CALLABLE, FOLLOWUP, + decltype(std::forward<CALLABLE>(callable)())>() + (std::move(callable), std::move(callback)); + } + + template <typename CALLABLE, typename FOLLOWUP> + bool WorkQueue::postTo(weak_t target, + const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback) + { + LL_PROFILE_ZONE_SCOPED; + // We're being asked to post to the WorkQueue at target. + // target is a weak_ptr: have to lock it to check it. + auto tptr = target.lock(); + if (! tptr) + // can't post() if the target WorkQueue has been destroyed + return false; + + // Here we believe target WorkQueue still exists. Post to it a + // lambda that packages our callable, our callback and a weak_ptr + // to this originating WorkQueue. + tptr->post( + time, + [reply = super::getWeak(), + callable = std::move(callable), + callback = std::move(callback)] + () + { + // Use postMaybe() below in case this originating WorkQueue + // has been closed or destroyed. Remember, the outer lambda is + // now running on a thread servicing the target WorkQueue, and + // real time has elapsed since postTo()'s tptr->post() call. + try + { + // Make a reply lambda to repost to THIS WorkQueue. + // Delegate to makeReplyLambda() so we can partially + // specialize on void return. + postMaybe(reply, makeReplyLambda(std::move(callable), std::move(callback))); + } + catch (...) + { + // Either variant of makeReplyLambda() is responsible for + // calling the caller's callable. If that throws, return + // the exception to the originating thread. + postMaybe( + reply, + // Bind the current exception to transport back to the + // originating WorkQueue. Once there, rethrow it. + [exc = std::current_exception()](){ std::rethrow_exception(exc); }); + } + }); + + // looks like we were able to post() + return true; + } + + template <typename CALLABLE> + bool WorkQueue::postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable) + { + LL_PROFILE_ZONE_SCOPED; + // target is a weak_ptr: have to lock it to check it + auto tptr = target.lock(); + if (tptr) + { + try + { + tptr->post(time, std::forward<CALLABLE>(callable)); + // we were able to post() + return true; + } + catch (const Closed&) + { + // target WorkQueue still exists, but is Closed + } + } + // either target no longer exists, or its WorkQueue is Closed + return false; + } + + /// general case: arbitrary C++ return type + template <typename CALLABLE, typename RETURNTYPE> + struct WorkQueue::WaitForResult + { + auto operator()(WorkQueue* self, const TimePoint& time, CALLABLE&& callable) + { + LLCoros::Promise<RETURNTYPE> promise; + self->post( + time, + // We dare to bind a reference to Promise because it's + // specifically designed for cross-thread communication. + [&promise, callable = std::move(callable)]() + { + try + { + // call the caller's callable and trigger promise with result + promise.set_value(callable()); + } + catch (...) + { + promise.set_exception(std::current_exception()); + } + }); + auto future{ LLCoros::getFuture(promise) }; + // now, on the calling thread, wait for that result + LLCoros::TempStatus st("waiting for WorkQueue::waitForResult()"); + return future.get(); + } + }; + + /// specialize for CALLABLE returning void + template <typename CALLABLE> + struct WorkQueue::WaitForResult<CALLABLE, void> + { + void operator()(WorkQueue* self, const TimePoint& time, CALLABLE&& callable) + { + LLCoros::Promise<void> promise; + self->post( + time, + // &promise is designed for cross-thread access + [&promise, callable = std::move(callable)]() + { + try + { + callable(); + promise.set_value(); + } + catch (...) + { + promise.set_exception(std::current_exception()); + } + }); + auto future{ LLCoros::getFuture(promise) }; + // block until set_value() + LLCoros::TempStatus st("waiting for void WorkQueue::waitForResult()"); + future.get(); + } + }; + + template <typename CALLABLE> + auto WorkQueue::waitForResult(const TimePoint& time, CALLABLE&& callable) + { + checkCoroutine("waitForResult()"); + // derive callable's return type so we can specialize for void + return WaitForResult<CALLABLE, decltype(std::forward<CALLABLE>(callable)())>() + (this, time, std::forward<CALLABLE>(callable)); + } + +} // namespace LL + +#endif /* ! defined(LL_WORKQUEUE_H) */ diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 8922f46ffe..15b07e5318 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -623,8 +623,7 @@ void LLImage::setLastError(const std::string& message) //--------------------------------------------------------------------------- LLImageBase::LLImageBase() -: LLTrace::MemTrackable<LLImageBase>("LLImage"), - mData(NULL), +: mData(NULL), mDataSize(0), mWidth(0), mHeight(0), @@ -673,7 +672,6 @@ void LLImageBase::sanityCheck() void LLImageBase::deleteData() { ll_aligned_free_16(mData); - disclaimMem(mDataSize); mDataSize = 0; mData = NULL; } @@ -731,7 +729,6 @@ U8* LLImageBase::allocateData(S32 size) } } mDataSize = size; - claimMem(mDataSize); return mData; } @@ -752,9 +749,7 @@ U8* LLImageBase::reallocateData(S32 size) ll_aligned_free_16(mData) ; } mData = new_datap; - disclaimMem(mDataSize); mDataSize = size; - claimMem(mDataSize); mBadBufferAllocation = false; return mData; } @@ -2254,9 +2249,7 @@ void LLImageBase::setDataAndSize(U8 *data, S32 size) { ll_assert_aligned(data, 16); mData = data; - disclaimMem(mDataSize); mDataSize = size; - claimMem(mDataSize); } //static diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index f66b1666d7..354926ee58 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -112,8 +112,7 @@ protected: // Image base class class LLImageBase -: public LLThreadSafeRefCount, - public LLTrace::MemTrackable<LLImageBase> +: public LLThreadSafeRefCount { protected: virtual ~LLImageBase(); diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 4bff21610f..e1809dbe59 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -60,7 +60,6 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), mAreaUsedForDataSizeCalcs(0) { mImpl.reset(fallbackCreateLLImageJ2CImpl()); - claimMem(mImpl); // Clear data size table for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++) diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp index 62638fa16c..32a5472ec8 100644 --- a/indra/llimage/llimagejpeg.cpp +++ b/indra/llimage/llimagejpeg.cpp @@ -393,9 +393,7 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo ) cinfo->dest->next_output_byte = self->mOutputBuffer + self->mOutputBufferSize; cinfo->dest->free_in_buffer = self->mOutputBufferSize; - self->disclaimMem(self->mOutputBufferSize); self->mOutputBufferSize = new_buffer_size; - self->claimMem(new_buffer_size); return true; } @@ -501,13 +499,10 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time ) // Allocate a temporary buffer big enough to hold the entire compressed image (and then some) // (Note: we make it bigger in emptyOutputBuffer() if we need to) delete[] mOutputBuffer; - disclaimMem(mOutputBufferSize); mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024; - claimMem(mOutputBufferSize); mOutputBuffer = new(std::nothrow) U8[ mOutputBufferSize ]; if (mOutputBuffer == NULL) { - disclaimMem(mOutputBufferSize); mOutputBufferSize = 0; setLastError("Failed to allocate output buffer"); return false; @@ -547,7 +542,6 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time ) jpeg_destroy_compress(&cinfo); delete[] mOutputBuffer; mOutputBuffer = NULL; - disclaimMem(mOutputBufferSize); mOutputBufferSize = 0; return false; } @@ -650,7 +644,6 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time ) // After finish_compress, we can release the temp output buffer. delete[] mOutputBuffer; mOutputBuffer = NULL; - disclaimMem(mOutputBufferSize); mOutputBufferSize = 0; //////////////////////////////////////// @@ -663,7 +656,6 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time ) jpeg_destroy_compress(&cinfo); delete[] mOutputBuffer; mOutputBuffer = NULL; - disclaimMem(mOutputBufferSize); mOutputBufferSize = 0; return false; } diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 5f42fba866..33f8dce6ee 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -48,6 +48,7 @@ LLImageDecodeThread::~LLImageDecodeThread() // virtual S32 LLImageDecodeThread::update(F32 max_time_ms) { + LL_PROFILE_ZONE_SCOPED; LLMutexLock lock(mCreationMutex); for (creation_list_t::iterator iter = mCreationList.begin(); iter != mCreationList.end(); ++iter) @@ -71,6 +72,7 @@ S32 LLImageDecodeThread::update(F32 max_time_ms) LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image, U32 priority, S32 discard, BOOL needs_aux, Responder* responder) { + LL_PROFILE_ZONE_SCOPED; LLMutexLock lock(mCreationMutex); handle_t handle = generateHandle(); mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); @@ -118,6 +120,7 @@ LLImageDecodeThread::ImageRequest::~ImageRequest() // Returns true when done, whether or not decode was successful. bool LLImageDecodeThread::ImageRequest::processRequest() { + LL_PROFILE_ZONE_SCOPED; const F32 decode_time_slice = .1f; bool done = true; if (!mDecodedRaw && mFormattedImage.notNull()) @@ -164,6 +167,7 @@ bool LLImageDecodeThread::ImageRequest::processRequest() void LLImageDecodeThread::ImageRequest::finishRequest(bool completed) { + LL_PROFILE_ZONE_SCOPED; if (mResponder.notNull()) { bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 51c5c63556..9011ac615c 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -45,8 +45,7 @@ // * A simulator for a class can be implemented here. Please comment and document thoroughly. LLImageBase::LLImageBase() -: LLTrace::MemTrackable<LLImageBase>("LLImageBase"), -mData(NULL), +: mData(NULL), mDataSize(0), mWidth(0), mHeight(0), diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 18bc1b5a91..81261f0767 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -74,20 +74,17 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid, const LLUUID& parent_uuid, LLAssetType::EType type, const std::string& name) -: LLTrace::MemTrackable<LLInventoryObject>("LLInventoryObject"), - mUUID(uuid), +: mUUID(uuid), mParentUUID(parent_uuid), mType(type), mName(name), mCreationDate(0) { - claimMem(mName); correctInventoryName(mName); } LLInventoryObject::LLInventoryObject() -: LLTrace::MemTrackable<LLInventoryObject>("LLInventoryObject"), - mType(LLAssetType::AT_NONE), +: mType(LLAssetType::AT_NONE), mCreationDate(0) { } @@ -101,9 +98,7 @@ void LLInventoryObject::copyObject(const LLInventoryObject* other) mUUID = other->mUUID; mParentUUID = other->mParentUUID; mType = other->mType; - disclaimMem(mName); mName = other->mName; - claimMem(mName); } const LLUUID& LLInventoryObject::getUUID() const @@ -156,9 +151,7 @@ void LLInventoryObject::rename(const std::string& n) correctInventoryName(new_name); if( !new_name.empty() && new_name != mName ) { - disclaimMem(mName); mName = new_name; - claimMem(mName); } } @@ -311,7 +304,6 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid, LLStringUtil::replaceNonstandardASCII(mDescription, ' '); LLStringUtil::replaceChar(mDescription, '|', ' '); - claimMem(mDescription); mPermissions.initMasks(inv_type); } @@ -344,9 +336,7 @@ void LLInventoryItem::copyItem(const LLInventoryItem* other) copyObject(other); mPermissions = other->mPermissions; mAssetUUID = other->mAssetUUID; - disclaimMem(mDescription); mDescription = other->mDescription; - claimMem(mDescription); mSaleInfo = other->mSaleInfo; mInventoryType = other->mInventoryType; mFlags = other->mFlags; @@ -426,9 +416,7 @@ void LLInventoryItem::setDescription(const std::string& d) LLInventoryItem::correctInventoryDescription(new_desc); if( new_desc != mDescription ) { - disclaimMem(mDescription); mDescription = new_desc; - claimMem(mDescription); } } @@ -708,10 +696,8 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) valuestr[0] = '\000'; } - disclaimMem(mDescription); mDescription.assign(valuestr); LLStringUtil::replaceNonstandardASCII(mDescription, ' '); - claimMem(mDescription); /* TODO -- ask Ian about this code const char *donkey = mDescription.c_str(); if (donkey[0] == '|') @@ -840,11 +826,9 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate; } -LLTrace::BlockTimerStatHandle FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize"); - bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) { - LL_RECORD_BLOCK_TIME(FTM_INVENTORY_SD_DESERIALIZE); + LL_PROFILE_ZONE_SCOPED; if (is_new) { // If we're adding LLSD to an existing object, need avoid @@ -961,10 +945,8 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) w = INV_DESC_LABEL; if (sd.has(w)) { - disclaimMem(mDescription); mDescription = sd[w].asString(); LLStringUtil::replaceNonstandardASCII(mDescription, ' '); - claimMem(mDescription); } w = INV_CREATION_DATE_LABEL; if (sd.has(w)) diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 0f336a072f..7d9f9704f1 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -44,7 +44,7 @@ class LLMessageSystem; // Base class for anything in the user's inventory. Handles the common code // between items and categories. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryObject : public LLRefCount, public LLTrace::MemTrackable<LLInventoryObject> +class LLInventoryObject : public LLRefCount { public: typedef std::list<LLPointer<LLInventoryObject> > object_list_t; diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp index 8a8e2bb340..aed972b150 100644 --- a/indra/llinventory/llsettingsbase.cpp +++ b/indra/llinventory/llsettingsbase.cpp @@ -683,6 +683,7 @@ bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, U32, S32 length) //========================================================================= void LLSettingsBlender::update(const LLSettingsBase::BlendFactor& blendf) { + LL_PROFILE_ZONE_SCOPED; F64 res = setBlendFactor(blendf); llassert(res >= 0.0 && res <= 1.0); (void)res; @@ -713,6 +714,7 @@ F64 LLSettingsBlender::setBlendFactor(const LLSettingsBase::BlendFactor& blendf_ void LLSettingsBlender::triggerComplete() { + LL_PROFILE_ZONE_SCOPED; if (mTarget) mTarget->replaceSettings(mFinal->getSettings()); LLSettingsBlender::ptr_t hold = shared_from_this(); // prevents this from deleting too soon @@ -725,11 +727,13 @@ const LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::MIN_BLEND_DELTA(FL LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const { + LL_PROFILE_ZONE_SCOPED; return LLSettingsBase::BlendFactor(fmod((F64)spanpos, (F64)spanlen) / (F64)spanlen); } bool LLSettingsBlenderTimeDelta::applyTimeDelta(const LLSettingsBase::Seconds& timedelta) { + LL_PROFILE_ZONE_SCOPED; mTimeSpent += timedelta; if (mTimeSpent > mBlendSpan) diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp index 2bb03e8391..241826604f 100644 --- a/indra/llinventory/llsettingsdaycycle.cpp +++ b/indra/llinventory/llsettingsdaycycle.cpp @@ -41,9 +41,6 @@ //========================================================================= namespace { - LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment Day"); - LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment Day"); - template<typename T> inline T get_wrapping_distance(T begin, T end) { diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 1470edbf38..979a284744 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -66,11 +66,6 @@ namespace { } } -static LLTrace::BlockTimerStatHandle FTM_BLEND_SKYVALUES("Blending Sky Environment"); -static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_SKYVALUES("Recalculate Sky"); -static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_BODIES("Recalculate Heavenly Bodies"); -static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_LIGHTING("Recalculate Lighting"); - //========================================================================= const std::string LLSettingsSky::SETTING_AMBIENT("ambient"); const std::string LLSettingsSky::SETTING_BLUE_DENSITY("blue_density"); @@ -444,6 +439,7 @@ void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) { + LL_PROFILE_ZONE_SCOPED; llassert(getSettingsType() == end->getSettingsType()); LLSettingsSky::ptr_t other = PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsSky>(end); @@ -939,7 +935,7 @@ LLSD LLSettingsSky::translateLegacySettings(const LLSD& legacy) void LLSettingsSky::updateSettings() { - LL_RECORD_BLOCK_TIME(FTM_RECALCULATE_SKYVALUES); + LL_PROFILE_ZONE_SCOPED; // base class clears dirty flag so as to not trigger recursive update LLSettingsBase::updateSettings(); @@ -1022,6 +1018,7 @@ LLColor3 LLSettingsSky::getLightDiffuse() const LLColor3 LLSettingsSky::getColor(const std::string& key, const LLColor3& default_value) const { + LL_PROFILE_ZONE_SCOPED; if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(key)) { return LLColor3(mSettings[SETTING_LEGACY_HAZE][key]); @@ -1035,6 +1032,7 @@ LLColor3 LLSettingsSky::getColor(const std::string& key, const LLColor3& default F32 LLSettingsSky::getFloat(const std::string& key, F32 default_value) const { + LL_PROFILE_ZONE_SCOPED; if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(key)) { return mSettings[SETTING_LEGACY_HAZE][key].asReal(); @@ -1206,11 +1204,19 @@ LLColor3 LLSettingsSky::getLightTransmittance(F32 distance) const return transmittance; } +// SL-16127: getTotalDensity() and getDensityMultiplier() call LLSettingsSky::getColor() and LLSettingsSky::getFloat() respectively which are S-L-O-W +LLColor3 LLSettingsSky::getLightTransmittanceFast( const LLColor3& total_density, const F32 density_multiplier, const F32 distance ) const +{ + // Transparency (-> density) from Beer's law + LLColor3 transmittance = componentExp(total_density * -(density_multiplier * distance)); + return transmittance; +} + // performs soft scale clip and gamma correction ala the shader implementation // scales colors down to 0 - 1 range preserving relative ratios -LLColor3 LLSettingsSky::gammaCorrect(const LLColor3& in) const +LLColor3 LLSettingsSky::gammaCorrect(const LLColor3& in,const F32 &gamma) const { - F32 gamma = getGamma(); + //F32 gamma = getGamma(); // SL-16127: Use cached gamma from atmospheric vars LLColor3 v(in); // scale down to 0 to 1 range preserving relative ratio (aka homegenize) diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h index 4127911643..fa9326f006 100644 --- a/indra/llinventory/llsettingssky.h +++ b/indra/llinventory/llsettingssky.h @@ -252,8 +252,9 @@ public: LLColor3 getLightAttenuation(F32 distance) const; LLColor3 getLightTransmittance(F32 distance) const; + LLColor3 getLightTransmittanceFast(const LLColor3& total_density, const F32 density_multiplier, const F32 distance) const; LLColor3 getTotalDensity() const; - LLColor3 gammaCorrect(const LLColor3& in) const; + LLColor3 gammaCorrect(const LLColor3& in,const F32 &gamma) const; LLColor3 getBlueDensity() const; LLColor3 getBlueHorizon() const; diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp index 1ae8d78b22..90f99e8198 100644 --- a/indra/llinventory/llsettingswater.cpp +++ b/indra/llinventory/llsettingswater.cpp @@ -33,14 +33,6 @@ #include "v3colorutil.h" #include "indra_constants.h" -//========================================================================= -namespace -{ - LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment"); - LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment"); -} - -//========================================================================= const std::string LLSettingsWater::SETTING_BLUR_MULTIPLIER("blur_multiplier"); const std::string LLSettingsWater::SETTING_FOG_COLOR("water_fog_color"); const std::string LLSettingsWater::SETTING_FOG_DENSITY("water_fog_density"); diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp index ee7b14be85..16213b7f45 100644 --- a/indra/llkdu/tests/llimagej2ckdu_test.cpp +++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp @@ -63,8 +63,7 @@ U8* LLImageRaw::reallocateData(S32 ) { return NULL; } bool LLImageRaw::resize(U16, U16, S8) { return true; } // this method always returns true... LLImageBase::LLImageBase() -: LLTrace::MemTrackable<LLImageBase>("LLImageBase"), -mData(NULL), +: mData(NULL), mDataSize(0), mWidth(0), mHeight(0), diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 7ba347062f..2cf50e9cd2 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -36,6 +36,26 @@ class LLMatrix4a public: LL_ALIGN_16(LLVector4a mMatrix[4]); + LLMatrix4a() + { + + } + + explicit LLMatrix4a(const LLMatrix4& val) + { + loadu(val); + } + + inline F32* getF32ptr() + { + return (F32*) &mMatrix; + } + + inline const F32* getF32ptr() const + { + return (F32*)&mMatrix; + } + inline void clear() { mMatrix[0].clear(); @@ -44,14 +64,29 @@ public: mMatrix[3].clear(); } + inline void setIdentity() + { + mMatrix[0].set(1.f, 0.f, 0.f, 0.f); + mMatrix[1].set(0.f, 1.f, 0.f, 0.f); + mMatrix[2].set(0.f, 0.f, 1.f, 0.f); + mMatrix[3].set(0.f, 0.f, 0.f, 1.f); + } + inline void loadu(const LLMatrix4& src) { mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]); mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]); mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]); mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]); - } + + inline void loadu(const F32* src) + { + mMatrix[0] = _mm_loadu_ps(src); + mMatrix[1] = _mm_loadu_ps(src+4); + mMatrix[2] = _mm_loadu_ps(src+8); + mMatrix[3] = _mm_loadu_ps(src+12); + } inline void loadu(const LLMatrix3& src) { @@ -105,7 +140,7 @@ public: mMatrix[3].setAdd(a.mMatrix[3],d3); } - inline void rotate(const LLVector4a& v, LLVector4a& res) + inline void rotate(const LLVector4a& v, LLVector4a& res) const { LLVector4a y,z; @@ -151,6 +186,8 @@ public: { affineTransformSSE(v,res); } + + const LLVector4a& getTranslation() const { return mMatrix[3]; } }; inline LLVector4a rowMul(const LLVector4a &row, const LLMatrix4a &mat) @@ -176,6 +213,15 @@ inline void matMul(const LLMatrix4a &a, const LLMatrix4a &b, LLMatrix4a &res) res.mMatrix[3] = row3; } +//Faster version of matMul wehere res must not be a or b +inline void matMulUnsafe(const LLMatrix4a &a, const LLMatrix4a &b, LLMatrix4a &res) +{ + res.mMatrix[0] = rowMul(a.mMatrix[0], b); + res.mMatrix[1] = rowMul(a.mMatrix[1], b); + res.mMatrix[2] = rowMul(a.mMatrix[2], b); + res.mMatrix[3] = rowMul(a.mMatrix[3], b); +} + inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m) { s << "[" << m.mMatrix[0] << ", " << m.mMatrix[1] << ", " << m.mMatrix[2] << ", " << m.mMatrix[3] << "]"; diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index 0e2f62f9db..8c4a1304b4 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -74,8 +74,9 @@ public: }; template <class T> -class LLOctreeNode : public LLTreeNode<T> +class alignas(16) LLOctreeNode : public LLTreeNode<T> { + LL_ALIGN_NEW public: typedef LLOctreeTraveler<T> oct_traveler; @@ -91,16 +92,6 @@ public: typedef LLOctreeNode<T> oct_node; typedef LLOctreeListener<T> oct_listener; - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - LLOctreeNode( const LLVector4a& center, const LLVector4a& size, BaseType* parent, diff --git a/indra/llmath/llrigginginfo.h b/indra/llmath/llrigginginfo.h index b3d6bc2d19..059c6ae082 100644 --- a/indra/llmath/llrigginginfo.h +++ b/indra/llmath/llrigginginfo.h @@ -34,9 +34,9 @@ // Extents are in joint space // isRiggedTo is based on the state of all currently associated rigged meshes -LL_ALIGN_PREFIX(16) -class LLJointRiggingInfo +class alignas(16) LLJointRiggingInfo { + LL_ALIGN_NEW public: LLJointRiggingInfo(); bool isRiggedTo() const; @@ -45,31 +45,10 @@ public: const LLVector4a *getRiggedExtents() const; void merge(const LLJointRiggingInfo& other); - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - - void* operator new[](size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete[](void* ptr) - { - ll_aligned_free_16(ptr); - } - - private: - LL_ALIGN_16(LLVector4a mRiggedExtents[2]); + LLVector4a mRiggedExtents[2]; bool mIsRiggedTo; -} LL_ALIGN_POSTFIX(16); +}; // For storing all the rigging info associated with a given avatar or // object, keyed by joint_num. diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 27abf39537..53c8f604f6 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -46,11 +46,10 @@ class LLRotation; // of this writing, July 08, 2010) about getting it implemented before you resort to // LLVector3/LLVector4. ///////////////////////////////// -struct LLVector4a; -LL_ALIGN_PREFIX(16) -struct LLVector4a +class alignas(16) LLVector4a { + LL_ALIGN_NEW public: /////////////////////////////////// @@ -138,10 +137,10 @@ public: // BASIC GET/SET //////////////////////////////////// - // Return a "this" as an F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) + // Return a "this" as an F32 pointer. inline F32* getF32ptr(); - // Return a "this" as a const F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) + // Return a "this" as a const F32 pointer. inline const F32* const getF32ptr() const; // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates @@ -324,7 +323,7 @@ public: private: LLQuad mQ; -} LL_ALIGN_POSTFIX(16); +}; inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) { diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 69d3d01efe..8be1c1b114 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -58,13 +58,13 @@ inline void LLVector4a::store4a(F32* dst) const // BASIC GET/SET //////////////////////////////////// -// Return a "this" as an F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) +// Return a "this" as an F32 pointer. F32* LLVector4a::getF32ptr() { return (F32*) &mQ; } -// Return a "this" as a const F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) +// Return a "this" as a const F32 pointer. const F32* const LLVector4a::getF32ptr() const { return (const F32* const) &mQ; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b036ece71e..c226315e5c 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -383,6 +383,7 @@ public: virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch) { //this is a depth first traversal, so it's safe to assum all children have complete //bounding data + LL_PROFILE_ZONE_SCOPED LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); @@ -822,6 +823,8 @@ S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 de BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, BOOL is_sculpted, S32 sculpt_size) { + LL_PROFILE_ZONE_SCOPED + if ((!mDirty) && (!is_sculpted)) { return FALSE; @@ -1302,6 +1305,8 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { + LL_PROFILE_ZONE_SCOPED + // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; @@ -1536,6 +1541,8 @@ S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail) BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted, S32 sculpt_size) { + LL_PROFILE_ZONE_SCOPED + if ((!mDirty) && (!is_sculpted)) { return FALSE; @@ -2112,6 +2119,8 @@ LLVolume::~LLVolume() BOOL LLVolume::generate() { + LL_PROFILE_ZONE_SCOPED + LL_CHECK_MEMORY llassert_always(mProfilep); @@ -2370,6 +2379,8 @@ bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { + LL_PROFILE_ZONE_SCOPED + //input stream is now pointing at a zlib compressed block of LLSD //decompress block LLSD mdl; @@ -2755,6 +2766,8 @@ S32 LLVolume::getNumFaces() const void LLVolume::createVolumeFaces() { + LL_PROFILE_ZONE_SCOPED + if (mGenerateSingleFace) { // do nothing @@ -3720,6 +3733,8 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, const LLMatrix3& norm_mat_in, S32 face_mask) { + LL_PROFILE_ZONE_SCOPED + LLMatrix4a mat; mat.loadu(mat_in); @@ -4846,6 +4861,8 @@ void LLVolumeFace::freeData() BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) { + LL_PROFILE_ZONE_SCOPED + //tree for this face is no longer valid delete mOctree; mOctree = NULL; @@ -5514,6 +5531,8 @@ bool LLVolumeFace::cacheOptimize() void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size) { + LL_PROFILE_ZONE_SCOPED + if (mOctree) { return; @@ -6287,6 +6306,8 @@ void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVe void LLVolumeFace::createTangents() { + LL_PROFILE_ZONE_SCOPED + if (!mTangents) { allocateTangents(mNumVertices); @@ -6482,6 +6503,8 @@ void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { + LL_PROFILE_ZONE_SCOPED + LL_CHECK_MEMORY BOOL flat = mTypeMask & FLAT_MASK; @@ -6974,6 +6997,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) { + LL_PROFILE_ZONE_SCOPED + //LLVector4a *tan1 = new LLVector4a[vertexCount * 2]; LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a)); // new(tan1) LLVector4a; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 13150028d8..b2bc440368 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -34,19 +34,10 @@ #include "llvolume.h" #include "llvector4a.h" -class LLVolumeTriangle : public LLRefCount +class alignas(16) LLVolumeTriangle : public LLRefCount { + LL_ALIGN_NEW public: - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - LLVolumeTriangle() { mBinIndex = -1; @@ -86,20 +77,10 @@ public: }; -class LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle> +class alignas(16) LLVolumeOctreeListener : public LLOctreeListener<LLVolumeTriangle> { + LL_ALIGN_NEW public: - - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node); ~LLVolumeOctreeListener(); diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 3baf1bad18..6e40dae30b 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -32,8 +32,7 @@ #include "m4math.h" #include "m3math.h" #include "llquaternion.h" - - +#include "llmatrix4a.h" // LLMatrix4 @@ -115,6 +114,12 @@ LLMatrix4::LLMatrix4(const LLQuaternion &q) *this = initRotation(q); } +LLMatrix4::LLMatrix4(const LLMatrix4a& mat) + : LLMatrix4(mat.getF32ptr()) +{ + +} + LLMatrix4::LLMatrix4(const LLQuaternion &q, const LLVector4 &pos) { *this = initRotTrans(q, pos); diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index bf60adb9b6..b9da970cde 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -32,6 +32,7 @@ class LLVector4; class LLMatrix3; class LLQuaternion; +class LLMatrix4a; // NOTA BENE: Currently assuming a right-handed, x-forward, y-left, z-up universe @@ -104,6 +105,7 @@ public: explicit LLMatrix4(const F32 *mat); // Initializes Matrix to values in mat explicit LLMatrix4(const LLMatrix3 &mat); // Initializes Matrix to values in mat and sets position to (0,0,0) explicit LLMatrix4(const LLQuaternion &q); // Initializes Matrix with rotation q and sets position to (0,0,0) + explicit LLMatrix4(const LLMatrix4a& mat); LLMatrix4(const LLMatrix3 &mat, const LLVector4 &pos); // Initializes Matrix to values in mat and pos diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index b04c67d926..93010d2250 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -316,6 +316,12 @@ LLVector3::LLVector3(const LLVector4 &vec) mV[VZ] = (F32)vec.mV[VZ]; } +LLVector3::LLVector3(const LLVector4a& vec) + : LLVector3(vec.getF32ptr()) +{ + +} + LLVector3::LLVector3(const LLSD& sd) { setValue(sd); diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 6f857d7061..068f489020 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -33,6 +33,7 @@ #include "llsd.h" class LLVector2; class LLVector4; +class LLVector4a; class LLMatrix3; class LLMatrix4; class LLVector3d; @@ -62,7 +63,9 @@ class LLVector3 explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0) explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) - explicit LLVector3(const LLSD& sd); + explicit LLVector3(const LLVector4a& vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) + explicit LLVector3(const LLSD& sd); + LLSD getValue() const; diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp index d3e195789b..0abdafbdfc 100644 --- a/indra/llmessage/llfiltersd2xmlrpc.cpp +++ b/indra/llmessage/llfiltersd2xmlrpc.cpp @@ -309,7 +309,6 @@ LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse() } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_SD2XMLRPC_RESPONSE("SD2XMLRPC Response"); // virtual LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( const LLChannelDescriptors& channels, @@ -318,7 +317,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_SD2XMLRPC_RESPONSE); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; // This pipe does not work if it does not have everyting. This @@ -386,8 +385,6 @@ LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest() { } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_SD2XMLRPC_REQUEST("S22XMLRPC Request"); - // virtual LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( const LLChannelDescriptors& channels, @@ -396,7 +393,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_SD2XMLRPC_REQUEST); + LL_PROFILE_ZONE_SCOPED; // This pipe does not work if it does not have everyting. This // could be addressed by making a stream parser for llsd which // handled partial information. @@ -593,8 +590,6 @@ LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD() { } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_XMLRPC2LLSD_RESPONSE("XMLRPC2LLSD Response"); - LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -602,7 +597,7 @@ LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_XMLRPC2LLSD_RESPONSE); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; if(!eos) return STATUS_BREAK; @@ -679,7 +674,6 @@ LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD() { } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_XMLRPC2LLSD_REQUEST("XMLRPC2LLSD Request"); LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -687,7 +681,7 @@ LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_XMLRPC2LLSD_REQUEST); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; if(!eos) return STATUS_BREAK; if(!buffer) return STATUS_ERROR; diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index 6fd17c9154..6e9598a0a3 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -121,6 +121,7 @@ LLSD LLHTTPNode::simplePost(const LLSD& input) const // virtual void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) const { + LL_PROFILE_ZONE_SCOPED; try { response->result(simpleGet()); @@ -134,6 +135,7 @@ void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) cons // virtual void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const { + LL_PROFILE_ZONE_SCOPED; try { response->result(simplePut(input)); @@ -147,6 +149,7 @@ void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, cons // virtual void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const { + LL_PROFILE_ZONE_SCOPED; try { response->result(simplePost(input)); @@ -160,6 +163,7 @@ void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, con // virtual void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) const { + LL_PROFILE_ZONE_SCOPED; try { response->result(simpleDel(context)); diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index d9042fa8b0..c707c7ad09 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -132,12 +132,6 @@ private: LLSD mHeaders; }; -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_PIPE("HTTP Pipe"); -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_GET("HTTP Get"); -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_PUT("HTTP Put"); -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_POST("HTTP Post"); -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_DELETE("HTTP Delete"); - LLIOPipe::EStatus LLHTTPPipe::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -145,7 +139,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_PIPE); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; LL_DEBUGS() << "LLSDHTTPServer::process_impl" << LL_ENDL; @@ -174,12 +168,10 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB]; if(verb == HTTP_VERB_GET) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_GET); mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_PUT) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_PUT); LLSD input; if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) { @@ -195,7 +187,6 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if(verb == HTTP_VERB_POST) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_POST); LLSD input; if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) { @@ -211,7 +202,6 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if(verb == HTTP_VERB_DELETE) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_DELETE); mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_OPTIONS) @@ -455,8 +445,6 @@ protected: * LLHTTPResponseHeader */ -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_HEADER("HTTP Header"); - // virtual LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( const LLChannelDescriptors& channels, @@ -465,7 +453,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_HEADER); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; if(eos) { @@ -655,8 +643,6 @@ void LLHTTPResponder::markBad( << "</body>\n</html>\n"; } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_HTTP_RESPONDER("HTTP Responder"); - // virtual LLIOPipe::EStatus LLHTTPResponder::process_impl( const LLChannelDescriptors& channels, @@ -665,7 +651,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_HTTP_RESPONDER); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; LLIOPipe::EStatus status = STATUS_OK; diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index a9cc71c365..321d7286eb 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -300,8 +300,6 @@ LLIOSocketReader::~LLIOSocketReader() //LL_DEBUGS() << "Destroying LLIOSocketReader" << LL_ENDL; } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_SOCKET_READER("Socket Reader"); - // virtual LLIOPipe::EStatus LLIOSocketReader::process_impl( const LLChannelDescriptors& channels, @@ -310,7 +308,7 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_READER); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; if(!mSource) return STATUS_PRECONDITION_NOT_MET; if(!mInitialized) @@ -400,7 +398,6 @@ LLIOSocketWriter::~LLIOSocketWriter() //LL_DEBUGS() << "Destroying LLIOSocketWriter" << LL_ENDL; } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_SOCKET_WRITER("Socket Writer"); // virtual LLIOPipe::EStatus LLIOSocketWriter::process_impl( const LLChannelDescriptors& channels, @@ -409,7 +406,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_SOCKET_WRITER); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; if(!mDestination) return STATUS_PRECONDITION_NOT_MET; if(!mInitialized) @@ -556,7 +553,6 @@ void LLIOServerSocket::setResponseTimeout(F32 timeout_secs) mResponseTimeout = timeout_secs; } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_SERVER_SOCKET("Server Socket"); // virtual LLIOPipe::EStatus LLIOServerSocket::process_impl( const LLChannelDescriptors& channels, @@ -565,7 +561,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_SERVER_SOCKET); + LL_PROFILE_ZONE_SCOPED; PUMP_DEBUG; if(!pump) { diff --git a/indra/llmessage/llioutil.cpp b/indra/llmessage/llioutil.cpp index b8443c0600..850bc2a616 100644 --- a/indra/llmessage/llioutil.cpp +++ b/indra/llmessage/llioutil.cpp @@ -45,7 +45,6 @@ LLIOPipe::EStatus LLIOFlush::process_impl( } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_SLEEP("IO Sleep"); /** * @class LLIOSleep */ @@ -56,7 +55,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_SLEEP); + LL_PROFILE_ZONE_SCOPED; if(mSeconds > 0.0) { if(pump) pump->sleepChain(mSeconds); @@ -66,7 +65,6 @@ LLIOPipe::EStatus LLIOSleep::process_impl( return STATUS_DONE; } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_ADD_CHAIN("Add Chain"); /** * @class LLIOAddChain */ @@ -77,7 +75,7 @@ LLIOPipe::EStatus LLIOAddChain::process_impl( LLSD& context, LLPumpIO* pump) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_ADD_CHAIN); + LL_PROFILE_ZONE_SCOPED; pump->addChain(mChain, mTimeout); return STATUS_DONE; } diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index a2524e9804..35365665f6 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -416,9 +416,6 @@ void LLPumpIO::pump() pump(DEFAULT_POLL_TIMEOUT); } -static LLTrace::BlockTimerStatHandle FTM_PUMP_IO("Pump IO"); -static LLTrace::BlockTimerStatHandle FTM_PUMP_POLL("Pump Poll"); - LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain) { std::for_each( @@ -431,7 +428,7 @@ LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t //timeout is in microseconds void LLPumpIO::pump(const S32& poll_timeout) { - LL_RECORD_BLOCK_TIME(FTM_PUMP_IO); + LL_PROFILE_ZONE_SCOPED; //LL_INFOS() << "LLPumpIO::pump()" << LL_ENDL; // Run any pending runners. @@ -509,7 +506,7 @@ void LLPumpIO::pump(const S32& poll_timeout) S32 count = 0; S32 client_id = 0; { - LL_RECORD_BLOCK_TIME(FTM_PUMP_POLL); + LL_PROFILE_ZONE_SCOPED; apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); } PUMP_DEBUG; @@ -737,10 +734,9 @@ bool LLPumpIO::respond( return true; } -static LLTrace::BlockTimerStatHandle FTM_PUMP_CALLBACK_CHAIN("Chain"); - void LLPumpIO::callback() { + LL_PROFILE_ZONE_SCOPED; //LL_INFOS() << "LLPumpIO::callback()" << LL_ENDL; if(true) { @@ -756,7 +752,6 @@ void LLPumpIO::callback() callbacks_t::iterator end = mCallbacks.end(); for(; it != end; ++it) { - LL_RECORD_BLOCK_TIME(FTM_PUMP_CALLBACK_CHAIN); // it's always the first and last time for respone chains (*it).mHead = (*it).mChainLinks.begin(); (*it).mInit = true; diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index 6d5ad0ba08..32f79f0546 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -533,6 +533,8 @@ static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages"); // decode a given message BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender ) { + LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES); + llassert( mReceiveSize >= 0 ); llassert( mCurrentRMessageTemplate); llassert( !mCurrentRMessageData ); @@ -707,12 +709,9 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender decode_timer.reset(); } + if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES); - if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) ) - { - LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL; - } + LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL; } if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback()) diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 93d492b42d..4b13da5586 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -1224,17 +1224,19 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do LLMeshSkinInfo& skin_info = model->mSkinInfo; + LLMatrix4 mat; for (int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { - skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; + mat.mMatrix[i][j] = dom_value[i + j*4]; } } - LLMatrix4 trans = normalized_transformation; - trans *= skin_info.mBindShapeMatrix; - skin_info.mBindShapeMatrix = trans; + skin_info.mBindShapeMatrix.loadu(mat); + + LLMatrix4a trans(normalized_transformation); + matMul(trans, skin_info.mBindShapeMatrix, skin_info.mBindShapeMatrix); } @@ -1452,7 +1454,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do mat.mMatrix[i][j] = transform[k*16 + i + j*4]; } } - model->mSkinInfo.mInvBindMatrix.push_back(mat); + model->mSkinInfo.mInvBindMatrix.push_back(LLMatrix4a(mat)); } } } @@ -1526,9 +1528,9 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do if (mJointMap.find(lookingForJoint) != mJointMap.end() && model->mSkinInfo.mInvBindMatrix.size() > i) { - LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; + LLMatrix4 newInverse = LLMatrix4(model->mSkinInfo.mInvBindMatrix[i].getF32ptr()); newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); - model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); + model->mSkinInfo.mAlternateBindMatrix.push_back( LLMatrix4a(newInverse) ); } else { diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 702a1b5238..dd37b8ce0b 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -31,6 +31,7 @@ #include "llconvexdecomposition.h" #include "llsdserialize.h" #include "llvector4a.h" +#include "llmd5.h" #ifdef LL_USESYSTEMLIBS # include <zlib.h> @@ -1396,7 +1397,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin) } } - mInvBindMatrix.push_back(mat); + mInvBindMatrix.push_back(LLMatrix4a(mat)); } if (mJointNames.size() != mInvBindMatrix.size()) @@ -1410,13 +1411,15 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin) if (skin.has("bind_shape_matrix")) { + LLMatrix4 mat; for (U32 j = 0; j < 4; j++) { for (U32 k = 0; k < 4; k++) { - mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal(); + mat.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal(); } } + mBindShapeMatrix.loadu(mat); } if (skin.has("alt_inverse_bind_matrix")) @@ -1432,7 +1435,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin) } } - mAlternateBindMatrix.push_back(mat); + mAlternateBindMatrix.push_back(LLMatrix4a(mat)); } } @@ -1449,6 +1452,8 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin) { mLockScaleIfJointPosition = false; } + + updateHash(); } LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_position) const @@ -1500,6 +1505,38 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi return ret; } +void LLMeshSkinInfo::updateHash() +{ + // get hash of data relevant to render batches + LLMD5 hash; + + //mJointNames + for (auto& name : mJointNames) + { + hash.update(name); + } + + //mJointNums + hash.update((U8*)&(mJointNums[0]), sizeof(S32) * mJointNums.size()); + + //mInvBindMatrix + F32* src = mInvBindMatrix[0].getF32ptr(); + + for (int i = 0; i < mInvBindMatrix.size() * 16; ++i) + { + S32 t = llround(src[i] * 10000.f); + hash.update((U8*)&t, sizeof(S32)); + } + //hash.update((U8*)&(mInvBindMatrix[0]), sizeof(LLMatrix4a) * mInvBindMatrix.size()); + + hash.finalize(); + + U64 digest[2]; + hash.raw_digest((U8*) digest); + + mHash = digest[0]; +} + LLModel::Decomposition::Decomposition(LLSD& data) { fromLLSD(data); diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 96368d64e5..3881b1338c 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -33,34 +33,44 @@ #include "m4math.h" #include <queue> +#include <boost/align/aligned_allocator.hpp> + class daeElement; class domMesh; #define MAX_MODEL_FACES 8 +LL_ALIGN_PREFIX(16) class LLMeshSkinInfo { + LL_ALIGN_NEW public: LLMeshSkinInfo(); LLMeshSkinInfo(LLSD& data); void fromLLSD(LLSD& data); LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const; + void updateHash(); LLUUID mMeshID; std::vector<std::string> mJointNames; mutable std::vector<S32> mJointNums; - std::vector<LLMatrix4> mInvBindMatrix; - std::vector<LLMatrix4> mAlternateBindMatrix; + typedef std::vector<LLMatrix4a, boost::alignment::aligned_allocator<LLMatrix4a, 16>> matrix_list_t; + matrix_list_t mInvBindMatrix; + matrix_list_t mAlternateBindMatrix; + + LL_ALIGN_16(LLMatrix4a mBindShapeMatrix); - LLMatrix4 mBindShapeMatrix; float mPelvisOffset; bool mLockScaleIfJointPosition; bool mInvalidJointsScrubbed; bool mJointNumsInitialized; -}; + U64 mHash = 0; +} LL_ALIGN_POSTFIX(16); +LL_ALIGN_PREFIX(16) class LLModel : public LLVolume { + LL_ALIGN_NEW public: enum @@ -284,7 +294,7 @@ public: // A model/object can only have 8 faces, spillover faces will // be moved to new model/object and assigned a submodel id. int mSubmodelID; -}; +} LL_ALIGN_POSTFIX(16); typedef std::vector<LLPointer<LLModel> > model_list; typedef std::queue<LLPointer<LLModel> > model_queue; diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 5947bca670..834084674e 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -47,7 +47,6 @@ bool LLCubeMap::sUseCubeMaps = true; LLCubeMap::LLCubeMap(bool init_as_srgb) : mTextureStage(0), - mTextureCoordStage(0), mMatrixStage(0), mIssRGB(init_as_srgb) { @@ -150,6 +149,7 @@ void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages void LLCubeMap::initGLData() { + LL_PROFILE_ZONE_SCOPED; for (int i = 0; i < 6; i++) { mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION); @@ -179,7 +179,6 @@ void LLCubeMap::bind() void LLCubeMap::enable(S32 stage) { enableTexture(stage); - enableTextureCoords(stage); } void LLCubeMap::enableTexture(S32 stage) @@ -191,35 +190,9 @@ void LLCubeMap::enableTexture(S32 stage) } } -void LLCubeMap::enableTextureCoords(S32 stage) -{ - mTextureCoordStage = stage; - if (!LLGLSLShader::sNoFixedFunction && gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps) - { - if (stage > 0) - { - gGL.getTexUnit(stage)->activate(); - } - - glEnable(GL_TEXTURE_GEN_R); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - - if (stage > 0) - { - gGL.getTexUnit(0)->activate(); - } - } -} - void LLCubeMap::disable(void) { disableTexture(); - disableTextureCoords(); } void LLCubeMap::disableTexture(void) @@ -234,24 +207,6 @@ void LLCubeMap::disableTexture(void) } } -void LLCubeMap::disableTextureCoords(void) -{ - if (!LLGLSLShader::sNoFixedFunction && gGLManager.mHasCubeMap && mTextureCoordStage >= 0 && LLCubeMap::sUseCubeMaps) - { - if (mTextureCoordStage > 0) - { - gGL.getTexUnit(mTextureCoordStage)->activate(); - } - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glDisable(GL_TEXTURE_GEN_R); - if (mTextureCoordStage > 0) - { - gGL.getTexUnit(0)->activate(); - } - } -} - void LLCubeMap::setMatrix(S32 stage) { mMatrixStage = stage; @@ -453,6 +408,7 @@ BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max, void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col) { + LL_PROFILE_ZONE_SCOPED; F32 v_min, v_max, h_min, h_max; LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3]; center.normVec(); diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h index 95b6d12099..a01636d8d4 100644 --- a/indra/llrender/llcubemap.h +++ b/indra/llrender/llcubemap.h @@ -48,12 +48,10 @@ public: void enable(S32 stage); void enableTexture(S32 stage); - void enableTextureCoords(S32 stage); S32 getStage(void) { return mTextureStage; } void disable(void); void disableTexture(void); - void disableTextureCoords(void); void setMatrix(S32 stage); void restoreMatrix(); void setReflection (void); @@ -80,7 +78,6 @@ protected: LLPointer<LLImageGL> mImages[6]; LLPointer<LLImageRaw> mRawImages[6]; S32 mTextureStage; - S32 mTextureCoordStage; S32 mMatrixStage; }; diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index f128636ab2..c71e24c83a 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -30,8 +30,7 @@ #include "llfontbitmapcache.h" LLFontBitmapCache::LLFontBitmapCache() -: LLTrace::MemTrackable<LLFontBitmapCache>("LLFontBitmapCache"), - mNumComponents(0), +: mNumComponents(0), mBitmapWidth(0), mBitmapHeight(0), mBitmapNum(-1), @@ -124,9 +123,6 @@ BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32 &pos_x, S32 &pos_y, S32& bitm image_gl->createGLTexture(0, image_raw); gGL.getTexUnit(0)->bind(image_gl); image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE); - - claimMem(image_raw); - claimMem(image_gl); } else { @@ -156,20 +152,8 @@ void LLFontBitmapCache::destroyGL() void LLFontBitmapCache::reset() { - for (std::vector<LLPointer<LLImageRaw> >::iterator it = mImageRawVec.begin(), end_it = mImageRawVec.end(); - it != end_it; - ++it) - { - disclaimMem(**it); - } mImageRawVec.clear(); - for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec.begin(), end_it = mImageGLVec.end(); - it != end_it; - ++it) - { - disclaimMem(**it); - } mImageGLVec.clear(); mBitmapWidth = 0; diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 75df3a94a7..7de3a6b56f 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -32,7 +32,7 @@ // Maintain a collection of bitmaps containing rendered glyphs. // Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL. -class LLFontBitmapCache : public LLTrace::MemTrackable<LLFontBitmapCache> +class LLFontBitmapCache { public: LLFontBitmapCache(); diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index c41730ebaa..e964d1586f 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -104,8 +104,7 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index) } LLFontFreetype::LLFontFreetype() -: LLTrace::MemTrackable<LLFontFreetype>("LLFontFreetype"), - mFontBitmapCachep(new LLFontBitmapCache), +: mFontBitmapCachep(new LLFontBitmapCache), mAscender(0.f), mDescender(0.f), mLineHeight(0.f), @@ -222,8 +221,6 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v S32 max_char_height = ll_round(0.5f + (y_max - y_min)); mFontBitmapCachep->init(components, max_char_width, max_char_height); - claimMem(mFontBitmapCachep); - if (!mFTFace->charmap) { @@ -238,7 +235,6 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v } mName = filename; - claimMem(mName); mPointSize = point_size; mStyle = LLFontGL::NORMAL; @@ -460,6 +456,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const { + LL_PROFILE_ZONE_SCOPED; if (mFTFace == NULL) return NULL; @@ -585,7 +582,6 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const } else { - claimMem(gi); mCharGlyphInfoMap[wch] = gi; } } @@ -631,11 +627,9 @@ void LLFontFreetype::resetBitmapCache() it != end_it; ++it) { - disclaimMem(it->second); delete it->second; } mCharGlyphInfoMap.clear(); - disclaimMem(mFontBitmapCachep); mFontBitmapCachep->reset(); // Adding default glyph is skipped for fallback fonts here as well as in loadFace(). diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 1afe84e770..f61f169987 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -76,7 +76,7 @@ struct LLFontGlyphInfo extern LLFontManager *gFontManagerp; -class LLFontFreetype : public LLRefCount, public LLTrace::MemTrackable<LLFontFreetype> +class LLFontFreetype : public LLRefCount { public: LLFontFreetype(); diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 86a4c35e6d..7f734e41f3 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -109,8 +109,6 @@ S32 LLFontGL::getNumFaces(const std::string& filename) return mFontFreetype->getNumFaces(filename); } -static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts"); - S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const { @@ -147,7 +145,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const { - LL_RECORD_BLOCK_TIME(FTM_RENDER_FONTS); + LL_PROFILE_ZONE_SCOPED; if(!sDisplayFont) //do not display texts { @@ -547,9 +545,19 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars return cur_x / sScaleX; } +void LLFontGL::generateASCIIglyphs() +{ + LL_PROFILE_ZONE_SCOPED + for (U32 i = 32; (i < 127); i++) + { + mFontFreetype->getGlyphInfo(i); + } +} + // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, EWordWrapStyle end_on_word_boundary) const { + LL_PROFILE_ZONE_SCOPED if (!wchars || !wchars[0] || max_chars == 0) { return 0; @@ -829,6 +837,8 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st { sFontRegistry->reset(); } + + LLFontGL::loadDefaultFonts(); } // Force standard fonts to get generated up front. @@ -838,6 +848,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st // static bool LLFontGL::loadDefaultFonts() { + LL_PROFILE_ZONE_SCOPED bool succ = true; succ &= (NULL != getFontSansSerifSmall()); succ &= (NULL != getFontSansSerif()); @@ -845,10 +856,18 @@ bool LLFontGL::loadDefaultFonts() succ &= (NULL != getFontSansSerifHuge()); succ &= (NULL != getFontSansSerifBold()); succ &= (NULL != getFontMonospace()); - succ &= (NULL != getFontExtChar()); return succ; } +void LLFontGL::loadCommonFonts() +{ + LL_PROFILE_ZONE_SCOPED + getFont(LLFontDescriptor("SansSerif", "Small", BOLD)); + getFont(LLFontDescriptor("SansSerif", "Large", BOLD)); + getFont(LLFontDescriptor("SansSerif", "Huge", BOLD)); + getFont(LLFontDescriptor("Monospace", "Medium", 0)); +} + // static void LLFontGL::destroyDefaultFonts() { @@ -1015,7 +1034,7 @@ LLFontGL* LLFontGL::getFontSansSerifBig() //static LLFontGL* LLFontGL::getFontSansSerifHuge() { - static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0)); + static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Huge",0)); return fontp; } @@ -1026,12 +1045,6 @@ LLFontGL* LLFontGL::getFontSansSerifBold() return fontp; } -//static -LLFontGL* LLFontGL::getFontExtChar() -{ - return getFontSansSerif(); -} - //static LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) { diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 10891faed9..3b58a37d33 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -160,12 +160,15 @@ public: const LLFontDescriptor& getFontDesc() const; + void generateASCIIglyphs(); + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true); // Load sans-serif, sans-serif-small, etc. // Slow, requires multiple seconds to load fonts. static bool loadDefaultFonts(); + static void loadCommonFonts(); static void destroyDefaultFonts(); static void destroyAllGL(); @@ -190,7 +193,6 @@ public: static LLFontGL* getFontSansSerifBig(); static LLFontGL* getFontSansSerifHuge(); static LLFontGL* getFontSansSerifBold(); - static LLFontGL* getFontExtChar(); static LLFontGL* getFont(const LLFontDescriptor& desc); // Use with legacy names like "SANSSERIF_SMALL" or "OCRA" static LLFontGL* getFontByName(const std::string& name); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 33a33af160..bc1a2f8887 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -597,6 +597,11 @@ LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc) <<" style=[" << ((S32) desc.getStyle()) << "]" << " size=[" << desc.getSize() << "]" << LL_ENDL; } + else + { + //generate glyphs for ASCII chars to avoid stalls later + fontp->generateASCIIglyphs(); + } return fontp; } } diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 43fedeca64..18a79d5264 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -62,6 +62,7 @@ BOOL gDebugSession = FALSE; BOOL gClothRipple = FALSE; BOOL gHeadlessClient = FALSE; +BOOL gNonInteractive = FALSE; BOOL gGLActive = FALSE; BOOL gGLDebugLoggingEnabled = TRUE; @@ -87,24 +88,32 @@ void APIENTRY gl_debug_callback(GLenum source, { if (gGLDebugLoggingEnabled) { - if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) - { - LL_WARNS() << "----- GL ERROR --------" << LL_ENDL; - } - else - { - LL_WARNS() << "----- GL WARNING -------" << LL_ENDL; - } - LL_WARNS() << "Type: " << std::hex << type << LL_ENDL; - LL_WARNS() << "ID: " << std::hex << id << LL_ENDL; - LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL; - LL_WARNS() << "Message: " << message << LL_ENDL; - LL_WARNS() << "-----------------------" << LL_ENDL; - if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) - { - LL_ERRS() << "Halting on GL Error" << LL_ENDL; - } -} + + if (severity != GL_DEBUG_SEVERITY_HIGH_ARB && + severity != GL_DEBUG_SEVERITY_MEDIUM_ARB && + severity != GL_DEBUG_SEVERITY_LOW_ARB) + { //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints) + return; + } + + if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) + { + LL_WARNS() << "----- GL ERROR --------" << LL_ENDL; + } + else + { + LL_WARNS() << "----- GL WARNING -------" << LL_ENDL; + } + LL_WARNS() << "Type: " << std::hex << type << LL_ENDL; + LL_WARNS() << "ID: " << std::hex << id << LL_ENDL; + LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL; + LL_WARNS() << "Message: " << message << LL_ENDL; + LL_WARNS() << "-----------------------" << LL_ENDL; + if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) + { + LL_ERRS() << "Halting on GL Error" << LL_ENDL; + } + } } #endif @@ -152,7 +161,6 @@ LLMatrix4 gGLObliqueProjectionInverse; std::list<LLGLUpdate*> LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS -// ATI prototypes #if LL_WINDOWS PFNGLGETSTRINGIPROC glGetStringi = NULL; @@ -199,21 +207,6 @@ PFNGLGETSYNCIVPROC glGetSynciv = NULL; PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL; PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL; -// vertex object prototypes -PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL; -PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL; -PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI = NULL; -PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI = NULL; -PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI = NULL; -PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI = NULL; -PFNGLARRAYOBJECTATIPROC glArrayObjectATI = NULL; -PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI = NULL; -PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI = NULL; -PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI = NULL; -PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI = NULL; -PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI = NULL; -PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI = NULL; - // GL_ARB_occlusion_query PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL; PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL; @@ -434,9 +427,6 @@ LLGLManager::LLGLManager() : mHasMapBufferRange(FALSE), mHasFlushBufferRange(FALSE), mHasPBuffer(FALSE), - mHasShaderObjects(FALSE), - mHasVertexShader(FALSE), - mHasFragmentShader(FALSE), mNumTextureImageUnits(0), mHasOcclusionQuery(FALSE), mHasTimerQuery(FALSE), @@ -456,14 +446,9 @@ LLGLManager::LLGLManager() : mHasCubeMap(FALSE), mHasDebugOutput(FALSE), - mIsATI(FALSE), + mIsAMD(FALSE), mIsNVIDIA(FALSE), mIsIntel(FALSE), - mIsGF2or4MX(FALSE), - mIsGF3(FALSE), - mIsGFFX(FALSE), - mATIOffsetVerticalLines(FALSE), - mATIOldDriver(FALSE), #if LL_DARWIN mIsMobileGF(FALSE), #endif @@ -559,7 +544,7 @@ bool LLGLManager::initGL() glGetIntegerv(GL_NUM_EXTENSIONS, &count); for (GLint i = 0; i < count; ++i) { - std::string ext((const char*) glGetStringi(GL_EXTENSIONS, i)); + std::string ext = ll_safe_string((const char*) glGetStringi(GL_EXTENSIONS, i)); str << ext << " "; LL_DEBUGS("GLExtensions") << ext << LL_ENDL; } @@ -622,59 +607,17 @@ bool LLGLManager::initGL() // Trailing space necessary to keep "nVidia Corpor_ati_on" cards // from being recognized as ATI. + // NOTE: AMD has been pretty good about not breaking this check, do not rename without good reason if (mGLVendor.substr(0,4) == "ATI ") { - mGLVendorShort = "ATI"; + mGLVendorShort = "AMD"; // *TODO: Fix this? - mIsATI = TRUE; - -#if LL_WINDOWS && !LL_MESA_HEADLESS - if (mDriverVersionRelease < 3842) - { - mATIOffsetVerticalLines = TRUE; - } -#endif // LL_WINDOWS - -#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS - // count any pre OpenGL 3.0 implementation as an old driver - if (mGLVersion < 3.f) - { - mATIOldDriver = TRUE; - } -#endif // (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS + mIsAMD = TRUE; } else if (mGLVendor.find("NVIDIA ") != std::string::npos) { mGLVendorShort = "NVIDIA"; mIsNVIDIA = TRUE; - if ( mGLRenderer.find("GEFORCE4 MX") != std::string::npos - || mGLRenderer.find("GEFORCE2") != std::string::npos - || mGLRenderer.find("GEFORCE 2") != std::string::npos - || mGLRenderer.find("GEFORCE4 460 GO") != std::string::npos - || mGLRenderer.find("GEFORCE4 440 GO") != std::string::npos - || mGLRenderer.find("GEFORCE4 420 GO") != std::string::npos) - { - mIsGF2or4MX = TRUE; - } - else if (mGLRenderer.find("GEFORCE FX") != std::string::npos - || mGLRenderer.find("QUADRO FX") != std::string::npos - || mGLRenderer.find("NV34") != std::string::npos) - { - mIsGFFX = TRUE; - } - else if(mGLRenderer.find("GEFORCE3") != std::string::npos) - { - mIsGF3 = TRUE; - } -#if LL_DARWIN - else if ((mGLRenderer.find("9400M") != std::string::npos) - || (mGLRenderer.find("9600M") != std::string::npos) - || (mGLRenderer.find("9800M") != std::string::npos)) - { - mIsMobileGF = TRUE; - } -#endif - } else if (mGLVendor.find("INTEL") != std::string::npos #if LL_LINUX @@ -775,14 +718,9 @@ bool LLGLManager::initGL() stop_glerror(); - stop_glerror(); - - if (mHasFragmentShader) - { - GLint num_tex_image_units; - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units); - mNumTextureImageUnits = llmin(num_tex_image_units, 32); - } + GLint num_tex_image_units; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units); + mNumTextureImageUnits = llmin(num_tex_image_units, 32); if (LLRender::sGLCoreProfile) { @@ -833,12 +771,6 @@ bool LLGLManager::initGL() //HACK always disable texture multisample, use FXAA instead mHasTextureMultisample = FALSE; #if LL_WINDOWS - if (mIsATI) - { //using multisample textures on ATI results in black screen for some reason - mHasTextureMultisample = FALSE; - } - - if (mIsIntel && mGLVersion <= 3.f) { //never try to use framebuffer objects on older intel drivers (crashy) mHasFramebufferObject = FALSE; @@ -975,9 +907,9 @@ void LLGLManager::asLLSD(LLSD& info) info["has_map_buffer_range"] = mHasMapBufferRange; info["has_flush_buffer_range"] = mHasFlushBufferRange; info["has_pbuffer"] = mHasPBuffer; - info["has_shader_objects"] = mHasShaderObjects; - info["has_vertex_shader"] = mHasVertexShader; - info["has_fragment_shader"] = mHasFragmentShader; + info["has_shader_objects"] = std::string("Assumed TRUE"); // was mHasShaderObjects; + info["has_vertex_shader"] = std::string("Assumed TRUE"); // was mHasVertexShader; + info["has_fragment_shader"] = std::string("Assumed TRUE"); // was mHasFragmentShader; info["num_texture_image_units"] = mNumTextureImageUnits; info["has_occlusion_query"] = mHasOcclusionQuery; info["has_timer_query"] = mHasTimerQuery; @@ -1003,14 +935,9 @@ void LLGLManager::asLLSD(LLSD& info) info["has_texture_srgb_decode"] = mHasTexturesRGBDecode; // Vendor-specific extensions - info["is_ati"] = mIsATI; + info["is_ati"] = mIsAMD; // note, do not rename is_ati to is_amd without coordinating with DW info["is_nvidia"] = mIsNVIDIA; info["is_intel"] = mIsIntel; - info["is_gf2or4mx"] = mIsGF2or4MX; - info["is_gf3"] = mIsGF3; - info["is_gf_gfx"] = mIsGFFX; - info["ati_offset_vertical_lines"] = mATIOffsetVerticalLines; - info["ati_old_driver"] = mATIOldDriver; // Other fields info["has_requirements"] = mHasRequirements; @@ -1083,9 +1010,6 @@ void LLGLManager::initExtensions() mHasCubeMap = FALSE; mHasOcclusionQuery = FALSE; mHasPointParameters = FALSE; - mHasShaderObjects = FALSE; - mHasVertexShader = FALSE; - mHasFragmentShader = FALSE; mHasTextureRectangle = FALSE; #else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); @@ -1105,8 +1029,7 @@ void LLGLManager::initExtensions() mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts); mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts); mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); - //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); - mHasDepthClamp = FALSE; + mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad #ifdef GL_ARB_framebuffer_object mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts); @@ -1141,12 +1064,8 @@ void LLGLManager::initExtensions() mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts); mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE; #if !LL_DARWIN - mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); + mHasPointParameters = ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif - mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); - mHasVertexShader = ExtensionExists("GL_ARB_vertex_program", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_vertex_shader", gGLHExts.mSysExts) - && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); - mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); #endif #if LL_LINUX @@ -1169,9 +1088,6 @@ void LLGLManager::initExtensions() mHasCubeMap = FALSE; mHasOcclusionQuery = FALSE; mHasPointParameters = FALSE; - mHasShaderObjects = FALSE; - mHasVertexShader = FALSE; - mHasFragmentShader = FALSE; LL_WARNS("RenderInit") << "GL extension support DISABLED via LL_GL_NOEXT" << LL_ENDL; } else if (getenv("LL_GL_BASICEXT")) /* Flawfinder: ignore */ @@ -1184,9 +1100,6 @@ void LLGLManager::initExtensions() mHasAnisotropic = FALSE; //mHasCubeMap = FALSE; // apparently fatal on Intel 915 & similar //mHasOcclusionQuery = FALSE; // source of many ATI system hangs - mHasShaderObjects = FALSE; - mHasVertexShader = FALSE; - mHasFragmentShader = FALSE; mHasBlendFuncSeparate = FALSE; LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL; } @@ -1208,9 +1121,6 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'j')) mHasCubeMap = FALSE;//S // if (strchr(blacklist,'k')) mHasATIVAO = FALSE;//S if (strchr(blacklist,'l')) mHasOcclusionQuery = FALSE; - if (strchr(blacklist,'m')) mHasShaderObjects = FALSE;//S - if (strchr(blacklist,'n')) mHasVertexShader = FALSE;//S - if (strchr(blacklist,'o')) mHasFragmentShader = FALSE;//S if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S @@ -1257,18 +1167,6 @@ void LLGLManager::initExtensions() { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL; } - if (!mHasShaderObjects) - { - LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_shader_objects" << LL_ENDL; - } - if (!mHasVertexShader) - { - LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_vertex_shader" << LL_ENDL; - } - if (!mHasFragmentShader) - { - LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL; - } if (!mHasBlendFuncSeparate) { LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL; @@ -1284,14 +1182,7 @@ void LLGLManager::initExtensions() LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL; mHasMipMapGeneration = FALSE; } -#if !LL_DARWIN - if (mIsATI && mHasMipMapGeneration) - { - LL_INFOS("RenderInit") << "Disabling mip-map generation for ATI GPUs (performance opt)" << LL_ENDL; - mHasMipMapGeneration = FALSE; - } -#endif - + // Misc glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange); @@ -1436,134 +1327,132 @@ void LLGLManager::initExtensions() glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB"); glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB"); } - if (mHasShaderObjects) - { - glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB"); - glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB"); - glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB"); - glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB"); - glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB"); - glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB"); - glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB"); - glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB"); - glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB"); - glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB"); - glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB"); - glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB"); - glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB"); - glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB"); - glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB"); - glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB"); - glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB"); - glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB"); - glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB"); - glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB"); - glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB"); - glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB"); - glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB"); - glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB"); - glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB"); - glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB"); - glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB"); - glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB"); - glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB"); - glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv"); - glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB"); - glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB"); - glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB"); - glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB"); - glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB"); - glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB"); - glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB"); - glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB"); - glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB"); - glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB"); - } - if (mHasVertexShader) - { - LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL; - - // nSight doesn't support use of ARB funcs that have been normalized in the API - if (!LLRender::sNsightDebugSupport) - { - glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); - glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); - } - else - { - glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation"); - glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation"); - } - glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB"); - glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB"); - glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB"); - glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB"); - glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB"); - glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB"); - glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB"); - glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB"); - glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB"); - glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB"); - glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB"); - glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB"); - glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB"); - glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB"); - glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB"); - glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB"); - glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB"); - glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB"); - glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB"); - glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB"); - glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB"); - glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB"); - glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB"); - glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB"); - glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB"); - glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB"); - glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB"); - glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB"); - glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB"); - glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB"); - glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB"); - glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB"); - glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB"); - glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB"); - glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB"); - glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB"); - glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB"); - glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB"); - glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer"); - glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB"); - glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB"); - glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB"); - glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB"); - glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB"); - glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB"); - glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB"); - glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB"); - glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB"); - glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB"); - glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB"); - glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB"); - glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB"); - glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB"); - glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB"); - glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB"); - glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB"); - glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB"); - glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB"); - glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB"); - glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB"); - glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB"); - glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB"); - glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB"); - glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB"); - } - LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL; + // Assume shader capabilities + glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB"); + glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB"); + glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB"); + glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB"); + glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB"); + glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB"); + glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB"); + glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB"); + glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB"); + glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB"); + glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB"); + glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB"); + glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB"); + glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB"); + glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB"); + glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB"); + glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB"); + glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB"); + glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB"); + glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB"); + glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB"); + glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB"); + glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB"); + glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB"); + glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB"); + glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB"); + glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB"); + glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB"); + glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB"); + glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3x4fv"); + glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB"); + glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB"); + glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB"); + glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB"); + glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB"); + glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB"); + glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB"); + glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB"); + glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB"); + glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB"); + + LL_INFOS() << "initExtensions() VertexShader-related procs..." << LL_ENDL; + + // nSight doesn't support use of ARB funcs that have been normalized in the API + if (!LLRender::sNsightDebugSupport) + { + glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); + glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); + } + else + { + glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocation"); + glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocation"); + } + + glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB"); + glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB"); + glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB"); + glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB"); + glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB"); + glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB"); + glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB"); + glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB"); + glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB"); + glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB"); + glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB"); + glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB"); + glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB"); + glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB"); + glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB"); + glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB"); + glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB"); + glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB"); + glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB"); + glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB"); + glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB"); + glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB"); + glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB"); + glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB"); + glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB"); + glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB"); + glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB"); + glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB"); + glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB"); + glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB"); + glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB"); + glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB"); + glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB"); + glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB"); + glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB"); + glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB"); + glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB"); + glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB"); + glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribIPointer"); + glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB"); + glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB"); + glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB"); + glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB"); + glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB"); + glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB"); + glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB"); + glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB"); + glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB"); + glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB"); + glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB"); + glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB"); + glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB"); + glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB"); + glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB"); + glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB"); + glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB"); + glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB"); + glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB"); + glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB"); + glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB"); + glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB"); + glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB"); + glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB"); + glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB"); + + LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL; #endif - mInited = TRUE; + mInited = TRUE; } void rotate_quat(LLQuaternion& rotation) @@ -1974,206 +1863,30 @@ void LLGLState::checkTextureChannels(const std::string& msg) #endif } -void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) -{ - if (!gDebugGL || LLGLSLShader::sNoFixedFunction) - { - return; - } - - stop_glerror(); - BOOL error = FALSE; - - GLint active_texture; - glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE_ARB, &active_texture); - - if (active_texture != GL_TEXTURE0_ARB) - { - LL_WARNS() << "Client active texture corrupted: " << active_texture << LL_ENDL; - if (gDebugSession) - { - gFailLog << "Client active texture corrupted: " << active_texture << std::endl; - } - error = TRUE; - } - - /*glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &active_texture); - if (active_texture != GL_TEXTURE0_ARB) - { - LL_WARNS() << "Active texture corrupted: " << active_texture << LL_ENDL; - if (gDebugSession) - { - gFailLog << "Active texture corrupted: " << active_texture << std::endl; - } - error = TRUE; - }*/ - - static const char* label[] = - { - "GL_VERTEX_ARRAY", - "GL_NORMAL_ARRAY", - "GL_COLOR_ARRAY", - "GL_TEXTURE_COORD_ARRAY" - }; - - static GLint value[] = - { - GL_VERTEX_ARRAY, - GL_NORMAL_ARRAY, - GL_COLOR_ARRAY, - GL_TEXTURE_COORD_ARRAY - }; - - static const U32 mask[] = - { //copied from llvertexbuffer.h - 0x0001, //MAP_VERTEX, - 0x0002, //MAP_NORMAL, - 0x0010, //MAP_COLOR, - 0x0004, //MAP_TEXCOORD - }; - - - for (S32 j = 1; j < 4; j++) - { - if (glIsEnabled(value[j])) - { - if (!(mask[j] & data_mask)) - { - error = TRUE; - LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL still has " << label[j] << " enabled." << std::endl; - } - } - } - else - { - if (mask[j] & data_mask) - { - error = TRUE; - LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL does not have " << label[j] << " enabled." << std::endl; - } - } - } - } - - glClientActiveTextureARB(GL_TEXTURE1_ARB); - gGL.getTexUnit(1)->activate(); - if (glIsEnabled(GL_TEXTURE_COORD_ARRAY)) - { - if (!(data_mask & 0x0008)) - { - error = TRUE; - LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; - } - } - } - else - { - if (data_mask & 0x0008) - { - error = TRUE; - LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; - } - } - } - - /*if (glIsEnabled(GL_TEXTURE_2D)) - { - if (!(data_mask & 0x0008)) - { - error = TRUE; - LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL still has GL_TEXTURE_2D enabled on channel 1." << std::endl; - } - } - } - else - { - if (data_mask & 0x0008) - { - error = TRUE; - LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; - } - } - }*/ - - glClientActiveTextureARB(GL_TEXTURE0_ARB); - gGL.getTexUnit(0)->activate(); - - if (gGLManager.mHasVertexShader && LLGLSLShader::sNoFixedFunction) - { //make sure vertex attribs are all disabled - GLint count; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &count); - for (GLint i = 0; i < count; i++) - { - GLint enabled; - glGetVertexAttribivARB((GLuint) i, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &enabled); - if (enabled) - { - error = TRUE; - LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL; - if (gDebugSession) - { - gFailLog << "GL still has vertex attrib array " << i << " enabled." << std::endl; - } - } - } - } - - if (error) - { - if (gDebugSession) - { - ll_fail("LLGLState::checkClientArrays failed."); - } - else - { - LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; - } - } -} - /////////////////////////////////////////////////////////////////////// LLGLState::LLGLState(LLGLenum state, S32 enabled) : mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) { - if (LLGLSLShader::sNoFixedFunction) - { //always ignore state that's deprecated post GL 3.0 - switch (state) - { - case GL_ALPHA_TEST: - case GL_NORMALIZE: - case GL_TEXTURE_GEN_R: - case GL_TEXTURE_GEN_S: - case GL_TEXTURE_GEN_T: - case GL_TEXTURE_GEN_Q: - case GL_LIGHTING: - case GL_COLOR_MATERIAL: - case GL_FOG: - case GL_LINE_STIPPLE: - case GL_POLYGON_STIPPLE: - mState = 0; - break; - } + LL_PROFILE_ZONE_SCOPED; + switch (state) + { + case GL_ALPHA_TEST: + case GL_NORMALIZE: + case GL_TEXTURE_GEN_R: + case GL_TEXTURE_GEN_S: + case GL_TEXTURE_GEN_T: + case GL_TEXTURE_GEN_Q: + case GL_LIGHTING: + case GL_COLOR_MATERIAL: + case GL_FOG: + case GL_LINE_STIPPLE: + case GL_POLYGON_STIPPLE: + mState = 0; + break; } + stop_glerror(); if (mState) { @@ -2212,6 +1925,7 @@ void LLGLState::setEnabled(S32 enabled) LLGLState::~LLGLState() { + LL_PROFILE_ZONE_SCOPED; stop_glerror(); if (mState) { @@ -2398,7 +2112,8 @@ LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& mode mModelview = modelview; mProjection = projection; - setPlane(p[0], p[1], p[2], p[3]); + //flip incoming LLPlane to get consistent behavior compared to frustum culling + setPlane(-p[0], -p[1], -p[2], -p[3]); } } @@ -2469,6 +2184,7 @@ void LLGLNamePool::cleanup() GLuint LLGLNamePool::allocate() { + LL_PROFILE_ZONE_SCOPED; #if LL_GL_NAME_POOLING for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter) { @@ -2723,22 +2439,10 @@ LLGLSPipelineSkyBox::LLGLSPipelineSkyBox() , mCullFace(GL_CULL_FACE) , mSquashClip() { - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glDisable(GL_CLIP_PLANE0); - } } LLGLSPipelineSkyBox::~LLGLSPipelineSkyBox() { - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - glEnable(GL_FOG); - glEnable(GL_CLIP_PLANE0); - } } LLGLSPipelineDepthTestSkyBox::LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write) diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index a07e2d9bb0..ec97eb0faa 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -94,9 +94,6 @@ public: BOOL mHasMapBufferRange; BOOL mHasFlushBufferRange; BOOL mHasPBuffer; - BOOL mHasShaderObjects; - BOOL mHasVertexShader; - BOOL mHasFragmentShader; S32 mNumTextureImageUnits; BOOL mHasOcclusionQuery; BOOL mHasTimerQuery; @@ -122,14 +119,9 @@ public: BOOL mHasTexturesRGBDecode; // Vendor-specific extensions - BOOL mIsATI; + BOOL mIsAMD; BOOL mIsNVIDIA; BOOL mIsIntel; - BOOL mIsGF2or4MX; - BOOL mIsGF3; - BOOL mIsGFFX; - BOOL mATIOffsetVerticalLines; - BOOL mATIOldDriver; #if LL_DARWIN // Needed to distinguish problem cards on older Macs that break with Materials @@ -269,7 +261,6 @@ public: static void dumpStates(); static void checkStates(const std::string& msg = ""); static void checkTextureChannels(const std::string& msg = ""); - static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0); protected: static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap; @@ -488,6 +479,7 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor extern BOOL gClothRipple; extern BOOL gHeadlessClient; +extern BOOL gNonInteractive; extern BOOL gGLActive; // Deal with changing glext.h definitions for newer SDK versions, specifically diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 6bca3623e0..3d93cc0762 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -812,4 +812,23 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); #define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD #endif +#if defined(TRACY_ENABLE) && LL_PROFILER_ENABLE_TRACY_OPENGL + // Tracy uses the following: + // glGenQueries + // glGetQueryiv + // glGetQueryObjectiv + #define glGenQueries glGenQueriesARB + #define glGetQueryiv glGetQueryivARB + #define glGetQueryObjectiv glGetQueryObjectivARB + #include <tracy/TracyOpenGL.hpp> + + #define LL_PROFILER_GPU_ZONEC(name,color) TracyGpuZoneC(name,color); + #define LL_PROFILER_GPU_COLLECT TracyGpuCollect + #define LL_PROFILER_GPU_CONTEXT TracyGpuContext +#else + #define LL_PROFILER_GPU_ZONEC(name,color) (void)name;(void)color; + #define LL_PROFILER_GPU_COLLECT + #define LL_PROFILER_GPU_CONTEXT +#endif + #endif // LL_LLGLHEADERS_H diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 4351f6e2c8..220e88386a 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -50,7 +50,6 @@ using std::string; GLhandleARB LLGLSLShader::sCurBoundShader = 0; LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; S32 LLGLSLShader::sIndexedTextureChannels = 0; -bool LLGLSLShader::sNoFixedFunction = false; bool LLGLSLShader::sProfileEnabled = false; std::set<LLGLSLShader*> LLGLSLShader::sInstances; U64 LLGLSLShader::sTotalTimeElapsed = 0; @@ -208,6 +207,7 @@ void LLGLSLShader::dumpStats() //static void LLGLSLShader::startProfile() { + LL_PROFILE_ZONE_SCOPED; if (sProfileEnabled && sCurBoundShaderPtr) { sCurBoundShaderPtr->placeProfileQuery(); @@ -218,6 +218,7 @@ void LLGLSLShader::startProfile() //static void LLGLSLShader::stopProfile(U32 count, U32 mode) { + LL_PROFILE_ZONE_SCOPED; if (sProfileEnabled && sCurBoundShaderPtr) { sCurBoundShaderPtr->readProfileQuery(count, mode); @@ -384,6 +385,8 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes, U32 varying_count, const char** varyings) { + LL_PROFILE_ZONE_SCOPED; + unloadInternal(); sInstances.insert(this); @@ -588,6 +591,8 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count) BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes) { + LL_PROFILE_ZONE_SCOPED; + //before linking, make sure reserved attributes always have consistent locations for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) { @@ -649,6 +654,8 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms) { + LL_PROFILE_ZONE_SCOPED; + if (index == -1) { return; @@ -770,6 +777,8 @@ void LLGLSLShader::removePermutation(std::string name) GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) { + LL_PROFILE_ZONE_SCOPED; + if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) || type == GL_SAMPLER_2D_MULTISAMPLE) { //this here is a texture @@ -782,7 +791,9 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms) { - BOOL res = TRUE; + LL_PROFILE_ZONE_SCOPED; + + BOOL res = TRUE; mTotalUniformSize = 0; mActiveTextureChannels = 0; @@ -925,6 +936,8 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms) BOOL LLGLSLShader::link(BOOL suppress_errors) { + LL_PROFILE_ZONE_SCOPED; + BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); if (!success && !suppress_errors) @@ -937,56 +950,65 @@ BOOL LLGLSLShader::link(BOOL suppress_errors) void LLGLSLShader::bind() { + LL_PROFILE_ZONE_SCOPED; + gGL.flush(); - if (gGLManager.mHasShaderObjects) + + if (sCurBoundShader != mProgramObject) // Don't re-bind current shader { LLVertexBuffer::unbind(); glUseProgramObjectARB(mProgramObject); sCurBoundShader = mProgramObject; sCurBoundShaderPtr = this; - if (mUniformsDirty) - { - LLShaderMgr::instance()->updateShaderUniforms(this); - mUniformsDirty = FALSE; - } + } + + if (mUniformsDirty) + { + LLShaderMgr::instance()->updateShaderUniforms(this); + mUniformsDirty = FALSE; } } -void LLGLSLShader::unbind() +void LLGLSLShader::bind(bool rigged) { - gGL.flush(); - if (gGLManager.mHasShaderObjects) + if (rigged) { - stop_glerror(); - if (gGLManager.mIsNVIDIA) - { - for (U32 i = 0; i < mAttribute.size(); ++i) - { - vertexAttrib4f(i, 0,0,0,1); - stop_glerror(); - } - } - LLVertexBuffer::unbind(); - glUseProgramObjectARB(0); - sCurBoundShader = 0; - sCurBoundShaderPtr = NULL; - stop_glerror(); + llassert(mRiggedVariant); + mRiggedVariant->bind(); + } + else + { + bind(); } } +void LLGLSLShader::unbind() +{ + LL_PROFILE_ZONE_SCOPED; + + gGL.flush(); + stop_glerror(); + LLVertexBuffer::unbind(); + glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; + stop_glerror(); +} + void LLGLSLShader::bindNoShader(void) { + LL_PROFILE_ZONE_SCOPED; + LLVertexBuffer::unbind(); - if (gGLManager.mHasShaderObjects) - { - glUseProgramObjectARB(0); - sCurBoundShader = 0; - sCurBoundShaderPtr = NULL; - } + glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; } S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) { + LL_PROFILE_ZONE_SCOPED; + S32 channel = 0; channel = getUniformLocation(uniform); @@ -995,6 +1017,8 @@ S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LL S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace) { + LL_PROFILE_ZONE_SCOPED; + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; @@ -1005,7 +1029,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu if (uniform > -1) { - gGL.getTexUnit(uniform)->bind(texture, mode); + gGL.getTexUnit(uniform)->bindFast(texture); gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace); } @@ -1014,6 +1038,8 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureType mode) { + LL_PROFILE_ZONE_SCOPED; + S32 channel = 0; channel = getUniformLocation(uniform); @@ -1022,6 +1048,8 @@ S32 LLGLSLShader::unbindTexture(const std::string &uniform, LLTexUnit::eTextureT S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) { + LL_PROFILE_ZONE_SCOPED; + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; @@ -1032,7 +1060,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) if (uniform > -1) { - gGL.getTexUnit(uniform)->unbind(mode); + gGL.getTexUnit(uniform)->unbindFast(mode); } return uniform; @@ -1040,6 +1068,8 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode) S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) { + LL_PROFILE_ZONE_SCOPED; + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; @@ -1057,6 +1087,8 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTex S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) { + LL_PROFILE_ZONE_SCOPED; + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; @@ -1084,6 +1116,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe void LLGLSLShader::uniform1i(U32 index, GLint x) { + LL_PROFILE_ZONE_SCOPED if (mProgramObject) { if (mUniform.size() <= index) @@ -1094,7 +1127,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1iARB(mUniform[index], x); @@ -1106,6 +1139,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x) void LLGLSLShader::uniform1f(U32 index, GLfloat x) { + LL_PROFILE_ZONE_SCOPED if (mProgramObject) { if (mUniform.size() <= index) @@ -1116,7 +1150,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); if (iter == mValue.end() || iter->second.mV[0] != x) { glUniform1fARB(mUniform[index], x); @@ -1138,7 +1172,7 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(x,y,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1161,7 +1195,7 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(x,y,z,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1184,7 +1218,7 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + const auto& iter = mValue.find(mUniform[index]); LLVector4 vec(x,y,z,w); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1207,7 +1241,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + 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) { @@ -1230,7 +1264,7 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + 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) { @@ -1253,7 +1287,7 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + 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) { @@ -1276,7 +1310,7 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + 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) { @@ -1299,10 +1333,11 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v) if (mUniform[index] >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); + 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) { + LL_PROFILE_ZONE_SCOPED; glUniform4fvARB(mUniform[index], count, v); mValue[mUniform[index]] = vec; } @@ -1346,6 +1381,8 @@ 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; + if (mProgramObject) { if (mUniform.size() <= index) @@ -1380,6 +1417,8 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) { + LL_PROFILE_ZONE_SCOPED; + GLint ret = -1; if (mProgramObject) { @@ -1404,10 +1443,16 @@ GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform) GLint LLGLSLShader::getUniformLocation(U32 index) { + LL_PROFILE_ZONE_SCOPED; + GLint ret = -1; if (mProgramObject) { - llassert(index < mUniform.size()); + if (index >= mUniform.size()) + { + LL_WARNS_ONCE("Shader") << "Uniform index " << index << " out of bounds " << (S32)mUniform.size() << LL_ENDL; + return ret; + } return mUniform[index]; } @@ -1416,6 +1461,8 @@ GLint LLGLSLShader::getUniformLocation(U32 index) GLint LLGLSLShader::getAttribLocation(U32 attrib) { + LL_PROFILE_ZONE_SCOPED; + if (attrib < mAttribute.size()) { return mAttribute[attrib]; @@ -1432,7 +1479,7 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v) if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v,0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1448,7 +1495,7 @@ void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(i,j,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1465,7 +1512,7 @@ void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v) if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(v,0.f,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1481,7 +1528,7 @@ void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLf if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(x,y,0.f,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1498,7 +1545,7 @@ void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLf if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); LLVector4 vec(x,y,z,0.f); if (iter == mValue.end() || shouldChange(iter->second,vec)) { @@ -1514,7 +1561,7 @@ void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + 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) { @@ -1530,7 +1577,7 @@ void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + 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) { @@ -1546,7 +1593,7 @@ void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + 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) { @@ -1563,12 +1610,11 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co if (location >= 0) { LLVector4 vec(v); - std::map<GLint, LLVector4>::iterator iter = mValue.find(location); + const auto& iter = mValue.find(location); if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) { - stop_glerror(); + LL_PROFILE_ZONE_SCOPED; glUniform4fvARB(location, count, v); - stop_glerror(); mValue[location] = vec; } } @@ -1608,3 +1654,27 @@ void LLGLSLShader::setMinimumAlpha(F32 minimum) gGL.flush(); uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum); } + +void LLShaderUniforms::apply(LLGLSLShader* shader) +{ + LL_PROFILE_ZONE_SCOPED; + for (auto& uniform : mIntegers) + { + shader->uniform1i(uniform.mUniform, uniform.mValue); + } + + for (auto& uniform : mFloats) + { + shader->uniform1f(uniform.mUniform, uniform.mValue); + } + + for (auto& uniform : mVectors) + { + shader->uniform4fv(uniform.mUniform, 1, uniform.mValue.mV); + } + + for (auto& uniform : mVector3s) + { + shader->uniform3fv(uniform.mUniform, 1, uniform.mValue.mV); + } +} diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7cf6d3c941..85e83dbcb9 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -30,6 +30,7 @@ #include "llgl.h" #include "llrender.h" #include "llstaticstringtable.h" +#include <unordered_map> class LLShaderFeatures { @@ -64,16 +65,79 @@ public: LLShaderFeatures(); }; +// ============= Structure for caching shader uniforms =============== +class LLGLSLShader; + +class LLShaderUniforms +{ +public: + + template<typename T> + struct UniformSetting + { + S32 mUniform; + T mValue; + }; + + typedef UniformSetting<S32> IntSetting; + typedef UniformSetting<F32> FloatSetting; + typedef UniformSetting<LLVector4> VectorSetting; + typedef UniformSetting<LLVector3> Vector3Setting; + + void clear() + { + mIntegers.resize(0); + mFloats.resize(0); + mVectors.resize(0); + mVector3s.resize(0); + } + + void uniform1i(S32 index, S32 value) + { + mIntegers.push_back({ index, value }); + } + + void uniform1f(S32 index, F32 value) + { + mFloats.push_back({ index, value }); + } + + void uniform4fv(S32 index, const LLVector4& value) + { + mVectors.push_back({ index, value }); + } + + void uniform4fv(S32 index, const F32* value) + { + mVectors.push_back({ index, LLVector4(value) }); + } + + void uniform3fv(S32 index, const LLVector3& value) + { + mVector3s.push_back({ index, value }); + } + + void apply(LLGLSLShader* shader); + + + std::vector<IntSetting> mIntegers; + std::vector<FloatSetting> mFloats; + std::vector<VectorSetting> mVectors; + std::vector<Vector3Setting> mVector3s; +}; class LLGLSLShader { public: - enum + // enum primarily used to control application sky settings uniforms + typedef enum { - SG_DEFAULT = 0, - SG_SKY, - SG_WATER - }; + SG_DEFAULT = 0, // not sky or water specific + SG_SKY, // + SG_WATER, + SG_ANY, + SG_COUNT + } eGroup; static std::set<LLGLSLShader*> sInstances; static bool sProfileEnabled; @@ -84,7 +148,6 @@ public: static GLhandleARB sCurBoundShader; static LLGLSLShader* sCurBoundShaderPtr; static S32 sIndexedTextureChannels; - static bool sNoFixedFunction; static void initProfile(); static void finishProfile(bool emit_report = true); @@ -166,6 +229,8 @@ public: BOOL link(BOOL suppress_errors = FALSE); void bind(); + //helper to conditionally bind mRiggedVariant instead of this + void bind(bool rigged); void unbind(); // Unbinds any previously bound shader by explicitly binding no shader. @@ -190,18 +255,21 @@ public: U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location - std::map<GLint, std::string> mUniformNameMap; //lookup map of uniform location to uniform name - std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value + typedef std::unordered_map<GLint, std::string> uniform_name_map_t; + typedef std::unordered_map<GLint, LLVector4> 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<GLint> mTexture; S32 mTotalUniformSize; S32 mActiveTextureChannels; S32 mShaderLevel; - S32 mShaderGroup; + S32 mShaderGroup; // see LLGLSLShader::eGroup BOOL mUniformsDirty; LLShaderFeatures mFeatures; std::vector< std::pair< std::string, GLenum > > mShaderFiles; std::string mName; - boost::unordered_map<std::string, std::string> mDefines; + typedef std::unordered_map<std::string, std::string> defines_map_t; + defines_map_t mDefines; //statistcis for profiling shader performance U32 mTimerQuery; @@ -219,6 +287,9 @@ public: std::vector<U32> mTextureMagFilter; std::vector<U32> mTextureMinFilter; + // this pointer should be set to whichever shader represents this shader's rigged variant + LLGLSLShader* mRiggedVariant = nullptr; + private: void unloadInternal(); }; diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index ad501687ed..a279e85bae 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -262,6 +262,7 @@ LLTexUnit::eTextureType LLGLTexture::getTarget(void) const BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) { + LL_PROFILE_ZONE_SCOPED; llassert(mGLTexturep.notNull()) ; return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; @@ -269,6 +270,7 @@ BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) { + LL_PROFILE_ZONE_SCOPED; llassert(mGLTexturep.notNull()) ; return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 071912c2c2..028457c510 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -176,7 +176,7 @@ private: protected: void setTexelsPerImage(); - //note: do not make this function public. +public: /*virtual*/ LLImageGL* getGLTexture() const ; protected: diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 0151d20128..9931ce7d3e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -39,6 +39,11 @@ #include "llgl.h" #include "llglslshader.h" #include "llrender.h" +#include "llwindow.h" + +#if !LL_IMAGEGL_THREAD_CHECK +#define checkActiveThread() +#endif //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; @@ -61,9 +66,11 @@ F32 LLImageGL::sLastFrameTime = 0.f; BOOL LLImageGL::sAllowReadBackRaw = FALSE ; LLImageGL* LLImageGL::sDefaultGLTexture = NULL ; bool LLImageGL::sCompressTextures = false; - std::set<LLImageGL*> LLImageGL::sImageList; + +bool LLImageGLThread::sEnabled = false; + //**************************************************************************************************** //The below for texture auditing use only //**************************************************************************************************** @@ -170,15 +177,24 @@ BOOL is_little_endian() return (*c == 0x78) ; } + //static -void LLImageGL::initClass(S32 num_catagories, BOOL skip_analyze_alpha /* = false */) +void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */, bool multi_threaded /* = false */) { + LL_PROFILE_ZONE_SCOPED; sSkipAnalyzeAlpha = skip_analyze_alpha; + + if (multi_threaded) + { + LLImageGLThread::createInstance(window); + } } //static void LLImageGL::cleanupClass() -{ +{ + LL_PROFILE_ZONE_SCOPED; + LLImageGLThread::deleteSingleton(); } //static @@ -258,11 +274,10 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) //---------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_STATS("Image Stats"); // static void LLImageGL::updateStats(F32 current_time) { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_STATS); + LL_PROFILE_ZONE_SCOPED; sLastFrameTime = current_time; sBoundTextureMemory = sCurBoundTextureMemory; sCurBoundTextureMemory = S32Bytes(0); @@ -295,10 +310,8 @@ void LLImageGL::destroyGL(BOOL save_state) if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) { glimage->mSaveData = new LLImageRaw; - glimage->claimMem(glimage->mSaveData); if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it. { - glimage->disclaimMem(glimage->mSaveData); glimage->mSaveData = NULL ; } } @@ -372,8 +385,7 @@ BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, B //---------------------------------------------------------------------------- LLImageGL::LLImageGL(BOOL usemipmaps) -: LLTrace::MemTrackable<LLImageGL>("LLImageGL"), - mSaveData(0), mExternalTexture(FALSE) +: mSaveData(0), mExternalTexture(FALSE) { init(usemipmaps); setSize(0, 0, 0); @@ -382,8 +394,7 @@ LLImageGL::LLImageGL(BOOL usemipmaps) } LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps) -: LLTrace::MemTrackable<LLImageGL>("LLImageGL"), - mSaveData(0), mExternalTexture(FALSE) +: mSaveData(0), mExternalTexture(FALSE) { llassert( components <= 4 ); init(usemipmaps); @@ -393,8 +404,7 @@ LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps) } LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps) -: LLTrace::MemTrackable<LLImageGL>("LLImageGL"), - mSaveData(0), mExternalTexture(FALSE) +: mSaveData(0), mExternalTexture(FALSE) { init(usemipmaps); setSize(0, 0, 0); @@ -412,7 +422,6 @@ LLImageGL::LLImageGL( LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode) - : LLTrace::MemTrackable<LLImageGL>("LLImageGL"), mSaveData(0), mExternalTexture(TRUE) { init(false); mTexName = texName; @@ -438,6 +447,10 @@ LLImageGL::~LLImageGL() void LLImageGL::init(BOOL usemipmaps) { +#if LL_IMAGEGL_THREAD_CHECK + mActiveThread = LLThread::currentID(); +#endif + // keep these members in the same order as declared in llimagehl.h // so that it is obvious by visual inspection if we forgot to // init a field. @@ -493,6 +506,9 @@ void LLImageGL::init(BOOL usemipmaps) #endif mCategory = -1; + + // Sometimes we have to post work for the main thread. + mMainQueue = LL::WorkQueue::getInstance("mainloop"); } void LLImageGL::cleanup() @@ -540,12 +556,6 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve return false; } - if (mTexName) - { -// LL_WARNS() << "Setting Size of LLImageGL with existing mTexName = " << mTexName << LL_ENDL; - destroyGLTexture(); - } - // pickmask validity depends on old image size, delete it freePickMask(); @@ -656,6 +666,7 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for void LLImageGL::setImage(const LLImageRaw* imageraw) { + LL_PROFILE_ZONE_SCOPED; llassert((imageraw->getWidth() == getWidth(mCurrentDiscardLevel)) && (imageraw->getHeight() == getHeight(mCurrentDiscardLevel)) && (imageraw->getComponents() == getComponents())); @@ -663,10 +674,9 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) setImage(rawdata, FALSE); } -static LLTrace::BlockTimerStatHandle FTM_SET_IMAGE("setImage"); -BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) +BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips, S32 usename) { - LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE); + LL_PROFILE_ZONE_SCOPED; bool is_compressed = false; switch (mFormatPrimary) @@ -683,12 +693,11 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) break; } - - if (mUseMipMaps) { //set has mip maps to true before binding image so tex parameters get set properly - gGL.getTexUnit(0)->unbind(mBindTarget); + gGL.getTexUnit(0)->unbind(mBindTarget); + mHasMipMaps = true; mTexOptionsDirty = true; setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); @@ -698,10 +707,10 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) mHasMipMaps = false; } - llverify(gGL.getTexUnit(0)->bind(this)); - - - if (mUseMipMaps) + gGL.getTexUnit(0)->bind(this, false, false, usename); + + + if (mUseMipMaps) { if (data_hasmips) { @@ -728,8 +737,6 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } else { -// LL_RECORD_BLOCK_TIME(FTM_TEMP4); - if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); @@ -760,8 +767,6 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { stop_glerror(); { -// LL_RECORD_BLOCK_TIME(FTM_TEMP4); - if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); @@ -781,7 +786,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); } - LLImageGL::setManualImage(mTarget, 0, mFormatInternal, + LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, data_in, mAllowCompression); @@ -871,14 +876,13 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) llassert(w > 0 && h > 0 && cur_mip_data); (void)cur_mip_data; { -// LL_RECORD_BLOCK_TIME(FTM_TEMP4); if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } - LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); + LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); if (m == 0) { analyzeAlpha(data_in, w, h); @@ -1067,6 +1071,7 @@ void LLImageGL::postAddToAtlas() BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { + LL_PROFILE_ZONE_SCOPED; if (!width || !height) { return TRUE; @@ -1163,6 +1168,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { + LL_PROFILE_ZONE_SCOPED; return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); } @@ -1183,15 +1189,14 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } // static -static LLTrace::BlockTimerStatHandle FTM_GENERATE_TEXTURES("generate textures"); void LLImageGL::generateTextures(S32 numTextures, U32 *textures) { - LL_RECORD_BLOCK_TIME(FTM_GENERATE_TEXTURES); + LL_PROFILE_ZONE_SCOPED; glGenTextures(numTextures, textures); } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) +void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures) { if (gGLManager.mInited) { @@ -1200,125 +1205,128 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) } // static -static LLTrace::BlockTimerStatHandle FTM_SET_MANUAL_IMAGE("setManualImage"); -void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression) +void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression) { - LL_RECORD_BLOCK_TIME(FTM_SET_MANUAL_IMAGE); - bool use_scratch = false; - U32* scratch = NULL; - if (LLRender::sGLCoreProfile) - { - if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) - { //GL_ALPHA is deprecated, convert to RGBA - use_scratch = true; - scratch = new U32[width*height]; + LL_PROFILE_ZONE_SCOPED; + bool use_scratch = false; + U32* scratch = NULL; + if (LLRender::sGLCoreProfile) + { + if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE) + { //GL_ALPHA is deprecated, convert to RGBA + use_scratch = true; + scratch = new U32[width * height]; - U32 pixel_count = (U32) (width*height); - for (U32 i = 0; i < pixel_count; i++) - { - U8* pix = (U8*) &scratch[i]; - pix[0] = pix[1] = pix[2] = 0; - pix[3] = ((U8*) pixels)[i]; - } - - pixformat = GL_RGBA; - intformat = GL_RGBA8; - } + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = 0; + pix[3] = ((U8*)pixels)[i]; + } - if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) - { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA - use_scratch = true; - scratch = new U32[width*height]; + pixformat = GL_RGBA; + intformat = GL_RGBA8; + } - U32 pixel_count = (U32) (width*height); - for (U32 i = 0; i < pixel_count; i++) - { - U8 lum = ((U8*) pixels)[i*2+0]; - U8 alpha = ((U8*) pixels)[i*2+1]; + if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA + use_scratch = true; + scratch = new U32[width * height]; - U8* pix = (U8*) &scratch[i]; - pix[0] = pix[1] = pix[2] = lum; - pix[3] = alpha; - } - - pixformat = GL_RGBA; - intformat = GL_RGBA8; - } + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8 lum = ((U8*)pixels)[i * 2 + 0]; + U8 alpha = ((U8*)pixels)[i * 2 + 1]; - if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) - { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB - use_scratch = true; - scratch = new U32[width*height]; + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = lum; + pix[3] = alpha; + } - U32 pixel_count = (U32) (width*height); - for (U32 i = 0; i < pixel_count; i++) - { - U8 lum = ((U8*) pixels)[i]; - - U8* pix = (U8*) &scratch[i]; - pix[0] = pix[1] = pix[2] = lum; - pix[3] = 255; - } - - pixformat = GL_RGBA; - intformat = GL_RGB8; - } - } + pixformat = GL_RGBA; + intformat = GL_RGBA8; + } - if (LLImageGL::sCompressTextures && allow_compression) - { - switch (intformat) - { - case GL_RGB: - case GL_RGB8: - intformat = GL_COMPRESSED_RGB; - break; - case GL_SRGB: - case GL_SRGB8: - intformat = GL_COMPRESSED_SRGB; - break; - case GL_RGBA: - case GL_RGBA8: - intformat = GL_COMPRESSED_RGBA; - break; - case GL_SRGB_ALPHA: - case GL_SRGB8_ALPHA8: - intformat = GL_COMPRESSED_SRGB_ALPHA; - break; - case GL_LUMINANCE: - case GL_LUMINANCE8: - intformat = GL_COMPRESSED_LUMINANCE; - break; - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE8_ALPHA8: - intformat = GL_COMPRESSED_LUMINANCE_ALPHA; - break; - case GL_ALPHA: - case GL_ALPHA8: - intformat = GL_COMPRESSED_ALPHA; - break; - default: - LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; - break; - } - } + if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE) + { //GL_LUMINANCE_ALPHA is deprecated, convert to RGB + use_scratch = true; + scratch = new U32[width * height]; - stop_glerror(); - glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); - stop_glerror(); + U32 pixel_count = (U32)(width * height); + for (U32 i = 0; i < pixel_count; i++) + { + U8 lum = ((U8*)pixels)[i]; - if (use_scratch) - { - delete [] scratch; - } + U8* pix = (U8*)&scratch[i]; + pix[0] = pix[1] = pix[2] = lum; + pix[3] = 255; + } + + pixformat = GL_RGBA; + intformat = GL_RGB8; + } + } + + if (LLImageGL::sCompressTextures && allow_compression) + { + switch (intformat) + { + case GL_RGB: + case GL_RGB8: + intformat = GL_COMPRESSED_RGB; + break; + case GL_SRGB: + case GL_SRGB8: + intformat = GL_COMPRESSED_SRGB; + break; + case GL_RGBA: + case GL_RGBA8: + intformat = GL_COMPRESSED_RGBA; + break; + case GL_SRGB_ALPHA: + case GL_SRGB8_ALPHA8: + intformat = GL_COMPRESSED_SRGB_ALPHA; + break; + case GL_LUMINANCE: + case GL_LUMINANCE8: + intformat = GL_COMPRESSED_LUMINANCE; + break; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE8_ALPHA8: + intformat = GL_COMPRESSED_LUMINANCE_ALPHA; + break; + case GL_ALPHA: + case GL_ALPHA8: + intformat = GL_COMPRESSED_ALPHA; + break; + default: + LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; + break; + } + } + + stop_glerror(); + { + LL_PROFILE_ZONE_NAMED("glTexImage2D"); + glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels); + } + stop_glerror(); + + if (use_scratch) + { + delete[] scratch; + } } //create an empty GL texture: just create a texture name //the texture is assiciate with some image by calling glTexImage outside LLImageGL -static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE1("createGLTexture()"); BOOL LLImageGL::createGLTexture() { - LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE1); + LL_PROFILE_ZONE_SCOPED; + checkActiveThread(); + if (gGLManager.mIsDisabled) { LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL; @@ -1333,6 +1341,7 @@ BOOL LLImageGL::createGLTexture() if(mTexName) { LLImageGL::deleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ; + mTexName = 0; } @@ -1347,23 +1356,24 @@ BOOL LLImageGL::createGLTexture() return TRUE ; } -static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE2("createGLTexture(raw)"); BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) { - LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE2); + LL_PROFILE_ZONE_SCOPED; + checkActiveThread(); + if (gGLManager.mIsDisabled) { LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL; return FALSE; } - mGLTextureCreated = false ; llassert(gGLManager.mInited); stop_glerror(); if (!imageraw || imageraw->isBufferInvalid()) { LL_WARNS() << "Trying to create a texture from invalid image data" << LL_ENDL; + mGLTextureCreated = false; return FALSE; } @@ -1383,6 +1393,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S if (!setSize(w, h, imageraw->getComponents(), discard_level)) { LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL; + mGLTextureCreated = false; return FALSE; } @@ -1451,6 +1462,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S destroyGLTexture(); mCurrentDiscardLevel = discard_level; mLastBindTime = sLastFrameTime; + mGLTextureCreated = false; return TRUE ; } @@ -1459,107 +1471,120 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S return createGLTexture(discard_level, rawdata, FALSE, usename); } -static LLTrace::BlockTimerStatHandle FTM_CREATE_GL_TEXTURE3("createGLTexture3(data)"); BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { - LL_RECORD_BLOCK_TIME(FTM_CREATE_GL_TEXTURE3); - llassert(data_in); - stop_glerror(); + LL_PROFILE_ZONE_SCOPED; + checkActiveThread(); - if (discard_level < 0) - { - llassert(mCurrentDiscardLevel >= 0); - discard_level = mCurrentDiscardLevel; - } - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); + llassert(data_in); + stop_glerror(); - if (mTexName != 0 && discard_level == mCurrentDiscardLevel) - { - // This will only be true if the size has not changed - return setImage(data_in, data_hasmips); - } - - U32 old_name = mTexName; -// S32 old_discard = mCurrentDiscardLevel; - - if (usename != 0) - { - mTexName = usename; - } - else - { - LLImageGL::generateTextures(1, &mTexName); - stop_glerror(); - { - llverify(gGL.getTexUnit(0)->bind(this)); - stop_glerror(); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); - stop_glerror(); - glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level); - stop_glerror(); - } - } - if (!mTexName) - { - if (old_name) - { - sGlobalTextureMemory -= mTextureMemory; - LLImageGL::deleteTextures(1, &old_name); - disclaimMem(mTextureMemory); - stop_glerror(); - } + if (discard_level < 0) + { + llassert(mCurrentDiscardLevel >= 0); + discard_level = mCurrentDiscardLevel; + } + discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - LL_WARNS() << "LLImageGL::createGLTexture failed to make texture" << LL_ENDL; - return FALSE; - } + if (mTexName != 0 && discard_level == mCurrentDiscardLevel) + { + // This will only be true if the size has not changed + return setImage(data_in, data_hasmips); + } - if (mUseMipMaps) - { - mAutoGenMips = gGLManager.mHasMipMapGeneration; -#if LL_DARWIN - // On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. - if(gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) - { - mAutoGenMips = FALSE; - } -#endif - } + GLuint old_texname = mTexName; + + if (usename != 0) + { + mNewTexName = usename; + } + else + { + LLImageGL::generateTextures(1, &mNewTexName); + { + gGL.getTexUnit(0)->bind(this, false, false, mNewTexName); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel - discard_level); + } + } + + if (mUseMipMaps) + { + mAutoGenMips = gGLManager.mHasMipMapGeneration; + } - mCurrentDiscardLevel = discard_level; + mCurrentDiscardLevel = discard_level; - if (!setImage(data_in, data_hasmips)) - { - stop_glerror(); - return FALSE; - } + if (!setImage(data_in, data_hasmips, mNewTexName)) + { + return FALSE; + } - // Set texture options to our defaults. - gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); - gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); - gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + // Set texture options to our defaults. + gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); + gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); + gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); - // things will break if we don't unbind after creation - gGL.getTexUnit(0)->unbind(mBindTarget); - stop_glerror(); + // things will break if we don't unbind after creation + gGL.getTexUnit(0)->unbind(mBindTarget); - if (old_name != 0) - { - sGlobalTextureMemory -= mTextureMemory; + if (old_texname != 0) + { + sGlobalTextureMemory -= mTextureMemory; + } - LLImageGL::deleteTextures(1, &old_name); + //if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread + if (! on_main_thread()) + { + { + LL_PROFILE_ZONE_NAMED("cglt - sync"); + if (gGLManager.mHasSync) + { + auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + glClientWaitSync(sync, 0, 0); + glDeleteSync(sync); + } + else + { + glFinish(); + } + } - stop_glerror(); - } + ref(); + LL::WorkQueue::postMaybe( + mMainQueue, + [=]() + { + LL_PROFILE_ZONE_NAMED("cglt - delete callback"); + if (old_texname != 0) + { + LLImageGL::deleteTextures(1, &old_texname); + } + mTexName = mNewTexName; + mNewTexName = 0; + unref(); + }); + } + else + { + //not on background thread, immediately set mTexName + if (old_texname != 0) + { + LLImageGL::deleteTextures(1, &old_texname); + } + mTexName = mNewTexName; + mNewTexName = 0; + } + + mTextureMemory = (S32Bytes)getMipBytes(mCurrentDiscardLevel); + sGlobalTextureMemory += mTextureMemory; + mTexelsInGLTexture = getWidth() * getHeight(); - disclaimMem(mTextureMemory); - mTextureMemory = (S32Bytes)getMipBytes(discard_level); - claimMem(mTextureMemory); - sGlobalTextureMemory += mTextureMemory; - mTexelsInGLTexture = getWidth() * getHeight() ; + // mark this as bound at this point, so we don't throw it out immediately + mLastBindTime = sLastFrameTime; - // mark this as bound at this point, so we don't throw it out immediately - mLastBindTime = sLastFrameTime; - return TRUE; + checkActiveThread(); + return TRUE; } BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const @@ -1673,28 +1698,19 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return TRUE ; } -void LLImageGL::deleteDeadTextures() -{ - bool reset = false; - - if (reset) - { - gGL.getTexUnit(0)->activate(); - } -} - void LLImageGL::destroyGLTexture() { + checkActiveThread(); + if (mTexName != 0) { if(mTextureMemory != S32Bytes(0)) { sGlobalTextureMemory -= mTextureMemory; - disclaimMem(mTextureMemory); mTextureMemory = (S32Bytes)0; } - LLImageGL::deleteTextures(1, &mTexName); + LLImageGL::deleteTextures(1, &mTexName); mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mTexName = 0; mGLTextureCreated = FALSE ; @@ -1704,6 +1720,7 @@ void LLImageGL::destroyGLTexture() //force to invalidate the gl texture, most likely a sculpty texture void LLImageGL::forceToInvalidateGLTexture() { + checkActiveThread(); if (mTexName != 0) { destroyGLTexture(); @@ -2043,7 +2060,6 @@ U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight) U32 size = pick_width * pick_height; size = (size + 7) / 8; // pixelcount-to-bits mPickMask = new U8[size]; - claimMem(size); mPickMaskWidth = pick_width - 1; mPickMaskHeight = pick_height - 1; @@ -2058,7 +2074,6 @@ void LLImageGL::freePickMask() // pickmask validity depends on old image size, delete it if (mPickMask != NULL) { - disclaimMem((mPickMaskWidth * mPickMaskHeight + 7) / 8); delete [] mPickMask; } mPickMask = NULL; @@ -2182,6 +2197,12 @@ void LLImageGL::resetCurTexSizebar() sCurTexPickSize = -1 ; } //---------------------------------------------------------------------------- +#if LL_IMAGEGL_THREAD_CHECK +void LLImageGL::checkActiveThread() +{ + llassert(mActiveThread == LLThread::currentID()); +} +#endif //---------------------------------------------------------------------------- @@ -2235,3 +2256,30 @@ void LLImageGL::resetCurTexSizebar() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips); */ + +LLImageGLThread::LLImageGLThread(LLWindow* window) + // We want exactly one thread, but a very large capacity: we never want + // anyone, especially inner-loop render code, to have to block on post() + // because we're full. + : ThreadPool("LLImageGL", 1, 1024*1024) + , mWindow(window) +{ + LL_PROFILE_ZONE_SCOPED; + sEnabled = true; + mFinished = false; + + mContext = mWindow->createSharedContext(); + ThreadPool::start(); +} + +void LLImageGLThread::run() +{ + LL_PROFILE_ZONE_SCOPED; + // We must perform setup on this thread before actually servicing our + // WorkQueue, likewise cleanup afterwards. + mWindow->makeContextCurrent(mContext); + gGL.init(); + ThreadPool::run(); + gGL.shutdown(); + mWindow->destroySharedContext(mContext); +} diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 61ddc8d59b..d6f4b13a51 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -35,21 +35,26 @@ #include "llrefcount.h" #include "v2math.h" #include "llunits.h" - +#include "llthreadsafequeue.h" #include "llrender.h" -class LLTextureAtlas ; +#include "threadpool.h" +#include "workqueue.h" + +#define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL + +class LLWindow; + #define BYTES_TO_MEGA_BYTES(x) ((x) >> 20) #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) //============================================================================ -class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL> +class LLImageGL : public LLRefCount { friend class LLTexUnit; public: // These 2 functions replace glGenTextures() and glDeleteTextures() static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures); - static void deleteDeadTextures(); + static void deleteTextures(S32 numTextures, const U32 *textures); // Size calculation static S32 dataFormatBits(S32 dataformat); @@ -102,13 +107,13 @@ public: void setAllowCompression(bool allow) { mAllowCompression = allow; } static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true); - + BOOL createGLTexture() ; BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = sMaxCategories-1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); - BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE); + BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0); BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); @@ -184,6 +189,12 @@ public: BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image); void postAddToAtlas() ; +#if LL_IMAGEGL_THREAD_CHECK + // thread debugging + std::thread::id mActiveThread; + void checkActiveThread(); +#endif + public: // Various GL/Rendering options S32Bytes mTextureMemory; @@ -194,6 +205,7 @@ private: void freePickMask(); LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL + LL::WorkQueue::weak_t mMainQueue; U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel U16 mPickMaskWidth; U16 mPickMaskHeight; @@ -208,8 +220,9 @@ private: bool mGLTextureCreated ; LLGLuint mTexName; + LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread U16 mWidth; - U16 mHeight; + U16 mHeight; S8 mCurrentDiscardLevel; S8 mDiscardLevelInAtlas; @@ -265,7 +278,7 @@ public: #endif public: - static void initClass(S32 num_catagories, BOOL skip_analyze_alpha = false); + static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool multi_threaded = false); static void cleanupClass() ; private: @@ -301,4 +314,28 @@ public: }; +class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool +{ +public: + // follows gSavedSettings "RenderGLMultiThreaded" + static bool sEnabled; + + LLImageGLThread(LLWindow* window); + + // post a function to be executed on the LLImageGL background thread + template <typename CALLABLE> + bool post(CALLABLE&& func) + { + return getQueue().postIfOpen(std::forward<CALLABLE>(func)); + } + + void run() override; + +private: + LLWindow* mWindow; + void* mContext = nullptr; + LLAtomicBool mFinished; +}; + + #endif // LL_LLIMAGEGL_H diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 03b6aac20c..8b4f250894 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -36,7 +36,7 @@ #include "lltexture.h" #include "llshadermgr.h" -LLRender gGL; +thread_local LLRender gGL; // Handy copies of last good GL matrices F32 gGLModelView[16]; @@ -71,18 +71,6 @@ static const GLint sGLAddressMode[] = GL_CLAMP_TO_EDGE }; -static const GLenum sGLCompareFunc[] = -{ - GL_NEVER, - GL_ALWAYS, - GL_LESS, - GL_LEQUAL, - GL_EQUAL, - GL_NOTEQUAL, - GL_GEQUAL, - GL_GREATER -}; - const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; static const GLenum sGLBlendFactor[] = @@ -102,10 +90,7 @@ static const GLenum sGLBlendFactor[] = }; LLTexUnit::LLTexUnit(S32 index) - : mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT), - mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), - mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), - mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), + : mCurrTexType(TT_NONE), mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR), mHasMipMaps(false), mIndex(index) @@ -128,42 +113,15 @@ void LLTexUnit::refreshState(void) glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); - // - // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units - // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html - // - bool enableDisable = !LLGLSLShader::sNoFixedFunction && - (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE; - if (mCurrTexType != TT_NONE) { - if (enableDisable) - { - glEnable(sGLTextureType[mCurrTexType]); - } - glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); } else { - if (enableDisable) - { - glDisable(GL_TEXTURE_2D); - } - glBindTexture(GL_TEXTURE_2D, 0); } - if (mCurrBlendType != TB_COMBINE) - { - setTextureBlendType(mCurrBlendType); - } - else - { - setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false); - setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true); - } - setTextureColorSpace(mTexColorSpace); } @@ -196,14 +154,6 @@ void LLTexUnit::enable(eTextureType type) mCurrTexType = type; gGL.flush(); - if (!LLGLSLShader::sNoFixedFunction && - type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && - mIndex < gGLManager.mNumTextureUnits) - { - stop_glerror(); - glEnable(sGLTextureType[type]); - stop_glerror(); - } } } @@ -216,21 +166,34 @@ void LLTexUnit::disable(void) activate(); unbind(mCurrTexType); gGL.flush(); - if (!LLGLSLShader::sNoFixedFunction && - mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && - mIndex < gGLManager.mNumTextureUnits) - { - glDisable(sGLTextureType[mCurrTexType]); - } - setTextureColorSpace(TCS_LINEAR); mCurrTexType = TT_NONE; } } +void LLTexUnit::bindFast(LLTexture* texture) +{ + LLImageGL* gl_tex = texture->getGLTexture(); + + glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); + gGL.mCurrTextureUnitIndex = mIndex; + mCurrTexture = gl_tex->getTexName(); + if (!mCurrTexture) + { + LL_PROFILE_ZONE_NAMED("MISSING TEXTURE"); + //if deleted, will re-generate it immediately + texture->forceImmediateUpdate(); + gl_tex->forceUpdateBindStats(); + texture->bindDefaultImage(mIndex); + } + glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); + mHasMipMaps = gl_tex->mHasMipMaps; +} + bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) { + LL_PROFILE_ZONE_SCOPED; stop_glerror(); if (mIndex >= 0) { @@ -294,18 +257,20 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) return true; } -bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) +bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 usename) { stop_glerror(); if (mIndex < 0) return false; + U32 texname = usename ? usename : texture->getTexName(); + if(!texture) { LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; return false; } - if(!texture->getTexName()) + if(!texname) { if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName()) { @@ -315,7 +280,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) return false ; } - if ((mCurrTexture != texture->getTexName()) || forceBind) + if ((mCurrTexture != texname) || forceBind) { gGL.flush(); stop_glerror(); @@ -323,7 +288,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) stop_glerror(); enable(texture->getTarget()); stop_glerror(); - mCurrTexture = texture->getTexName(); + mCurrTexture = texname; glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); stop_glerror(); texture->updateBindStats(texture->mTextureMemory); @@ -447,7 +412,7 @@ void LLTexUnit::unbind(eTextureType type) // Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping". mTexColorSpace = TCS_LINEAR; - if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) + if (type == LLTexUnit::TT_TEXTURE) { glBindTexture(sGLTextureType[type], sWhiteTexture); } @@ -459,6 +424,28 @@ void LLTexUnit::unbind(eTextureType type) } } +void LLTexUnit::unbindFast(eTextureType type) +{ + activate(); + + // Disabled caching of binding state. + if (mCurrTexType == type) + { + mCurrTexture = 0; + + // Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping". + mTexColorSpace = TCS_LINEAR; + if (type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } + } +} + void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) { if (mIndex < 0 || mCurrTexture == 0) return; @@ -537,55 +524,6 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio } } -void LLTexUnit::setTextureBlendType(eTextureBlendType type) -{ - if (LLGLSLShader::sNoFixedFunction) - { //texture blend type means nothing when using shaders - return; - } - - if (mIndex < 0) return; - - // Do nothing if it's already correctly set. - if (mCurrBlendType == type && !gGL.mDirty) - { - return; - } - - gGL.flush(); - - activate(); - mCurrBlendType = type; - S32 scale_amount = 1; - switch (type) - { - case TB_REPLACE: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - break; - case TB_ADD: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); - break; - case TB_MULT: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - break; - case TB_MULT_X2: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - scale_amount = 2; - break; - case TB_ALPHA_BLEND: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); - break; - case TB_COMBINE: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); - break; - default: - LL_ERRS() << "Unknown Texture Blend Type: " << type << LL_ENDL; - break; - } - setColorScale(scale_amount); - setAlphaScale(1); -} - GLint LLTexUnit::getTextureSource(eTextureBlendSrc src) { switch(src) @@ -662,159 +600,6 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) } } -void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha) -{ - if (LLGLSLShader::sNoFixedFunction) - { //register combiners do nothing when not using fixed function - return; - } - - if (mIndex < 0) return; - - activate(); - if (mCurrBlendType != TB_COMBINE || gGL.mDirty) - { - mCurrBlendType = TB_COMBINE; - gGL.flush(); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); - } - - // We want an early out, because this function does a LOT of stuff. - if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2)) - || (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty) - { - return; - } - - gGL.flush(); - - // Get the gl source enums according to the eTextureBlendSrc sources passed in - GLint source1 = getTextureSource(src1); - GLint source2 = getTextureSource(src2); - // Get the gl operand enums according to the eTextureBlendSrc sources passed in - GLint operand1 = getTextureSourceType(src1, isAlpha); - GLint operand2 = getTextureSourceType(src2, isAlpha); - // Default the scale amount to 1 - S32 scale_amount = 1; - GLenum comb_enum, src0_enum, src1_enum, src2_enum, operand0_enum, operand1_enum, operand2_enum; - - if (isAlpha) - { - // Set enums to ALPHA ones - comb_enum = GL_COMBINE_ALPHA_ARB; - src0_enum = GL_SOURCE0_ALPHA_ARB; - src1_enum = GL_SOURCE1_ALPHA_ARB; - src2_enum = GL_SOURCE2_ALPHA_ARB; - operand0_enum = GL_OPERAND0_ALPHA_ARB; - operand1_enum = GL_OPERAND1_ALPHA_ARB; - operand2_enum = GL_OPERAND2_ALPHA_ARB; - - // cache current combiner - mCurrAlphaOp = op; - mCurrAlphaSrc1 = src1; - mCurrAlphaSrc2 = src2; - } - else - { - // Set enums to RGB ones - comb_enum = GL_COMBINE_RGB_ARB; - src0_enum = GL_SOURCE0_RGB_ARB; - src1_enum = GL_SOURCE1_RGB_ARB; - src2_enum = GL_SOURCE2_RGB_ARB; - operand0_enum = GL_OPERAND0_RGB_ARB; - operand1_enum = GL_OPERAND1_RGB_ARB; - operand2_enum = GL_OPERAND2_RGB_ARB; - - // cache current combiner - mCurrColorOp = op; - mCurrColorSrc1 = src1; - mCurrColorSrc2 = src2; - } - - switch(op) - { - case TBO_REPLACE: - // Slightly special syntax (no second sources), just set all and return. - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, src0_enum, source1); - glTexEnvi(GL_TEXTURE_ENV, operand0_enum, operand1); - (isAlpha) ? setAlphaScale(1) : setColorScale(1); - return; - - case TBO_MULT: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_MODULATE); - break; - - case TBO_MULT_X2: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_MODULATE); - scale_amount = 2; - break; - - case TBO_MULT_X4: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_MODULATE); - scale_amount = 4; - break; - - case TBO_ADD: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_ADD); - break; - - case TBO_ADD_SIGNED: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_ADD_SIGNED_ARB); - break; - - case TBO_SUBTRACT: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_SUBTRACT_ARB); - break; - - case TBO_LERP_VERT_ALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_PRIMARY_COLOR_ARB); - glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA); - break; - - case TBO_LERP_TEX_ALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA); - break; - - case TBO_LERP_PREV_ALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_PREVIOUS_ARB); - glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA); - break; - - case TBO_LERP_CONST_ALPHA: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_CONSTANT_ARB); - glTexEnvi(GL_TEXTURE_ENV, operand2_enum, GL_SRC_ALPHA); - break; - - case TBO_LERP_VERT_COLOR: - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, src2_enum, GL_PRIMARY_COLOR_ARB); - glTexEnvi(GL_TEXTURE_ENV, operand2_enum, (isAlpha) ? GL_SRC_ALPHA : GL_SRC_COLOR); - break; - - default: - LL_WARNS() << "Unknown eTextureBlendOp: " << op << ". Setting op to replace." << LL_ENDL; - // Slightly special syntax (no second sources), just set all and return. - glTexEnvi(GL_TEXTURE_ENV, comb_enum, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, src0_enum, source1); - glTexEnvi(GL_TEXTURE_ENV, operand0_enum, operand1); - (isAlpha) ? setAlphaScale(1) : setColorScale(1); - return; - } - - // Set sources, operands, and scale accordingly - glTexEnvi(GL_TEXTURE_ENV, src0_enum, source1); - glTexEnvi(GL_TEXTURE_ENV, operand0_enum, operand1); - glTexEnvi(GL_TEXTURE_ENV, src1_enum, source2); - glTexEnvi(GL_TEXTURE_ENV, operand1_enum, operand2); - (isAlpha) ? setAlphaScale(scale_amount) : setColorScale(scale_amount); -} - void LLTexUnit::setColorScale(S32 scale) { if (mCurrColorScale != scale || gGL.mDirty) @@ -903,26 +688,12 @@ LLLightState::LLLightState(S32 index) void LLLightState::enable() { - if (!mEnabled) - { - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHT0+mIndex); - } - mEnabled = true; - } + mEnabled = true; } void LLLightState::disable() { - if (mEnabled) - { - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHT0+mIndex); - } - mEnabled = false; - } + mEnabled = false; } void LLLightState::setDiffuse(const LLColor4& diffuse) @@ -931,10 +702,6 @@ void LLLightState::setDiffuse(const LLColor4& diffuse) { ++gGL.mLightHash; mDiffuse = diffuse; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_DIFFUSE, mDiffuse.mV); - } } } @@ -962,10 +729,6 @@ void LLLightState::setAmbient(const LLColor4& ambient) { ++gGL.mLightHash; mAmbient = ambient; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_AMBIENT, mAmbient.mV); - } } } @@ -975,10 +738,6 @@ void LLLightState::setSpecular(const LLColor4& specular) { ++gGL.mLightHash; mSpecular = specular; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_SPECULAR, mSpecular.mV); - } } } @@ -987,20 +746,11 @@ void LLLightState::setPosition(const LLVector4& position) //always set position because modelview matrix may have changed ++gGL.mLightHash; mPosition = position; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_POSITION, mPosition.mV); - } - else - { //transform position by current modelview matrix - glh::vec4f pos(position.mV); - - const glh::matrix4f& mat = gGL.getModelviewMatrix(); - mat.mult_matrix_vec(pos); - - mPosition.set(pos.v); - } - + //transform position by current modelview matrix + glh::vec4f pos(position.mV); + const glh::matrix4f& mat = gGL.getModelviewMatrix(); + mat.mult_matrix_vec(pos); + mPosition.set(pos.v); } void LLLightState::setConstantAttenuation(const F32& atten) @@ -1009,10 +759,6 @@ void LLLightState::setConstantAttenuation(const F32& atten) { mConstantAtten = atten; ++gGL.mLightHash; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_CONSTANT_ATTENUATION, atten); - } } } @@ -1022,10 +768,6 @@ void LLLightState::setLinearAttenuation(const F32& atten) { ++gGL.mLightHash; mLinearAtten = atten; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_LINEAR_ATTENUATION, atten); - } } } @@ -1035,10 +777,6 @@ void LLLightState::setQuadraticAttenuation(const F32& atten) { ++gGL.mLightHash; mQuadraticAtten = atten; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_QUADRATIC_ATTENUATION, atten); - } } } @@ -1048,10 +786,6 @@ void LLLightState::setSpotExponent(const F32& exponent) { ++gGL.mLightHash; mSpotExponent = exponent; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_SPOT_EXPONENT, exponent); - } } } @@ -1061,10 +795,6 @@ void LLLightState::setSpotCutoff(const F32& cutoff) { ++gGL.mLightHash; mSpotCutoff = cutoff; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightf(GL_LIGHT0+mIndex, GL_SPOT_CUTOFF, cutoff); - } } } @@ -1073,19 +803,12 @@ void LLLightState::setSpotDirection(const LLVector3& direction) //always set direction because modelview matrix may have changed ++gGL.mLightHash; mSpotDirection = direction; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightfv(GL_LIGHT0+mIndex, GL_SPOT_DIRECTION, direction.mV); - } - else - { //transform direction by current modelview matrix - glh::vec3f dir(direction.mV); - - const glh::matrix4f& mat = gGL.getModelviewMatrix(); - mat.mult_matrix_dir(dir); + //transform direction by current modelview matrix + glh::vec3f dir(direction.mV); + const glh::matrix4f& mat = gGL.getModelviewMatrix(); + mat.mult_matrix_dir(dir); - mSpotDirection.set(dir.v); - } + mSpotDirection.set(dir.v); } LLRender::LLRender() @@ -1113,8 +836,6 @@ LLRender::LLRender() mCurrColorMask[i] = true; } - mCurrAlphaFunc = CF_DEFAULT; - mCurrAlphaFuncVal = 0.01f; mCurrBlendColorSFactor = BF_UNDEF; mCurrBlendAlphaSFactor = BF_UNDEF; mCurrBlendColorDFactor = BF_UNDEF; @@ -1192,7 +913,7 @@ void LLRender::refreshState(void) setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]); - setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal); + flush(); mDirty = false; } @@ -1243,9 +964,7 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - stop_glerror(); - - static const U32 name[] = + static const U32 name[] = { LLShaderMgr::MODELVIEW_MATRIX, LLShaderMgr::PROJECTION_MATRIX, @@ -1382,41 +1101,6 @@ void LLRender::syncMatrices() syncLightState(); } } - else if (!LLGLSLShader::sNoFixedFunction) - { - static const GLenum mode[] = - { - GL_MODELVIEW, - GL_PROJECTION, - GL_TEXTURE, - GL_TEXTURE, - GL_TEXTURE, - GL_TEXTURE, - }; - - for (U32 i = 0; i < MM_TEXTURE0; ++i) - { - if (mMatHash[i] != mCurMatHash[i]) - { - glMatrixMode(mode[i]); - glLoadMatrixf(mMatrix[i][mMatIdx[i]].m); - mCurMatHash[i] = mMatHash[i]; - } - } - - for (U32 i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i) - { - if (mMatHash[i] != mCurMatHash[i]) - { - gGL.getTexUnit(i-MM_TEXTURE0)->activate(); - glMatrixMode(mode[i]); - glLoadMatrixf(mMatrix[i][mMatIdx[i]].m); - mCurMatHash[i] = mMatHash[i]; - } - } - } - - stop_glerror(); } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) @@ -1732,55 +1416,6 @@ void LLRender::setSceneBlendType(eBlendType type) } } -void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) -{ - flush(); - - if (LLGLSLShader::sNoFixedFunction) - { //glAlphaFunc is deprecated in OpenGL 3.3 - return; - } - - if (mCurrAlphaFunc != func || - mCurrAlphaFuncVal != value) - { - mCurrAlphaFunc = func; - mCurrAlphaFuncVal = value; - if (func == CF_DEFAULT) - { - glAlphaFunc(GL_GREATER, 0.01f); - } - else - { - glAlphaFunc(sGLCompareFunc[func], value); - } - } - - if (gDebugGL) - { //make sure cached state is correct - GLint cur_func = 0; - glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func); - - if (func == CF_DEFAULT) - { - func = CF_GREATER; - } - - if (cur_func != sGLCompareFunc[func]) - { - LL_ERRS() << "Alpha test function corrupted!" << LL_ENDL; - } - - F32 ref = 0.f; - glGetFloatv(GL_ALPHA_TEST_REF, &ref); - - if (ref != value) - { - LL_ERRS() << "Alpha test value corrupted!" << LL_ENDL; - } - } -} - void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) { llassert(sfactor < BF_UNDEF); @@ -1848,14 +1483,11 @@ LLLightState* LLRender::getLight(U32 index) void LLRender::setAmbientLightColor(const LLColor4& color) { + LL_PROFILE_ZONE_SCOPED if (color != mAmbientLightColor) { ++mLightHash; mAmbientLightColor = color; - if (!LLGLSLShader::sNoFixedFunction) - { - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color.mV); - } } } @@ -1926,6 +1558,7 @@ void LLRender::flush() { if (mCount > 0) { + LL_PROFILE_ZONE_SCOPED; if (!mUIOffset.empty()) { sUICalls++; @@ -2307,7 +1940,7 @@ void LLRender::color3fv(const GLfloat* c) void LLRender::diffuseColor3f(F32 r, F32 g, F32 b) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + llassert(shader != NULL); if (shader) { @@ -2322,7 +1955,7 @@ void LLRender::diffuseColor3f(F32 r, F32 g, F32 b) void LLRender::diffuseColor3fv(const F32* c) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + llassert(shader != NULL); if (shader) { @@ -2337,7 +1970,7 @@ void LLRender::diffuseColor3fv(const F32* c) void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + llassert(shader != NULL); if (shader) { @@ -2352,7 +1985,7 @@ void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) void LLRender::diffuseColor4fv(const F32* c) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + llassert(shader != NULL); if (shader) { @@ -2367,7 +2000,7 @@ void LLRender::diffuseColor4fv(const F32* c) void LLRender::diffuseColor4ubv(const U8* c) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + llassert(shader != NULL); if (shader) { @@ -2382,7 +2015,7 @@ void LLRender::diffuseColor4ubv(const U8* c) void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + llassert(shader != NULL); if (shader) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index af8568f8a3..e2489876e4 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -105,10 +105,7 @@ public: TBO_LERP_VERT_ALPHA, // Interpolate based on Vertex Alpha (VA): ( Source1 * VA + Source2 * (1-VA) ) TBO_LERP_TEX_ALPHA, // Interpolate based on Texture Alpha (TA): ( Source1 * TA + Source2 * (1-TA) ) TBO_LERP_PREV_ALPHA, // Interpolate based on Previous Alpha (PA): ( Source1 * PA + Source2 * (1-PA) ) - TBO_LERP_CONST_ALPHA, // Interpolate based on Const Alpha (CA): ( Source1 * CA + Source2 * (1-CA) ) - TBO_LERP_VERT_COLOR // Interpolate based on Vertex Col (VC): ( Source1 * VC + Source2 * (1-VC) ) - // *Note* TBO_LERP_VERTEX_COLOR only works with setTextureColorBlend(), - // and falls back to TBO_LERP_VERTEX_ALPHA for setTextureAlphaBlend(). + TBO_LERP_CONST_ALPHA // Interpolate based on Const Alpha (CA): ( Source1 * CA + Source2 * (1-CA) ) } eTextureBlendOp; typedef enum @@ -158,9 +155,20 @@ public: // Binds the LLImageGL to this texture unit // (automatically enables the unit for the LLImageGL's texture type) - bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false); + bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false, S32 usename = 0); bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false); + // bind implementation for inner loops + // makes the following assumptions: + // - No need for gGL.flush() + // - texture is not null + // - gl_tex->getTexName() is not zero + // - This texture is not being bound redundantly + // - USE_SRGB_DECODE is disabled + // - mTexOptionsDirty is false + // - + void bindFast(LLTexture* texture); + // Binds a cubemap to this texture unit // (automatically enables the texture unit for cubemaps) bool bind(LLCubeMap* cubeMap); @@ -177,6 +185,9 @@ public: // (only if there's a texture of the given type currently bound) void unbind(eTextureType type); + // Fast but unsafe version of unbind + void unbindFast(eTextureType type); + // Sets the addressing mode used to sample the texture // Warning: this stays set for the bound texture forever, // make sure you want to permanently change the address mode for the bound texture. @@ -187,15 +198,6 @@ public: // make sure you want to permanently change the filtering for the bound texture. void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option); - void setTextureBlendType(eTextureBlendType type); - - inline void setTextureColorBlend(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2 = TBS_PREV_COLOR) - { setTextureCombiner(op, src1, src2, false); } - - // NOTE: If *_COLOR enums are passed to src1 or src2, the corresponding *_ALPHA enum will be used instead. - inline void setTextureAlphaBlend(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2 = TBS_PREV_ALPHA) - { setTextureCombiner(op, src1, src2, true); } - static U32 getInternalType(eTextureType type); U32 getCurrTexture(void) { return mCurrTexture; } @@ -212,13 +214,6 @@ protected: const S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; - eTextureBlendType mCurrBlendType; - eTextureBlendOp mCurrColorOp; - eTextureBlendSrc mCurrColorSrc1; - eTextureBlendSrc mCurrColorSrc2; - eTextureBlendOp mCurrAlphaOp; - eTextureBlendSrc mCurrAlphaSrc1; - eTextureBlendSrc mCurrAlphaSrc2; eTextureColorSpace mTexColorSpace; S32 mCurrColorScale; S32 mCurrAlphaScale; @@ -229,7 +224,6 @@ protected: void setAlphaScale(S32 scale); GLint getTextureSource(eTextureBlendSrc src); GLint getTextureSourceType(eTextureBlendSrc src, bool isAlpha = false); - void setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha = false); }; class LLLightState @@ -430,8 +424,6 @@ public: void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); void setSceneBlendType(eBlendType type); - void setAlphaRejectSettings(eCompareFunc func, F32 value = 0.01f); - // applies blend func to both color and alpha void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor); // applies separate blend functions to color and alpha @@ -482,8 +474,6 @@ private: U32 mMode; U32 mCurrTextureUnitIndex; bool mCurrColorMask[4]; - eCompareFunc mCurrAlphaFunc; - F32 mCurrAlphaFuncVal; LLPointer<LLVertexBuffer> mBuffer; LLStrider<LLVector3> mVerticesp; @@ -511,7 +501,7 @@ extern F32 gGLLastProjection[16]; extern F32 gGLProjection[16]; extern S32 gGLViewport[4]; -extern LLRender gGL; +extern thread_local LLRender gGL; // This rotation matrix moves the default OpenGL reference frame // (-Z at, Y up) to Cory's favorite reference frame (X at, Z up) diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index dd34f3e383..ad0c6262a4 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -132,40 +132,15 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled ) } else { - if( gGLManager.mATIOffsetVerticalLines ) - { - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - gGL.begin( LLRender::LINES ); - - // Verticals - gGL.vertex2i(left + 1, top); - gGL.vertex2i(left + 1, bottom); - - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - - // Horizontals - top--; - right--; - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - - gGL.vertex2i(left, top); - gGL.vertex2i(right, top); - gGL.end(); - } - else - { - top--; - right--; - gGL.begin( LLRender::LINE_STRIP ); - gGL.vertex2i(left, top); - gGL.vertex2i(left, bottom); - gGL.vertex2i(right, bottom); - gGL.vertex2i(right, top); - gGL.vertex2i(left, top); - gGL.end(); - } + top--; + right--; + gGL.begin( LLRender::LINE_STRIP ); + gGL.vertex2i(left, top); + gGL.vertex2i(left, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top); + gGL.vertex2i(left, top); + gGL.end(); } stop_glerror(); } @@ -250,15 +225,6 @@ void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &st void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) { - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin(LLRender::LINES); @@ -269,15 +235,6 @@ void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 ) void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color ) { - // Work around bug in ATI driver: vertical lines are offset by (-1,-1) - if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines ) - { - x1++; - x2++; - y1++; - y2++; - } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4fv( color.mV ); @@ -395,15 +352,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex if (solid_color) { - if (LLGLSLShader::sNoFixedFunction) - { - gSolidColorProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - } + gSolidColorProgram.bind(); } if (center_rect.mLeft == 0.f @@ -650,14 +599,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex if (solid_color) { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - else - { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } + gUIProgram.bind(); } } @@ -774,10 +716,6 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) { - phase = fmod(phase, 1.f); - - S32 shift = S32(phase * 4.f) % 4; - // Stippled line LLGLEnable stipple(GL_LINE_STIPPLE); @@ -786,11 +724,6 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL gGL.flush(); glLineWidth(2.5f); - if (!LLGLSLShader::sNoFixedFunction) - { - glLineStipple(2, 0x3333 << shift); - } - gGL.begin(LLRender::LINES); { gGL.vertex3fv( start.mV ); @@ -930,52 +863,16 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor // Draw gray and white checkerboard with black border void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha) { - if (!LLGLSLShader::sNoFixedFunction) - { - // Initialize the first time this is called. - const S32 PIXELS = 32; - static GLubyte checkerboard[PIXELS * PIXELS]; - static BOOL first = TRUE; - if( first ) - { - for( S32 i = 0; i < PIXELS; i++ ) - { - for( S32 j = 0; j < PIXELS; j++ ) - { - checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; - } - } - first = FALSE; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // ...white squares - gGL.color4f( 1.f, 1.f, 1.f, alpha ); - gl_rect_2d(rect); - - // ...gray squares - gGL.color4f( .7f, .7f, .7f, alpha ); - gGL.flush(); + //polygon stipple is deprecated, use "Checker" texture + LLPointer<LLUIImage> img = LLRender2D::getInstance()->getUIImage("Checker"); + gGL.getTexUnit(0)->bind(img->getImage()); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - glPolygonStipple( checkerboard ); + LLColor4 color(1.f, 1.f, 1.f, alpha); + LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); - LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE); - gl_rect_2d(rect); - } - else - { //polygon stipple is deprecated, use "Checker" texture - LLPointer<LLUIImage> img = LLRender2D::getInstance()->getUIImage("Checker"); - gGL.getTexUnit(0)->bind(img->getImage()); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - - LLColor4 color(1.f, 1.f, 1.f, alpha); - LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); - - gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), - img->getImage(), color, uv_rect); - } + gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), img->getImage(), color, uv_rect); gGL.flush(); } @@ -1083,8 +980,6 @@ void gl_rect_2d_simple( S32 width, S32 height ) gGL.end(); } -static LLTrace::BlockTimerStatHandle FTM_RENDER_SEGMENTED_RECT ("Render segmented rectangle"); - void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, @@ -1094,7 +989,7 @@ void gl_segmented_rect_2d_tex(const S32 left, const S32 border_size, const U32 edges) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_SEGMENTED_RECT); + LL_PROFILE_ZONE_SCOPED; S32 width = llabs(right - left); S32 height = llabs(top - bottom); @@ -1253,7 +1148,7 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, const F32 end_fragment, const U32 edges) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_SEGMENTED_RECT); + LL_PROFILE_ZONE_SCOPED; const S32 left = rect.mLeft; const S32 right = rect.mRight; const S32 top = rect.mTop; @@ -1440,7 +1335,7 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_SEGMENTED_RECT); + LL_PROFILE_ZONE_SCOPED; gGL.begin(LLRender::QUADS); { diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index e3c0255290..401085a00b 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -437,11 +437,13 @@ void LLRenderTarget::bindTarget() GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; + LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x4000FF ) glDrawBuffersARB(mTex.size(), drawbuffers); } if (mTex.empty()) { //no color buffer to draw to + LL_PROFILER_GPU_ZONEC( "gl.DrawBuffer", 0x0000FF ) glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index e8c6295930..c100c182dd 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -165,6 +165,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasObjectSkinning) { + shader->mRiggedVariant = shader; if (!shader->attachVertexObject("avatar/objectSkinV.glsl")) { return FALSE; @@ -599,7 +600,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& } } -GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines, S32 texture_index_channels) +GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels) { // endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl) @@ -774,14 +775,14 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (defines) { - for (boost::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter) + for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter) { std::string define = "#define " + iter->first + " " + iter->second + "\n"; extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str()); } } - if( gGLManager.mIsATI ) + if( gGLManager.mIsAMD ) { extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" ); } @@ -1053,43 +1054,6 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL; } -#if LL_DARWIN - - // For some reason this absolutely kills the frame rate when VBO's are enabled - if (0) - { - // Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software - // per Apple's suggestion - LLGLSLShader::sNoFixedFunction = false; - - glUseProgramObjectARB(obj); - - gGL.begin(LLRender::TRIANGLES); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.end(); - gGL.flush(); - - glUseProgramObjectARB(0); - - LLGLSLShader::sNoFixedFunction = true; - - // Query whether the shader can or cannot run in hardware - // http://developer.apple.com/qa/qa2007/qa1502.html - GLint vertexGPUProcessing, fragmentGPUProcessing; - CGLContextObj ctx = CGLGetCurrentContext(); - CGLGetParameter(ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing); - CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing); - if (!fragmentGPUProcessing || !vertexGPUProcessing) - { - LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; - success = GL_FALSE; - suppress_errors = FALSE; - } - } - -#else std::string log = get_object_log(obj); LLStringUtil::toLower(log); if (log.find("software") != std::string::npos) @@ -1098,7 +1062,6 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) success = GL_FALSE; suppress_errors = FALSE; } -#endif return success; } diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 3908efd4ec..67c0d6ab10 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -264,7 +264,7 @@ public: void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); - GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1); + GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 41481fb8a7..e890a5a30b 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -42,7 +42,7 @@ class LLFontGL ; // //this is an abstract class as the parent for the class LLGLTexture // -class LLTexture : public virtual LLRefCount, public LLTrace::MemTrackable<LLTexture> +class LLTexture : public virtual LLRefCount { friend class LLTexUnit ; friend class LLFontGL ; @@ -52,7 +52,6 @@ protected: public: LLTexture() - : LLTrace::MemTrackable<LLTexture>("LLTexture") {} // @@ -67,11 +66,9 @@ public: virtual S32 getWidth(S32 discard_level = -1) const; virtual S32 getHeight(S32 discard_level = -1) const; virtual bool isActiveFetching(); + virtual LLImageGL* getGLTexture() const; private: - //note: do not make this function public. - virtual LLImageGL* getGLTexture() const; - virtual void updateBindStatsForTester(); }; #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 7d2b09ca4a..9926447ef8 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -91,6 +91,8 @@ LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_ U32 LLVBOPool::sBytesPooled = 0; U32 LLVBOPool::sIndexBytesPooled = 0; +U32 LLVBOPool::sNameIdx = 0; +U32 LLVBOPool::sNamePool[1024]; std::list<U32> LLVertexBuffer::sAvailableVAOName; U32 LLVertexBuffer::sCurVAOName = 1; @@ -121,15 +123,20 @@ bool LLVertexBuffer::sPreferStreamDraw = false; U32 LLVBOPool::genBuffer() { - U32 ret = 0; + LL_PROFILE_ZONE_SCOPED - glGenBuffersARB(1, &ret); - - return ret; + if (sNameIdx == 0) + { + glGenBuffersARB(1024, sNamePool); + sNameIdx = 1024; + } + + return sNamePool[--sNameIdx]; } void LLVBOPool::deleteBuffer(U32 name) { + LL_PROFILE_ZONE_SCOPED if (gGLManager.mInited) { LLVertexBuffer::unbind(); @@ -150,11 +157,12 @@ LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType) std::fill(mMissCount.begin(), mMissCount.end(), 0); } -volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) +U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) { + LL_PROFILE_ZONE_SCOPED llassert(vbo_block_size(size) == size); - volatile U8* ret = NULL; + U8* ret = NULL; U32 i = vbo_block_index(size); @@ -248,7 +256,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) return ret; } -void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) +void LLVBOPool::release(U32 name, U8* buffer, U32 size) { llassert(vbo_block_size(size) == size); @@ -267,10 +275,12 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) void LLVBOPool::seedPool() { + LL_PROFILE_ZONE_SCOPED U32 dummy_name = 0; if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT) { + LL_PROFILE_ZONE_NAMED("VBOPool Resize"); mFreeList.resize(LL_VBO_POOL_SEED_COUNT); } @@ -411,6 +421,7 @@ void LLVertexBuffer::releaseVAOName(U32 name) //static void LLVertexBuffer::seedPools() { + LL_PROFILE_ZONE_SCOPED sStreamVBOPool.seedPool(); sDynamicVBOPool.seedPool(); sDynamicCopyVBOPool.seedPool(); @@ -430,135 +441,26 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) data_mask = data_mask & ~MAP_TEXTURE_INDEX; } - if (LLGLSLShader::sNoFixedFunction) + for (U32 i = 0; i < TYPE_MAX; ++i) { - for (U32 i = 0; i < TYPE_MAX; ++i) - { - S32 loc = i; + S32 loc = i; - U32 mask = 1 << i; - - if (sLastMask & (1 << i)) - { //was enabled - if (!(data_mask & mask)) - { //needs to be disabled - glDisableVertexAttribArrayARB(loc); - } - } - else - { //was disabled - if (data_mask & mask) - { //needs to be enabled - glEnableVertexAttribArrayARB(loc); - } - } - } - } - else - { - - static const GLenum array[] = - { - GL_VERTEX_ARRAY, - GL_NORMAL_ARRAY, - GL_TEXTURE_COORD_ARRAY, - GL_COLOR_ARRAY, - }; - - static const GLenum mask[] = - { - MAP_VERTEX, - MAP_NORMAL, - MAP_TEXCOORD0, - MAP_COLOR - }; - - - - for (U32 i = 0; i < 4; ++i) - { - if (sLastMask & mask[i]) - { //was enabled - if (!(data_mask & mask[i])) - { //needs to be disabled - glDisableClientState(array[i]); - } - else if (gDebugGL) - { //needs to be enabled, make sure it was (DEBUG) - if (!glIsEnabled(array[i])) - { - if (gDebugSession) - { - gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl; - } - else - { - LL_ERRS() << "Bad client state! " << array[i] << " disabled." << LL_ENDL; - } - } - } - } - else - { //was disabled - if (data_mask & mask[i]) - { //needs to be enabled - glEnableClientState(array[i]); - } - else if (gDebugGL && glIsEnabled(array[i])) - { //needs to be disabled, make sure it was (DEBUG TEMPORARY) - if (gDebugSession) - { - gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl; - } - else - { - LL_ERRS() << "Bad client state! " << array[i] << " enabled." << LL_ENDL; - } - } - } - } - - static const U32 map_tc[] = - { - MAP_TEXCOORD1, - MAP_TEXCOORD2, - MAP_TEXCOORD3 - }; + U32 mask = 1 << i; - for (U32 i = 0; i < 3; i++) - { - if (sLastMask & map_tc[i]) - { - if (!(data_mask & map_tc[i])) - { //disable - glClientActiveTextureARB(GL_TEXTURE1_ARB+i); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - } - else if (data_mask & map_tc[i]) - { - glClientActiveTextureARB(GL_TEXTURE1_ARB+i); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + if (sLastMask & (1 << i)) + { //was enabled + if (!(data_mask & mask)) + { //needs to be disabled + glDisableVertexAttribArrayARB(loc); } } - - if (sLastMask & MAP_TANGENT) - { - if (!(data_mask & MAP_TANGENT)) - { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); + else + { //was disabled + if (data_mask & mask) + { //needs to be enabled + glEnableVertexAttribArrayARB(loc); } } - else if (data_mask & MAP_TANGENT) - { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } } sLastMask = data_mask; @@ -566,63 +468,23 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } //static -static LLTrace::BlockTimerStatHandle FTM_VB_DRAW_ARRAYS("drawArrays"); -void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) +void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos) { - LL_RECORD_BLOCK_TIME(FTM_VB_DRAW_ARRAYS); - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - gGL.syncMatrices(); - - U32 count = pos.size(); - - llassert(norm.size() >= pos.size()); - llassert(count > 0); - - if( count == 0 ) - { - LL_WARNS() << "Called drawArrays with 0 vertices" << LL_ENDL; - return; - } - - if( norm.size() < pos.size() ) - { - LL_WARNS() << "Called drawArrays with #" << norm.size() << " normals and #" << pos.size() << " vertices" << LL_ENDL; - return; - } - - unbind(); - - setupClientArrays(MAP_VERTEX | MAP_NORMAL); - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - if (shader) - { - S32 loc = LLVertexBuffer::TYPE_VERTEX; - if (loc > -1) - { - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV); - } - loc = LLVertexBuffer::TYPE_NORMAL; - if (loc > -1) - { - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV); - } - } - else - { - glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); - glNormalPointer(GL_FLOAT, 0, norm[0].mV); - } - LLGLSLShader::startProfile(); - glDrawArrays(sGLMode[mode], 0, count); - LLGLSLShader::stopProfile(count, mode); + LL_PROFILE_ZONE_SCOPED; + gGL.begin(mode); + for (auto& v : pos) + { + gGL.vertex3fv(v.mV); + } + gGL.end(); + gGL.flush(); } //static void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp) { - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + LL_PROFILE_ZONE_SCOPED; + llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); gGL.syncMatrices(); @@ -634,28 +496,27 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto unbind(); - setupClientArrays(mask); - - if (LLGLSLShader::sNoFixedFunction) - { - S32 loc = LLVertexBuffer::TYPE_VERTEX; - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos); - - if (tc) - { - loc = LLVertexBuffer::TYPE_TEXCOORD0; - glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc); - } - } - else - { - glTexCoordPointer(2, GL_FLOAT, 0, tc); - glVertexPointer(3, GL_FLOAT, 16, pos); - } - - LLGLSLShader::startProfile(); - glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp); - LLGLSLShader::stopProfile(num_indices, mode); + gGL.begin(mode); + + if (tc != nullptr) + { + for (int i = 0; i < num_indices; ++i) + { + U16 idx = indicesp[i]; + gGL.texCoord2fv(tc[idx].mV); + gGL.vertex3fv(pos[idx].getF32ptr()); + } + } + else + { + for (int i = 0; i < num_indices; ++i) + { + U16 idx = indicesp[i]; + gGL.vertex3fv(pos[idx].getF32ptr()); + } + } + gGL.end(); + gGL.flush(); } void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const @@ -720,7 +581,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi gGL.syncMatrices(); llassert(mNumVerts >= 0); - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); if (mGLArray) { @@ -763,6 +624,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi stop_glerror(); LLGLSLShader::startProfile(); + LL_PROFILER_GPU_ZONEC( "gl.DrawRangeElements", 0xFFFF00 ) glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, idx); LLGLSLShader::stopProfile(count, mode); @@ -773,9 +635,21 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi 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; + + LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00) + glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, + idx); +} + void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); + llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); mMappable = false; gGL.syncMatrices(); @@ -814,6 +688,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const stop_glerror(); LLGLSLShader::startProfile(); + LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0xA0FFA0 ) glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); LLGLSLShader::stopProfile(count, mode); @@ -821,53 +696,53 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const placeFence(); } -static LLTrace::BlockTimerStatHandle FTM_GL_DRAW_ARRAYS("GL draw arrays"); + void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL); - mMappable = false; - gGL.syncMatrices(); - - llassert(mNumVerts >= 0); - if (first >= (U32) mNumVerts || - first + count > (U32) mNumVerts) - { - LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << LL_ENDL; - } - - if (mGLArray) - { - 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_PROFILE_ZONE_SCOPED; + llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); + mMappable = false; + gGL.syncMatrices(); + +#ifndef LL_RELEASE_FOR_DOWNLOAD + llassert(mNumVerts >= 0); + if (first >= (U32)mNumVerts || + first + count > (U32)mNumVerts) + { + LL_ERRS() << "Bad vertex buffer draw range: [" << first << ", " << first + count << "]" << LL_ENDL; + } + + if (mGLArray) + { + 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; + } + } + + if (mode >= LLRender::NUM_MODES) + { + LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL; + return; + } +#endif - if (mode >= LLRender::NUM_MODES) - { - LL_ERRS() << "Invalid draw mode: " << mode << LL_ENDL; - return; - } + LLGLSLShader::startProfile(); + { + LL_PROFILER_GPU_ZONEC("gl.DrawArrays", 0xFF4040) + glDrawArrays(sGLMode[mode], first, count); + } + LLGLSLShader::stopProfile(count, mode); - { - LL_RECORD_BLOCK_TIME(FTM_GL_DRAW_ARRAYS); - stop_glerror(); - LLGLSLShader::startProfile(); - stop_glerror(); - glDrawArrays(sGLMode[mode], first, count); - stop_glerror(); - LLGLSLShader::stopProfile(count, mode); - } - - stop_glerror(); - placeFence(); + stop_glerror(); + placeFence(); } //static @@ -964,8 +839,7 @@ S32 LLVertexBuffer::determineUsage(S32 usage) } LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) -: LLTrace::MemTrackable<LLVertexBuffer>("LLVertexBuffer"), - LLRefCount(), +: LLRefCount(), mNumVerts(0), mNumIndices(0), @@ -1110,9 +984,7 @@ void LLVertexBuffer::waitFence() const void LLVertexBuffer::genBuffer(U32 size) { - disclaimMem(mSize); mSize = vbo_block_size(size); - claimMem(mSize); if (mUsage == GL_STREAM_DRAW_ARB) { @@ -1208,9 +1080,7 @@ bool LLVertexBuffer::createGLBuffer(U32 size) static int gl_buffer_idx = 0; mGLBuffer = ++gl_buffer_idx; mMappedData = (U8*)ll_aligned_malloc_16(size); - disclaimMem(mSize); mSize = size; - claimMem(mSize); } if (!mMappedData) @@ -1380,8 +1250,6 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) return success; } -static LLTrace::BlockTimerStatHandle FTM_SETUP_VERTEX_ARRAY("Setup VAO"); - void LLVertexBuffer::setupVertexArray() { if (!mGLArray) @@ -1389,7 +1257,7 @@ void LLVertexBuffer::setupVertexArray() return; } - LL_RECORD_BLOCK_TIME(FTM_SETUP_VERTEX_ARRAY); + LL_PROFILE_ZONE_SCOPED; #if GL_ARB_vertex_array_object glBindVertexArray(mGLArray); #endif @@ -1562,12 +1430,11 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) return true; } -static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range"); -static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_BUFFER("VBO Map"); // Map for data access -volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) +U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { + LL_PROFILE_ZONE_SCOPED; bindGLBuffer(true); if (mFinal) { @@ -1627,14 +1494,13 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } else { - volatile U8* src = NULL; + U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { #ifdef GL_ARB_map_buffer_range - LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_BUFFER_RANGE); S32 offset = mOffsets[type] + sTypeSize[type]*index; S32 length = (sTypeSize[type]*count+0xF) & ~0xF; src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, @@ -1658,7 +1524,6 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } } - LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_BUFFER); src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1688,7 +1553,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo llassert(src != NULL); - mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src); + mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); mAlignedOffset = mMappedData - src; stop_glerror(); @@ -1744,11 +1609,9 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo } -static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_INDEX_RANGE("IBO Map Range"); -static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_INDEX("IBO Map"); - -volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) +U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { + LL_PROFILE_ZONE_SCOPED; bindGLIndices(true); if (mFinal) { @@ -1816,14 +1679,13 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } else { - volatile U8* src = NULL; + U8* src = NULL; waitFence(); if (gGLManager.mHasMapBufferRange) { if (map_range) { #ifdef GL_ARB_map_buffer_range - LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX_RANGE); S32 offset = sizeof(U16)*index; S32 length = sizeof(U16)*count; src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, @@ -1835,7 +1697,6 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range else { #ifdef GL_ARB_map_buffer_range - LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX); src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); @@ -1859,7 +1720,6 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } else { - LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX); map_range = false; src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } @@ -1910,13 +1770,6 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range } } -static LLTrace::BlockTimerStatHandle FTM_VBO_UNMAP("VBO Unmap"); -static LLTrace::BlockTimerStatHandle FTM_VBO_FLUSH_RANGE("Flush VBO Range"); - - -static LLTrace::BlockTimerStatHandle FTM_IBO_UNMAP("IBO Unmap"); -static LLTrace::BlockTimerStatHandle FTM_IBO_FLUSH_RANGE("Flush IBO Range"); - void LLVertexBuffer::unmapBuffer() { if (!useVBOs()) @@ -1925,10 +1778,10 @@ void LLVertexBuffer::unmapBuffer() } bool updated_all = false; - + LL_PROFILE_ZONE_SCOPED; if (mMappedData && mVertexLocked) { - LL_RECORD_BLOCK_TIME(FTM_VBO_UNMAP); + LL_PROFILE_ZONE_NAMED("unmapBuffer - vertex"); bindGLBuffer(true); updated_all = mIndexLocked; //both vertex and index buffers done updating @@ -1975,7 +1828,7 @@ void LLVertexBuffer::unmapBuffer() { if (!mMappedVertexRegions.empty()) { - stop_glerror(); + LL_PROFILE_ZONE_NAMED("unmapBuffer - flush vertex"); for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { const MappedRegion& region = mMappedVertexRegions[i]; @@ -1983,18 +1836,16 @@ void LLVertexBuffer::unmapBuffer() S32 length = sTypeSize[region.mType]*region.mCount; if (gGLManager.mHasMapBufferRange) { - LL_RECORD_BLOCK_TIME(FTM_VBO_FLUSH_RANGE); #ifdef GL_ARB_map_buffer_range glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length); #endif } else if (gGLManager.mHasFlushBufferRange) - { + { #ifndef LL_MESA_HEADLESS glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length); #endif } - stop_glerror(); } mMappedVertexRegions.clear(); @@ -2013,7 +1864,7 @@ void LLVertexBuffer::unmapBuffer() if (mMappedIndexData && mIndexLocked) { - LL_RECORD_BLOCK_TIME(FTM_IBO_UNMAP); + LL_PROFILE_ZONE_NAMED("unmapBuffer - index"); bindGLIndices(); if(!mMappable) { @@ -2059,12 +1910,12 @@ void LLVertexBuffer::unmapBuffer() { for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { + LL_PROFILE_ZONE_NAMED("unmapBuffer - flush index"); const MappedRegion& region = mMappedIndexRegions[i]; S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; S32 length = sizeof(U16)*region.mCount; if (gGLManager.mHasMapBufferRange) { - LL_RECORD_BLOCK_TIME(FTM_IBO_FLUSH_RANGE); #ifdef GL_ARB_map_buffer_range glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); #endif @@ -2083,9 +1934,8 @@ void LLVertexBuffer::unmapBuffer() mMappedIndexRegions.clear(); } } - stop_glerror(); - glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); - stop_glerror(); + + glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); mMappedIndexData = NULL; } @@ -2111,7 +1961,7 @@ template <class T,S32 type> struct VertexBufferStrider { if (type == LLVertexBuffer::TYPE_INDEX) { - volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range); + U8* ptr = vbo.mapIndexBuffer(index, count, map_range); if (ptr == NULL) { @@ -2127,7 +1977,7 @@ template <class T,S32 type> struct VertexBufferStrider { S32 stride = LLVertexBuffer::sTypeSize[type]; - volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); + U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); if (ptr == NULL) { @@ -2208,13 +2058,12 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 in //---------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_BIND_GL_ARRAY("Bind Array"); bool LLVertexBuffer::bindGLArray() { if (mGLArray && sGLRenderArray != mGLArray) { { - LL_RECORD_BLOCK_TIME(FTM_BIND_GL_ARRAY); + LL_PROFILE_ZONE_SCOPED; #if GL_ARB_vertex_array_object glBindVertexArray(mGLArray); #endif @@ -2231,8 +2080,6 @@ bool LLVertexBuffer::bindGLArray() return false; } -static LLTrace::BlockTimerStatHandle FTM_BIND_GL_BUFFER("Bind Buffer"); - bool LLVertexBuffer::bindGLBuffer(bool force_bind) { bindGLArray(); @@ -2241,8 +2088,7 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind) if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)))) { - //LL_RECORD_BLOCK_TIME(FTM_BIND_GL_BUFFER); - + LL_PROFILE_ZONE_SCOPED; glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); sGLRenderBuffer = mGLBuffer; sBindCount++; @@ -2256,16 +2102,29 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind) return ret; } -static LLTrace::BlockTimerStatHandle FTM_BIND_GL_INDICES("Bind Indices"); +bool LLVertexBuffer::bindGLBufferFast() +{ + if (mGLBuffer != sGLRenderBuffer || !sVBOActive) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + sBindCount++; + sVBOActive = true; + + return true; + } + + return false; +} bool LLVertexBuffer::bindGLIndices(bool force_bind) { + LL_PROFILE_ZONE_SCOPED; bindGLArray(); bool ret = false; if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)))) { - LL_RECORD_BLOCK_TIME(FTM_BIND_GL_INDICES); /*if (sMapped) { LL_ERRS() << "VBO bound while another VBO mapped!" << LL_ENDL; @@ -2281,6 +2140,21 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind) return ret; } +bool LLVertexBuffer::bindGLIndicesFast() +{ + if (mGLIndices != sGLRenderIndices || !sIBOActive) + { + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); + sGLRenderIndices = mGLIndices; + sBindCount++; + sIBOActive = true; + + return true; + } + + return false; +} + void LLVertexBuffer::flush() { if (useVBOs()) @@ -2471,11 +2345,39 @@ void LLVertexBuffer::setBuffer(U32 data_mask) } } +void LLVertexBuffer::setBufferFast(U32 data_mask) +{ + if (useVBOs()) + { + //set up pointers if the data mask is different ... + bool setup = (sLastMask != data_mask); + + const bool bindBuffer = bindGLBufferFast(); + const bool bindIndices = bindGLIndicesFast(); + + setup = setup || bindBuffer || bindIndices; + + setupClientArrays(data_mask); + + if (data_mask && setup) + { + setupVertexBufferFast(data_mask); + sSetCount++; + } + } + else + { + //fallback to slow path when not using VBOs + setBuffer(data_mask); + } +} + + // virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) { stop_glerror(); - volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; if (gDebugGL && ((data_mask & mTypeMask) != data_mask)) { @@ -2490,144 +2392,191 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) LL_ERRS() << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << LL_ENDL; } - if (LLGLSLShader::sNoFixedFunction) + if (data_mask & MAP_NORMAL) { - if (data_mask & MAP_NORMAL) - { - S32 loc = TYPE_NORMAL; - void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); - glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); - } - if (data_mask & MAP_TEXCOORD3) - { - S32 loc = TYPE_TEXCOORD3; - void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); - glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); - } - if (data_mask & MAP_TEXCOORD2) - { - S32 loc = TYPE_TEXCOORD2; - void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); - glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); - } - if (data_mask & MAP_TEXCOORD1) - { - S32 loc = TYPE_TEXCOORD1; - void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); - glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); - } - if (data_mask & MAP_TANGENT) - { - S32 loc = TYPE_TANGENT; - void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]); - glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); - } - if (data_mask & MAP_TEXCOORD0) - { - S32 loc = TYPE_TEXCOORD0; - void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); - glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); - } - if (data_mask & MAP_COLOR) - { - S32 loc = TYPE_COLOR; - //bind emissive instead of color pointer if emissive is present - void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); - glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); - } - if (data_mask & MAP_EMISSIVE) - { - S32 loc = TYPE_EMISSIVE; - void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); - glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + S32 loc = TYPE_NORMAL; + void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); + } + if (data_mask & MAP_TEXCOORD3) + { + S32 loc = TYPE_TEXCOORD3; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); + } + if (data_mask & MAP_TEXCOORD2) + { + S32 loc = TYPE_TEXCOORD2; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + } + if (data_mask & MAP_TEXCOORD1) + { + S32 loc = TYPE_TEXCOORD1; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); + } + if (data_mask & MAP_TANGENT) + { + S32 loc = TYPE_TANGENT; + void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]); + glVertexAttribPointerARB(loc, 4,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + } + if (data_mask & MAP_TEXCOORD0) + { + S32 loc = TYPE_TEXCOORD0; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); + glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + } + if (data_mask & MAP_COLOR) + { + S32 loc = TYPE_COLOR; + //bind emissive instead of color pointer if emissive is present + void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + } + if (data_mask & MAP_EMISSIVE) + { + S32 loc = TYPE_EMISSIVE; + void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); - if (!(data_mask & MAP_COLOR)) - { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps - loc = TYPE_COLOR; - glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); - } - } - if (data_mask & MAP_WEIGHT) - { - S32 loc = TYPE_WEIGHT; - void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); - glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); - } - if (data_mask & MAP_WEIGHT4) - { - S32 loc = TYPE_WEIGHT4; - void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]); - glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); - } - if (data_mask & MAP_CLOTHWEIGHT) - { - S32 loc = TYPE_CLOTHWEIGHT; - void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); - glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + if (!(data_mask & MAP_COLOR)) + { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps + loc = TYPE_COLOR; + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); } - if (data_mask & MAP_TEXTURE_INDEX && - (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later - { + } + if (data_mask & MAP_WEIGHT) + { + S32 loc = TYPE_WEIGHT; + void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); + glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); + } + if (data_mask & MAP_WEIGHT4) + { + S32 loc = TYPE_WEIGHT4; + void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); + } + if (data_mask & MAP_CLOTHWEIGHT) + { + S32 loc = TYPE_CLOTHWEIGHT; + void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + } + if (data_mask & MAP_TEXTURE_INDEX && + (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)) //indexed texture rendering requires GLSL 1.30 or later + { #if !LL_DARWIN - S32 loc = TYPE_TEXTURE_INDEX; - void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); - glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + S32 loc = TYPE_TEXTURE_INDEX; + void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); + glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); #endif - } - if (data_mask & MAP_VERTEX) - { - S32 loc = TYPE_VERTEX; - void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); - glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); - } - } - else - { - if (data_mask & MAP_NORMAL) - { - glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); - } - if (data_mask & MAP_TEXCOORD3) - { - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TEXCOORD2) - { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TEXCOORD1) - { - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TANGENT) - { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TANGENT], (void*)(base + mOffsets[TYPE_TANGENT])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TEXCOORD0) - { - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); - } - if (data_mask & MAP_COLOR) - { - glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); - } - if (data_mask & MAP_VERTEX) - { - glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); - } } + if (data_mask & MAP_VERTEX) + { + S32 loc = TYPE_VERTEX; + void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); + glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + } llglassertok(); } +void LLVertexBuffer::setupVertexBufferFast(U32 data_mask) +{ + U8* base = (U8*)mAlignedOffset; + + if (data_mask & MAP_NORMAL) + { + S32 loc = TYPE_NORMAL; + void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); + glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); + } + if (data_mask & MAP_TEXCOORD3) + { + S32 loc = TYPE_TEXCOORD3; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); + } + if (data_mask & MAP_TEXCOORD2) + { + S32 loc = TYPE_TEXCOORD2; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); + } + if (data_mask & MAP_TEXCOORD1) + { + S32 loc = TYPE_TEXCOORD1; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); + } + if (data_mask & MAP_TANGENT) + { + S32 loc = TYPE_TANGENT; + void* ptr = (void*)(base + mOffsets[TYPE_TANGENT]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TANGENT], ptr); + } + if (data_mask & MAP_TEXCOORD0) + { + S32 loc = TYPE_TEXCOORD0; + void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); + glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); + } + if (data_mask & MAP_COLOR) + { + S32 loc = TYPE_COLOR; + //bind emissive instead of color pointer if emissive is present + void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]); + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); + } + if (data_mask & MAP_EMISSIVE) + { + S32 loc = TYPE_EMISSIVE; + void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + + if (!(data_mask & MAP_COLOR)) + { //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps + loc = TYPE_COLOR; + glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + } + } + if (data_mask & MAP_WEIGHT) + { + S32 loc = TYPE_WEIGHT; + void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); + glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); + } + if (data_mask & MAP_WEIGHT4) + { + S32 loc = TYPE_WEIGHT4; + void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT4]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); + } + if (data_mask & MAP_CLOTHWEIGHT) + { + S32 loc = TYPE_CLOTHWEIGHT; + void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); + glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); + } + if (data_mask & MAP_TEXTURE_INDEX) + { +#if !LL_DARWIN + S32 loc = TYPE_TEXTURE_INDEX; + void* ptr = (void*)(base + mOffsets[TYPE_VERTEX] + 12); + glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); +#endif + } + if (data_mask & MAP_VERTEX) + { + S32 loc = TYPE_VERTEX; + void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]); + glVertexAttribPointerARB(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) { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index dbe1a3687f..baf8407fc6 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -64,10 +64,10 @@ public: const U32 mType; //size MUST be a power of 2 - volatile U8* allocate(U32& name, U32 size, bool for_seed = false); + 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, volatile U8* buffer, U32 size); + void release(U32 name, U8* buffer, U32 size); //batch allocate buffers to be provided to the application on demand void seedPool(); @@ -82,20 +82,23 @@ public: { public: U32 mGLName; - volatile U8* mClientData; + U8* mClientData; }; typedef std::list<Record> record_list_t; std::vector<record_list_t> mFreeList; std::vector<U32> 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 LLTrace::MemTrackable<LLVertexBuffer> +class LLVertexBuffer : public LLRefCount { public: class MappedRegion @@ -110,8 +113,7 @@ public: }; LLVertexBuffer(const LLVertexBuffer& rhs) - : LLTrace::MemTrackable<LLVertexBuffer>("LLVertexBuffer"), - mUsage(rhs.mUsage) + : mUsage(rhs.mUsage) { *this = rhs; } @@ -127,7 +129,7 @@ public: static LLVBOPool sDynamicCopyVBOPool; static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; - + static std::list<U32> sAvailableVAOName; static U32 sCurVAOName; @@ -143,8 +145,7 @@ public: static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); - static void pushPositions(U32 mode, const LLVector4a* pos, U32 count); - static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); + static void drawArrays(U32 mode, const std::vector<LLVector3>& pos); static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); static void unbind(); //unbind any bound vertex buffer @@ -207,13 +208,17 @@ protected: virtual ~LLVertexBuffer(); // use unref() - virtual void setupVertexBuffer(U32 data_mask); // pure virtual, called from mapBuffer() + 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(); @@ -229,13 +234,15 @@ public: LLVertexBuffer(U32 typemask, S32 usage); // map for data access - volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); - volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range); + U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); + U8* mapIndexBuffer(S32 index, S32 count, bool map_range); void bindForFeedback(U32 channel, U32 type, U32 index, U32 count); // set for rendering 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 // allocate buffer bool allocateBuffer(S32 nverts, S32 nindices, bool create); @@ -271,14 +278,14 @@ public: S32 getNumVerts() const { return mNumVerts; } S32 getNumIndices() const { return mNumIndices; } - volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } - volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } U32 getTypeMask() const { return mTypeMask; } bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } S32 getSize() const; S32 getIndicesSize() const { return mIndicesSize; } - volatile U8* getMappedData() const { return mMappedData; } - volatile U8* getMappedIndices() const { return mMappedIndexData; } + U8* getMappedData() const { return mMappedData; } + 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_ARB) ? true : false; } @@ -287,6 +294,9 @@ public: void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //implementation for inner loops that does no safety checking + void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //for debugging, validate data in given range is valid void validateRange(U32 start, U32 end, U32 count, U32 offset) const; @@ -308,8 +318,8 @@ protected: U32 mGLIndices; // GL IBO handle U32 mGLArray; // GL VAO handle - volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) - volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) + U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) + U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) U32 mMappedDataUsingVBOs : 1; U32 mMappedIndexDataUsingVBOs : 1; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index d96824bbf8..e0579352d3 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -308,6 +308,10 @@ if(LL_TESTS) ${BOOST_FIBER_LIBRARY} ${BOOST_CONTEXT_LIBRARY} ${BOOST_SYSTEM_LIBRARY} ${WINDOWS_LIBRARIES}) if(NOT LINUX) - LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}") + if(WINDOWS) + LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "imm32;${test_libs}") + else(WINDOWS) + LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}") + endif(WINDOWS) endif(NOT LINUX) endif(LL_TESTS) diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 0e42922543..03efd09689 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -3268,11 +3268,9 @@ boost::signals2::connection LLFloater::setCloseCallback( const commit_signal_t:: return mCloseSignal.connect(cb); } -LLTrace::BlockTimerStatHandle POST_BUILD("Floater Post Build"); -static LLTrace::BlockTimerStatHandle FTM_EXTERNAL_FLOATER_LOAD("Load Extern Floater Reference"); - bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node) { + LL_PROFILE_ZONE_SCOPED; Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>()); Params params(default_params); @@ -3299,7 +3297,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str LLUICtrlFactory::instance().pushFileName(xml_filename); - LL_RECORD_BLOCK_TIME(FTM_EXTERNAL_FLOATER_LOAD); if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml)) { LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL; @@ -3375,12 +3372,8 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str } BOOL result; - { - LL_RECORD_BLOCK_TIME(POST_BUILD); - - result = postBuild(); - } - + result = postBuild(); + if (!result) { LL_ERRS() << "Failed to construct floater " << getName() << LL_ENDL; @@ -3424,11 +3417,9 @@ bool LLFloater::isVisible(const LLFloater* floater) return floater && floater->getVisible(); } -static LLTrace::BlockTimerStatHandle FTM_BUILD_FLOATERS("Build Floaters"); - bool LLFloater::buildFromFile(const std::string& filename) { - LL_RECORD_BLOCK_TIME(FTM_BUILD_FLOATERS); + LL_PROFILE_ZONE_SCOPED; LLXMLNodePtr root; if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 2672d600c6..306760b7fb 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -346,6 +346,8 @@ public: // handle refocusing. static void closeFrontmostFloater(); + static bool isQuitRequested() { return sQuitting; } + // LLNotification::Params contextualNotification(const std::string& name) // { // return LLNotification::Params(name).context(mNotificationContext); diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 622c9edba7..0996e82bf7 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -189,7 +189,6 @@ LLFolderView::LLFolderView(const Params& p) mViewModel(p.view_model), mGroupedItemModel(p.grouped_item_model) { - claimMem(mViewModel); LLPanel* panel = p.parent_panel; mParentPanel = panel->getHandle(); mViewModel->setFolderView(this); @@ -337,11 +336,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) return ll_round(mTargetHeight); } -static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View"); - void LLFolderView::filter( LLFolderViewFilter& filter ) { - LL_RECORD_BLOCK_TIME(FTM_FILTER); + LL_PROFILE_ZONE_SCOPED; static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100)); @@ -503,10 +500,9 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) return rv; } -static LLTrace::BlockTimerStatHandle FTM_SANITIZE_SELECTION("Sanitize Selection"); void LLFolderView::sanitizeSelection() { - LL_RECORD_BLOCK_TIME(FTM_SANITIZE_SELECTION); + LL_PROFILE_ZONE_SCOPED; // store off current item in case it is automatically deselected // and we want to preserve context LLFolderViewItem* original_selected_item = getCurSelectedItem(); @@ -1621,7 +1617,6 @@ void LLFolderView::setShowSingleSelection(bool show) } } -static LLTrace::BlockTimerStatHandle FTM_AUTO_SELECT("Open and Select"); static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory"); // Main idle routine @@ -1657,7 +1652,6 @@ void LLFolderView::update() // automatically show matching items, and select first one if we had a selection if (mNeedsAutoSelect) { - LL_RECORD_BLOCK_TIME(FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected and there was a selection LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible()) diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index e62b2779dd..093e213be3 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -108,11 +108,10 @@ public: virtual S32 getFirstRequiredGeneration() const = 0; }; -class LLFolderViewModelInterface : public LLTrace::MemTrackable<LLFolderViewModelInterface> +class LLFolderViewModelInterface { public: LLFolderViewModelInterface() - : LLTrace::MemTrackable<LLFolderViewModelInterface>("LLFolderViewModelInterface") {} virtual ~LLFolderViewModelInterface() {} @@ -133,11 +132,10 @@ public: // This is an abstract base class that users of the folderview classes // would use to bridge the folder view with the underlying data -class LLFolderViewModelItem : public LLRefCount, public LLTrace::MemTrackable<LLFolderViewModelItem> +class LLFolderViewModelItem : public LLRefCount { public: LLFolderViewModelItem() - : LLTrace::MemTrackable<LLFolderViewModelItem>("LLFolderViewModelItem") {} virtual ~LLFolderViewModelItem() { } diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 29a156e933..528d2e70ad 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -340,8 +340,6 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed) mNeedsLayout = true; } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_LAYOUT("Update LayoutStacks"); - class LLImagePanel : public LLPanel { public: @@ -369,7 +367,7 @@ private: void LLLayoutStack::updateLayout() { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_LAYOUT); + LL_PROFILE_ZONE_SCOPED; if (!mNeedsLayout) return; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index b791a19c2b..88eda1c172 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1387,7 +1387,7 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload) LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName) { - return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName)); + return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName).get()); } diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 00da0f5fec..f770920c4a 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -800,14 +800,12 @@ boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t:: return mVisibleSignal->connect(cb); } -static LLTrace::BlockTimerStatHandle FTM_BUILD_PANELS("Build Panels"); - //----------------------------------------------------------------------------- // buildPanel() //----------------------------------------------------------------------------- BOOL LLPanel::buildFromFile(const std::string& filename, const LLPanel::Params& default_params) { - LL_RECORD_BLOCK_TIME(FTM_BUILD_PANELS); + LL_PROFILE_ZONE_SCOPED; BOOL didPost = FALSE; LLXMLNodePtr root; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index de644185fd..c70085b72f 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3045,10 +3045,9 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name) return NULL; } -LLTrace::BlockTimerStatHandle FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item"); LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) { - LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); + LL_PROFILE_ZONE_SCOPED; LLScrollListItem::Params item_params; LLParamSDParser parser; parser.readSD(element, item_params); @@ -3058,14 +3057,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos) { - LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); + LL_PROFILE_ZONE_SCOPED; LLScrollListItem *new_item = new LLScrollListItem(item_p); return addRow(new_item, item_p, pos); } LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos) { - LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); + LL_PROFILE_ZONE_SCOPED; if (!item_p.validateBlock() || !new_item) return NULL; new_item->setNumColumns(mColumns.size()); diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 6c8e63442b..2449100952 100644 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -160,6 +160,7 @@ LLStatBar::Params::Params() tick_spacing("tick_spacing", 0.f), decimal_digits("decimal_digits", 3), show_bar("show_bar", false), + show_median("show_median", false), show_history("show_history", false), scale_range("scale_range", true), num_frames("num_frames", 200), @@ -186,6 +187,7 @@ LLStatBar::LLStatBar(const Params& p) mNumShortHistoryFrames(p.num_frames_short), mMaxHeight(p.max_height), mDisplayBar(p.show_bar), + mShowMedian(p.show_median), mDisplayHistory(p.show_history), mOrientation(p.orientation), mAutoScaleMax(!p.bar_max.isProvided()), @@ -318,7 +320,14 @@ void LLStatBar::draw() min = frame_recording.getPeriodMinPerSec(count_stat, num_frames); max = frame_recording.getPeriodMaxPerSec(count_stat, num_frames); mean = frame_recording.getPeriodMeanPerSec(count_stat, num_frames); - display_value = mean; + if (mShowMedian) + { + display_value = frame_recording.getPeriodMedianPerSec(count_stat, num_frames); + } + else + { + display_value = mean; + } } break; case STAT_EVENT: @@ -344,7 +353,11 @@ void LLStatBar::draw() mean = frame_recording.getPeriodMean(sample_stat, num_frames); num_rapid_changes = calc_num_rapid_changes(frame_recording, sample_stat, RAPID_CHANGE_WINDOW); - if (num_rapid_changes / RAPID_CHANGE_WINDOW.value() > MAX_RAPID_CHANGES_PER_SEC) + if (mShowMedian) + { + display_value = frame_recording.getPeriodMedian(sample_stat, num_frames); + } + else if (num_rapid_changes / RAPID_CHANGE_WINDOW.value() > MAX_RAPID_CHANGES_PER_SEC) { display_value = mean; } @@ -554,29 +567,25 @@ void LLStatBar::draw() void LLStatBar::setStat(const std::string& stat_name) { using namespace LLTrace; - const StatType<CountAccumulator>* count_stat; - const StatType<EventAccumulator>* event_stat; - const StatType<SampleAccumulator>* sample_stat; - const StatType<MemAccumulator>* mem_stat; - if ((count_stat = StatType<CountAccumulator>::getInstance(stat_name))) + if (auto count_stat = StatType<CountAccumulator>::getInstance(stat_name)) { - mStat.countStatp = count_stat; + mStat.countStatp = count_stat.get(); mStatType = STAT_COUNT; } - else if ((event_stat = StatType<EventAccumulator>::getInstance(stat_name))) + else if (auto event_stat = StatType<EventAccumulator>::getInstance(stat_name)) { - mStat.eventStatp = event_stat; + mStat.eventStatp = event_stat.get(); mStatType = STAT_EVENT; } - else if ((sample_stat = StatType<SampleAccumulator>::getInstance(stat_name))) + else if (auto sample_stat = StatType<SampleAccumulator>::getInstance(stat_name)) { - mStat.sampleStatp = sample_stat; + mStat.sampleStatp = sample_stat.get(); mStatType = STAT_SAMPLE; } - else if ((mem_stat = StatType<MemAccumulator>::getInstance(stat_name))) + else if (auto mem_stat = StatType<MemAccumulator>::getInstance(stat_name)) { - mStat.memStatp = mem_stat; + mStat.memStatp = mem_stat.get(); mStatType = STAT_MEM; } } diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index 1ff4c67fc5..6b481ca68f 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -44,9 +44,10 @@ public: bar_max, tick_spacing; - Optional<bool> show_bar, + Optional<bool> show_bar, show_history, - scale_range; + scale_range, + show_median; // default is mean Optional<S32> decimal_digits, num_frames, @@ -112,6 +113,7 @@ private: bool mDisplayBar, // Display the bar graph. mDisplayHistory, + mShowMedian, mAutoScaleMax, mAutoScaleMin; }; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 05788f1b6c..3b0789892f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1490,11 +1490,9 @@ S32 LLTextBase::getLeftOffset(S32 width) } } - -static LLTrace::BlockTimerStatHandle FTM_TEXT_REFLOW ("Text Reflow"); void LLTextBase::reflow() { - LL_RECORD_BLOCK_TIME(FTM_TEXT_REFLOW); + LL_PROFILE_ZONE_SCOPED; updateSegments(); @@ -1839,10 +1837,9 @@ void LLTextBase::removeDocumentChild(LLView* view) } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments"); void LLTextBase::updateSegments() { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_TEXT_SEGMENTS); + LL_PROFILE_ZONE_SCOPED; createDefaultSegment(); } @@ -2102,19 +2099,16 @@ static LLUIImagePtr image_from_icon_name(const std::string& icon_name) } } -static LLTrace::BlockTimerStatHandle FTM_PARSE_HTML("Parse HTML"); - - void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params) { + LL_PROFILE_ZONE_SCOPED; LLStyle::Params style_params(input_params); style_params.fillFrom(getStyleParams()); S32 part = (S32)LLTextParser::WHOLE; if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358). { - LL_RECORD_BLOCK_TIME(FTM_PARSE_HTML); S32 start=0,end=0; LLUrlMatch match; std::string text = new_text; @@ -2208,11 +2202,9 @@ void LLTextBase::setLastSegmentToolTip(const std::string &tooltip) } } -static LLTrace::BlockTimerStatHandle FTM_APPEND_TEXT("Append Text"); - void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) { - LL_RECORD_BLOCK_TIME(FTM_APPEND_TEXT); + LL_PROFILE_ZONE_SCOPED; if (new_text.empty()) return; diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 5924542a19..51391bb5e8 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -121,7 +121,6 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel) mDoubleClickSignal(NULL), mTransparencyType(TT_DEFAULT) { - claimMem(viewmodel.get()); } void LLUICtrl::initFromParams(const Params& p) @@ -476,6 +475,7 @@ LLViewModel* LLUICtrl::getViewModel() const //virtual BOOL LLUICtrl::postBuild() { + LL_PROFILE_ZONE_SCOPED; // // Find all of the children that want to be in front and move them to the front // @@ -781,12 +781,9 @@ BOOL LLUICtrl::getIsChrome() const } - -LLTrace::BlockTimerStatHandle FTM_FOCUS_FIRST_ITEM("Focus First Item"); - BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash) { - LL_RECORD_BLOCK_TIME(FTM_FOCUS_FIRST_ITEM); + LL_PROFILE_ZONE_SCOPED; // try to select default tab group child LLViewQuery query = getTabOrderQuery(); child_list_t result = query(this); @@ -1005,7 +1002,6 @@ boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (L boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb ) { if (!mValidateSignal) mValidateSignal = new enable_signal_t(); - claimMem(mValidateSignal); return mValidateSignal->connect(boost::bind(cb, _2)); } @@ -1070,7 +1066,6 @@ boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackPa boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb ) { if (!mCommitSignal) mCommitSignal = new commit_signal_t(); - claimMem(mCommitSignal); return mCommitSignal->connect(cb); } @@ -1078,7 +1073,6 @@ boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t:: boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb ) { if (!mValidateSignal) mValidateSignal = new enable_signal_t(); - claimMem(mValidateSignal); return mValidateSignal->connect(cb); } @@ -1086,7 +1080,6 @@ boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb ) { if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t(); - claimMem(mMouseEnterSignal); return mMouseEnterSignal->connect(cb); } @@ -1094,7 +1087,6 @@ boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) { if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t(); - claimMem(mMouseLeaveSignal); return mMouseLeaveSignal->connect(cb); } @@ -1102,7 +1094,6 @@ boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) { if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t(); - claimMem(mMouseDownSignal); return mMouseDownSignal->connect(cb); } @@ -1110,7 +1101,6 @@ boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb ) { if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t(); - claimMem(mMouseUpSignal); return mMouseUpSignal->connect(cb); } @@ -1118,7 +1108,6 @@ boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t:: boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb ) { if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t(); - claimMem(mRightMouseDownSignal); return mRightMouseDownSignal->connect(cb); } @@ -1126,7 +1115,6 @@ boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_sig boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb ) { if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t(); - claimMem(mRightMouseUpSignal); return mRightMouseUpSignal->connect(cb); } @@ -1134,7 +1122,6 @@ boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signa boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb ) { if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t(); - claimMem(mDoubleClickSignal); return mDoubleClickSignal->connect(cb); } diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index fdefae01b1..2d0c0ea8aa 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -44,10 +44,6 @@ // this library includes #include "llpanel.h" -LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION("Widget Construction"); -LLTrace::BlockTimerStatHandle FTM_INIT_FROM_PARAMS("Widget InitFromParams"); -LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP("Widget Setup"); - //----------------------------------------------------------------------------- // UI Ctrl class for padding @@ -117,12 +113,10 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa } } -static LLTrace::BlockTimerStatHandle FTM_CREATE_CHILDREN("Create XUI Children"); - //static void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t& registry, LLXMLNodePtr output_node) { - LL_RECORD_BLOCK_TIME(FTM_CREATE_CHILDREN); + LL_PROFILE_ZONE_SCOPED; if (node.isNull()) return; for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling()) @@ -159,14 +153,13 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const wid } -static LLTrace::BlockTimerStatHandle FTM_XML_PARSE("XML Reading/Parsing"); //----------------------------------------------------------------------------- // getLayeredXMLNode() //----------------------------------------------------------------------------- bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root, LLDir::ESkinConstraint constraint) { - LL_RECORD_BLOCK_TIME(FTM_XML_PARSE); + LL_PROFILE_ZONE_SCOPED; std::vector<std::string> paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xui_filename, constraint); @@ -191,11 +184,9 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_CREATE_FROM_XML("Create child widget"); - LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node) { - LL_RECORD_BLOCK_TIME(FTM_CREATE_FROM_XML); + LL_PROFILE_ZONE_SCOPED; std::string ctrl_type = node->getName()->mString; LLStringUtil::toLower(ctrl_type); diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 135ed57a4f..3f24a3f1a5 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -79,10 +79,6 @@ class LLWidgetNameRegistry // LLSINGLETON(LLDefaultParamBlockRegistry); //}; -extern LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP; -extern LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION; -extern LLTrace::BlockTimerStatHandle FTM_INIT_FROM_PARAMS; - // Build time optimization, generate this once in .cpp file #ifndef LLUICTRLFACTORY_CPP extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance(); @@ -213,6 +209,7 @@ private: template<typename T> static T* createWidgetImpl(const typename T::Params& params, LLView* parent = NULL) { + LL_PROFILE_ZONE_SCOPED; T* widget = NULL; if (!params.validateBlock()) @@ -221,12 +218,9 @@ private: //return NULL; } - { LL_RECORD_BLOCK_TIME(FTM_WIDGET_CONSTRUCTION); - widget = new T(params); - } - { LL_RECORD_BLOCK_TIME(FTM_INIT_FROM_PARAMS); - widget->initFromParams(params); - } + widget = new T(params); + + widget->initFromParams(params); if (parent) { @@ -239,7 +233,7 @@ private: template<typename T> static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) { - LL_RECORD_BLOCK_TIME(FTM_WIDGET_SETUP); + LL_PROFILE_ZONE_SCOPED; typename T::Params params(getDefaultParams<T>()); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index b942be2a4a..bd0b9d3db2 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -140,8 +140,7 @@ LLView::Params::Params() } LLView::LLView(const LLView::Params& p) -: LLTrace::MemTrackable<LLView>("LLView"), - mVisible(p.visible), +: mVisible(p.visible), mInDraw(false), mName(p.name), mParentView(NULL), @@ -1597,15 +1596,11 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse) const return getChild<LLView>(name, recurse); } -static LLTrace::BlockTimerStatHandle FTM_FIND_VIEWS("Find Widgets"); - LLView* LLView::findChildView(const std::string& name, BOOL recurse) const { - LL_RECORD_BLOCK_TIME(FTM_FIND_VIEWS); - //richard: should we allow empty names? - //if(name.empty()) - // return NULL; - // Look for direct children *first* + LL_PROFILE_ZONE_SCOPED; + + // Look for direct children *first* BOOST_FOREACH(LLView* childp, mChildList) { llassert(childp); diff --git a/indra/llui/llview.h b/indra/llui/llview.h index c60dcf3344..bec45df78a 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -100,8 +100,7 @@ class LLView : public LLMouseHandler, // handles mouse events public LLFocusableElement, // handles keyboard events public LLMortician, // lazy deletion - public LLHandleProvider<LLView>, // passes out weak references to self - public LLTrace::MemTrackable<LLView> // track memory usage + public LLHandleProvider<LLView> // passes out weak references to self { public: diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index 94e66f5dc4..6170005b2b 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -41,12 +41,12 @@ #include "llsingleton.h" // includes llerror which we need here so we can skip the include here -class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder> +class LLViewerEventRecorder : public LLSimpleton<LLViewerEventRecorder> { - LLSINGLETON(LLViewerEventRecorder); - ~LLViewerEventRecorder(); - - public: +public: + LLViewerEventRecorder(); + ~LLViewerEventRecorder(); + void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y, std::string mName); void setMouseLocalCoords(S32 x,S32 y); void setMouseGlobalCoords(S32 x,S32 y); diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp index 282addf692..a400eb70c0 100644 --- a/indra/llui/llviewmodel.cpp +++ b/indra/llui/llviewmodel.cpp @@ -37,15 +37,13 @@ /// LLViewModel::LLViewModel() -: LLTrace::MemTrackable<LLViewModel>("LLViewModel"), - mDirty(false) +: mDirty(false) { } /// Instantiate an LLViewModel with an existing data value LLViewModel::LLViewModel(const LLSD& value) -: LLTrace::MemTrackable<LLViewModel>("LLViewModel"), - mDirty(false) +: mDirty(false) { setValue(value); } @@ -82,15 +80,9 @@ LLTextViewModel::LLTextViewModel(const LLSD& value) void LLTextViewModel::setValue(const LLSD& value) { // approximate LLSD storage usage - disclaimMem(mDisplay.size()); LLViewModel::setValue(value); - disclaimMem(mDisplay); mDisplay = utf8str_to_wstring(value.asString()); - claimMem(mDisplay); - // approximate LLSD storage usage - claimMem(mDisplay.size()); - // mDisplay and mValue agree mUpdateFromDisplay = false; } @@ -101,12 +93,8 @@ void LLTextViewModel::setDisplay(const LLWString& value) // and do the utf8str_to_wstring() to get the corresponding mDisplay // value. But a text editor might want to edit the display string // directly, then convert back to UTF8 on commit. - disclaimMem(mDisplay.size()); - disclaimMem(mDisplay); - mDisplay = value; - claimMem(mDisplay); - claimMem(mDisplay.size()); - mDirty = true; + mDisplay = value; + mDirty = true; // Don't immediately convert to UTF8 -- do it lazily -- we expect many // more setDisplay() calls than getValue() calls. Just flag that it needs // doing. diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index 49d7c322a3..e7dceb6c31 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -62,8 +62,7 @@ typedef LLPointer<LLListViewModel> LLListViewModelPtr; * last referencing widget is destroyed. */ class LLViewModel -: public LLRefCount, - public LLTrace::MemTrackable<LLViewModel> +: public LLRefCount { public: LLViewModel(); diff --git a/indra/llwindow/GL/glh_extensions.h b/indra/llwindow/GL/glh_extensions.h deleted file mode 100644 index 554cb1731f..0000000000 --- a/indra/llwindow/GL/glh_extensions.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * glh_extensions.h - * $LicenseInfo:firstyear=2006&license=mit$ (mit used here to satisfy validity checker) - * Copyright (C) 2006, NVIDIA - * From nVidia Corporation, downloaded 2006-12-18 from: - * http://developer.nvidia.com/attach/8196 - * ("NVParse Library with Source (.zip) (2390 KB)") - * - * License (quoted from license_info.txt in aforementioned file): - * "The files bison.exe, bison.simple, and flex.exe are covered by - * the GPL. All other files in this distribution can be used however - * you want." - * $/LicenseInfo$ - - */ - -#ifndef GLH_EXTENSIONS -#define GLH_EXTENSIONS - -#include <string.h> -#include <stdio.h> - -#ifdef _WIN32 -# include <windows.h> -#endif - -#ifndef __APPLE__ -#include <GL/gl.h> -#endif - -#ifdef _WIN32 -# include "GL/wglext.h" -#endif - -#define CHECK_MEMORY(ptr) \ - if (NULL == ptr) { \ - printf("Error allocating memory in file %s, line %d\n", __FILE__, __LINE__); \ - exit(-1); \ - } - -#ifdef GLH_EXT_SINGLE_FILE -# define GLH_EXTENSIONS_SINGLE_FILE // have to do this because glh_genext.h unsets GLH_EXT_SINGLE_FILE -#endif - -#include "glh_genext.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef GLH_EXTENSIONS_SINGLE_FILE - -class GLHExts -{ -public: - GLHExts() - { - mSysExts = NULL; -// mUnsupportedExts = NULL; - } - ~GLHExts() - { - if (mSysExts) - { - free(mSysExts); - } -// if (mUnsupportedExts) -// { -// free(mUnsupportedExts); -// } - } - char *mSysExts; -// char *mUnsupportedExts; -}; - -GLHExts gGLHExts; - -static int ExtensionExists(const char* extName, const char* sysExts) -{ - char *padExtName = (char*)malloc(strlen(extName) + 2); - strcat(strcpy(padExtName, extName), " "); - - if (0 == strcmp(extName, "GL_VERSION_1_2")) { - const char *version = (const char*)glGetString(GL_VERSION); - if (strstr(version, "1.0") == version || strstr(version, "1.1") == version) { - return FALSE; - } else { - return TRUE; - } - } - if (strstr(sysExts, padExtName)) { - free(padExtName); - return TRUE; - } else { - free(padExtName); - return FALSE; - } -} - -static const char* EatWhiteSpace(const char *str) -{ - for (; *str && (' ' == *str || '\t' == *str || '\n' == *str); str++); - return str; -} - -static const char* EatNonWhiteSpace(const char *str) -{ - for (; *str && (' ' != *str && '\t' != *str && '\n' != *str); str++); - return str; -} - - -int glh_init_extensions(const char *origReqExts) -{ - // Length of requested extensions string - //unsigned reqExtsLen; - char *reqExts; - // Ptr for individual extensions within reqExts - char *reqExt; - int success = TRUE; - - // build space-padded extension string - if (NULL == gGLHExts.mSysExts) { - const char *extensions = (const char*)glGetString(GL_EXTENSIONS); - int sysExtsLen = (int)strlen(extensions); - const char *winsys_extensions = 0; - int winsysExtsLen = 0; -#ifdef _WIN32 - { - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; - wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); - if(wglGetExtensionsStringARB) - { - winsys_extensions = wglGetExtensionsStringARB(wglGetCurrentDC()); - winsysExtsLen = (S32)strlen(winsys_extensions); - } - } -#endif - // Add 2 bytes, one for padding space, one for terminating NULL - gGLHExts.mSysExts = (char*)malloc(sysExtsLen + winsysExtsLen + 3); - CHECK_MEMORY(gGLHExts.mSysExts); - strcpy(gGLHExts.mSysExts, extensions); - gGLHExts.mSysExts[sysExtsLen] = ' '; - gGLHExts.mSysExts[sysExtsLen + 1] = 0; - if (winsysExtsLen) - { - strcat(gGLHExts.mSysExts, winsys_extensions); - } - gGLHExts.mSysExts[sysExtsLen + 1 + winsysExtsLen] = ' '; - gGLHExts.mSysExts[sysExtsLen + 1 + winsysExtsLen + 1] = 0; - } - - if (NULL == origReqExts) - { - return TRUE; - } - reqExts = strdup(origReqExts); - /* - reqExtsLen = (S32)strlen(reqExts); - if (NULL == gGLHExts.mUnsupportedExts) - { - gGLHExts.mUnsupportedExts = (char*)malloc(reqExtsLen + 1); - } - else if (reqExtsLen > strlen(gGLHExts.mUnsupportedExts)) - { - gGLHExts.mUnsupportedExts = (char*)realloc(gGLHExts.mUnsupportedExts, reqExtsLen + 1); - } - CHECK_MEMORY(gGLHExts.mUnsupportedExts); - *gGLHExts.mUnsupportedExts = 0; - */ - - // Parse requested extension list - for (reqExt = reqExts; - (reqExt = (char*)EatWhiteSpace(reqExt)) && *reqExt; - reqExt = (char*)EatNonWhiteSpace(reqExt)) - { - char *extEnd = (char*)EatNonWhiteSpace(reqExt); - char saveChar = *extEnd; - *extEnd = (char)0; - - if (!ExtensionExists(reqExt, gGLHExts.mSysExts) || - !glh_init_extension(reqExt)) { - /* - // add reqExt to end of unsupportedExts - strcat(gGLHExts.mUnsupportedExts, reqExt); - strcat(gGLHExts.mUnsupportedExts, " "); - */ - success = FALSE; - } - *extEnd = saveChar; - } - free(reqExts); - return success; -} - -const char* glh_get_unsupported_extensions() -{ - return ""; -// return (const char*)gGLHExts.mUnsupportedExts; -} - -#else -int glh_init_extensions(const char *origReqExts); -const char* glh_get_unsupported_extensions(); -#endif /* GLH_EXT_SINGLE_FILE */ - -#ifdef __cplusplus -} -#endif - -#endif /* GLH_EXTENSIONS */ diff --git a/indra/llwindow/GL/glh_genext.h b/indra/llwindow/GL/glh_genext.h deleted file mode 100644 index cd5d1604a8..0000000000 --- a/indra/llwindow/GL/glh_genext.h +++ /dev/null @@ -1,1674 +0,0 @@ -/* - * glh_genext.h - * $LicenseInfo:firstyear=2008&license=mit$ (mit used here to satisfy validity checker) - * Copyright (C) 2008, NVIDIA - * From nVidia Corporation, downloaded 2006-12-18 from: - * http://developer.nvidia.com/attach/8196 - * ("NVParse Library with Source (.zip) (2390 KB)") - * - * License (quoted from license_info.txt in aforementioned file): - * "The files bison.exe, bison.simple, and flex.exe are covered by - * the GPL. All other files in this distribution can be used however - * you want." - * $/LicenseInfo$ - */ - -/* File generated by extgen.cpp -- do not modify */ -#ifndef GLH_GENEXT_H -#define GLH_GENEXT_H - -// MBW -- None of this is necessary on Mac OS. -#ifndef __APPLE__ - -#include <GL/gl.h> -#include <GL/glext.h> - -#ifdef _WIN32 /* supports windows, x -- need to generalize */ -# include <GL/wglext.h> -# define GLH_EXT_GET_PROC_ADDRESS(p) wglGetProcAddress(p) -#else if GLX_VERSION_1_3 -# include <GL/glxext.h> -# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB(p) -#endif - -#ifdef GLH_EXT_SINGLE_FILE - #define GLH_EXTERN - #define GLH_INITIALIZER = 0 -#else - #define GLH_EXTERN extern - #define GLH_INITIALIZER -#endif - -#define GLH__PREPROCESSOR_GYMNASTICS2(a,b) a##b -#define GLH__PREPROCESSOR_GYMNASTICS(a,b) GLH__PREPROCESSOR_GYMNASTICS2(a,b) - -#ifndef GLH_EXT_PREFIX -# define GLH_EXT_NAME(a) a -#else -# define GLH_EXT_NAME(a) GLH__PREPROCESSOR_GYMNASTICS(GLH_EXT_PREFIX,a) -#endif - -#ifndef _WIN32 -# ifndef GLH_CORE_1_2_PREFIX -# define GLH_CORE_1_2_PREFIX _ -# endif -#endif - -#ifndef GLH_CORE_1_2_PREFIX -# define GLH_CORE_1_2_NAME(a) a -#else -# define GLH_CORE_1_2_NAME(a) GLH__PREPROCESSOR_GYMNASTICS(GLH_CORE_1_2_PREFIX,a) -#endif - -#ifdef GL_ARB_multitexture - GLH_EXTERN PFNGLMULTITEXCOORD1DARBPROC GLH_EXT_NAME(glMultiTexCoord1dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1DVARBPROC GLH_EXT_NAME(glMultiTexCoord1dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1FARBPROC GLH_EXT_NAME(glMultiTexCoord1fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1FVARBPROC GLH_EXT_NAME(glMultiTexCoord1fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1IARBPROC GLH_EXT_NAME(glMultiTexCoord1iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1IVARBPROC GLH_EXT_NAME(glMultiTexCoord1ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1SARBPROC GLH_EXT_NAME(glMultiTexCoord1sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD1SVARBPROC GLH_EXT_NAME(glMultiTexCoord1svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2DARBPROC GLH_EXT_NAME(glMultiTexCoord2dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2DVARBPROC GLH_EXT_NAME(glMultiTexCoord2dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2FARBPROC GLH_EXT_NAME(glMultiTexCoord2fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2FVARBPROC GLH_EXT_NAME(glMultiTexCoord2fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2IARBPROC GLH_EXT_NAME(glMultiTexCoord2iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2IVARBPROC GLH_EXT_NAME(glMultiTexCoord2ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2SARBPROC GLH_EXT_NAME(glMultiTexCoord2sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD2SVARBPROC GLH_EXT_NAME(glMultiTexCoord2svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3DARBPROC GLH_EXT_NAME(glMultiTexCoord3dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3DVARBPROC GLH_EXT_NAME(glMultiTexCoord3dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3FARBPROC GLH_EXT_NAME(glMultiTexCoord3fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3FVARBPROC GLH_EXT_NAME(glMultiTexCoord3fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3IARBPROC GLH_EXT_NAME(glMultiTexCoord3iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3IVARBPROC GLH_EXT_NAME(glMultiTexCoord3ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3SARBPROC GLH_EXT_NAME(glMultiTexCoord3sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD3SVARBPROC GLH_EXT_NAME(glMultiTexCoord3svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4DARBPROC GLH_EXT_NAME(glMultiTexCoord4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4DVARBPROC GLH_EXT_NAME(glMultiTexCoord4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4FARBPROC GLH_EXT_NAME(glMultiTexCoord4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4FVARBPROC GLH_EXT_NAME(glMultiTexCoord4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4IARBPROC GLH_EXT_NAME(glMultiTexCoord4iARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4IVARBPROC GLH_EXT_NAME(glMultiTexCoord4ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4SARBPROC GLH_EXT_NAME(glMultiTexCoord4sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTITEXCOORD4SVARBPROC GLH_EXT_NAME(glMultiTexCoord4svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLACTIVETEXTUREARBPROC GLH_EXT_NAME(glActiveTextureARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCLIENTACTIVETEXTUREARBPROC GLH_EXT_NAME(glClientActiveTextureARB) GLH_INITIALIZER; -#endif - -#ifdef GL_ARB_texture_border_clamp -#endif - -#ifdef GL_ARB_texture_compression - GLH_EXTERN PFNGLCOMPRESSEDTEXIMAGE3DARBPROC GLH_EXT_NAME(glCompressedTexImage3DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXIMAGE2DARBPROC GLH_EXT_NAME(glCompressedTexImage2DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXIMAGE1DARBPROC GLH_EXT_NAME(glCompressedTexImage1DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC GLH_EXT_NAME(glCompressedTexSubImage3DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC GLH_EXT_NAME(glCompressedTexSubImage2DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC GLH_EXT_NAME(glCompressedTexSubImage1DARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMPRESSEDTEXIMAGEARBPROC GLH_EXT_NAME(glGetCompressedTexImageARB) GLH_INITIALIZER; -#endif - -#ifdef GL_ARB_texture_cube_map -#endif - -#ifdef GL_ARB_transpose_matrix - GLH_EXTERN PFNGLLOADTRANSPOSEMATRIXFARBPROC GLH_EXT_NAME(glLoadTransposeMatrixfARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLLOADTRANSPOSEMATRIXDARBPROC GLH_EXT_NAME(glLoadTransposeMatrixdARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTTRANSPOSEMATRIXFARBPROC GLH_EXT_NAME(glMultTransposeMatrixfARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLMULTTRANSPOSEMATRIXDARBPROC GLH_EXT_NAME(glMultTransposeMatrixdARB) GLH_INITIALIZER; -#endif - -#ifdef GL_ARB_vertex_program - GLH_EXTERN PFNGLVERTEXATTRIB1SARBPROC GLH_EXT_NAME(glVertexAttrib1sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FARBPROC GLH_EXT_NAME(glVertexAttrib1fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DARBPROC GLH_EXT_NAME(glVertexAttrib1dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SARBPROC GLH_EXT_NAME(glVertexAttrib2sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FARBPROC GLH_EXT_NAME(glVertexAttrib2fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DARBPROC GLH_EXT_NAME(glVertexAttrib2dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SARBPROC GLH_EXT_NAME(glVertexAttrib3sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FARBPROC GLH_EXT_NAME(glVertexAttrib3fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DARBPROC GLH_EXT_NAME(glVertexAttrib3dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SARBPROC GLH_EXT_NAME(glVertexAttrib4sARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FARBPROC GLH_EXT_NAME(glVertexAttrib4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DARBPROC GLH_EXT_NAME(glVertexAttrib4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUBARBPROC GLH_EXT_NAME(glVertexAttrib4NubARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1SVARBPROC GLH_EXT_NAME(glVertexAttrib1svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FVARBPROC GLH_EXT_NAME(glVertexAttrib1fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DVARBPROC GLH_EXT_NAME(glVertexAttrib1dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SVARBPROC GLH_EXT_NAME(glVertexAttrib2svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FVARBPROC GLH_EXT_NAME(glVertexAttrib2fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DVARBPROC GLH_EXT_NAME(glVertexAttrib2dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SVARBPROC GLH_EXT_NAME(glVertexAttrib3svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FVARBPROC GLH_EXT_NAME(glVertexAttrib3fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DVARBPROC GLH_EXT_NAME(glVertexAttrib3dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4BVARBPROC GLH_EXT_NAME(glVertexAttrib4bvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SVARBPROC GLH_EXT_NAME(glVertexAttrib4svARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4IVARBPROC GLH_EXT_NAME(glVertexAttrib4ivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4UBVARBPROC GLH_EXT_NAME(glVertexAttrib4ubvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4USVARBPROC GLH_EXT_NAME(glVertexAttrib4usvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4UIVARBPROC GLH_EXT_NAME(glVertexAttrib4uivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FVARBPROC GLH_EXT_NAME(glVertexAttrib4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DVARBPROC GLH_EXT_NAME(glVertexAttrib4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NBVARBPROC GLH_EXT_NAME(glVertexAttrib4NbvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NSVARBPROC GLH_EXT_NAME(glVertexAttrib4NsvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NIVARBPROC GLH_EXT_NAME(glVertexAttrib4NivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUBVARBPROC GLH_EXT_NAME(glVertexAttrib4NubvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUSVARBPROC GLH_EXT_NAME(glVertexAttrib4NusvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4NUIVARBPROC GLH_EXT_NAME(glVertexAttrib4NuivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBPOINTERARBPROC GLH_EXT_NAME(glVertexAttribPointerARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLENABLEVERTEXATTRIBARRAYARBPROC GLH_EXT_NAME(glEnableVertexAttribArrayARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLDISABLEVERTEXATTRIBARRAYARBPROC GLH_EXT_NAME(glDisableVertexAttribArrayARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMSTRINGARBPROC GLH_EXT_NAME(glProgramStringARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLBINDPROGRAMARBPROC GLH_EXT_NAME(glBindProgramARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETEPROGRAMSARBPROC GLH_EXT_NAME(glDeleteProgramsARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGENPROGRAMSARBPROC GLH_EXT_NAME(glGenProgramsARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4DARBPROC GLH_EXT_NAME(glProgramEnvParameter4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4DVARBPROC GLH_EXT_NAME(glProgramEnvParameter4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4FARBPROC GLH_EXT_NAME(glProgramEnvParameter4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMENVPARAMETER4FVARBPROC GLH_EXT_NAME(glProgramEnvParameter4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4DARBPROC GLH_EXT_NAME(glProgramLocalParameter4dARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4DVARBPROC GLH_EXT_NAME(glProgramLocalParameter4dvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4FARBPROC GLH_EXT_NAME(glProgramLocalParameter4fARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMLOCALPARAMETER4FVARBPROC GLH_EXT_NAME(glProgramLocalParameter4fvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMENVPARAMETERDVARBPROC GLH_EXT_NAME(glGetProgramEnvParameterdvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMENVPARAMETERFVARBPROC GLH_EXT_NAME(glGetProgramEnvParameterfvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC GLH_EXT_NAME(glGetProgramLocalParameterdvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC GLH_EXT_NAME(glGetProgramLocalParameterfvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMIVARBPROC GLH_EXT_NAME(glGetProgramivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMSTRINGARBPROC GLH_EXT_NAME(glGetProgramStringARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBDVARBPROC GLH_EXT_NAME(glGetVertexAttribdvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBFVARBPROC GLH_EXT_NAME(glGetVertexAttribfvARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBIVARBPROC GLH_EXT_NAME(glGetVertexAttribivARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBPOINTERVARBPROC GLH_EXT_NAME(glGetVertexAttribPointervARB) GLH_INITIALIZER; - GLH_EXTERN PFNGLISPROGRAMARBPROC GLH_EXT_NAME(glIsProgramARB) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_abgr -#endif - -#ifdef GL_EXT_bgra -#endif - -#ifdef GL_EXT_blend_color - GLH_EXTERN PFNGLBLENDCOLOREXTPROC GLH_EXT_NAME(glBlendColorEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_blend_minmax - GLH_EXTERN PFNGLBLENDEQUATIONEXTPROC GLH_EXT_NAME(glBlendEquationEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_blend_subtract -#endif - -#ifdef GL_EXT_compiled_vertex_array - GLH_EXTERN PFNGLLOCKARRAYSEXTPROC GLH_EXT_NAME(glLockArraysEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLUNLOCKARRAYSEXTPROC GLH_EXT_NAME(glUnlockArraysEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_fog_coord - GLH_EXTERN PFNGLFOGCOORDDEXTPROC GLH_EXT_NAME(glFogCoorddEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDDVEXTPROC GLH_EXT_NAME(glFogCoorddvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDFEXTPROC GLH_EXT_NAME(glFogCoordfEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDFVEXTPROC GLH_EXT_NAME(glFogCoordfvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLFOGCOORDPOINTEREXTPROC GLH_EXT_NAME(glFogCoordPointerEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_light_max_exponent -#endif - -#ifdef GL_EXT_packed_pixels -#endif - -#ifdef GL_EXT_paletted_texture - GLH_EXTERN PFNGLCOLORSUBTABLEEXTPROC GLH_EXT_NAME(glColorSubTableEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEEXTPROC GLH_EXT_NAME(glColorTableEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEEXTPROC GLH_EXT_NAME(glGetColorTableEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERFVEXTPROC GLH_EXT_NAME(glGetColorTableParameterfvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERIVEXTPROC GLH_EXT_NAME(glGetColorTableParameterivEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_point_parameters - GLH_EXTERN PFNGLPOINTPARAMETERFEXTPROC GLH_EXT_NAME(glPointParameterfEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLPOINTPARAMETERFVEXTPROC GLH_EXT_NAME(glPointParameterfvEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_rescale_normal -#endif - -#ifdef GL_EXT_secondary_color - GLH_EXTERN PFNGLSECONDARYCOLOR3BEXTPROC GLH_EXT_NAME(glSecondaryColor3bEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3BVEXTPROC GLH_EXT_NAME(glSecondaryColor3bvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3DEXTPROC GLH_EXT_NAME(glSecondaryColor3dEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3DVEXTPROC GLH_EXT_NAME(glSecondaryColor3dvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3FEXTPROC GLH_EXT_NAME(glSecondaryColor3fEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3FVEXTPROC GLH_EXT_NAME(glSecondaryColor3fvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3IEXTPROC GLH_EXT_NAME(glSecondaryColor3iEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3IVEXTPROC GLH_EXT_NAME(glSecondaryColor3ivEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3SEXTPROC GLH_EXT_NAME(glSecondaryColor3sEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3SVEXTPROC GLH_EXT_NAME(glSecondaryColor3svEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UBEXTPROC GLH_EXT_NAME(glSecondaryColor3ubEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UBVEXTPROC GLH_EXT_NAME(glSecondaryColor3ubvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UIEXTPROC GLH_EXT_NAME(glSecondaryColor3uiEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3UIVEXTPROC GLH_EXT_NAME(glSecondaryColor3uivEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3USEXTPROC GLH_EXT_NAME(glSecondaryColor3usEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLOR3USVEXTPROC GLH_EXT_NAME(glSecondaryColor3usvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLSECONDARYCOLORPOINTEREXTPROC GLH_EXT_NAME(glSecondaryColorPointerEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_separate_specular_color -#endif - -#ifdef GL_EXT_shared_texture_palette -#endif - -#ifdef GL_EXT_stencil_wrap -#endif - -#ifdef GL_EXT_texture_compression_s3tc -#endif - -#ifdef GL_EXT_texture_cube_map -#endif - -#ifdef GL_EXT_texture_edge_clamp -#endif - -#ifdef GL_EXT_texture_env_add -#endif - -#ifdef GL_EXT_texture_env_combine -#endif - -#ifdef GL_EXT_texture_filter_anisotropic -#endif - -#ifdef GL_EXT_texture_lod_bias -#endif - -#ifdef GL_EXT_texture_object - GLH_EXTERN PFNGLARETEXTURESRESIDENTEXTPROC GLH_EXT_NAME(glAreTexturesResidentEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLBINDTEXTUREEXTPROC GLH_EXT_NAME(glBindTextureEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETETEXTURESEXTPROC GLH_EXT_NAME(glDeleteTexturesEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGENTEXTURESEXTPROC GLH_EXT_NAME(glGenTexturesEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLISTEXTUREEXTPROC GLH_EXT_NAME(glIsTextureEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLPRIORITIZETEXTURESEXTPROC GLH_EXT_NAME(glPrioritizeTexturesEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_texture3D - GLH_EXTERN PFNGLTEXIMAGE3DEXTPROC GLH_EXT_NAME(glTexImage3DEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_vertex_array - GLH_EXTERN PFNGLARRAYELEMENTEXTPROC GLH_EXT_NAME(glArrayElementEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORPOINTEREXTPROC GLH_EXT_NAME(glColorPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLEDGEFLAGPOINTEREXTPROC GLH_EXT_NAME(glEdgeFlagPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPOINTERVEXTPROC GLH_EXT_NAME(glGetPointervEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLINDEXPOINTEREXTPROC GLH_EXT_NAME(glIndexPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLNORMALPOINTEREXTPROC GLH_EXT_NAME(glNormalPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLTEXCOORDPOINTEREXTPROC GLH_EXT_NAME(glTexCoordPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXPOINTEREXTPROC GLH_EXT_NAME(glVertexPointerEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLDRAWARRAYSEXTPROC GLH_EXT_NAME(glDrawArraysEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_EXT_vertex_weighting - GLH_EXTERN PFNGLVERTEXWEIGHTFEXTPROC GLH_EXT_NAME(glVertexWeightfEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXWEIGHTFVEXTPROC GLH_EXT_NAME(glVertexWeightfvEXT) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXWEIGHTPOINTEREXTPROC GLH_EXT_NAME(glVertexWeightPointerEXT) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_blend_square -#endif - -#ifdef GL_NV_evaluators - GLH_EXTERN PFNGLMAPCONTROLPOINTSNVPROC GLH_EXT_NAME(glMapControlPointsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLMAPPARAMETERIVNVPROC GLH_EXT_NAME(glMapParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLMAPPARAMETERFVNVPROC GLH_EXT_NAME(glMapParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPCONTROLPOINTSNVPROC GLH_EXT_NAME(glGetMapControlPointsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPPARAMETERIVNVPROC GLH_EXT_NAME(glGetMapParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPPARAMETERFVNVPROC GLH_EXT_NAME(glGetMapParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPATTRIBPARAMETERIVNVPROC GLH_EXT_NAME(glGetMapAttribParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETMAPATTRIBPARAMETERFVNVPROC GLH_EXT_NAME(glGetMapAttribParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLEVALMAPSNVPROC GLH_EXT_NAME(glEvalMapsNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_fence - GLH_EXTERN PFNGLGENFENCESNVPROC GLH_EXT_NAME(glGenFencesNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETEFENCESNVPROC GLH_EXT_NAME(glDeleteFencesNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLSETFENCENVPROC GLH_EXT_NAME(glSetFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLTESTFENCENVPROC GLH_EXT_NAME(glTestFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLFINISHFENCENVPROC GLH_EXT_NAME(glFinishFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLISFENCENVPROC GLH_EXT_NAME(glIsFenceNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETFENCEIVNVPROC GLH_EXT_NAME(glGetFenceivNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_fog_distance -#endif - -#ifdef GL_NV_packed_depth_stencil -#endif - -#ifdef GL_NV_register_combiners - GLH_EXTERN PFNGLCOMBINERPARAMETERFVNVPROC GLH_EXT_NAME(glCombinerParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERPARAMETERFNVPROC GLH_EXT_NAME(glCombinerParameterfNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERPARAMETERIVNVPROC GLH_EXT_NAME(glCombinerParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERPARAMETERINVPROC GLH_EXT_NAME(glCombinerParameteriNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINERINPUTNVPROC GLH_EXT_NAME(glCombinerInputNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOMBINEROUTPUTNVPROC GLH_EXT_NAME(glCombinerOutputNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLFINALCOMBINERINPUTNVPROC GLH_EXT_NAME(glFinalCombinerInputNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC GLH_EXT_NAME(glGetCombinerInputParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC GLH_EXT_NAME(glGetCombinerInputParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC GLH_EXT_NAME(glGetCombinerOutputParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC GLH_EXT_NAME(glGetCombinerOutputParameterivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC GLH_EXT_NAME(glGetFinalCombinerInputParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC GLH_EXT_NAME(glGetFinalCombinerInputParameterivNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_register_combiners2 - GLH_EXTERN PFNGLCOMBINERSTAGEPARAMETERFVNVPROC GLH_EXT_NAME(glCombinerStageParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC GLH_EXT_NAME(glGetCombinerStageParameterfvNV) GLH_INITIALIZER; -#endif - -#ifdef GL_NV_texgen_reflection -#endif - -#ifdef GL_NV_texture_env_combine4 -#endif - -#ifdef GL_NV_texture_rectangle -#endif - -#ifdef GL_NV_texture_shader -#endif - -#ifdef GL_NV_vertex_array_range - GLH_EXTERN PFNGLFLUSHVERTEXARRAYRANGENVPROC GLH_EXT_NAME(glFlushVertexArrayRangeNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXARRAYRANGENVPROC GLH_EXT_NAME(glVertexArrayRangeNV) GLH_INITIALIZER; -# ifdef _WIN32 - GLH_EXTERN PFNWGLALLOCATEMEMORYNVPROC GLH_EXT_NAME(wglAllocateMemoryNV) GLH_INITIALIZER; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXTERN PFNGLXALLOCATEMEMORYNVPROC GLH_EXT_NAME(glXAllocateMemoryNV) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLFREEMEMORYNVPROC GLH_EXT_NAME(wglFreeMemoryNV) GLH_INITIALIZER; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXTERN PFNGLXFREEMEMORYNVPROC GLH_EXT_NAME(glXFreeMemoryNV) GLH_INITIALIZER; -# endif -#endif - -#ifdef GL_NV_vertex_program - GLH_EXTERN PFNGLAREPROGRAMSRESIDENTNVPROC GLH_EXT_NAME(glAreProgramsResidentNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLBINDPROGRAMNVPROC GLH_EXT_NAME(glBindProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLDELETEPROGRAMSNVPROC GLH_EXT_NAME(glDeleteProgramsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLEXECUTEPROGRAMNVPROC GLH_EXT_NAME(glExecuteProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGENPROGRAMSNVPROC GLH_EXT_NAME(glGenProgramsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMPARAMETERDVNVPROC GLH_EXT_NAME(glGetProgramParameterdvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMPARAMETERFVNVPROC GLH_EXT_NAME(glGetProgramParameterfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMIVNVPROC GLH_EXT_NAME(glGetProgramivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETPROGRAMSTRINGNVPROC GLH_EXT_NAME(glGetProgramStringNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETTRACKMATRIXIVNVPROC GLH_EXT_NAME(glGetTrackMatrixivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBDVNVPROC GLH_EXT_NAME(glGetVertexAttribdvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBFVNVPROC GLH_EXT_NAME(glGetVertexAttribfvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBIVNVPROC GLH_EXT_NAME(glGetVertexAttribivNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETVERTEXATTRIBPOINTERVNVPROC GLH_EXT_NAME(glGetVertexAttribPointervNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLISPROGRAMNVPROC GLH_EXT_NAME(glIsProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLLOADPROGRAMNVPROC GLH_EXT_NAME(glLoadProgramNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4DNVPROC GLH_EXT_NAME(glProgramParameter4dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4DVNVPROC GLH_EXT_NAME(glProgramParameter4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4FNVPROC GLH_EXT_NAME(glProgramParameter4fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETER4FVNVPROC GLH_EXT_NAME(glProgramParameter4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETERS4DVNVPROC GLH_EXT_NAME(glProgramParameters4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLPROGRAMPARAMETERS4FVNVPROC GLH_EXT_NAME(glProgramParameters4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLREQUESTRESIDENTPROGRAMSNVPROC GLH_EXT_NAME(glRequestResidentProgramsNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLTRACKMATRIXNVPROC GLH_EXT_NAME(glTrackMatrixNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBPOINTERNVPROC GLH_EXT_NAME(glVertexAttribPointerNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DNVPROC GLH_EXT_NAME(glVertexAttrib1dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1DVNVPROC GLH_EXT_NAME(glVertexAttrib1dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FNVPROC GLH_EXT_NAME(glVertexAttrib1fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1FVNVPROC GLH_EXT_NAME(glVertexAttrib1fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1SNVPROC GLH_EXT_NAME(glVertexAttrib1sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB1SVNVPROC GLH_EXT_NAME(glVertexAttrib1svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DNVPROC GLH_EXT_NAME(glVertexAttrib2dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2DVNVPROC GLH_EXT_NAME(glVertexAttrib2dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FNVPROC GLH_EXT_NAME(glVertexAttrib2fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2FVNVPROC GLH_EXT_NAME(glVertexAttrib2fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SNVPROC GLH_EXT_NAME(glVertexAttrib2sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB2SVNVPROC GLH_EXT_NAME(glVertexAttrib2svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DNVPROC GLH_EXT_NAME(glVertexAttrib3dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3DVNVPROC GLH_EXT_NAME(glVertexAttrib3dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FNVPROC GLH_EXT_NAME(glVertexAttrib3fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3FVNVPROC GLH_EXT_NAME(glVertexAttrib3fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SNVPROC GLH_EXT_NAME(glVertexAttrib3sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB3SVNVPROC GLH_EXT_NAME(glVertexAttrib3svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DNVPROC GLH_EXT_NAME(glVertexAttrib4dNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4DVNVPROC GLH_EXT_NAME(glVertexAttrib4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FNVPROC GLH_EXT_NAME(glVertexAttrib4fNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4FVNVPROC GLH_EXT_NAME(glVertexAttrib4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SNVPROC GLH_EXT_NAME(glVertexAttrib4sNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4SVNVPROC GLH_EXT_NAME(glVertexAttrib4svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIB4UBVNVPROC GLH_EXT_NAME(glVertexAttrib4ubvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS1DVNVPROC GLH_EXT_NAME(glVertexAttribs1dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS1FVNVPROC GLH_EXT_NAME(glVertexAttribs1fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS1SVNVPROC GLH_EXT_NAME(glVertexAttribs1svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS2DVNVPROC GLH_EXT_NAME(glVertexAttribs2dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS2FVNVPROC GLH_EXT_NAME(glVertexAttribs2fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS2SVNVPROC GLH_EXT_NAME(glVertexAttribs2svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS3DVNVPROC GLH_EXT_NAME(glVertexAttribs3dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS3FVNVPROC GLH_EXT_NAME(glVertexAttribs3fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS3SVNVPROC GLH_EXT_NAME(glVertexAttribs3svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4DVNVPROC GLH_EXT_NAME(glVertexAttribs4dvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4FVNVPROC GLH_EXT_NAME(glVertexAttribs4fvNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4SVNVPROC GLH_EXT_NAME(glVertexAttribs4svNV) GLH_INITIALIZER; - GLH_EXTERN PFNGLVERTEXATTRIBS4UBVNVPROC GLH_EXT_NAME(glVertexAttribs4ubvNV) GLH_INITIALIZER; -#endif - -#ifdef GL_SGIS_generate_mipmap -#endif - -#ifdef GL_SGIS_texture_lod -#endif - -#ifdef GL_SGIX_depth_texture -#endif - -#ifdef GL_SGIX_shadow -#endif - -#ifdef GL_VERSION_1_2 - /* These routines are prefixed by the preprocessor constant - GLH_CORE_1_2_PREFIX to avoid colliding with the OpenGL 1.2 namespace. */ - GLH_EXTERN PFNGLBLENDCOLORPROC GLH_CORE_1_2_NAME(glBlendColor) GLH_INITIALIZER; - GLH_EXTERN PFNGLBLENDEQUATIONPROC GLH_CORE_1_2_NAME(glBlendEquation) GLH_INITIALIZER; - GLH_EXTERN PFNGLDRAWRANGEELEMENTSPROC GLH_CORE_1_2_NAME(glDrawRangeElements) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEPROC GLH_CORE_1_2_NAME(glColorTable) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEPARAMETERFVPROC GLH_CORE_1_2_NAME(glColorTableParameterfv) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOLORTABLEPARAMETERIVPROC GLH_CORE_1_2_NAME(glColorTableParameteriv) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOPYCOLORTABLEPROC GLH_CORE_1_2_NAME(glCopyColorTable) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPROC GLH_CORE_1_2_NAME(glGetColorTable) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERFVPROC GLH_CORE_1_2_NAME(glGetColorTableParameterfv) GLH_INITIALIZER; - GLH_EXTERN PFNGLGETCOLORTABLEPARAMETERIVPROC GLH_CORE_1_2_NAME(glGetColorTableParameteriv) GLH_INITIALIZER; - GLH_EXTERN PFNGLTEXIMAGE3DPROC GLH_CORE_1_2_NAME(glTexImage3D) GLH_INITIALIZER; - GLH_EXTERN PFNGLTEXSUBIMAGE3DPROC GLH_CORE_1_2_NAME(glTexSubImage3D) GLH_INITIALIZER; - GLH_EXTERN PFNGLCOPYTEXSUBIMAGE3DPROC GLH_CORE_1_2_NAME(glCopyTexSubImage3D) GLH_INITIALIZER; -#endif - -#ifdef GL_WIN_swap_hint - GLH_EXTERN PFNGLADDSWAPHINTRECTWINPROC GLH_EXT_NAME(glAddSwapHintRectWIN) GLH_INITIALIZER; -#endif - -#ifdef WGL_ARB_pbuffer -# ifdef _WIN32 - GLH_EXTERN PFNWGLCREATEPBUFFERARBPROC GLH_EXT_NAME(wglCreatePbufferARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLGETPBUFFERDCARBPROC GLH_EXT_NAME(wglGetPbufferDCARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLRELEASEPBUFFERDCARBPROC GLH_EXT_NAME(wglReleasePbufferDCARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLDESTROYPBUFFERARBPROC GLH_EXT_NAME(wglDestroyPbufferARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLQUERYPBUFFERARBPROC GLH_EXT_NAME(wglQueryPbufferARB) GLH_INITIALIZER; -# endif -#endif - -#ifdef WGL_ARB_render_texture -# ifdef _WIN32 - GLH_EXTERN PFNWGLBINDTEXIMAGEARBPROC GLH_EXT_NAME(wglBindTexImageARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLRELEASETEXIMAGEARBPROC GLH_EXT_NAME(wglReleaseTexImageARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLSETPBUFFERATTRIBARBPROC GLH_EXT_NAME(wglSetPbufferAttribARB) GLH_INITIALIZER; -# endif -#endif - -#ifdef WGL_ARB_pixel_format -# ifdef _WIN32 - GLH_EXTERN PFNWGLGETPIXELFORMATATTRIBIVARBPROC GLH_EXT_NAME(wglGetPixelFormatAttribivARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLGETPIXELFORMATATTRIBFVARBPROC GLH_EXT_NAME(wglGetPixelFormatAttribfvARB) GLH_INITIALIZER; -# endif -# ifdef _WIN32 - GLH_EXTERN PFNWGLCHOOSEPIXELFORMATARBPROC GLH_EXT_NAME(wglChoosePixelFormatARB) GLH_INITIALIZER; -# endif -#endif - - -#ifdef GLH_EXT_SINGLE_FILE - -int glh_init_extension(const char* extension) -{ - if (NULL == extension) { - return FALSE; -#ifdef GL_ARB_multitexture - } else if (0 == strcmp(extension, "GL_ARB_multitexture")) { - GLH_EXT_NAME(glMultiTexCoord1dARB) = (PFNGLMULTITEXCOORD1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1dvARB) = (PFNGLMULTITEXCOORD1DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1fARB) = (PFNGLMULTITEXCOORD1FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1fvARB) = (PFNGLMULTITEXCOORD1FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1iARB) = (PFNGLMULTITEXCOORD1IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1ivARB) = (PFNGLMULTITEXCOORD1IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1sARB) = (PFNGLMULTITEXCOORD1SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord1svARB) = (PFNGLMULTITEXCOORD1SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord1svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord1svARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2dARB) = (PFNGLMULTITEXCOORD2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2dvARB) = (PFNGLMULTITEXCOORD2DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2fARB) = (PFNGLMULTITEXCOORD2FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2fvARB) = (PFNGLMULTITEXCOORD2FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2iARB) = (PFNGLMULTITEXCOORD2IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2ivARB) = (PFNGLMULTITEXCOORD2IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2sARB) = (PFNGLMULTITEXCOORD2SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord2svARB) = (PFNGLMULTITEXCOORD2SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord2svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord2svARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3dARB) = (PFNGLMULTITEXCOORD3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3dvARB) = (PFNGLMULTITEXCOORD3DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3fARB) = (PFNGLMULTITEXCOORD3FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3fvARB) = (PFNGLMULTITEXCOORD3FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3iARB) = (PFNGLMULTITEXCOORD3IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3ivARB) = (PFNGLMULTITEXCOORD3IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3sARB) = (PFNGLMULTITEXCOORD3SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord3svARB) = (PFNGLMULTITEXCOORD3SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord3svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord3svARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4dARB) = (PFNGLMULTITEXCOORD4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4dARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4dARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4dvARB) = (PFNGLMULTITEXCOORD4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4dvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4dvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4fARB) = (PFNGLMULTITEXCOORD4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4fARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4fARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4fvARB) = (PFNGLMULTITEXCOORD4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4fvARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4fvARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4iARB) = (PFNGLMULTITEXCOORD4IARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4iARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4iARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4ivARB) = (PFNGLMULTITEXCOORD4IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4ivARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4ivARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4sARB) = (PFNGLMULTITEXCOORD4SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4sARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4sARB)) - return FALSE; - GLH_EXT_NAME(glMultiTexCoord4svARB) = (PFNGLMULTITEXCOORD4SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultiTexCoord4svARB"); - if (NULL == GLH_EXT_NAME(glMultiTexCoord4svARB)) - return FALSE; - GLH_EXT_NAME(glActiveTextureARB) = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB"); - if (NULL == GLH_EXT_NAME(glActiveTextureARB)) - return FALSE; - GLH_EXT_NAME(glClientActiveTextureARB) = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB"); - if (NULL == GLH_EXT_NAME(glClientActiveTextureARB)) - return FALSE; -#endif - -#ifdef GL_ARB_texture_border_clamp - } else if (0 == strcmp(extension, "GL_ARB_texture_border_clamp")) { -#endif - -#ifdef GL_ARB_texture_compression - } else if (0 == strcmp(extension, "GL_ARB_texture_compression")) { - GLH_EXT_NAME(glCompressedTexImage3DARB) = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage3DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexImage3DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexImage2DARB) = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage2DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexImage2DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexImage1DARB) = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexImage1DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexImage1DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexSubImage3DARB) = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage3DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexSubImage3DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexSubImage2DARB) = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage2DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexSubImage2DARB)) - return FALSE; - GLH_EXT_NAME(glCompressedTexSubImage1DARB) = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glCompressedTexSubImage1DARB"); - if (NULL == GLH_EXT_NAME(glCompressedTexSubImage1DARB)) - return FALSE; - GLH_EXT_NAME(glGetCompressedTexImageARB) = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCompressedTexImageARB"); - if (NULL == GLH_EXT_NAME(glGetCompressedTexImageARB)) - return FALSE; -#endif - -#ifdef GL_ARB_texture_cube_map - } else if (0 == strcmp(extension, "GL_ARB_texture_cube_map")) { -#endif - -#ifdef GL_ARB_transpose_matrix - } else if (0 == strcmp(extension, "GL_ARB_transpose_matrix")) { - GLH_EXT_NAME(glLoadTransposeMatrixfARB) = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixfARB"); - if (NULL == GLH_EXT_NAME(glLoadTransposeMatrixfARB)) - return FALSE; - GLH_EXT_NAME(glLoadTransposeMatrixdARB) = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadTransposeMatrixdARB"); - if (NULL == GLH_EXT_NAME(glLoadTransposeMatrixdARB)) - return FALSE; - GLH_EXT_NAME(glMultTransposeMatrixfARB) = (PFNGLMULTTRANSPOSEMATRIXFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixfARB"); - if (NULL == GLH_EXT_NAME(glMultTransposeMatrixfARB)) - return FALSE; - GLH_EXT_NAME(glMultTransposeMatrixdARB) = (PFNGLMULTTRANSPOSEMATRIXDARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMultTransposeMatrixdARB"); - if (NULL == GLH_EXT_NAME(glMultTransposeMatrixdARB)) - return FALSE; -#endif - -#ifdef GL_ARB_vertex_program - } else if (0 == strcmp(extension, "GL_ARB_vertex_program")) { - GLH_EXT_NAME(glVertexAttrib1sARB) = (PFNGLVERTEXATTRIB1SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1fARB) = (PFNGLVERTEXATTRIB1FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1dARB) = (PFNGLVERTEXATTRIB1DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2sARB) = (PFNGLVERTEXATTRIB2SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2fARB) = (PFNGLVERTEXATTRIB2FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2dARB) = (PFNGLVERTEXATTRIB2DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3sARB) = (PFNGLVERTEXATTRIB3SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3fARB) = (PFNGLVERTEXATTRIB3FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3dARB) = (PFNGLVERTEXATTRIB3DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4sARB) = (PFNGLVERTEXATTRIB4SARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4sARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4fARB) = (PFNGLVERTEXATTRIB4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4dARB) = (PFNGLVERTEXATTRIB4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NubARB) = (PFNGLVERTEXATTRIB4NUBARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NubARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NubARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1svARB) = (PFNGLVERTEXATTRIB1SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1fvARB) = (PFNGLVERTEXATTRIB1FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib1dvARB) = (PFNGLVERTEXATTRIB1DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2svARB) = (PFNGLVERTEXATTRIB2SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2fvARB) = (PFNGLVERTEXATTRIB2FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib2dvARB) = (PFNGLVERTEXATTRIB2DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3svARB) = (PFNGLVERTEXATTRIB3SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3fvARB) = (PFNGLVERTEXATTRIB3FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib3dvARB) = (PFNGLVERTEXATTRIB3DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4bvARB) = (PFNGLVERTEXATTRIB4BVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4bvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4svARB) = (PFNGLVERTEXATTRIB4SVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4svARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4ivARB) = (PFNGLVERTEXATTRIB4IVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4ivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4ubvARB) = (PFNGLVERTEXATTRIB4UBVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4ubvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4usvARB) = (PFNGLVERTEXATTRIB4USVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4usvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4uivARB) = (PFNGLVERTEXATTRIB4UIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4uivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4fvARB) = (PFNGLVERTEXATTRIB4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4dvARB) = (PFNGLVERTEXATTRIB4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NbvARB) = (PFNGLVERTEXATTRIB4NBVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NbvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NbvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NsvARB) = (PFNGLVERTEXATTRIB4NSVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NsvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NsvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NivARB) = (PFNGLVERTEXATTRIB4NIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NubvARB) = (PFNGLVERTEXATTRIB4NUBVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NubvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NubvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NusvARB) = (PFNGLVERTEXATTRIB4NUSVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NusvARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NusvARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttrib4NuivARB) = (PFNGLVERTEXATTRIB4NUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4NuivARB"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4NuivARB)) - return GL_FALSE; - GLH_EXT_NAME(glVertexAttribPointerARB) = (PFNGLVERTEXATTRIBPOINTERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB"); - if (NULL == GLH_EXT_NAME(glVertexAttribPointerARB)) - return GL_FALSE; - GLH_EXT_NAME(glEnableVertexAttribArrayARB) = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB"); - if (NULL == GLH_EXT_NAME(glEnableVertexAttribArrayARB)) - return GL_FALSE; - GLH_EXT_NAME(glDisableVertexAttribArrayARB) = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB"); - if (NULL == GLH_EXT_NAME(glDisableVertexAttribArrayARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramStringARB) = (PFNGLPROGRAMSTRINGARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB"); - if (NULL == GLH_EXT_NAME(glProgramStringARB)) - return GL_FALSE; - GLH_EXT_NAME(glBindProgramARB) = (PFNGLBINDPROGRAMARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB"); - if (NULL == GLH_EXT_NAME(glBindProgramARB)) - return GL_FALSE; - GLH_EXT_NAME(glDeleteProgramsARB) = (PFNGLDELETEPROGRAMSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB"); - if (NULL == GLH_EXT_NAME(glDeleteProgramsARB)) - return GL_FALSE; - GLH_EXT_NAME(glGenProgramsARB) = (PFNGLGENPROGRAMSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB"); - if (NULL == GLH_EXT_NAME(glGenProgramsARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4dARB) = (PFNGLPROGRAMENVPARAMETER4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4dARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4dvARB) = (PFNGLPROGRAMENVPARAMETER4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4fARB) = (PFNGLPROGRAMENVPARAMETER4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4fARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramEnvParameter4fvARB) = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB"); - if (NULL == GLH_EXT_NAME(glProgramEnvParameter4fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4dARB) = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4dARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4dvARB) = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4dvARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4fARB) = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4fARB)) - return GL_FALSE; - GLH_EXT_NAME(glProgramLocalParameter4fvARB) = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB"); - if (NULL == GLH_EXT_NAME(glProgramLocalParameter4fvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramEnvParameterdvARB) = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramEnvParameterdvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramEnvParameterfvARB) = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramEnvParameterfvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramLocalParameterdvARB) = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramLocalParameterdvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramLocalParameterfvARB) = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB"); - if (NULL == GLH_EXT_NAME(glGetProgramLocalParameterfvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramivARB) = (PFNGLGETPROGRAMIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB"); - if (NULL == GLH_EXT_NAME(glGetProgramivARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetProgramStringARB) = (PFNGLGETPROGRAMSTRINGARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB"); - if (NULL == GLH_EXT_NAME(glGetProgramStringARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribdvARB) = (PFNGLGETVERTEXATTRIBDVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribdvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribfvARB) = (PFNGLGETVERTEXATTRIBFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribfvARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribivARB) = (PFNGLGETVERTEXATTRIBIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribivARB)) - return GL_FALSE; - GLH_EXT_NAME(glGetVertexAttribPointervARB) = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribPointervARB"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribPointervARB)) - return GL_FALSE; - GLH_EXT_NAME(glIsProgramARB) = (PFNGLISPROGRAMARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB"); - if (NULL == GLH_EXT_NAME(glIsProgramARB)) - return GL_FALSE; -#endif - -#ifdef GL_EXT_abgr - } else if (0 == strcmp(extension, "GL_EXT_abgr")) { -#endif - -#ifdef GL_EXT_bgra - } else if (0 == strcmp(extension, "GL_EXT_bgra")) { -#endif - -#ifdef GL_EXT_blend_color - } else if (0 == strcmp(extension, "GL_EXT_blend_color")) { - GLH_EXT_NAME(glBlendColorEXT) = (PFNGLBLENDCOLOREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendColorEXT"); - if (NULL == GLH_EXT_NAME(glBlendColorEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_blend_minmax - } else if (0 == strcmp(extension, "GL_EXT_blend_minmax")) { - GLH_EXT_NAME(glBlendEquationEXT) = (PFNGLBLENDEQUATIONEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquationEXT"); - if (NULL == GLH_EXT_NAME(glBlendEquationEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_blend_subtract - } else if (0 == strcmp(extension, "GL_EXT_blend_subtract")) { -#endif - -#ifdef GL_EXT_compiled_vertex_array - } else if (0 == strcmp(extension, "GL_EXT_compiled_vertex_array")) { - GLH_EXT_NAME(glLockArraysEXT) = (PFNGLLOCKARRAYSEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glLockArraysEXT"); - if (NULL == GLH_EXT_NAME(glLockArraysEXT)) - return FALSE; - GLH_EXT_NAME(glUnlockArraysEXT) = (PFNGLUNLOCKARRAYSEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glUnlockArraysEXT"); - if (NULL == GLH_EXT_NAME(glUnlockArraysEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_fog_coord - } else if (0 == strcmp(extension, "GL_EXT_fog_coord")) { - GLH_EXT_NAME(glFogCoorddEXT) = (PFNGLFOGCOORDDEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoorddEXT"); - if (NULL == GLH_EXT_NAME(glFogCoorddEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoorddvEXT) = (PFNGLFOGCOORDDVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoorddvEXT"); - if (NULL == GLH_EXT_NAME(glFogCoorddvEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoordfEXT) = (PFNGLFOGCOORDFEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordfEXT"); - if (NULL == GLH_EXT_NAME(glFogCoordfEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoordfvEXT) = (PFNGLFOGCOORDFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordfvEXT"); - if (NULL == GLH_EXT_NAME(glFogCoordfvEXT)) - return FALSE; - GLH_EXT_NAME(glFogCoordPointerEXT) = (PFNGLFOGCOORDPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glFogCoordPointerEXT"); - if (NULL == GLH_EXT_NAME(glFogCoordPointerEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_light_max_exponent - } else if (0 == strcmp(extension, "GL_EXT_light_max_exponent")) { -#endif - -#ifdef GL_EXT_packed_pixels - } else if (0 == strcmp(extension, "GL_EXT_packed_pixels")) { -#endif - -#ifdef GL_EXT_paletted_texture - } else if (0 == strcmp(extension, "GL_EXT_paletted_texture")) { - GLH_EXT_NAME(glColorSubTableEXT) = (PFNGLCOLORSUBTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorSubTableEXT"); - if (NULL == GLH_EXT_NAME(glColorSubTableEXT)) - return FALSE; - GLH_EXT_NAME(glColorTableEXT) = (PFNGLCOLORTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableEXT"); - if (NULL == GLH_EXT_NAME(glColorTableEXT)) - return FALSE; - GLH_EXT_NAME(glGetColorTableEXT) = (PFNGLGETCOLORTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableEXT"); - if (NULL == GLH_EXT_NAME(glGetColorTableEXT)) - return FALSE; - GLH_EXT_NAME(glGetColorTableParameterfvEXT) = (PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameterfvEXT"); - if (NULL == GLH_EXT_NAME(glGetColorTableParameterfvEXT)) - return FALSE; - GLH_EXT_NAME(glGetColorTableParameterivEXT) = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameterivEXT"); - if (NULL == GLH_EXT_NAME(glGetColorTableParameterivEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_point_parameters - } else if (0 == strcmp(extension, "GL_EXT_point_parameters")) { - GLH_EXT_NAME(glPointParameterfEXT) = (PFNGLPOINTPARAMETERFEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfEXT"); - if (NULL == GLH_EXT_NAME(glPointParameterfEXT)) - return FALSE; - GLH_EXT_NAME(glPointParameterfvEXT) = (PFNGLPOINTPARAMETERFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvEXT"); - if (NULL == GLH_EXT_NAME(glPointParameterfvEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_rescale_normal - } else if (0 == strcmp(extension, "GL_EXT_rescale_normal")) { -#endif - -#ifdef GL_EXT_secondary_color - } else if (0 == strcmp(extension, "GL_EXT_secondary_color")) { - GLH_EXT_NAME(glSecondaryColor3bEXT) = (PFNGLSECONDARYCOLOR3BEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3bEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3bEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3bvEXT) = (PFNGLSECONDARYCOLOR3BVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3bvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3bvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3dEXT) = (PFNGLSECONDARYCOLOR3DEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3dEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3dEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3dvEXT) = (PFNGLSECONDARYCOLOR3DVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3dvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3dvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3fEXT) = (PFNGLSECONDARYCOLOR3FEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3fEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3fEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3fvEXT) = (PFNGLSECONDARYCOLOR3FVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3fvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3fvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3iEXT) = (PFNGLSECONDARYCOLOR3IEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3iEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3iEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3ivEXT) = (PFNGLSECONDARYCOLOR3IVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ivEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3ivEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3sEXT) = (PFNGLSECONDARYCOLOR3SEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3sEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3sEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3svEXT) = (PFNGLSECONDARYCOLOR3SVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3svEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3svEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3ubEXT) = (PFNGLSECONDARYCOLOR3UBEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ubEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3ubEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3ubvEXT) = (PFNGLSECONDARYCOLOR3UBVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3ubvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3ubvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3uiEXT) = (PFNGLSECONDARYCOLOR3UIEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3uiEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3uiEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3uivEXT) = (PFNGLSECONDARYCOLOR3UIVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3uivEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3uivEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3usEXT) = (PFNGLSECONDARYCOLOR3USEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3usEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3usEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColor3usvEXT) = (PFNGLSECONDARYCOLOR3USVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColor3usvEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColor3usvEXT)) - return FALSE; - GLH_EXT_NAME(glSecondaryColorPointerEXT) = (PFNGLSECONDARYCOLORPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glSecondaryColorPointerEXT"); - if (NULL == GLH_EXT_NAME(glSecondaryColorPointerEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_separate_specular_color - } else if (0 == strcmp(extension, "GL_EXT_separate_specular_color")) { -#endif - -#ifdef GL_EXT_shared_texture_palette - } else if (0 == strcmp(extension, "GL_EXT_shared_texture_palette")) { -#endif - -#ifdef GL_EXT_stencil_wrap - } else if (0 == strcmp(extension, "GL_EXT_stencil_wrap")) { -#endif - -#ifdef GL_EXT_texture_compression_s3tc - } else if (0 == strcmp(extension, "GL_EXT_texture_compression_s3tc")) { -#endif - -#ifdef GL_EXT_texture_cube_map - } else if (0 == strcmp(extension, "GL_EXT_texture_cube_map")) { -#endif - -#ifdef GL_EXT_texture_edge_clamp - } else if (0 == strcmp(extension, "GL_EXT_texture_edge_clamp")) { -#endif - -#ifdef GL_EXT_texture_env_add - } else if (0 == strcmp(extension, "GL_EXT_texture_env_add")) { -#endif - -#ifdef GL_EXT_texture_env_combine - } else if (0 == strcmp(extension, "GL_EXT_texture_env_combine")) { -#endif - -#ifdef GL_EXT_texture_filter_anisotropic - } else if (0 == strcmp(extension, "GL_EXT_texture_filter_anisotropic")) { -#endif - -#ifdef GL_EXT_texture_lod_bias - } else if (0 == strcmp(extension, "GL_EXT_texture_lod_bias")) { -#endif - -#ifdef GL_EXT_texture_object - } else if (0 == strcmp(extension, "GL_EXT_texture_object")) { - GLH_EXT_NAME(glAreTexturesResidentEXT) = (PFNGLARETEXTURESRESIDENTEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glAreTexturesResidentEXT"); - if (NULL == GLH_EXT_NAME(glAreTexturesResidentEXT)) - return FALSE; - GLH_EXT_NAME(glBindTextureEXT) = (PFNGLBINDTEXTUREEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glBindTextureEXT"); - if (NULL == GLH_EXT_NAME(glBindTextureEXT)) - return FALSE; - GLH_EXT_NAME(glDeleteTexturesEXT) = (PFNGLDELETETEXTURESEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteTexturesEXT"); - if (NULL == GLH_EXT_NAME(glDeleteTexturesEXT)) - return FALSE; - GLH_EXT_NAME(glGenTexturesEXT) = (PFNGLGENTEXTURESEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGenTexturesEXT"); - if (NULL == GLH_EXT_NAME(glGenTexturesEXT)) - return FALSE; - GLH_EXT_NAME(glIsTextureEXT) = (PFNGLISTEXTUREEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glIsTextureEXT"); - if (NULL == GLH_EXT_NAME(glIsTextureEXT)) - return FALSE; - GLH_EXT_NAME(glPrioritizeTexturesEXT) = (PFNGLPRIORITIZETEXTURESEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glPrioritizeTexturesEXT"); - if (NULL == GLH_EXT_NAME(glPrioritizeTexturesEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_texture3D - } else if (0 == strcmp(extension, "GL_EXT_texture3D")) { - GLH_EXT_NAME(glTexImage3DEXT) = (PFNGLTEXIMAGE3DEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3DEXT"); - if (NULL == GLH_EXT_NAME(glTexImage3DEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_vertex_array - } else if (0 == strcmp(extension, "GL_EXT_vertex_array")) { - GLH_EXT_NAME(glArrayElementEXT) = (PFNGLARRAYELEMENTEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glArrayElementEXT"); - if (NULL == GLH_EXT_NAME(glArrayElementEXT)) - return FALSE; - GLH_EXT_NAME(glColorPointerEXT) = (PFNGLCOLORPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorPointerEXT"); - if (NULL == GLH_EXT_NAME(glColorPointerEXT)) - return FALSE; - GLH_EXT_NAME(glEdgeFlagPointerEXT) = (PFNGLEDGEFLAGPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glEdgeFlagPointerEXT"); - if (NULL == GLH_EXT_NAME(glEdgeFlagPointerEXT)) - return FALSE; - GLH_EXT_NAME(glGetPointervEXT) = (PFNGLGETPOINTERVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetPointervEXT"); - if (NULL == GLH_EXT_NAME(glGetPointervEXT)) - return FALSE; - GLH_EXT_NAME(glIndexPointerEXT) = (PFNGLINDEXPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glIndexPointerEXT"); - if (NULL == GLH_EXT_NAME(glIndexPointerEXT)) - return FALSE; - GLH_EXT_NAME(glNormalPointerEXT) = (PFNGLNORMALPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glNormalPointerEXT"); - if (NULL == GLH_EXT_NAME(glNormalPointerEXT)) - return FALSE; - GLH_EXT_NAME(glTexCoordPointerEXT) = (PFNGLTEXCOORDPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glTexCoordPointerEXT"); - if (NULL == GLH_EXT_NAME(glTexCoordPointerEXT)) - return FALSE; - GLH_EXT_NAME(glVertexPointerEXT) = (PFNGLVERTEXPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexPointerEXT"); - if (NULL == GLH_EXT_NAME(glVertexPointerEXT)) - return FALSE; - GLH_EXT_NAME(glDrawArraysEXT) = (PFNGLDRAWARRAYSEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawArraysEXT"); - if (NULL == GLH_EXT_NAME(glDrawArraysEXT)) - return FALSE; -#endif - -#ifdef GL_EXT_vertex_weighting - } else if (0 == strcmp(extension, "GL_EXT_vertex_weighting")) { - GLH_EXT_NAME(glVertexWeightfEXT) = (PFNGLVERTEXWEIGHTFEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexWeightfEXT"); - if (NULL == GLH_EXT_NAME(glVertexWeightfEXT)) - return FALSE; - GLH_EXT_NAME(glVertexWeightfvEXT) = (PFNGLVERTEXWEIGHTFVEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexWeightfvEXT"); - if (NULL == GLH_EXT_NAME(glVertexWeightfvEXT)) - return FALSE; - GLH_EXT_NAME(glVertexWeightPointerEXT) = (PFNGLVERTEXWEIGHTPOINTEREXTPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexWeightPointerEXT"); - if (NULL == GLH_EXT_NAME(glVertexWeightPointerEXT)) - return FALSE; -#endif - -#ifdef GL_NV_blend_square - } else if (0 == strcmp(extension, "GL_NV_blend_square")) { -#endif - -#ifdef GL_NV_evaluators - } else if (0 == strcmp(extension, "GL_NV_evaluators")) { - GLH_EXT_NAME(glMapControlPointsNV) = (PFNGLMAPCONTROLPOINTSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glMapControlPointsNV"); - if (NULL == GLH_EXT_NAME(glMapControlPointsNV)) - return FALSE; - GLH_EXT_NAME(glMapParameterivNV) = (PFNGLMAPPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glMapParameterivNV"); - if (NULL == GLH_EXT_NAME(glMapParameterivNV)) - return FALSE; - GLH_EXT_NAME(glMapParameterfvNV) = (PFNGLMAPPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glMapParameterfvNV"); - if (NULL == GLH_EXT_NAME(glMapParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetMapControlPointsNV) = (PFNGLGETMAPCONTROLPOINTSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapControlPointsNV"); - if (NULL == GLH_EXT_NAME(glGetMapControlPointsNV)) - return FALSE; - GLH_EXT_NAME(glGetMapParameterivNV) = (PFNGLGETMAPPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetMapParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetMapParameterfvNV) = (PFNGLGETMAPPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetMapParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetMapAttribParameterivNV) = (PFNGLGETMAPATTRIBPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapAttribParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetMapAttribParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetMapAttribParameterfvNV) = (PFNGLGETMAPATTRIBPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetMapAttribParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetMapAttribParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glEvalMapsNV) = (PFNGLEVALMAPSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glEvalMapsNV"); - if (NULL == GLH_EXT_NAME(glEvalMapsNV)) - return FALSE; -#endif - -#ifdef GL_NV_fence - } else if (0 == strcmp(extension, "GL_NV_fence")) { - GLH_EXT_NAME(glGenFencesNV) = (PFNGLGENFENCESNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGenFencesNV"); - if (NULL == GLH_EXT_NAME(glGenFencesNV)) - return FALSE; - GLH_EXT_NAME(glDeleteFencesNV) = (PFNGLDELETEFENCESNVPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteFencesNV"); - if (NULL == GLH_EXT_NAME(glDeleteFencesNV)) - return FALSE; - GLH_EXT_NAME(glSetFenceNV) = (PFNGLSETFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glSetFenceNV"); - if (NULL == GLH_EXT_NAME(glSetFenceNV)) - return FALSE; - GLH_EXT_NAME(glTestFenceNV) = (PFNGLTESTFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glTestFenceNV"); - if (NULL == GLH_EXT_NAME(glTestFenceNV)) - return FALSE; - GLH_EXT_NAME(glFinishFenceNV) = (PFNGLFINISHFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glFinishFenceNV"); - if (NULL == GLH_EXT_NAME(glFinishFenceNV)) - return FALSE; - GLH_EXT_NAME(glIsFenceNV) = (PFNGLISFENCENVPROC)GLH_EXT_GET_PROC_ADDRESS("glIsFenceNV"); - if (NULL == GLH_EXT_NAME(glIsFenceNV)) - return FALSE; - GLH_EXT_NAME(glGetFenceivNV) = (PFNGLGETFENCEIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFenceivNV"); - if (NULL == GLH_EXT_NAME(glGetFenceivNV)) - return FALSE; -#endif - -#ifdef GL_NV_fog_distance - } else if (0 == strcmp(extension, "GL_NV_fog_distance")) { -#endif - -#ifdef GL_NV_packed_depth_stencil - } else if (0 == strcmp(extension, "GL_NV_packed_depth_stencil")) { -#endif - -#ifdef GL_NV_register_combiners - } else if (0 == strcmp(extension, "GL_NV_register_combiners")) { - GLH_EXT_NAME(glCombinerParameterfvNV) = (PFNGLCOMBINERPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameterfvNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glCombinerParameterfNV) = (PFNGLCOMBINERPARAMETERFNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameterfNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameterfNV)) - return FALSE; - GLH_EXT_NAME(glCombinerParameterivNV) = (PFNGLCOMBINERPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameterivNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameterivNV)) - return FALSE; - GLH_EXT_NAME(glCombinerParameteriNV) = (PFNGLCOMBINERPARAMETERINVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerParameteriNV"); - if (NULL == GLH_EXT_NAME(glCombinerParameteriNV)) - return FALSE; - GLH_EXT_NAME(glCombinerInputNV) = (PFNGLCOMBINERINPUTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerInputNV"); - if (NULL == GLH_EXT_NAME(glCombinerInputNV)) - return FALSE; - GLH_EXT_NAME(glCombinerOutputNV) = (PFNGLCOMBINEROUTPUTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerOutputNV"); - if (NULL == GLH_EXT_NAME(glCombinerOutputNV)) - return FALSE; - GLH_EXT_NAME(glFinalCombinerInputNV) = (PFNGLFINALCOMBINERINPUTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glFinalCombinerInputNV"); - if (NULL == GLH_EXT_NAME(glFinalCombinerInputNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerInputParameterfvNV) = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerInputParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerInputParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerInputParameterivNV) = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerInputParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerInputParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerOutputParameterfvNV) = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerOutputParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerOutputParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerOutputParameterivNV) = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerOutputParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerOutputParameterivNV)) - return FALSE; - GLH_EXT_NAME(glGetFinalCombinerInputParameterfvNV) = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFinalCombinerInputParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetFinalCombinerInputParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetFinalCombinerInputParameterivNV) = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetFinalCombinerInputParameterivNV"); - if (NULL == GLH_EXT_NAME(glGetFinalCombinerInputParameterivNV)) - return FALSE; -#endif - -#ifdef GL_NV_register_combiners2 - } else if (0 == strcmp(extension, "GL_NV_register_combiners2")) { - GLH_EXT_NAME(glCombinerStageParameterfvNV) = (PFNGLCOMBINERSTAGEPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glCombinerStageParameterfvNV"); - if (NULL == GLH_EXT_NAME(glCombinerStageParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetCombinerStageParameterfvNV) = (PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetCombinerStageParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetCombinerStageParameterfvNV)) - return FALSE; -#endif - -#ifdef GL_NV_texgen_reflection - } else if (0 == strcmp(extension, "GL_NV_texgen_reflection")) { -#endif - -#ifdef GL_NV_texture_env_combine4 - } else if (0 == strcmp(extension, "GL_NV_texture_env_combine4")) { -#endif - -#ifdef GL_NV_texture_rectangle - } else if (0 == strcmp(extension, "GL_NV_texture_rectangle")) { -#endif - -#ifdef GL_NV_texture_shader - } else if (0 == strcmp(extension, "GL_NV_texture_shader")) { -#endif - -#ifdef GL_NV_vertex_array_range - } else if (0 == strcmp(extension, "GL_NV_vertex_array_range")) { - GLH_EXT_NAME(glFlushVertexArrayRangeNV) = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)GLH_EXT_GET_PROC_ADDRESS("glFlushVertexArrayRangeNV"); - if (NULL == GLH_EXT_NAME(glFlushVertexArrayRangeNV)) - return FALSE; - GLH_EXT_NAME(glVertexArrayRangeNV) = (PFNGLVERTEXARRAYRANGENVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexArrayRangeNV"); - if (NULL == GLH_EXT_NAME(glVertexArrayRangeNV)) - return FALSE; -# ifdef _WIN32 - GLH_EXT_NAME(wglAllocateMemoryNV) = (PFNWGLALLOCATEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("wglAllocateMemoryNV"); - if (NULL == GLH_EXT_NAME(wglAllocateMemoryNV)) - return FALSE; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXT_NAME(glXAllocateMemoryNV) = (PFNGLXALLOCATEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("glXAllocateMemoryNV"); - if (NULL == GLH_EXT_NAME(glXAllocateMemoryNV)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglFreeMemoryNV) = (PFNWGLFREEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("wglFreeMemoryNV"); - if (NULL == GLH_EXT_NAME(wglFreeMemoryNV)) - return FALSE; -# endif -# ifdef GLX_VERSION_1_3 - GLH_EXT_NAME(glXFreeMemoryNV) = (PFNGLXFREEMEMORYNVPROC)GLH_EXT_GET_PROC_ADDRESS("glXFreeMemoryNV"); - if (NULL == GLH_EXT_NAME(glXFreeMemoryNV)) - return FALSE; -# endif -#endif - -#ifdef GL_NV_vertex_program - } else if (0 == strcmp(extension, "GL_NV_vertex_program")) { - GLH_EXT_NAME(glAreProgramsResidentNV) = (PFNGLAREPROGRAMSRESIDENTNVPROC)GLH_EXT_GET_PROC_ADDRESS("glAreProgramsResidentNV"); - if (NULL == GLH_EXT_NAME(glAreProgramsResidentNV)) - return FALSE; - GLH_EXT_NAME(glBindProgramNV) = (PFNGLBINDPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glBindProgramNV"); - if (NULL == GLH_EXT_NAME(glBindProgramNV)) - return FALSE; - GLH_EXT_NAME(glDeleteProgramsNV) = (PFNGLDELETEPROGRAMSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsNV"); - if (NULL == GLH_EXT_NAME(glDeleteProgramsNV)) - return FALSE; - GLH_EXT_NAME(glExecuteProgramNV) = (PFNGLEXECUTEPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glExecuteProgramNV"); - if (NULL == GLH_EXT_NAME(glExecuteProgramNV)) - return FALSE; - GLH_EXT_NAME(glGenProgramsNV) = (PFNGLGENPROGRAMSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGenProgramsNV"); - if (NULL == GLH_EXT_NAME(glGenProgramsNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramParameterdvNV) = (PFNGLGETPROGRAMPARAMETERDVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramParameterdvNV"); - if (NULL == GLH_EXT_NAME(glGetProgramParameterdvNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramParameterfvNV) = (PFNGLGETPROGRAMPARAMETERFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramParameterfvNV"); - if (NULL == GLH_EXT_NAME(glGetProgramParameterfvNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramivNV) = (PFNGLGETPROGRAMIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramivNV"); - if (NULL == GLH_EXT_NAME(glGetProgramivNV)) - return FALSE; - GLH_EXT_NAME(glGetProgramStringNV) = (PFNGLGETPROGRAMSTRINGNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringNV"); - if (NULL == GLH_EXT_NAME(glGetProgramStringNV)) - return FALSE; - GLH_EXT_NAME(glGetTrackMatrixivNV) = (PFNGLGETTRACKMATRIXIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetTrackMatrixivNV"); - if (NULL == GLH_EXT_NAME(glGetTrackMatrixivNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribdvNV) = (PFNGLGETVERTEXATTRIBDVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribdvNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribfvNV) = (PFNGLGETVERTEXATTRIBFVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribfvNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribivNV) = (PFNGLGETVERTEXATTRIBIVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribivNV)) - return FALSE; - GLH_EXT_NAME(glGetVertexAttribPointervNV) = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribPointervNV"); - if (NULL == GLH_EXT_NAME(glGetVertexAttribPointervNV)) - return FALSE; - GLH_EXT_NAME(glIsProgramNV) = (PFNGLISPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glIsProgramNV"); - if (NULL == GLH_EXT_NAME(glIsProgramNV)) - return FALSE; - GLH_EXT_NAME(glLoadProgramNV) = (PFNGLLOADPROGRAMNVPROC)GLH_EXT_GET_PROC_ADDRESS("glLoadProgramNV"); - if (NULL == GLH_EXT_NAME(glLoadProgramNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4dNV) = (PFNGLPROGRAMPARAMETER4DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4dNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4dNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4dvNV) = (PFNGLPROGRAMPARAMETER4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4dvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4dvNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4fNV) = (PFNGLPROGRAMPARAMETER4FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4fNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4fNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameter4fvNV) = (PFNGLPROGRAMPARAMETER4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameter4fvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameter4fvNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameters4dvNV) = (PFNGLPROGRAMPARAMETERS4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameters4dvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameters4dvNV)) - return FALSE; - GLH_EXT_NAME(glProgramParameters4fvNV) = (PFNGLPROGRAMPARAMETERS4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glProgramParameters4fvNV"); - if (NULL == GLH_EXT_NAME(glProgramParameters4fvNV)) - return FALSE; - GLH_EXT_NAME(glRequestResidentProgramsNV) = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC)GLH_EXT_GET_PROC_ADDRESS("glRequestResidentProgramsNV"); - if (NULL == GLH_EXT_NAME(glRequestResidentProgramsNV)) - return FALSE; - GLH_EXT_NAME(glTrackMatrixNV) = (PFNGLTRACKMATRIXNVPROC)GLH_EXT_GET_PROC_ADDRESS("glTrackMatrixNV"); - if (NULL == GLH_EXT_NAME(glTrackMatrixNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribPointerNV) = (PFNGLVERTEXATTRIBPOINTERNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribPointerNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1dNV) = (PFNGLVERTEXATTRIB1DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1dvNV) = (PFNGLVERTEXATTRIB1DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1fNV) = (PFNGLVERTEXATTRIB1FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1fvNV) = (PFNGLVERTEXATTRIB1FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1sNV) = (PFNGLVERTEXATTRIB1SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib1svNV) = (PFNGLVERTEXATTRIB1SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib1svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2dNV) = (PFNGLVERTEXATTRIB2DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2dvNV) = (PFNGLVERTEXATTRIB2DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2fNV) = (PFNGLVERTEXATTRIB2FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2fvNV) = (PFNGLVERTEXATTRIB2FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2sNV) = (PFNGLVERTEXATTRIB2SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib2svNV) = (PFNGLVERTEXATTRIB2SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib2svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3dNV) = (PFNGLVERTEXATTRIB3DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3dvNV) = (PFNGLVERTEXATTRIB3DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3fNV) = (PFNGLVERTEXATTRIB3FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3fvNV) = (PFNGLVERTEXATTRIB3FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3sNV) = (PFNGLVERTEXATTRIB3SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib3svNV) = (PFNGLVERTEXATTRIB3SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib3svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4dNV) = (PFNGLVERTEXATTRIB4DNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4dvNV) = (PFNGLVERTEXATTRIB4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4fNV) = (PFNGLVERTEXATTRIB4FNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4fvNV) = (PFNGLVERTEXATTRIB4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4sNV) = (PFNGLVERTEXATTRIB4SNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4sNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4svNV) = (PFNGLVERTEXATTRIB4SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttrib4ubvNV) = (PFNGLVERTEXATTRIB4UBVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttrib4ubvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs1dvNV) = (PFNGLVERTEXATTRIBS1DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs1dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs1dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs1fvNV) = (PFNGLVERTEXATTRIBS1FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs1fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs1fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs1svNV) = (PFNGLVERTEXATTRIBS1SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs1svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs1svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs2dvNV) = (PFNGLVERTEXATTRIBS2DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs2dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs2dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs2fvNV) = (PFNGLVERTEXATTRIBS2FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs2fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs2fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs2svNV) = (PFNGLVERTEXATTRIBS2SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs2svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs2svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs3dvNV) = (PFNGLVERTEXATTRIBS3DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs3dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs3dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs3fvNV) = (PFNGLVERTEXATTRIBS3FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs3fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs3fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs3svNV) = (PFNGLVERTEXATTRIBS3SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs3svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs3svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4dvNV) = (PFNGLVERTEXATTRIBS4DVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4dvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4dvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4fvNV) = (PFNGLVERTEXATTRIBS4FVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4fvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4fvNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4svNV) = (PFNGLVERTEXATTRIBS4SVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4svNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4svNV)) - return FALSE; - GLH_EXT_NAME(glVertexAttribs4ubvNV) = (PFNGLVERTEXATTRIBS4UBVNVPROC)GLH_EXT_GET_PROC_ADDRESS("glVertexAttribs4ubvNV"); - if (NULL == GLH_EXT_NAME(glVertexAttribs4ubvNV)) - return FALSE; -#endif - -#ifdef GL_SGIS_generate_mipmap - } else if (0 == strcmp(extension, "GL_SGIS_generate_mipmap")) { -#endif - -#ifdef GL_SGIS_texture_lod - } else if (0 == strcmp(extension, "GL_SGIS_texture_lod")) { -#endif - -#ifdef GL_SGIX_depth_texture - } else if (0 == strcmp(extension, "GL_SGIX_depth_texture")) { -#endif - -#ifdef GL_SGIX_shadow - } else if (0 == strcmp(extension, "GL_SGIX_shadow")) { -#endif - -#ifdef GL_VERSION_1_2 - } else if (0 == strcmp(extension, "GL_VERSION_1_2")) { - GLH_CORE_1_2_NAME(glBlendColor) = (PFNGLBLENDCOLORPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendColor"); - if (NULL == GLH_CORE_1_2_NAME(glBlendColor)) - return FALSE; - GLH_CORE_1_2_NAME(glBlendEquation) = (PFNGLBLENDEQUATIONPROC)GLH_EXT_GET_PROC_ADDRESS("glBlendEquation"); - if (NULL == GLH_CORE_1_2_NAME(glBlendEquation)) - return FALSE; - GLH_CORE_1_2_NAME(glDrawRangeElements) = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); - if (NULL == GLH_CORE_1_2_NAME(glDrawRangeElements)) - return FALSE; - GLH_CORE_1_2_NAME(glColorTable) = (PFNGLCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTable"); - if (NULL == GLH_CORE_1_2_NAME(glColorTable)) - return FALSE; - GLH_CORE_1_2_NAME(glColorTableParameterfv) = (PFNGLCOLORTABLEPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableParameterfv"); - if (NULL == GLH_CORE_1_2_NAME(glColorTableParameterfv)) - return FALSE; - GLH_CORE_1_2_NAME(glColorTableParameteriv) = (PFNGLCOLORTABLEPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableParameteriv"); - if (NULL == GLH_CORE_1_2_NAME(glColorTableParameteriv)) - return FALSE; - GLH_CORE_1_2_NAME(glCopyColorTable) = (PFNGLCOPYCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyColorTable"); - if (NULL == GLH_CORE_1_2_NAME(glCopyColorTable)) - return FALSE; - GLH_CORE_1_2_NAME(glGetColorTable) = (PFNGLGETCOLORTABLEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTable"); - if (NULL == GLH_CORE_1_2_NAME(glGetColorTable)) - return FALSE; - GLH_CORE_1_2_NAME(glGetColorTableParameterfv) = (PFNGLGETCOLORTABLEPARAMETERFVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameterfv"); - if (NULL == GLH_CORE_1_2_NAME(glGetColorTableParameterfv)) - return FALSE; - GLH_CORE_1_2_NAME(glGetColorTableParameteriv) = (PFNGLGETCOLORTABLEPARAMETERIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetColorTableParameteriv"); - if (NULL == GLH_CORE_1_2_NAME(glGetColorTableParameteriv)) - return FALSE; - GLH_CORE_1_2_NAME(glTexImage3D) = (PFNGLTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3D"); - if (NULL == GLH_CORE_1_2_NAME(glTexImage3D)) - return FALSE; - GLH_CORE_1_2_NAME(glTexSubImage3D) = (PFNGLTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexSubImage3D"); - if (NULL == GLH_CORE_1_2_NAME(glTexSubImage3D)) - return FALSE; - GLH_CORE_1_2_NAME(glCopyTexSubImage3D) = (PFNGLCOPYTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTexSubImage3D"); - if (NULL == GLH_CORE_1_2_NAME(glCopyTexSubImage3D)) - return FALSE; -#endif - -#ifdef GL_WIN_swap_hint - } else if (0 == strcmp(extension, "GL_WIN_swap_hint")) { - GLH_EXT_NAME(glAddSwapHintRectWIN) = (PFNGLADDSWAPHINTRECTWINPROC)GLH_EXT_GET_PROC_ADDRESS("glAddSwapHintRectWIN"); - if (NULL == GLH_EXT_NAME(glAddSwapHintRectWIN)) - return FALSE; -#endif - -#ifdef WGL_ARB_pbuffer - } else if (0 == strcmp(extension, "WGL_ARB_pbuffer")) { -# ifdef _WIN32 - GLH_EXT_NAME(wglCreatePbufferARB) = (PFNWGLCREATEPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreatePbufferARB"); - if (NULL == GLH_EXT_NAME(wglCreatePbufferARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglGetPbufferDCARB) = (PFNWGLGETPBUFFERDCARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetPbufferDCARB"); - if (NULL == GLH_EXT_NAME(wglGetPbufferDCARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglReleasePbufferDCARB) = (PFNWGLRELEASEPBUFFERDCARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglReleasePbufferDCARB"); - if (NULL == GLH_EXT_NAME(wglReleasePbufferDCARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglDestroyPbufferARB) = (PFNWGLDESTROYPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglDestroyPbufferARB"); - if (NULL == GLH_EXT_NAME(wglDestroyPbufferARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglQueryPbufferARB) = (PFNWGLQUERYPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglQueryPbufferARB"); - if (NULL == GLH_EXT_NAME(wglQueryPbufferARB)) - return FALSE; -# endif -#endif - -#ifdef WGL_ARB_render_texture -# ifdef _WIN32 - GLH_EXT_NAME(wglBindTexImageARB) = (PFNWGLBINDTEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglBindTexImageARB"); - if (NULL == GLH_EXT_NAME(wglBindTexImageARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglReleaseTexImageARB) = (PFNWGLRELEASETEXIMAGEARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglReleaseTexImageARB"); - if (NULL == GLH_EXT_NAME(wglReleaseTexImageARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglSetPbufferAttribARB) = (PFNWGLSETPBUFFERATTRIBARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglSetPbufferAttribARB"); - if (NULL == GLH_EXT_NAME(wglSetPbufferAttribARB)) - return FALSE; -# endif -#endif - -#ifdef WGL_ARB_pixel_format - } else if (0 == strcmp(extension, "WGL_ARB_pixel_format")) { -# ifdef _WIN32 - GLH_EXT_NAME(wglGetPixelFormatAttribivARB) = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetPixelFormatAttribivARB"); - if (NULL == GLH_EXT_NAME(wglGetPixelFormatAttribivARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglGetPixelFormatAttribfvARB) = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetPixelFormatAttribfvARB"); - if (NULL == GLH_EXT_NAME(wglGetPixelFormatAttribfvARB)) - return FALSE; -# endif -# ifdef _WIN32 - GLH_EXT_NAME(wglChoosePixelFormatARB) = (PFNWGLCHOOSEPIXELFORMATARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglChoosePixelFormatARB"); - if (NULL == GLH_EXT_NAME(wglChoosePixelFormatARB)) - return FALSE; -# endif -#endif - - } else { - return FALSE; - } - return TRUE; -} -#endif - -#else // defined(__APPLE__) - -#ifdef GLH_EXT_SINGLE_FILE - -int glh_init_extension(const char* extension) -{ - // MBW -- XXX -- Should this check for extension availability? - return TRUE; -} -#endif // GLH_EXT_SINGLE_FILE - -#endif // defined(__APPLE__) - -#undef GLH_EXT_SINGLE_FILE - -#endif /* GLH_GENEXT_H */ diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index f9b387b00b..fd20f2ad15 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -288,7 +288,8 @@ attributedStringInfo getSegments(NSAttributedString *str) if (vsync) { - [glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval]; + GLint value = 1; + [glContext setValues:&value forParameter:NSOpenGLCPSwapInterval]; } else { // supress this error after move to Xcode 7: // error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull] diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 30bc743e72..f4678a70c5 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -137,6 +137,12 @@ BOOL LLWindow::canDelete() return TRUE; } +//virtual +void LLWindow::setTitle(const std::string title) +{ + // the action happens in the platform specific impl +} + // virtual void LLWindow::incBusyCount() { @@ -397,7 +403,7 @@ LLWindow* LLWindowManager::createWindow( const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, - BOOL disable_vsync, + BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) @@ -409,26 +415,26 @@ LLWindow* LLWindowManager::createWindow( #if LL_MESA_HEADLESS new_window = new LLWindowMesaHeadless(callbacks, title, name, x, y, width, height, flags, - fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth); + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth); #elif LL_SDL new_window = new LLWindowSDL(callbacks, title, x, y, width, height, flags, - fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #elif LL_WINDOWS new_window = new LLWindowWin32(callbacks, title, name, x, y, width, height, flags, - fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #elif LL_DARWIN new_window = new LLWindowMacOSX(callbacks, title, name, x, y, width, height, flags, - fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #endif } else { new_window = new LLWindowHeadless(callbacks, title, name, x, y, width, height, flags, - fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth); + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth); } if (FALSE == new_window->isValid()) diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index d4d5b76937..0edf39f6ef 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -77,15 +77,37 @@ public: BOOL setSize(LLCoordScreen size); BOOL setSize(LLCoordWindow size); virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true); - virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) = 0; - virtual BOOL setCursorPosition(LLCoordWindow position) = 0; + virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) = 0; + + //create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread + // returns a pointer to be handed back to destroySharedConext/makeContextCurrent + virtual void* createSharedContext() = 0; + //make the given context current on the current thread + virtual void makeContextCurrent(void* context) = 0; + //destroy the given context that was retrieved by createSharedContext() + //Must be called on the same thread that called createSharedContext() + virtual void destroySharedContext(void* context) = 0; + + virtual void toggleVSync(bool enable_vsync) = 0; + + virtual BOOL setCursorPosition(LLCoordWindow position) = 0; virtual BOOL getCursorPosition(LLCoordWindow *position) = 0; +#if LL_WINDOWS + virtual BOOL getCursorDelta(LLCoordCommon* delta) = 0; +#endif virtual void showCursor() = 0; virtual void hideCursor() = 0; virtual BOOL isCursorHidden() = 0; virtual void showCursorFromMouseMove() = 0; virtual void hideCursorUntilMouseMove() = 0; + // Provide a way to set the Viewer window title after the + // windows has been created. The initial use case for this + // is described in SL-16102 (update window title with agent + // name, location etc. for non-interactive viewer) but it + // may also be useful in other cases. + virtual void setTitle(const std::string title); + // These two functions create a way to make a busy cursor instead // of an arrow when someone's busy doing something. Draw an // arrow/hour if busycount > 0. @@ -274,7 +296,7 @@ public: U32 flags = 0, BOOL fullscreen = FALSE, BOOL clearBg = FALSE, - BOOL disable_vsync = TRUE, + BOOL enable_vsync = FALSE, BOOL use_gl = TRUE, BOOL ignore_pixel_depth = FALSE, U32 fsaa_samples = 0); diff --git a/indra/llwindow/llwindowheadless.cpp b/indra/llwindow/llwindowheadless.cpp index 70f473281b..c3738af6ca 100644 --- a/indra/llwindow/llwindowheadless.cpp +++ b/indra/llwindow/llwindowheadless.cpp @@ -35,7 +35,7 @@ // LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clear_background, - BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth) + BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth) : LLWindow(callbacks, fullscreen, flags) { // Initialize a headless keyboard. diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index c692666df1..410da79623 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -48,9 +48,16 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;}; - /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; - /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;}; + void* createSharedContext() { return nullptr; } + void makeContextCurrent(void*) {} + void destroySharedContext(void*) {} + /*virtual*/ void toggleVSync(bool enable_vsync) { } + /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; + /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; +#if LL_WINDOWS + /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; } +#endif /*virtual*/ void showCursor() {}; /*virtual*/ void hideCursor() {}; /*virtual*/ void showCursorFromMouseMove() {}; @@ -97,7 +104,7 @@ public: S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clear_background, - BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth); + BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth); virtual ~LLWindowHeadless(); private: diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index dfdfe4aa33..0e37e82091 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -111,7 +111,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, - BOOL disable_vsync, BOOL use_gl, + BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) : LLWindow(NULL, fullscreen, flags) @@ -165,7 +165,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, // Stash an object pointer for OSMessageBox() gWindowImplementation = this; // Create the GL context and set it up for windowed or fullscreen, as appropriate. - if(createContext(x, y, width, height, 32, fullscreen, disable_vsync)) + if(createContext(x, y, width, height, 32, fullscreen, enable_vsync)) { if(mWindow != NULL) { @@ -619,7 +619,7 @@ void LLWindowMacOSX::getMouseDeltas(float* delta) delta[1] = mCursorLastEventDeltaY; } -BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) +BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync) { BOOL glNeedsInit = FALSE; @@ -634,7 +634,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits { // Our OpenGL view is already defined within SecondLife.xib. // Get the view instead. - mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync); + mGLView = createOpenGLView(mWindow, mFSAASamples, enable_vsync); mContext = getCGLContextObj(mGLView); // Since we just created the context, it needs to be set up. @@ -661,17 +661,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits } // Disable vertical sync for swap - GLint frames_per_swap = 0; - if (disable_vsync) - { - frames_per_swap = 0; - } - else - { - frames_per_swap = 1; - } - - CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap); + toggleVSync(enable_vsync); //enable multi-threaded OpenGL if (sUseMultGL) @@ -698,7 +688,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits // We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop. // This makes this method obsolete. -BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) +BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp) { return FALSE; } @@ -1916,6 +1906,49 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit } +class sharedContext +{ +public: + CGLContextObj mContext; +}; + +void* LLWindowMacOSX::createSharedContext() +{ + sharedContext* sc = new sharedContext(); + CGLCreateContext(mPixelFormat, mContext, &(sc->mContext)); + + return (void *)sc; +} + +void LLWindowMacOSX::makeContextCurrent(void* context) +{ + CGLSetCurrentContext(((sharedContext*)context)->mContext); +} + +void LLWindowMacOSX::destroySharedContext(void* context) +{ + sharedContext* sc = (sharedContext*)context; + + CGLDestroyContext(sc->mContext); + + delete sc; +} + +void LLWindowMacOSX::toggleVSync(bool enable_vsync) +{ + GLint frames_per_swap = 0; + if (!enable_vsync) + { + frames_per_swap = 0; + } + else + { + frames_per_swap = 1; + } + + CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap); +} + void LLWindowMacOSX::interruptLanguageTextInput() { commitCurrentPreedit(mGLView); diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index bf45238c8d..b0f339e1db 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -41,85 +41,84 @@ #undef verify #undef require - class LLWindowMacOSX : public LLWindow { public: - /*virtual*/ void show(); - /*virtual*/ void hide(); - /*virtual*/ void close(); - /*virtual*/ BOOL getVisible(); - /*virtual*/ BOOL getMinimized(); - /*virtual*/ BOOL getMaximized(); - /*virtual*/ BOOL maximize(); - /*virtual*/ void minimize(); - /*virtual*/ void restore(); - /*virtual*/ BOOL getFullscreen(); - /*virtual*/ BOOL getPosition(LLCoordScreen *position); - /*virtual*/ BOOL getSize(LLCoordScreen *size); - /*virtual*/ BOOL getSize(LLCoordWindow *size); - /*virtual*/ BOOL setPosition(LLCoordScreen position); - /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); - /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL); - /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); - /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); - /*virtual*/ void showCursor(); - /*virtual*/ void hideCursor(); - /*virtual*/ void showCursorFromMouseMove(); - /*virtual*/ void hideCursorUntilMouseMove(); - /*virtual*/ BOOL isCursorHidden(); - /*virtual*/ void updateCursor(); - /*virtual*/ ECursorType getCursor() const; - /*virtual*/ void captureMouse(); - /*virtual*/ void releaseMouse(); - /*virtual*/ void setMouseClipping( BOOL b ); - /*virtual*/ BOOL isClipboardTextAvailable(); - /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst); - /*virtual*/ BOOL copyTextToClipboard(const LLWString & src); - /*virtual*/ void flashIcon(F32 seconds); - /*virtual*/ F32 getGamma(); - /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma - /*virtual*/ U32 getFSAASamples(); - /*virtual*/ void setFSAASamples(const U32 fsaa_samples); - /*virtual*/ BOOL restoreGamma(); // Restore original gamma table (before updating gamma) - /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } - /*virtual*/ void gatherInput(); - /*virtual*/ void delayInputProcessing() {}; - /*virtual*/ void swapBuffers(); + void show() override; + void hide() override; + void close() override; + BOOL getVisible() override; + BOOL getMinimized() override; + BOOL getMaximized() override; + BOOL maximize() override; + void minimize() override; + void restore() override; + BOOL getFullscreen(); + BOOL getPosition(LLCoordScreen *position) override; + BOOL getSize(LLCoordScreen *size) override; + BOOL getSize(LLCoordWindow *size) override; + BOOL setPosition(LLCoordScreen position) override; + BOOL setSizeImpl(LLCoordScreen size) override; + BOOL setSizeImpl(LLCoordWindow size) override; + BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override; + BOOL setCursorPosition(LLCoordWindow position) override; + BOOL getCursorPosition(LLCoordWindow *position) override; + void showCursor() override; + void hideCursor() override; + void showCursorFromMouseMove() override; + void hideCursorUntilMouseMove() override; + BOOL isCursorHidden() override; + void updateCursor() override; + ECursorType getCursor() const override; + void captureMouse() override; + void releaseMouse() override; + void setMouseClipping( BOOL b ) override; + BOOL isClipboardTextAvailable() override; + BOOL pasteTextFromClipboard(LLWString &dst) override; + BOOL copyTextToClipboard(const LLWString & src) override; + void flashIcon(F32 seconds) override; + F32 getGamma() override; + BOOL setGamma(const F32 gamma) override; // Set the gamma + U32 getFSAASamples() override; + void setFSAASamples(const U32 fsaa_samples) override; + BOOL restoreGamma() override; // Restore original gamma table (before updating gamma) + ESwapMethod getSwapMethod() override { return mSwapMethod; } + void gatherInput() override; + void delayInputProcessing() override {}; + void swapBuffers() override; // handy coordinate space conversion routines - /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to); - /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to); - /*virtual*/ BOOL convertCoords(LLCoordWindow from, LLCoordGL *to); - /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordWindow *to); - /*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordGL *to); - /*virtual*/ BOOL convertCoords(LLCoordGL from, LLCoordScreen *to); + BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to) override; + BOOL convertCoords(LLCoordWindow from, LLCoordScreen *to) override; + BOOL convertCoords(LLCoordWindow from, LLCoordGL *to) override; + BOOL convertCoords(LLCoordGL from, LLCoordWindow *to) override; + BOOL convertCoords(LLCoordScreen from, LLCoordGL *to) override; + BOOL convertCoords(LLCoordGL from, LLCoordScreen *to) override; - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions); - /*virtual*/ F32 getNativeAspectRatio(); - /*virtual*/ F32 getPixelAspectRatio(); - /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } + LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override; + F32 getNativeAspectRatio() override; + F32 getPixelAspectRatio() override; + void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } - /*virtual*/ void beforeDialog(); - /*virtual*/ void afterDialog(); + void beforeDialog() override; + void afterDialog() override; - /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); + BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b) override; - /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void bringToFront() {}; + void *getPlatformWindow() override; + void bringToFront() override {}; - /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b); - /*virtual*/ void interruptLanguageTextInput(); - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); - /*virtual*/ F32 getSystemUISize(); + void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) override; + void interruptLanguageTextInput() override; + void spawnWebBrowser(const std::string& escaped_url, bool async) override; + F32 getSystemUISize() override; static std::vector<std::string> getDisplaysResolutionList(); static std::vector<std::string> getDynamicFallbackFontList(); // Provide native key event data - /*virtual*/ LLSD getNativeKeyData(); + LLSD getNativeKeyData() override; void* getWindow() { return mWindow; } LLWindowCallbacks* getCallbacks() { return mCallbacks; } @@ -132,16 +131,27 @@ public: bool allowsLanguageInput() { return mLanguageTextInputAllowed; } + //create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread + // returns a pointer to be handed back to destroySharedConext/makeContextCurrent + void* createSharedContext() override; + //make the given context current on the current thread + void makeContextCurrent(void* context) override; + //destroy the given context that was retrieved by createSharedContext() + //Must be called on the same thread that called createSharedContext() + void destroySharedContext(void* context) override; + + void toggleVSync(bool enable_vsync) override; + protected: LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, - BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, + BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples); ~LLWindowMacOSX(); void initCursors(); - BOOL isValid(); + BOOL isValid() override; void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); @@ -157,7 +167,7 @@ protected: BOOL shouldPostQuit() { return mPostQuit; } //Satisfy MAINT-3135 and MAINT-3288 with a flag. - /*virtual */ void setOldResize(bool oldresize) {setResizeMode(oldresize, mGLView); } + /*virtual */ void setOldResize(bool oldresize) override {setResizeMode(oldresize, mGLView); } private: void restoreGLContext(); @@ -168,7 +178,7 @@ protected: // // create or re-create the GL context/window. Called from the constructor and switchContext(). - BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync); + BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync); void destroyContext(); void setupFailure(const std::string& text, const std::string& caption, U32 type); void adjustCursorDecouple(bool warpingMouse = false); @@ -231,9 +241,9 @@ public: LLSplashScreenMacOSX(); virtual ~LLSplashScreenMacOSX(); - /*virtual*/ void showImpl(); - /*virtual*/ void updateImpl(const std::string& mesg); - /*virtual*/ void hideImpl(); + void showImpl(); + void updateImpl(const std::string& mesg); + void hideImpl(); private: WindowRef mWindow; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b2b123f0da..e4d771978a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -45,6 +45,8 @@ #include "lldir.h" #include "llsdutil.h" #include "llglslshader.h" +#include "llthreadsafequeue.h" +#include "stringize.h" // System includes #include <commdlg.h> @@ -54,6 +56,10 @@ #include <shellapi.h> #include <fstream> #include <Imm.h> +#include <iomanip> +#include <future> +#include <sstream> +#include <utility> // std::pair // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 @@ -77,8 +83,24 @@ const F32 ICON_FLASH_TIME = 0.5f; #define USER_DEFAULT_SCREEN_DPI 96 // Win7 #endif +// Claim a couple unused GetMessage() message IDs +const UINT WM_DUMMY_(WM_USER + 0x0017); +const UINT WM_POST_FUNCTION_(WM_USER + 0x0018); + extern BOOL gDebugWindowProc; +static std::thread::id sWindowThreadId; +static std::thread::id sMainThreadId; + +#if 1 // flip to zero to enable assertions for functions being called from wrong thread +#define ASSERT_MAIN_THREAD() +#define ASSERT_WINDOW_THREAD() +#else +#define ASSERT_MAIN_THREAD() llassert(LLThread::currentID() == sMainThreadId) +#define ASSERT_WINDOW_THREAD() llassert(LLThread::currentID() == sWindowThreadId) +#endif + + LPWSTR gIconResource = IDI_APPLICATION; LPDIRECTINPUT8 gDirectInput8; @@ -161,23 +183,19 @@ DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1); // The following class LLWinImm delegates Windows IMM APIs. -// We need this because some language versions of Windows, -// e.g., US version of Windows XP, doesn't install IMM32.DLL -// as a default, and we can't link against imm32.lib statically. -// I believe DLL loading of this type is best suited to do -// in a static initialization of a class. What I'm not sure is -// whether it follows the Linden Conding Standard... -// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members +// It was originally introduced to support US Windows XP, on which we needed +// to dynamically load IMM32.DLL and use GetProcAddress to resolve its entry +// points. Now that that's moot, we retain this wrapper only for hooks for +// metrics. class LLWinImm { public: - static bool isAvailable() { return sTheInstance.mHImmDll != NULL; } + static bool isAvailable() { return true; } public: // Wrappers for IMM API. static BOOL isIME(HKL hkl); - static HWND getDefaultIMEWnd(HWND hwnd); static HIMC getContext(HWND hwnd); static BOOL releaseContext(HWND hwnd, HIMC himc); static BOOL getOpenStatus(HIMC himc); @@ -191,236 +209,96 @@ public: static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont); static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form); static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value); - -private: - LLWinImm(); - ~LLWinImm(); - -private: - // Pointers to IMM API. - BOOL (WINAPI *mImmIsIME)(HKL); - HWND (WINAPI *mImmGetDefaultIMEWnd)(HWND); - HIMC (WINAPI *mImmGetContext)(HWND); - BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC); - BOOL (WINAPI *mImmGetOpenStatus)(HIMC); - BOOL (WINAPI *mImmSetOpenStatus)(HIMC, BOOL); - BOOL (WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); - BOOL (WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD); - BOOL (WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); - BOOL (WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); - LONG (WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD); - BOOL (WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD); - BOOL (WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW); - BOOL (WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM); - BOOL (WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD); - -private: - HMODULE mHImmDll; - static LLWinImm sTheInstance; }; -LLWinImm LLWinImm::sTheInstance; - -LLWinImm::LLWinImm() : mHImmDll(NULL) -{ - // Check system metrics - if ( !GetSystemMetrics( SM_IMMENABLED ) ) - return; - - mHImmDll = LoadLibraryA("Imm32"); - if (mHImmDll != NULL) - { - mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME"); - mImmGetDefaultIMEWnd = (HWND (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd"); - mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext"); - mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext"); - mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus"); - mImmSetOpenStatus = (BOOL (WINAPI *)(HIMC, BOOL)) GetProcAddress(mHImmDll, "ImmSetOpenStatus"); - mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus"); - mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmSetConversionStatus"); - mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmGetCompositionWindow"); - mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmSetCompositionWindow"); - mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmGetCompositionStringW"); - mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmSetCompositionStringW"); - mImmSetCompositionFont = (BOOL (WINAPI *)(HIMC, LPLOGFONTW)) GetProcAddress(mHImmDll, "ImmSetCompositionFontW"); - mImmSetCandidateWindow = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM)) GetProcAddress(mHImmDll, "ImmSetCandidateWindow"); - mImmNotifyIME = (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmNotifyIME"); - - if (mImmIsIME == NULL || - mImmGetDefaultIMEWnd == NULL || - mImmGetContext == NULL || - mImmReleaseContext == NULL || - mImmGetOpenStatus == NULL || - mImmSetOpenStatus == NULL || - mImmGetConversionStatus == NULL || - mImmSetConversionStatus == NULL || - mImmGetCompostitionWindow == NULL || - mImmSetCompostitionWindow == NULL || - mImmGetCompositionString == NULL || - mImmSetCompositionString == NULL || - mImmSetCompositionFont == NULL || - mImmSetCandidateWindow == NULL || - mImmNotifyIME == NULL) - { - // If any of the above API entires are not found, we can't use IMM API. - // So, turn off the IMM support. We should log some warning message in - // the case, since it is very unusual; these APIs are available from - // the beginning, and all versions of IMM32.DLL should have them all. - // Unfortunately, this code may be executed before initialization of - // the logging channel (LL_WARNS()), and we can't do it here... Yes, this - // is one of disadvantages to use static constraction to DLL loading. - FreeLibrary(mHImmDll); - mHImmDll = NULL; - - // If we unload the library, make sure all the function pointers are cleared - mImmIsIME = NULL; - mImmGetDefaultIMEWnd = NULL; - mImmGetContext = NULL; - mImmReleaseContext = NULL; - mImmGetOpenStatus = NULL; - mImmSetOpenStatus = NULL; - mImmGetConversionStatus = NULL; - mImmSetConversionStatus = NULL; - mImmGetCompostitionWindow = NULL; - mImmSetCompostitionWindow = NULL; - mImmGetCompositionString = NULL; - mImmSetCompositionString = NULL; - mImmSetCompositionFont = NULL; - mImmSetCandidateWindow = NULL; - mImmNotifyIME = NULL; - } - } -} - - // static -BOOL LLWinImm::isIME(HKL hkl) +BOOL LLWinImm::isIME(HKL hkl) { - if ( sTheInstance.mImmIsIME ) - return sTheInstance.mImmIsIME(hkl); - return FALSE; + return ImmIsIME(hkl); } // static HIMC LLWinImm::getContext(HWND hwnd) { - if ( sTheInstance.mImmGetContext ) - return sTheInstance.mImmGetContext(hwnd); - return 0; + return ImmGetContext(hwnd); } //static BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc) { - if ( sTheInstance.mImmIsIME ) - return sTheInstance.mImmReleaseContext(hwnd, himc); - return FALSE; + return ImmReleaseContext(hwnd, himc); } // static BOOL LLWinImm::getOpenStatus(HIMC himc) { - if ( sTheInstance.mImmGetOpenStatus ) - return sTheInstance.mImmGetOpenStatus(himc); - return FALSE; + return ImmGetOpenStatus(himc); } // static -BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) +BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) { - if ( sTheInstance.mImmSetOpenStatus ) - return sTheInstance.mImmSetOpenStatus(himc, status); - return FALSE; + return ImmSetOpenStatus(himc, status); } // static BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { - if ( sTheInstance.mImmGetConversionStatus ) - return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); - return FALSE; + return ImmGetConversionStatus(himc, conversion, sentence); } // static BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { - if ( sTheInstance.mImmSetConversionStatus ) - return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); - return FALSE; + return ImmSetConversionStatus(himc, conversion, sentence); } // static BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - if ( sTheInstance.mImmGetCompostitionWindow ) - return sTheInstance.mImmGetCompostitionWindow(himc, form); - return FALSE; + return ImmGetCompositionWindow(himc, form); } // static BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) { - if ( sTheInstance.mImmSetCompostitionWindow ) - return sTheInstance.mImmSetCompostitionWindow(himc, form); - return FALSE; + return ImmSetCompositionWindow(himc, form); } // static LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length) { - if ( sTheInstance.mImmGetCompositionString ) - return sTheInstance.mImmGetCompositionString(himc, index, data, length); - return FALSE; + return ImmGetCompositionString(himc, index, data, length); } // static BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength) { - if ( sTheInstance.mImmSetCompositionString ) - return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); - return FALSE; + return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength); } // static BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont) { - if ( sTheInstance.mImmSetCompositionFont ) - return sTheInstance.mImmSetCompositionFont(himc, pFont); - return FALSE; + return ImmSetCompositionFont(himc, pFont); } // static BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form) { - if ( sTheInstance.mImmSetCandidateWindow ) - return sTheInstance.mImmSetCandidateWindow(himc, form); - return FALSE; + return ImmSetCandidateWindow(himc, form); } // static BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value) { - if ( sTheInstance.mImmNotifyIME ) - return sTheInstance.mImmNotifyIME(himc, action, index, value); - return FALSE; + return ImmNotifyIME(himc, action, index, value); } - -// ---------------------------------------------------------------------------------------- -LLWinImm::~LLWinImm() -{ - if (mHImmDll != NULL) - { - FreeLibrary(mHImmDll); - mHImmDll = NULL; - } -} - - class LLMonitorInfo { public: @@ -454,16 +332,83 @@ private: static LLMonitorInfo sMonitorInfo; + +// Thread that owns the Window Handle +// This whole struct is private to LLWindowWin32, which needs to mess with its +// members, which is why it's a struct rather than a class. In effect, we make +// the containing class a friend. +struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool +{ + static const int MAX_QUEUE_SIZE = 2048; + + LLThreadSafeQueue<MSG> mMessageQueue; + + LLWindowWin32Thread(); + + void run() override; + + /// called by main thread to post work to this window thread + template <typename CALLABLE> + void post(CALLABLE&& func) + { + try + { + getQueue().post(std::forward<CALLABLE>(func)); + } + catch (const LLThreadSafeQueueInterrupt&) + { + // Shutdown timing is tricky. The main thread can end up trying + // to post a cursor position after having closed the WorkQueue. + } + } + + /** + * Like post(), Post() is a way of conveying a single work item to this + * thread. Its virtue is that it will definitely be executed "soon" rather + * than potentially waiting for the next frame: it uses PostMessage() to + * break us out of the window thread's blocked GetMessage() call. It's + * more expensive, though, not only from the Windows API latency of + * PostMessage() and GetMessage(), but also because it involves heap + * allocation and release. + * + * Require HWND from caller, even though we store an HWND locally. + * Otherwise, if our mWindowHandle was accessed from both threads, we'd + * have to protect it with a mutex. + */ + template <typename CALLABLE> + void Post(HWND windowHandle, CALLABLE&& func) + { + // Move func to the heap. If we knew FuncType could fit into LPARAM, + // we could simply instantiate FuncType and pass it by value. But + // since we don't, we must put that on the heap as well as the + // internal heap allocation it likely requires to store func. + auto ptr = new FuncType(std::move(func)); + WPARAM wparam{ 0xF1C }; + LL_DEBUGS("Window") << "PostMessage(" << std::hex << windowHandle + << ", " << WM_POST_FUNCTION_ + << ", " << wparam << std::dec << LL_ENDL; + PostMessage(windowHandle, WM_POST_FUNCTION_, wparam, LPARAM(ptr)); + } + + using FuncType = std::function<void()>; + // call GetMessage() and pull enqueue messages for later processing + void gatherInput(); + HWND mWindowHandle = NULL; + HDC mhDC = 0; +}; + + LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, - BOOL disable_vsync, BOOL use_gl, + BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) : LLWindow(callbacks, fullscreen, flags) { - + sMainThreadId = LLThread::currentID(); + mWindowThread = new LLWindowWin32Thread(); //MAINT-516 -- force a load of opengl32.dll just in case windows went sideways LoadLibrary(L"opengl32.dll"); @@ -471,7 +416,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mIconResource = gIconResource; mOverrideAspectRatio = 0.f; mNativeAspectRatio = 0.f; - mMousePositionModified = FALSE; mInputProcessingPaused = FALSE; mPreeditor = NULL; mKeyCharCode = 0; @@ -483,6 +427,9 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp)); mCustomGammaSet = FALSE; mWindowHandle = NULL; + + mRect = {0, 0, 0, 0}; + mClientRect = {0, 0, 0, 0}; if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &mMouseVanish, 0)) { @@ -535,7 +482,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, // Make an instance of our window then define the window class mhInstance = GetModuleHandle(NULL); - mWndProc = NULL; // Init Direct Input - needed for joystick / Spacemouse @@ -784,7 +730,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, LLCoordScreen windowPos(x,y); LLCoordScreen windowSize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); - if (!switchContext(mFullscreen, windowSize, TRUE, &windowPos)) + if (!switchContext(mFullscreen, windowSize, enable_vsync, &windowPos)) { return; } @@ -793,6 +739,13 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, initCursors(); setCursor( UI_CURSOR_ARROW ); + mRawMouse.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC + mRawMouse.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE + mRawMouse.dwFlags = 0; // adds mouse and also ignores legacy mouse messages + mRawMouse.hwndTarget = 0; + + RegisterRawInputDevices(&mRawMouse, 1, sizeof(mRawMouse)); + // Initialize (boot strap) the Language text input management, // based on the system's (or user's) default settings. allowLanguageTextInput(NULL, FALSE); @@ -811,6 +764,8 @@ LLWindowWin32::~LLWindowWin32() delete [] mWindowClassName; mWindowClassName = NULL; + + delete mWindowThread; } void LLWindowWin32::show() @@ -850,7 +805,7 @@ void LLWindowWin32::restore() // I'm turning off optimizations for this part to be sure code executes as intended // (it is a straw, but I have no idea why else __try can get overruled) #pragma optimize("", off) -bool destroy_window_handler(HWND &hWnd) +bool destroy_window_handler(HWND hWnd) { bool res; __try @@ -930,26 +885,33 @@ void LLWindowWin32::close() LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; - if (IsWindow(mWindowHandle)) - { - // Make sure we don't leave a blank toolbar button. - ShowWindow(mWindowHandle, SW_HIDE); - - // This causes WM_DESTROY to be sent *immediately* - if (!destroy_window_handler(mWindowHandle)) + mWindowThread->post([=]() { - OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), - mCallbacks->translateString("MBShutdownErr"), - OSMB_OK); - } - } - else - { - // Something killed the window while we were busy destroying gl or handle somehow got broken - LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; - } + if (IsWindow(mWindowHandle)) + { + // Make sure we don't leave a blank toolbar button. + ShowWindow(mWindowHandle, SW_HIDE); + + // This causes WM_DESTROY to be sent *immediately* + if (!destroy_window_handler(mWindowHandle)) + { + OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), + mCallbacks->translateString("MBShutdownErr"), + OSMB_OK); + } + } + else + { + // Something killed the window while we were busy destroying gl or handle somehow got broken + LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; + } - mWindowHandle = NULL; + }); + // Even though the above lambda might not yet have run, we've already + // bound mWindowHandle into it by value, which should suffice for the + // operations we're asking. That's the last time WE should touch it. + mWindowHandle = NULL; + mWindowThread->close(); } BOOL LLWindowWin32::isValid() @@ -996,49 +958,22 @@ BOOL LLWindowWin32::getFullscreen() BOOL LLWindowWin32::getPosition(LLCoordScreen *position) { - RECT window_rect; - - if (!mWindowHandle || - !GetWindowRect(mWindowHandle, &window_rect) || - NULL == position) - { - return FALSE; - } - - position->mX = window_rect.left; - position->mY = window_rect.top; + position->mX = mRect.left; + position->mY = mRect.top; return TRUE; } BOOL LLWindowWin32::getSize(LLCoordScreen *size) { - RECT window_rect; - - if (!mWindowHandle || - !GetWindowRect(mWindowHandle, &window_rect) || - NULL == size) - { - return FALSE; - } - - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + size->mX = mRect.right - mRect.left; + size->mY = mRect.bottom - mRect.top; return TRUE; } BOOL LLWindowWin32::getSize(LLCoordWindow *size) { - RECT client_rect; - - if (!mWindowHandle || - !GetClientRect(mWindowHandle, &client_rect) || - NULL == size) - { - return FALSE; - } - - size->mX = client_rect.right - client_rect.left; - size->mY = client_rect.bottom - client_rect.top; + size->mX = mClientRect.right - mClientRect.left; + size->mY = mClientRect.bottom - mClientRect.top; return TRUE; } @@ -1065,14 +1000,17 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size) return FALSE; } - WINDOWPLACEMENT placement; - placement.length = sizeof(WINDOWPLACEMENT); - - if (!GetWindowPlacement(mWindowHandle, &placement)) return FALSE; - - placement.showCmd = SW_RESTORE; + mWindowThread->post([=]() + { + WINDOWPLACEMENT placement; + placement.length = sizeof(WINDOWPLACEMENT); - if (!SetWindowPlacement(mWindowHandle, &placement)) return FALSE; + if (GetWindowPlacement(mWindowHandle, &placement)) + { + placement.showCmd = SW_RESTORE; + SetWindowPlacement(mWindowHandle, &placement); + } + }); moveWindow(position, size); return TRUE; @@ -1084,177 +1022,165 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dw_style = WS_OVERLAPPEDWINDOW; - AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); + AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top)); } // changing fullscreen resolution -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL enable_vsync, const LLCoordScreen* const posp) { - GLuint pixel_format; - DEVMODE dev_mode; - ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); - dev_mode.dmSize = sizeof(DEVMODE); - DWORD current_refresh; - DWORD dw_ex_style; - DWORD dw_style; - RECT window_rect = {0, 0, 0, 0}; - S32 width = size.mX; - S32 height = size.mY; - BOOL auto_show = FALSE; - - if (mhRC) - { - auto_show = TRUE; - resetDisplayResolution(); - } - - if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) - { - current_refresh = dev_mode.dmDisplayFrequency; - } - else - { - current_refresh = 60; - } - - gGLManager.shutdownGL(); - //destroy gl context - if (mhRC) - { - if (!wglMakeCurrent(NULL, NULL)) - { - LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; - } + //called from main thread + GLuint pixel_format; + DEVMODE dev_mode; + ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); + DWORD current_refresh; + DWORD dw_ex_style; + DWORD dw_style; + RECT window_rect = { 0, 0, 0, 0 }; + S32 width = size.mX; + S32 height = size.mY; + BOOL auto_show = FALSE; + + if (mhRC) + { + auto_show = TRUE; + resetDisplayResolution(); + } - if (!wglDeleteContext(mhRC)) - { - LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; - } + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) + { + current_refresh = dev_mode.dmDisplayFrequency; + } + else + { + current_refresh = 60; + } - mhRC = NULL; - } + gGLManager.shutdownGL(); + //destroy gl context + if (mhRC) + { + if (!wglMakeCurrent(NULL, NULL)) + { + LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; + } - if (fullscreen) - { - mFullscreen = TRUE; - BOOL success = FALSE; - DWORD closest_refresh = 0; + if (!wglDeleteContext(mhRC)) + { + LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; + } - for (S32 mode_num = 0;; mode_num++) - { - if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) - { - break; - } + mhRC = NULL; + } - if (dev_mode.dmPelsWidth == width && - dev_mode.dmPelsHeight == height && - dev_mode.dmBitsPerPel == BITS_PER_PIXEL) - { - success = TRUE; - if ((dev_mode.dmDisplayFrequency - current_refresh) - < (closest_refresh - current_refresh)) - { - closest_refresh = dev_mode.dmDisplayFrequency; - } - } - } + if (fullscreen) + { + mFullscreen = TRUE; + BOOL success = FALSE; + DWORD closest_refresh = 0; - if (closest_refresh == 0) - { - LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; - return FALSE; - } + for (S32 mode_num = 0;; mode_num++) + { + if (!EnumDisplaySettings(NULL, mode_num, &dev_mode)) + { + break; + } - // If we found a good resolution, use it. - if (success) - { - success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); - } + if (dev_mode.dmPelsWidth == width && + dev_mode.dmPelsHeight == height && + dev_mode.dmBitsPerPel == BITS_PER_PIXEL) + { + success = TRUE; + if ((dev_mode.dmDisplayFrequency - current_refresh) + < (closest_refresh - current_refresh)) + { + closest_refresh = dev_mode.dmDisplayFrequency; + } + } + } - // Keep a copy of the actual current device mode in case we minimize - // and change the screen resolution. JC - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); + if (closest_refresh == 0) + { + LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; + return FALSE; + } - if (success) - { - mFullscreen = TRUE; - mFullscreenWidth = dev_mode.dmPelsWidth; - mFullscreenHeight = dev_mode.dmPelsHeight; - mFullscreenBits = dev_mode.dmBitsPerPel; - mFullscreenRefresh = dev_mode.dmDisplayFrequency; + // If we found a good resolution, use it. + if (success) + { + success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh); + } - LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth - << "x" << dev_mode.dmPelsHeight - << "x" << dev_mode.dmBitsPerPel - << " @ " << dev_mode.dmDisplayFrequency - << LL_ENDL; + // Keep a copy of the actual current device mode in case we minimize + // and change the screen resolution. JC + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); - window_rect.left = (long) 0; - window_rect.right = (long) width; // Windows GDI rects don't include rightmost pixel - window_rect.top = (long) 0; - window_rect.bottom = (long) height; - dw_ex_style = WS_EX_APPWINDOW; - dw_style = WS_POPUP; + if (success) + { + mFullscreen = TRUE; + mFullscreenWidth = dev_mode.dmPelsWidth; + mFullscreenHeight = dev_mode.dmPelsHeight; + mFullscreenBits = dev_mode.dmBitsPerPel; + mFullscreenRefresh = dev_mode.dmDisplayFrequency; + + LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth + << "x" << dev_mode.dmPelsHeight + << "x" << dev_mode.dmBitsPerPel + << " @ " << dev_mode.dmDisplayFrequency + << LL_ENDL; + + window_rect.left = (long)0; + window_rect.right = (long)width; // Windows GDI rects don't include rightmost pixel + window_rect.top = (long)0; + window_rect.bottom = (long)height; + dw_ex_style = WS_EX_APPWINDOW; + dw_style = WS_POPUP; + + // Move window borders out not to cover window contents. + // This converts client rect to window rect, i.e. expands it by the window border size. + AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); + } + // If it failed, we don't want to run fullscreen + else + { + mFullscreen = FALSE; + mFullscreenWidth = -1; + mFullscreenHeight = -1; + mFullscreenBits = -1; + mFullscreenRefresh = -1; - // Move window borders out not to cover window contents. - // This converts client rect to window rect, i.e. expands it by the window border size. - AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style); - } - // If it failed, we don't want to run fullscreen - else - { - mFullscreen = FALSE; - mFullscreenWidth = -1; - mFullscreenHeight = -1; - mFullscreenBits = -1; - mFullscreenRefresh = -1; + LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; + return FALSE; + } + } + else + { + mFullscreen = FALSE; + window_rect.left = (long)(posp ? posp->mX : 0); + window_rect.right = (long)width + window_rect.left; // Windows GDI rects don't include rightmost pixel + window_rect.top = (long)(posp ? posp->mY : 0); + window_rect.bottom = (long)height + window_rect.top; + // Window with an edge + dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dw_style = WS_OVERLAPPEDWINDOW; + } - LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL; - return FALSE; - } - } - else - { - mFullscreen = FALSE; - window_rect.left = (long) (posp ? posp->mX : 0); - window_rect.right = (long) width + window_rect.left; // Windows GDI rects don't include rightmost pixel - window_rect.top = (long) (posp ? posp->mY : 0); - window_rect.bottom = (long) height + window_rect.top; - // Window with an edge - dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - dw_style = WS_OVERLAPPEDWINDOW; - } + // don't post quit messages when destroying old windows + mPostQuit = FALSE; - // don't post quit messages when destroying old windows - mPostQuit = FALSE; - // create window + // create window LL_DEBUGS("Window") << "Creating window with X: " << window_rect.left << " Y: " << window_rect.top << " Width: " << (window_rect.right - window_rect.left) << " Height: " << (window_rect.bottom - window_rect.top) << " Fullscreen: " << mFullscreen << LL_ENDL; - if (mWindowHandle && !destroy_window_handler(mWindowHandle)) - { - LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; - } - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); + + recreateWindow(window_rect, dw_ex_style, dw_style); if (mWindowHandle) { @@ -1288,7 +1214,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO 0, 0, 0 }; - if (!(mhDC = GetDC(mWindowHandle))) + if (!mhDC) { close(); OSMessageBox(mCallbacks->translateString("MBDevContextErr"), @@ -1582,25 +1508,17 @@ const S32 max_format = (S32)num_formats - 1; mhDC = 0; // Zero The Device Context } - // Destroy The Window - if (mWindowHandle && !destroy_window_handler(mWindowHandle)) + recreateWindow(window_rect, dw_ex_style, dw_style); + + RECT rect; + RECT client_rect; + //initialize immediately on main thread + if (GetWindowRect(mWindowHandle, &rect) && + GetClientRect(mWindowHandle, &client_rect)) { - LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL; - } - - mWindowHandle = CreateWindowEx(dw_ex_style, - mWindowClassName, - mWindowTitle, - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, - window_rect.left, // x pos - window_rect.top, // y pos - window_rect.right - window_rect.left, // width - window_rect.bottom - window_rect.top, // height - NULL, - NULL, - mhInstance, - NULL); - + mRect = rect; + mClientRect = client_rect; + }; if (mWindowHandle) { @@ -1612,7 +1530,7 @@ const S32 max_format = (S32)num_formats - 1; LL_WARNS("Window") << "Window recreation failed, code: " << GetLastError() << LL_ENDL; } - if (!(mhDC = GetDC(mWindowHandle))) + if (!mhDC) { close(); OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); @@ -1687,58 +1605,11 @@ const S32 max_format = (S32)num_formats - 1; mhRC = 0; if (wglCreateContextAttribsARB) { //attempt to create a specific versioned context - S32 attribs[] = - { //start at 4.2 - WGL_CONTEXT_MAJOR_VERSION_ARB, 4, - WGL_CONTEXT_MINOR_VERSION_ARB, 2, - WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, - 0 - }; - - bool done = false; - while (!done) - { - mhRC = wglCreateContextAttribsARB(mhDC, mhRC, attribs); - - if (!mhRC) - { - if (attribs[3] > 0) - { //decrement minor version - attribs[3]--; - } - else if (attribs[1] > 3) - { //decrement major version and start minor version over at 3 - attribs[1]--; - attribs[3] = 3; - } - else - { //we reached 3.0 and still failed, bail out - done = true; - } - } - else - { - LL_INFOS() << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << - (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << LL_ENDL; - done = true; - - // force sNoFixedFunction iff we're trying to use nsight debugging which does not support many legacy API uses - - // nSight doesn't support use of legacy API funcs in the fixed function pipe - if (LLRender::sGLCoreProfile || LLRender::sNsightDebugSupport) - { - LLGLSLShader::sNoFixedFunction = true; - } - } - } - } - - if (!mhRC && !(mhRC = wglCreateContext(mhDC))) - { - close(); - OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); - return FALSE; + mhRC = (HGLRC) createSharedContext(); + if (!mhRC) + { + return FALSE; + } } if (!wglMakeCurrent(mhDC, mhRC)) @@ -1748,6 +1619,8 @@ const S32 max_format = (S32)num_formats - 1; return FALSE; } + LL_PROFILER_GPU_CONTEXT + if (!gGLManager.initGL()) { close(); @@ -1756,15 +1629,7 @@ const S32 max_format = (S32)num_formats - 1; } // Disable vertical sync for swap - if (disable_vsync && wglSwapIntervalEXT) - { - LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL; - wglSwapIntervalEXT(0); - } - else - { - LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL; - } + toggleVSync(enable_vsync); SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this); @@ -1790,6 +1655,177 @@ const S32 max_format = (S32)num_formats - 1; return TRUE; } +void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style) +{ + auto oldHandle = mWindowHandle; + + // zero out mWindowHandle and mhDC before destroying window so window + // thread falls back to peekmessage + mWindowHandle = 0; + mhDC = 0; + + std::promise<std::pair<HWND, HDC>> promise; + // What follows must be done on the window thread. + auto window_work = + [this, + self=mWindowThread, + oldHandle, + // bind CreateWindowEx() parameters by value instead of + // back-referencing LLWindowWin32 members + windowClassName=mWindowClassName, + windowTitle=mWindowTitle, + hInstance=mhInstance, + window_rect, + dw_ex_style, + dw_style, + &promise] + () + { + LL_DEBUGS("Window") << "recreateWindow(): window_work entry" << LL_ENDL; + self->mWindowHandle = 0; + self->mhDC = 0; + + // important to call DestroyWindow() from the window thread + if (oldHandle && !destroy_window_handler(oldHandle)) + { + LL_WARNS("Window") << "Failed to properly close window before recreating it!" + << LL_ENDL; + } + + auto handle = CreateWindowEx(dw_ex_style, + windowClassName, + windowTitle, + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style, + window_rect.left, // x pos + window_rect.top, // y pos + window_rect.right - window_rect.left, // width + window_rect.bottom - window_rect.top, // height + NULL, + NULL, + hInstance, + NULL); + + if (! handle) + { + // Failed to create window: clear the variables. This + // assignment is valid because we're running on mWindowThread. + self->mWindowHandle = NULL; + self->mhDC = 0; + } + else + { + // Update mWindowThread's own mWindowHandle and mhDC. + self->mWindowHandle = handle; + self->mhDC = GetDC(handle); + } + + updateWindowRect(); + + // It's important to wake up the future either way. + promise.set_value(std::make_pair(self->mWindowHandle, self->mhDC)); + LL_DEBUGS("Window") << "recreateWindow(): window_work done" << LL_ENDL; + }; + // But how we pass window_work to the window thread depends on whether we + // already have a window handle. + if (! oldHandle) + { + // Pass window_work using the WorkQueue: without an existing window + // handle, the window thread can't call GetMessage(). + LL_DEBUGS("Window") << "posting window_work to WorkQueue" << LL_ENDL; + mWindowThread->post(window_work); + } + else + { + // Pass window_work using PostMessage(). We can still + // PostMessage(oldHandle) because oldHandle won't be destroyed until + // the window thread has retrieved and executed window_work. + LL_DEBUGS("Window") << "posting window_work to message queue" << LL_ENDL; + mWindowThread->Post(oldHandle, window_work); + } + + auto future = promise.get_future(); + // This blocks until mWindowThread processes CreateWindowEx() and calls + // promise.set_value(). + auto pair = future.get(); + mWindowHandle = pair.first; + mhDC = pair.second; +} + +void* LLWindowWin32::createSharedContext() +{ + S32 attribs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, 4, + WGL_CONTEXT_MINOR_VERSION_ARB, 6, + WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, + 0 + }; + + HGLRC rc = 0; + + bool done = false; + while (!done) + { + rc = wglCreateContextAttribsARB(mhDC, mhRC, attribs); + + if (!rc) + { + if (attribs[3] > 0) + { //decrement minor version + attribs[3]--; + } + else if (attribs[1] > 3) + { //decrement major version and start minor version over at 3 + attribs[1]--; + attribs[3] = 3; + } + else + { //we reached 3.0 and still failed, bail out + done = true; + } + } + else + { + LL_INFOS() << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << + (LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << LL_ENDL; + done = true; + } + } + + if (!rc && !(rc = wglCreateContext(mhDC))) + { + close(); + OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); + } + + return rc; +} + +void LLWindowWin32::makeContextCurrent(void* contextPtr) +{ + wglMakeCurrent(mhDC, (HGLRC) contextPtr); +} + +void LLWindowWin32::destroySharedContext(void* contextPtr) +{ + wglDeleteContext((HGLRC)contextPtr); +} + +void LLWindowWin32::toggleVSync(bool enable_vsync) +{ + if (!enable_vsync && wglSwapIntervalEXT) + { + LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL; + wglSwapIntervalEXT(0); + } + else + { + LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL; + wglSwapIntervalEXT(1); + } +} + void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size ) { if( mIsMouseClipping ) @@ -1808,66 +1844,106 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre // THIS CAUSES DEV-15484 and DEV-15949 //ShowWindow(mWindowHandle, SW_RESTORE); // NOW we can call MoveWindow - MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); + mWindowThread->post([=]() + { + MoveWindow(mWindowHandle, position.mX, position.mY, size.mX, size.mY, TRUE); + }); +} + +void LLWindowWin32::setTitle(const std::string title) +{ + // TODO: Do we need to use the wide string version of this call + // to support non-ascii usernames (and region names?) + mWindowThread->post([=]() + { + SetWindowTextA(mWindowHandle, title.c_str()); + }); } BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position) { - mMousePositionModified = TRUE; - if (!mWindowHandle) - { - return FALSE; - } + ASSERT_MAIN_THREAD(); + if (!mWindowHandle) + { + return FALSE; + } - // Inform the application of the new mouse position (needed for per-frame - // hover/picking to function). - mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); - - // DEV-18951 VWR-8524 Camera moves wildly when alt-clicking. - // Because we have preemptively notified the application of the new - // mouse position via handleMouseMove() above, we need to clear out - // any stale mouse move events. RN/JC - MSG msg; - while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - { } - - LLCoordScreen screen_pos(position.convert()); - return ::SetCursorPos(screen_pos.mX, screen_pos.mY); + LLCoordScreen screen_pos(position.convert()); + + // instantly set the cursor position from the app's point of view + mCursorPosition = position; + mLastCursorPosition = position; + + // Inform the application of the new mouse position (needed for per-frame + // hover/picking to function). + mCallbacks->handleMouseMove(this, position.convert(), (MASK)0); + + // actually set the cursor position on the window thread + mWindowThread->post([=]() + { + // actually set the OS cursor position + SetCursorPos(screen_pos.mX, screen_pos.mY); + }); + + return TRUE; } BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position) { - POINT cursor_point; - - if (!mWindowHandle - || !GetCursorPos(&cursor_point) - || !position) - { - return FALSE; - } + ASSERT_MAIN_THREAD(); + if (!position) + { + return FALSE; + } - *position = LLCoordScreen(cursor_point.x, cursor_point.y).convert(); + *position = mCursorPosition; return TRUE; } +BOOL LLWindowWin32::getCursorDelta(LLCoordCommon* delta) +{ + if (delta == nullptr) + { + return FALSE; + } + + *delta = mMouseFrameDelta; + + return TRUE; +} + void LLWindowWin32::hideCursor() { - while (ShowCursor(FALSE) >= 0) - { - // nothing, wait for cursor to push down - } + ASSERT_MAIN_THREAD(); + + mWindowThread->post([=]() + { + while (ShowCursor(FALSE) >= 0) + { + // nothing, wait for cursor to push down + } + }); + mCursorHidden = TRUE; mHideCursorPermanent = TRUE; } void LLWindowWin32::showCursor() { - // makes sure the cursor shows up - while (ShowCursor(TRUE) < 0) - { - // do nothing, wait for cursor to pop out - } + LL_PROFILE_ZONE_SCOPED; + + ASSERT_MAIN_THREAD(); + + mWindowThread->post([=]() + { + // makes sure the cursor shows up + while (ShowCursor(TRUE) < 0) + { + // do nothing, wait for cursor to pop out + } + }); + mCursorHidden = FALSE; mHideCursorPermanent = FALSE; } @@ -1969,6 +2045,8 @@ void LLWindowWin32::initCursors() void LLWindowWin32::updateCursor() { + ASSERT_MAIN_THREAD(); + LL_PROFILE_ZONE_SCOPED if (mNextCursor == UI_CURSOR_ARROW && mBusyCount > 0) { @@ -1978,7 +2056,11 @@ void LLWindowWin32::updateCursor() if( mCurrentCursor != mNextCursor ) { mCurrentCursor = mNextCursor; - SetCursor( mCursor[mNextCursor] ); + auto nextCursor = mCursor[mNextCursor]; + mWindowThread->post([=]() + { + SetCursor(nextCursor); + }); } } @@ -1994,13 +2076,8 @@ void LLWindowWin32::captureMouse() void LLWindowWin32::releaseMouse() { - // *NOTE:Mani ReleaseCapture will spawn new windows messages... - // which will in turn call our MainWindowProc. It therefore requires - // pausing *and more importantly resumption* of the mainlooptimeout... - // just like DispatchMessage below. - mCallbacks->handlePauseWatchdog(this); + LL_PROFILE_ZONE_SCOPED; ReleaseCapture(); - mCallbacks->handleResumeWatchdog(this); } @@ -2009,1003 +2086,1006 @@ void LLWindowWin32::delayInputProcessing() mInputProcessingPaused = TRUE; } + void LLWindowWin32::gatherInput() { - MSG msg; - int msg_count = 0; + ASSERT_MAIN_THREAD(); + LL_PROFILE_ZONE_SCOPED + MSG msg; - while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput"); - TranslateMessage(&msg); + { + LLMutexLock lock(&mRawMouseMutex); + mMouseFrameDelta = mRawMouseDelta; - // turn watchdog off in here to not fail if windows is doing something wacky - mCallbacks->handlePauseWatchdog(this); - DispatchMessage(&msg); - mCallbacks->handleResumeWatchdog(this); - msg_count++; + mRawMouseDelta.mX = 0; + mRawMouseDelta.mY = 0; + } - if ( mInputProcessingPaused ) - { - break; - } - /* Attempted workaround for problem where typing fast and hitting - return would result in only part of the text being sent. JC - BOOL key_posted = TranslateMessage(&msg); - DispatchMessage(&msg); - msg_count++; + if (mWindowThread->getQueue().size()) + { + LL_PROFILE_ZONE_NAMED("gi - PostMessage"); + kickWindowThread(); + } + + while (mWindowThread->mMessageQueue.tryPopBack(msg)) + { + LL_PROFILE_ZONE_NAMED("gi - message queue"); + if (mInputProcessingPaused) + { + continue; + } - // If a key was translated, a WM_CHAR might have been posted to the end - // of the event queue. We need it immediately. - if (key_posted && msg.message == WM_KEYDOWN) - { - if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - msg_count++; - } - } - */ - mCallbacks->handlePingWatchdog(this, "Main:AsyncCallbackGatherInput"); - // For async host by name support. Really hacky. - if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) - { - gAsyncMsgCallback(msg); - } - } + // For async host by name support. Really hacky. + if (gAsyncMsgCallback && (LL_WM_HOST_RESOLVED == msg.message)) + { + LL_PROFILE_ZONE_NAMED("gi - callback"); + gAsyncMsgCallback(msg); + } + } + + { + LL_PROFILE_ZONE_NAMED("gi - PeekMessage"); + S32 msg_count = 0; + while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + msg_count++; + } + } + + { + LL_PROFILE_ZONE_NAMED("gi - function queue"); + //process any pending functions + std::function<void()> curFunc; + while (mFunctionQueue.tryPopBack(curFunc)) + { + curFunc(); + } + } + + // send one and only one mouse move event per frame BEFORE handling mouse button presses + if (mLastCursorPosition != mCursorPosition) + { + LL_PROFILE_ZONE_NAMED("gi - mouse move"); + mCallbacks->handleMouseMove(this, mCursorPosition.convert(), mMouseMask); + } + + mLastCursorPosition = mCursorPosition; + + { + LL_PROFILE_ZONE_NAMED("gi - mouse queue"); + // handle mouse button presses AFTER updating mouse cursor position + std::function<void()> curFunc; + while (mMouseQueue.tryPopBack(curFunc)) + { + curFunc(); + } + } mInputProcessingPaused = FALSE; updateCursor(); - - // clear this once we've processed all mouse messages that might have occurred after - // we slammed the mouse position - mMousePositionModified = FALSE; } static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard"); static LLTrace::BlockTimerStatHandle FTM_MOUSEHANDLER("Handle Mouse"); +#define WINDOW_IMP_POST(x) window_imp->post([=]() { x; }) + LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param) { - // Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN. - // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. - static bool sHandleLeftMouseUp = true; - - // Ignore the double click received right after activating app. - // This is to avoid triggering double click teleport after returning focus (see MAINT-3786). - static bool sHandleDoubleClick = true; - - LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLongPtr( h_wnd, GWLP_USERDATA ); - - bool debug_window_proc = gDebugWindowProc || debugLoggingEnabled("Window"); - - - if (NULL != window_imp) - { - window_imp->mCallbacks->handleResumeWatchdog(window_imp); - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:StartWndProc"); - // Has user provided their own window callback? - if (NULL != window_imp->mWndProc) - { - if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param)) - { - // user has handled window message - return 0; - } - } - - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:PreSwitchWndProc"); - - // Juggle to make sure we can get negative positions for when - // mouse is outside window. - LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); - - // This doesn't work, as LOWORD returns unsigned short. - //LLCoordWindow window_coord(LOWORD(l_param), HIWORD(l_param)); - LLCoordGL gl_coord; - - // pass along extended flag in mask - MASK mask = (l_param>>16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; - BOOL eat_keystroke = TRUE; - - switch(u_msg) - { - RECT update_rect; - S32 update_width; - S32 update_height; - - case WM_TIMER: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_TIMER"); - window_imp->mCallbacks->handleTimerEvent(window_imp); - break; - - case WM_DEVICECHANGE: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DEVICECHANGE"); - if (debug_window_proc) - { - LL_INFOS("Window") << " WM_DEVICECHANGE: wParam=" << w_param - << "; lParam=" << l_param << LL_ENDL; - } - if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) - { - if (window_imp->mCallbacks->handleDeviceChange(window_imp)) - { - return 0; - } - } - break; + ASSERT_WINDOW_THREAD(); + LL_PROFILE_ZONE_SCOPED; - case WM_PAINT: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PAINT"); - GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); - update_width = update_rect.right - update_rect.left + 1; - update_height = update_rect.bottom - update_rect.top + 1; - window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top, - update_width, update_height); - break; - case WM_PARENTNOTIFY: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_PARENTNOTIFY"); - u_msg = u_msg; - break; - - case WM_SETCURSOR: - // This message is sent whenever the cursor is moved in a window. - // You need to set the appropriate cursor appearance. - - // Only take control of cursor over client region of window - // This allows Windows(tm) to handle resize cursors, etc. - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETCURSOR"); - if (LOWORD(l_param) == HTCLIENT) - { - SetCursor(window_imp->mCursor[ window_imp->mCurrentCursor] ); - return 0; - } - break; - - case WM_ENTERMENULOOP: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ENTERMENULOOP"); - window_imp->mCallbacks->handleWindowBlock(window_imp); - break; - - case WM_EXITMENULOOP: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_EXITMENULOOP"); - window_imp->mCallbacks->handleWindowUnblock(window_imp); - break; - - case WM_ACTIVATEAPP: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATEAPP"); - { - // This message should be sent whenever the app gains or loses focus. - BOOL activating = (BOOL) w_param; - BOOL minimized = window_imp->getMinimized(); - - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC ActivateApp " - << " activating " << S32(activating) - << " minimized " << S32(minimized) - << " fullscreen " << S32(window_imp->mFullscreen) - << LL_ENDL; - } - - if (window_imp->mFullscreen) - { - // When we run fullscreen, restoring or minimizing the app needs - // to switch the screen resolution - if (activating) - { - window_imp->setFullscreenResolution(); - window_imp->restore(); - } - else - { - window_imp->minimize(); - window_imp->resetDisplayResolution(); - } - } - - if (!activating) - { - sHandleDoubleClick = false; - } - - window_imp->mCallbacks->handleActivateApp(window_imp, activating); - - break; - } - - case WM_ACTIVATE: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_ACTIVATE"); - { - // Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE - BOOL activating = (LOWORD(w_param) != WA_INACTIVE); - - BOOL minimized = BOOL(HIWORD(w_param)); - - if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } - - // JC - I'm not sure why, but if we don't report that we handled the - // WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work - // properly when we run fullscreen. - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC Activate " - << " activating " << S32(activating) - << " minimized " << S32(minimized) - << LL_ENDL; - } - - // Don't handle this. - break; - } - - case WM_QUERYOPEN: - // TODO: use this to return a nice icon - break; + LL_DEBUGS("Window") << "mainWindowProc(" << std::hex << h_wnd + << ", " << u_msg + << ", " << w_param << ")" << std::dec << LL_ENDL; - case WM_SYSCOMMAND: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSCOMMAND"); - switch(w_param) - { - case SC_KEYMENU: - // Disallow the ALT key from triggering the default system menu. - return 0; - - case SC_SCREENSAVE: - case SC_MONITORPOWER: - // eat screen save messages and prevent them! - return 0; - } - break; - - case WM_CLOSE: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CLOSE"); - // Will the app allow the window to close? - if (window_imp->mCallbacks->handleCloseRequest(window_imp)) - { - // Get the app to initiate cleanup. - window_imp->mCallbacks->handleQuit(window_imp); - // The app is responsible for calling destroyWindow when done with GL - } - return 0; - - case WM_DESTROY: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_DESTROY"); - if (window_imp->shouldPostQuit()) - { - PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0 - } - return 0; + if (u_msg == WM_POST_FUNCTION_) + { + LL_DEBUGS("Window") << "WM_POST_FUNCTION_" << LL_ENDL; + // from LLWindowWin32Thread::Post() + // Cast l_param back to the pointer to the heap FuncType + // allocated by Post(). Capture in unique_ptr so we'll delete + // once we're done with it. + std::unique_ptr<LLWindowWin32Thread::FuncType> + ptr(reinterpret_cast<LLWindowWin32Thread::FuncType*>(l_param)); + (*ptr)(); + return 0; + } - case WM_COMMAND: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COMMAND"); - if (!HIWORD(w_param)) // this message is from a menu - { - window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param)); - } - break; + // Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN. + // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. + static bool sHandleLeftMouseUp = true; - case WM_SYSKEYDOWN: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SYSKEYDOWN"); - // allow system keys, such as ALT-F4 to be processed by Windows - eat_keystroke = FALSE; - case WM_KEYDOWN: - window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next - window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; - window_imp->mKeyVirtualKey = w_param; - window_imp->mRawMsg = u_msg; - window_imp->mRawWParam = w_param; - window_imp->mRawLParam = l_param; - - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN"); - { - if (debug_window_proc) - { - LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN " - << " key " << S32(w_param) - << LL_ENDL; - } - if(gKeyboard->handleKeyDown(w_param, mask) && eat_keystroke) - { - return 0; - } - // pass on to windows if we didn't handle it - break; - } - case WM_SYSKEYUP: - eat_keystroke = FALSE; - case WM_KEYUP: - { - window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; - window_imp->mKeyVirtualKey = w_param; - window_imp->mRawMsg = u_msg; - window_imp->mRawWParam = w_param; - window_imp->mRawLParam = l_param; + // Ignore the double click received right after activating app. + // This is to avoid triggering double click teleport after returning focus (see MAINT-3786). + static bool sHandleDoubleClick = true; - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); - LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER); + LLWindowWin32* window_imp = (LLWindowWin32*)GetWindowLongPtr(h_wnd, GWLP_USERDATA); - if (debug_window_proc) - { - LL_INFOS("Window") << "Debug WindowProc WM_KEYUP " - << " key " << S32(w_param) - << LL_ENDL; - } - if (gKeyboard->handleKeyUp(w_param, mask) && eat_keystroke) - { - return 0; - } + bool debug_window_proc = false; // gDebugWindowProc || debugLoggingEnabled("Window"); - // pass on to windows - break; - } - case WM_IME_SETCONTEXT: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_SETCONTEXT"); - if (debug_window_proc) - { - LL_INFOS("Window") << "WM_IME_SETCONTEXT" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; - // Invoke DefWinProc with the modified LPARAM. - } - break; + if (NULL != window_imp) + { + // Juggle to make sure we can get negative positions for when + // mouse is outside window. + LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)); - case WM_IME_STARTCOMPOSITION: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_STARTCOMPOSITION"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_STARTCOMPOSITION" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->handleStartCompositionMessage(); - return 0; - } - break; + // pass along extended flag in mask + MASK mask = (l_param >> 16 & KF_EXTENDED) ? MASK_EXTENDED : 0x0; + BOOL eat_keystroke = TRUE; - case WM_IME_ENDCOMPOSITION: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_ENDCOMPOSITION"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_ENDCOMPOSITION" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - return 0; - } - break; + switch (u_msg) + { + RECT update_rect; + S32 update_width; + S32 update_height; - case WM_IME_COMPOSITION: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_COMPOSITION"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_COMPOSITION" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->handleCompositionMessage(l_param); - return 0; - } - break; + case WM_TIMER: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_TIMER"); + WINDOW_IMP_POST(window_imp->mCallbacks->handleTimerEvent(window_imp)); + break; + } - case WM_IME_REQUEST: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_IME_REQUEST"); - if (debug_window_proc) - { - LL_INFOS() << "WM_IME_REQUEST" << LL_ENDL; - } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - LRESULT result = 0; - if (window_imp->handleImeRequests(w_param, l_param, &result)) - { - return result; - } - } - break; + case WM_DEVICECHANGE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_DEVICECHANGE"); + if (debug_window_proc) + { + LL_INFOS("Window") << " WM_DEVICECHANGE: wParam=" << w_param + << "; lParam=" << l_param << LL_ENDL; + } + if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleDeviceChange(window_imp)); + + return TRUE; + } + break; + } - case WM_CHAR: - window_imp->mKeyCharCode = w_param; - window_imp->mRawMsg = u_msg; - window_imp->mRawWParam = w_param; - window_imp->mRawLParam = l_param; - - // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need - // to figure out how that works. - Doug - // - // ... Well, I don't think so. - // How it works is explained in Win32 API document, but WM_UNICHAR didn't work - // as specified at least on Windows XP SP1 Japanese version. I have never used - // it since then, and I'm not sure whether it has been fixed now, but I don't think - // it is worth trying. The good old WM_CHAR works just fine even for supplementary - // characters. We just need to take care of surrogate pairs sent as two WM_CHAR's - // by ourselves. It is not that tough. -- Alissa Sabre @ SL - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_CHAR"); - if (debug_window_proc) - { - LL_INFOS("Window") << "Debug WindowProc WM_CHAR " - << " key " << S32(w_param) - << LL_ENDL; - } - // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE, - // we *did* processed the event, so I believe we should not pass it to DefWindowProc... - window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); - return 0; + case WM_PAINT: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_PAINT"); + GetUpdateRect(window_imp->mWindowHandle, &update_rect, FALSE); + update_width = update_rect.right - update_rect.left + 1; + update_height = update_rect.bottom - update_rect.top + 1; + + WINDOW_IMP_POST(window_imp->mCallbacks->handlePaint(window_imp, update_rect.left, update_rect.top, + update_width, update_height)); + break; + } + case WM_PARENTNOTIFY: + { + break; + } - case WM_NCLBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN"); - // A click in a non-client area, e.g. title bar or window border. - sHandleLeftMouseUp = false; - sHandleDoubleClick = true; - } - break; + case WM_SETCURSOR: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SETCURSOR"); + // This message is sent whenever the cursor is moved in a window. + // You need to set the appropriate cursor appearance. - case WM_LBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - sHandleLeftMouseUp = true; + // Only take control of cursor over client region of window + // This allows Windows(tm) to handle resize cursors, etc. + if (LOWORD(l_param) == HTCLIENT) + { + SetCursor(window_imp->mCursor[window_imp->mCurrentCursor]); + return 0; + } + break; + } + case WM_ENTERMENULOOP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_ENTERMENULOOP"); + WINDOW_IMP_POST(window_imp->mCallbacks->handleWindowBlock(window_imp)); + break; + } - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + case WM_EXITMENULOOP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_EXITMENULOOP"); + WINDOW_IMP_POST(window_imp->mCallbacks->handleWindowUnblock(window_imp)); + break; + } - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_ACTIVATEAPP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_ACTIVATEAPP"); + window_imp->post([=]() + { + // This message should be sent whenever the app gains or loses focus. + BOOL activating = (BOOL)w_param; + BOOL minimized = window_imp->getMinimized(); + + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC ActivateApp " + << " activating " << S32(activating) + << " minimized " << S32(minimized) + << " fullscreen " << S32(window_imp->mFullscreen) + << LL_ENDL; + } + + if (window_imp->mFullscreen) + { + // When we run fullscreen, restoring or minimizing the app needs + // to switch the screen resolution + if (activating) + { + window_imp->setFullscreenResolution(); + window_imp->restore(); + } + else + { + window_imp->minimize(); + window_imp->resetDisplayResolution(); + } + } + + if (!activating) + { + sHandleDoubleClick = false; + } + + window_imp->mCallbacks->handleActivateApp(window_imp, activating); + }); + break; + } + case WM_ACTIVATE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_ACTIVATE"); + window_imp->post([=]() + { + // Can be one of WA_ACTIVE, WA_CLICKACTIVE, or WA_INACTIVE + BOOL activating = (LOWORD(w_param) != WA_INACTIVE); + + BOOL minimized = BOOL(HIWORD(w_param)); + + if (!activating && LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + // JC - I'm not sure why, but if we don't report that we handled the + // WM_ACTIVATE message, the WM_ACTIVATEAPP messages don't work + // properly when we run fullscreen. + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC Activate " + << " activating " << S32(activating) + << " minimized " << S32(minimized) + << LL_ENDL; + } + }); + + break; + } - case WM_LBUTTONDBLCLK: - //RN: ignore right button double clicks for now - //case WM_RBUTTONDBLCLK: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK"); + case WM_QUERYOPEN: + // TODO: use this to return a nice icon + break; - if (!sHandleDoubleClick) - { - sHandleDoubleClick = true; - break; - } + case WM_SYSCOMMAND: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SYSCOMMAND"); + switch (w_param) + { + case SC_KEYMENU: + // Disallow the ALT key from triggering the default system menu. + return 0; + + case SC_SCREENSAVE: + case SC_MONITORPOWER: + // eat screen save messages and prevent them! + return 0; + } + break; + } + case WM_CLOSE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_CLOSE"); + window_imp->post([=]() + { + // Will the app allow the window to close? + if (window_imp->mCallbacks->handleCloseRequest(window_imp)) + { + // Get the app to initiate cleanup. + window_imp->mCallbacks->handleQuit(window_imp); + // The app is responsible for calling destroyWindow when done with GL + } + }); + return 0; + } + case WM_DESTROY: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_DESTROY"); + if (window_imp->shouldPostQuit()) + { + PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0 + } + return 0; + } + case WM_COMMAND: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_COMMAND"); + if (!HIWORD(w_param)) // this message is from a menu + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleMenuSelect(window_imp, LOWORD(w_param))); + } + break; + } + case WM_SYSKEYDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SYSKEYDOWN"); + // allow system keys, such as ALT-F4 to be processed by Windows + eat_keystroke = FALSE; + } + case WM_KEYDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_KEYDOWN"); + window_imp->post([=]() + { + window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next + window_imp->mKeyScanCode = (l_param >> 16) & 0xff; + window_imp->mKeyVirtualKey = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; + + { + if (debug_window_proc) + { + LL_INFOS("Window") << "Debug WindowProc WM_KEYDOWN " + << " key " << S32(w_param) + << LL_ENDL; + } + + gKeyboard->handleKeyDown(w_param, mask); + } + }); + return eat_keystroke; + } + case WM_SYSKEYUP: + eat_keystroke = FALSE; + case WM_KEYUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_KEYUP"); + window_imp->post([=]() + { + window_imp->mKeyScanCode = (l_param >> 16) & 0xff; + window_imp->mKeyVirtualKey = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; + + { + LL_RECORD_BLOCK_TIME(FTM_KEYHANDLER); + + if (debug_window_proc) + { + LL_INFOS("Window") << "Debug WindowProc WM_KEYUP " + << " key " << S32(w_param) + << LL_ENDL; + } + gKeyboard->handleKeyUp(w_param, mask); + } + }); + return eat_keystroke; + } + case WM_IME_SETCONTEXT: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_SETCONTEXT"); + if (debug_window_proc) + { + LL_INFOS("Window") << "WM_IME_SETCONTEXT" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; + // Invoke DefWinProc with the modified LPARAM. + } + break; + } + case WM_IME_STARTCOMPOSITION: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_STARTCOMPOSITION"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_STARTCOMPOSITION" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->handleStartCompositionMessage()); + return 0; + } + break; + } + case WM_IME_ENDCOMPOSITION: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_ENDCOMPOSITION"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_ENDCOMPOSITION" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + return 0; + } + break; + } + case WM_IME_COMPOSITION: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_COMPOSITION"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_COMPOSITION" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->handleCompositionMessage(l_param)); + return 0; + } + break; + } + case WM_IME_REQUEST: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_IME_REQUEST"); + if (debug_window_proc) + { + LL_INFOS() << "WM_IME_REQUEST" << LL_ENDL; + } + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + LRESULT result; + window_imp->handleImeRequests(w_param, l_param, &result); + return result; + } + break; + } + case WM_CHAR: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_CHAR"); + window_imp->post([=]() + { + window_imp->mKeyCharCode = w_param; + window_imp->mRawMsg = u_msg; + window_imp->mRawWParam = w_param; + window_imp->mRawLParam = l_param; + + // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need + // to figure out how that works. - Doug + // + // ... Well, I don't think so. + // How it works is explained in Win32 API document, but WM_UNICHAR didn't work + // as specified at least on Windows XP SP1 Japanese version. I have never used + // it since then, and I'm not sure whether it has been fixed now, but I don't think + // it is worth trying. The good old WM_CHAR works just fine even for supplementary + // characters. We just need to take care of surrogate pairs sent as two WM_CHAR's + // by ourselves. It is not that tough. -- Alissa Sabre @ SL + if (debug_window_proc) + { + LL_INFOS("Window") << "Debug WindowProc WM_CHAR " + << " key " << S32(w_param) + << LL_ENDL; + } + // Even if LLWindowCallbacks::handleUnicodeChar(llwchar, BOOL) returned FALSE, + // we *did* processed the event, so I believe we should not pass it to DefWindowProc... + window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE)); + }); + return 0; + } + case WM_NCLBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_NCLBUTTONDOWN"); + { + // A click in a non-client area, e.g. title bar or window border. + window_imp->post([=]() + { + sHandleLeftMouseUp = false; + sHandleDoubleClick = true; + }); + } + break; + } + case WM_LBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + window_imp->postMouseButtonEvent([=]() + { + sHandleLeftMouseUp = true; + + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + MASK mask = gKeyboard->currentMask(TRUE); + auto gl_coord = window_imp->mCursorPosition.convert(); + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleMouseDown(window_imp, gl_coord, mask); + }); + + return 0; + } + break; + } - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleDoubleClick(window_imp, gl_coord, mask) ) - { - return 0; - } - } - break; + case WM_LBUTTONDBLCLK: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONDBLCLK"); + window_imp->postMouseButtonEvent([=]() + { + //RN: ignore right button double clicks for now + //case WM_RBUTTONDBLCLK: + if (!sHandleDoubleClick) + { + sHandleDoubleClick = true; + return; + } + MASK mask = gKeyboard->currentMask(TRUE); + + // generate move event to update mouse coordinates + window_imp->mCursorPosition = window_coord; + window_imp->mCallbacks->handleDoubleClick(window_imp, window_imp->mCursorPosition.convert(), mask); + }); + + return 0; + } + case WM_LBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_LBUTTONUP"); + { + window_imp->postMouseButtonEvent([=]() + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + if (!sHandleLeftMouseUp) + { + sHandleLeftMouseUp = true; + return; + } + sHandleDoubleClick = true; + + + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + window_imp->mCursorPosition = window_coord; + window_imp->mCallbacks->handleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); + } + return 0; + } + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + window_imp->post([=]() + { + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + WINDOW_IMP_POST(window_imp->interruptLanguageTextInput()); + } + + MASK mask = gKeyboard->currentMask(TRUE); + // generate move event to update mouse coordinates + auto gl_coord = window_imp->mCursorPosition.convert(); + window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); + window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask); + }); + } + return 0; + } + break; - case WM_LBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + case WM_RBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_RBUTTONUP"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + window_imp->postMouseButtonEvent([=]() + { + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleRightMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); + } + } + break; - if (!sHandleLeftMouseUp) - { - sHandleLeftMouseUp = true; - break; - } - sHandleDoubleClick = true; - - //if (gDebugClicks) - //{ - // LL_INFOS("Window") << "WndProc left button up" << LL_ENDL; - //} - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_MBUTTONDOWN: + // case WM_MBUTTONDBLCLK: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONDOWN"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + window_imp->postMouseButtonEvent([=]() + { + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleMiddleMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask); + }); + } + } + break; - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + case WM_MBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MBUTTONUP"); + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + window_imp->postMouseButtonEvent([=]() + { + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mCallbacks->handleMiddleMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask); + }); + } + } + break; + case WM_XBUTTONDOWN: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONDOWN"); + window_imp->postMouseButtonEvent([=]() + { + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); + S32 button = GET_XBUTTON_WPARAM(w_param); + if (LLWinImm::isAvailable() && window_imp->mPreeditor) + { + window_imp->interruptLanguageTextInput(); + } + + MASK mask = gKeyboard->currentMask(TRUE); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + window_imp->mCallbacks->handleOtherMouseDown(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3); + }); + + } + break; - // Because we move the cursor position in the llviewerapp, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleRightMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_XBUTTONUP: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_XBUTTONUP"); + window_imp->postMouseButtonEvent([=]() + { - case WM_RBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleRightMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - case WM_MBUTTONDOWN: -// case WM_MBUTTONDBLCLK: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + S32 button = GET_XBUTTON_WPARAM(w_param); + MASK mask = gKeyboard->currentMask(TRUE); + // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 + window_imp->mCallbacks->handleOtherMouseUp(window_imp, window_imp->mCursorPosition.convert(), mask, button + 3); + }); + } + break; - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseDown(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; + case WM_MOUSEWHEEL: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEWHEEL"); + static short z_delta = 0; - case WM_MBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - if (window_imp->mCallbacks->handleMiddleMouseUp(window_imp, gl_coord, mask)) - { - return 0; - } - } - break; - case WM_XBUTTONDOWN: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - if (LLWinImm::isAvailable() && window_imp->mPreeditor) - { - window_imp->interruptLanguageTextInput(); - } + RECT client_rect; - // Because we move the cursor position in tllviewerhe app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } - break; + // eat scroll events that occur outside our window, since we use mouse position to direct scroll + // instead of keyboard focus + // NOTE: mouse_coord is in *window* coordinates for scroll events + POINT mouse_coord = { (S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param) }; - case WM_XBUTTONUP: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP"); - LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER); - S32 button = GET_XBUTTON_WPARAM(w_param); - // Because we move the cursor position in the llviewer app, we need to query - // to find out where the cursor at the time the event is handled. - // If we don't do this, many clicks could get buffered up, and if the - // first click changes the cursor position, all subsequent clicks - // will occur at the wrong location. JC - if (window_imp->mMousePositionModified) - { - LLCoordWindow cursor_coord_window; - window_imp->getCursorPosition(&cursor_coord_window); - gl_coord = cursor_coord_window.convert(); - } - else - { - gl_coord = window_coord.convert(); - } - MASK mask = gKeyboard->currentMask(TRUE); - // generate move event to update mouse coordinates - window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); - // Windows uses numbers 1 and 2 for buttons, remap to 4, 5 - if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3)) - { - return 0; - } - } - break; + if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) + && GetClientRect(window_imp->mWindowHandle, &client_rect)) + { + // we have a valid mouse point and client rect + if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x + || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) + { + // mouse is outside of client rect, so don't do anything + return 0; + } + } - case WM_MOUSEWHEEL: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL"); - static short z_delta = 0; + S16 incoming_z_delta = HIWORD(w_param); + z_delta += incoming_z_delta; + // cout << "z_delta " << z_delta << endl; + + // current mouse wheels report changes in increments of zDelta (+120, -120) + // Future, higher resolution mouse wheels may report smaller deltas. + // So we sum the deltas and only act when we've exceeded WHEEL_DELTA + // + // If the user rapidly spins the wheel, we can get messages with + // large deltas, like 480 or so. Thus we need to scroll more quickly. + if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) + { + short clicks = -z_delta / WHEEL_DELTA; + WINDOW_IMP_POST(window_imp->mCallbacks->handleScrollWheel(window_imp, clicks)); + z_delta = 0; + } + return 0; + } + /* + // TODO: add this after resolving _WIN32_WINNT issue + case WM_MOUSELEAVE: + { + window_imp->mCallbacks->handleMouseLeave(window_imp); + + // TRACKMOUSEEVENT track_mouse_event; + // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); + // track_mouse_event.dwFlags = TME_LEAVE; + // track_mouse_event.hwndTrack = h_wnd; + // track_mouse_event.dwHoverTime = HOVER_DEFAULT; + // TrackMouseEvent( &track_mouse_event ); + return 0; + } + */ + case WM_MOUSEHWHEEL: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEHWHEEL"); + static short h_delta = 0; - RECT client_rect; + RECT client_rect; - // eat scroll events that occur outside our window, since we use mouse position to direct scroll - // instead of keyboard focus - // NOTE: mouse_coord is in *window* coordinates for scroll events - POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)}; + // eat scroll events that occur outside our window, since we use mouse position to direct scroll + // instead of keyboard focus + // NOTE: mouse_coord is in *window* coordinates for scroll events + POINT mouse_coord = { (S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param) }; - if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) - && GetClientRect(window_imp->mWindowHandle, &client_rect)) - { - // we have a valid mouse point and client rect - if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x - || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) - { - // mouse is outside of client rect, so don't do anything - return 0; - } - } + if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) + && GetClientRect(window_imp->mWindowHandle, &client_rect)) + { + // we have a valid mouse point and client rect + if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x + || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) + { + // mouse is outside of client rect, so don't do anything + return 0; + } + } - S16 incoming_z_delta = HIWORD(w_param); - z_delta += incoming_z_delta; - // cout << "z_delta " << z_delta << endl; - - // current mouse wheels report changes in increments of zDelta (+120, -120) - // Future, higher resolution mouse wheels may report smaller deltas. - // So we sum the deltas and only act when we've exceeded WHEEL_DELTA - // - // If the user rapidly spins the wheel, we can get messages with - // large deltas, like 480 or so. Thus we need to scroll more quickly. - if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) - { - window_imp->mCallbacks->handleScrollWheel(window_imp, -z_delta / WHEEL_DELTA); - z_delta = 0; - } - return 0; - } - /* - // TODO: add this after resolving _WIN32_WINNT issue - case WM_MOUSELEAVE: - { - window_imp->mCallbacks->handleMouseLeave(window_imp); - - // TRACKMOUSEEVENT track_mouse_event; - // track_mouse_event.cbSize = sizeof( TRACKMOUSEEVENT ); - // track_mouse_event.dwFlags = TME_LEAVE; - // track_mouse_event.hwndTrack = h_wnd; - // track_mouse_event.dwHoverTime = HOVER_DEFAULT; - // TrackMouseEvent( &track_mouse_event ); - return 0; - } - */ - case WM_MOUSEHWHEEL: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEHWHEEL"); - static short h_delta = 0; + S16 incoming_h_delta = HIWORD(w_param); + h_delta += incoming_h_delta; - RECT client_rect; + // If the user rapidly spins the wheel, we can get messages with + // large deltas, like 480 or so. Thus we need to scroll more quickly. + if (h_delta <= -WHEEL_DELTA || WHEEL_DELTA <= h_delta) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleScrollHWheel(window_imp, h_delta / WHEEL_DELTA)); + h_delta = 0; + } + return 0; + } + // Handle mouse movement within the window + case WM_MOUSEMOVE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE"); + // DO NOT use mouse event queue for move events to ensure cursor position is updated + // when button events are handled + WINDOW_IMP_POST( + { + LL_PROFILE_ZONE_NAMED("mwp - WM_MOUSEMOVE lambda"); + + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->mMouseMask = mask; + window_imp->mCursorPosition = window_coord; + }); + return 0; + } - // eat scroll events that occur outside our window, since we use mouse position to direct scroll - // instead of keyboard focus - // NOTE: mouse_coord is in *window* coordinates for scroll events - POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)}; + case WM_GETMINMAXINFO: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_GETMINMAXINFO"); + LPMINMAXINFO min_max = (LPMINMAXINFO)l_param; + min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth; + min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight; + return 0; + } - if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) - && GetClientRect(window_imp->mWindowHandle, &client_rect)) - { - // we have a valid mouse point and client rect - if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x - || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) - { - // mouse is outside of client rect, so don't do anything - return 0; - } - } + case WM_MOVE: + { + window_imp->updateWindowRect(); + return 0; + } + case WM_SIZE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SIZE"); + window_imp->updateWindowRect(); + S32 width = S32(LOWORD(l_param)); + S32 height = S32(HIWORD(l_param)); - S16 incoming_h_delta = HIWORD(w_param); - h_delta += incoming_h_delta; + + if (debug_window_proc) + { + BOOL maximized = (w_param == SIZE_MAXIMIZED); + BOOL restored = (w_param == SIZE_RESTORED); + BOOL minimized = (w_param == SIZE_MINIMIZED); + + LL_INFOS("Window") << "WINDOWPROC Size " + << width << "x" << height + << " max " << S32(maximized) + << " min " << S32(minimized) + << " rest " << S32(restored) + << LL_ENDL; + } - // If the user rapidly spins the wheel, we can get messages with - // large deltas, like 480 or so. Thus we need to scroll more quickly. - if (h_delta <= -WHEEL_DELTA || WHEEL_DELTA <= h_delta) - { - window_imp->mCallbacks->handleScrollHWheel(window_imp, h_delta / WHEEL_DELTA); - h_delta = 0; - } - return 0; - } - // Handle mouse movement within the window - case WM_MOUSEMOVE: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE"); - MASK mask = gKeyboard->currentMask(TRUE); - window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask); - return 0; - } + // There's an odd behavior with WM_SIZE that I would call a bug. If + // the window is maximized, and you call MoveWindow() with a size smaller + // than a maximized window, it ends up sending WM_SIZE with w_param set + // to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work. + // (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see + // LLWindowWin32::moveWindow in this file). - case WM_GETMINMAXINFO: - { - LPMINMAXINFO min_max = (LPMINMAXINFO)l_param; - min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth; - min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight; - return 0; - } + // If we are now restored, but we weren't before, this + // means that the window was un-minimized. + if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, TRUE)); + } - case WM_SIZE: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SIZE"); - S32 width = S32( LOWORD(l_param) ); - S32 height = S32( HIWORD(l_param) ); + // handle case of window being maximized from fully minimized state + if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, TRUE)); + } - if (debug_window_proc) - { - BOOL maximized = ( w_param == SIZE_MAXIMIZED ); - BOOL restored = ( w_param == SIZE_RESTORED ); - BOOL minimized = ( w_param == SIZE_MINIMIZED ); - - LL_INFOS("Window") << "WINDOWPROC Size " - << width << "x" << height - << " max " << S32(maximized) - << " min " << S32(minimized) - << " rest " << S32(restored) - << LL_ENDL; - } + // Also handle the minimization case + if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED) + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleActivate(window_imp, FALSE)); + } - // There's an odd behavior with WM_SIZE that I would call a bug. If - // the window is maximized, and you call MoveWindow() with a size smaller - // than a maximized window, it ends up sending WM_SIZE with w_param set - // to SIZE_MAXIMIZED -- which isn't true. So the logic below doesn't work. - // (SL-44655). Fixed it by calling ShowWindow(SW_RESTORE) first (see - // LLWindowWin32::moveWindow in this file). + // Actually resize all of our views + if (w_param != SIZE_MINIMIZED) + { + // Ignore updates for minimizing and minimized "windows" + WINDOW_IMP_POST(window_imp->mCallbacks->handleResize(window_imp, + LOWORD(l_param), + HIWORD(l_param))); + } - // If we are now restored, but we weren't before, this - // means that the window was un-minimized. - if (w_param == SIZE_RESTORED && window_imp->mLastSizeWParam != SIZE_RESTORED) - { - window_imp->mCallbacks->handleActivate(window_imp, TRUE); - } + window_imp->mLastSizeWParam = w_param; - // handle case of window being maximized from fully minimized state - if (w_param == SIZE_MAXIMIZED && window_imp->mLastSizeWParam != SIZE_MAXIMIZED) - { - window_imp->mCallbacks->handleActivate(window_imp, TRUE); - } + return 0; + } - // Also handle the minimization case - if (w_param == SIZE_MINIMIZED && window_imp->mLastSizeWParam != SIZE_MINIMIZED) - { - window_imp->mCallbacks->handleActivate(window_imp, FALSE); - } + case WM_DPICHANGED: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_DPICHANGED"); + LPRECT lprc_new_scale; + F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI); + lprc_new_scale = (LPRECT)l_param; + S32 new_width = lprc_new_scale->right - lprc_new_scale->left; + S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top; + WINDOW_IMP_POST(window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height)); + + SetWindowPos(h_wnd, + HWND_TOP, + lprc_new_scale->left, + lprc_new_scale->top, + new_width, + new_height, + SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } - // Actually resize all of our views - if (w_param != SIZE_MINIMIZED) - { - // Ignore updates for minimizing and minimized "windows" - window_imp->mCallbacks->handleResize( window_imp, - LOWORD(l_param), - HIWORD(l_param) ); - } + case WM_SETFOCUS: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SETFOCUS"); + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; + } + WINDOW_IMP_POST(window_imp->mCallbacks->handleFocus(window_imp)); + return 0; + } - window_imp->mLastSizeWParam = w_param; + case WM_KILLFOCUS: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_KILLFOCUS"); + if (debug_window_proc) + { + LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; + } + WINDOW_IMP_POST(window_imp->mCallbacks->handleFocusLost(window_imp)); + return 0; + } - return 0; - } + case WM_COPYDATA: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_COPYDATA"); + { + // received a URL + PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT)l_param; + void* data = new U8[myCDS->cbData]; + memcpy(data, myCDS->lpData, myCDS->cbData); + auto myType = myCDS->dwData; + + window_imp->post([=]() + { + window_imp->mCallbacks->handleDataCopy(window_imp, myType, data); + delete[] data; + }); + }; + return 0; + + break; + } + case WM_SETTINGCHANGE: + { + LL_PROFILE_ZONE_NAMED("mwp - WM_SETTINGCHANGE"); + if (w_param == SPI_SETMOUSEVANISH) + { + if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0)) + { + WINDOW_IMP_POST(window_imp->mMouseVanish = TRUE); + } + } + } + break; - case WM_DPICHANGED: - { - LPRECT lprc_new_scale; - F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI); - lprc_new_scale = (LPRECT)l_param; - S32 new_width = lprc_new_scale->right - lprc_new_scale->left; - S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top; - if (window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height)) - { - SetWindowPos(h_wnd, - HWND_TOP, - lprc_new_scale->left, - lprc_new_scale->top, - new_width, - new_height, - SWP_NOZORDER | SWP_NOACTIVATE); - } - return 0; - } - - case WM_SETFOCUS: - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC SetFocus" << LL_ENDL; - } - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_SETFOCUS"); - window_imp->mCallbacks->handleFocus(window_imp); - return 0; - - case WM_KILLFOCUS: - if (debug_window_proc) - { - LL_INFOS("Window") << "WINDOWPROC KillFocus" << LL_ENDL; - } - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KILLFOCUS"); - window_imp->mCallbacks->handleFocusLost(window_imp); - return 0; - - case WM_COPYDATA: - { - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); - // received a URL - PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; - window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); - }; - return 0; + case WM_INPUT: + { + LL_PROFILE_ZONE_NAMED("MWP - WM_INPUT"); + + UINT dwSize = 0; + GetRawInputData((HRAWINPUT)l_param, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + llassert(dwSize < 1024); + + U8 lpb[1024]; + + if (GetRawInputData((HRAWINPUT)l_param, RID_INPUT, (void*)lpb, &dwSize, sizeof(RAWINPUTHEADER)) == dwSize) + { + RAWINPUT* raw = (RAWINPUT*)lpb; + + if (raw->header.dwType == RIM_TYPEMOUSE) + { + LLMutexLock lock(&window_imp->mRawMouseMutex); + window_imp->mRawMouseDelta.mX += raw->data.mouse.lLastX; + window_imp->mRawMouseDelta.mY -= raw->data.mouse.lLastY; + } + } + } - break; + //list of messages we get often that we don't care to log about + case WM_NCHITTEST: + case WM_NCMOUSEMOVE: + case WM_NCMOUSELEAVE: + case WM_MOVING: + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + break; - case WM_SETTINGCHANGE: - { - if (w_param == SPI_SETMOUSEVANISH) - { - if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &window_imp->mMouseVanish, 0)) - { - window_imp->mMouseVanish = TRUE; - } - } - } - break; - default: - { - if (debug_window_proc) - { - LL_INFOS("Window") << "Unhandled windows message code: " << U32(u_msg) << LL_ENDL; - } - } - break; - } - - window_imp->mCallbacks->handlePauseWatchdog(window_imp); - } + default: + { + LL_PROFILE_ZONE_NAMED("mwp - default"); + if (debug_window_proc) + { + LL_INFOS("Window") << "Unhandled windows message code: 0x" << std::hex << U32(u_msg) << LL_ENDL; + } + } + break; + } + } else { // (NULL == window_imp) LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL; } - // pass unhandled messages down to Windows - return DefWindowProc(h_wnd, u_msg, w_param, l_param); + // pass unhandled messages down to Windows + LRESULT ret; + { + LL_PROFILE_ZONE_NAMED("mwp - DefWindowProc"); + ret = DefWindowProc(h_wnd, u_msg, w_param, l_param); + } + return ret; } BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) @@ -3184,6 +3264,8 @@ BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr) // Constrains the mouse to the window. void LLWindowWin32::setMouseClipping( BOOL b ) { + LL_PROFILE_ZONE_SCOPED; + ASSERT_MAIN_THREAD(); if( b != mIsMouseClipping ) { BOOL success = FALSE; @@ -3214,43 +3296,46 @@ void LLWindowWin32::setMouseClipping( BOOL b ) BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) { - BOOL success = FALSE; + BOOL success = FALSE; - RECT client_rect; - if( mWindowHandle && GetClientRect(mWindowHandle, &client_rect) ) - { - POINT top_left; - top_left.x = client_rect.left; - top_left.y = client_rect.top; - ClientToScreen(mWindowHandle, &top_left); - - POINT bottom_right; - bottom_right.x = client_rect.right; - bottom_right.y = client_rect.bottom; - ClientToScreen(mWindowHandle, &bottom_right); - - SetRect( rectp, - top_left.x, - top_left.y, - bottom_right.x, - bottom_right.y ); - - success = TRUE; - } + RECT client_rect; + if (mWindowHandle && GetClientRect(mWindowHandle, &client_rect)) + { + POINT top_left; + top_left.x = client_rect.left; + top_left.y = client_rect.top; + ClientToScreen(mWindowHandle, &top_left); + + POINT bottom_right; + bottom_right.x = client_rect.right; + bottom_right.y = client_rect.bottom; + ClientToScreen(mWindowHandle, &bottom_right); + + SetRect(rectp, + top_left.x, + top_left.y, + bottom_right.x, + bottom_right.y); + + success = TRUE; + } - return success; + return success; } void LLWindowWin32::flashIcon(F32 seconds) { - FLASHWINFO flash_info; - - flash_info.cbSize = sizeof(FLASHWINFO); - flash_info.hwnd = mWindowHandle; - flash_info.dwFlags = FLASHW_TRAY; - flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); - flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds - FlashWindowEx(&flash_info); + mWindowThread->post([=]() + { + FLASHWINFO flash_info; + + flash_info.cbSize = sizeof(FLASHWINFO); + flash_info.hwnd = mWindowHandle; + flash_info.dwFlags = FLASHW_TRAY; + flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); + flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds + FlashWindowEx(&flash_info); + }); } F32 LLWindowWin32::getGamma() @@ -3260,6 +3345,7 @@ F32 LLWindowWin32::getGamma() BOOL LLWindowWin32::restoreGamma() { + ASSERT_MAIN_THREAD(); if (mCustomGammaSet != FALSE) { LL_DEBUGS("Window") << "Restoring gamma" << LL_ENDL; @@ -3271,6 +3357,7 @@ BOOL LLWindowWin32::restoreGamma() BOOL LLWindowWin32::setGamma(const F32 gamma) { + ASSERT_MAIN_THREAD(); mCurrentGamma = gamma; //Get the previous gamma ramp to restore later. @@ -3309,6 +3396,7 @@ BOOL LLWindowWin32::setGamma(const F32 gamma) void LLWindowWin32::setFSAASamples(const U32 fsaa_samples) { + ASSERT_MAIN_THREAD(); mFSAASamples = fsaa_samples; } @@ -3319,6 +3407,7 @@ U32 LLWindowWin32::getFSAASamples() LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_resolutions) { + ASSERT_MAIN_THREAD(); if (!mSupportedResolutions) { mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; @@ -3473,7 +3562,11 @@ BOOL LLWindowWin32::resetDisplayResolution() void LLWindowWin32::swapBuffers() { + LL_PROFILE_ZONE_SCOPED; + ASSERT_MAIN_THREAD(); SwapBuffers(mhDC); + + LL_PROFILER_GPU_COLLECT } @@ -3698,13 +3791,19 @@ void *LLWindowWin32::getPlatformWindow() void LLWindowWin32::bringToFront() { - BringWindowToTop(mWindowHandle); + mWindowThread->post([=]() + { + BringWindowToTop(mWindowHandle); + }); } // set (OS) window focus back to the client void LLWindowWin32::focusClient() { - SetFocus ( mWindowHandle ); + mWindowThread->post([=]() + { + SetFocus(mWindowHandle); + }); } void LLWindowWin32::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) @@ -3946,6 +4045,7 @@ void LLWindowWin32::updateLanguageTextInputArea() void LLWindowWin32::interruptLanguageTextInput() { + ASSERT_MAIN_THREAD(); if (mPreeditor && LLWinImm::isAvailable()) { HIMC himc = LLWinImm::getContext(mWindowHandle); @@ -4148,6 +4248,7 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng // for files and via IDropTarget interface requests. LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ) { + ASSERT_MAIN_THREAD(); return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url ); } @@ -4196,6 +4297,7 @@ BOOL LLWindowWin32::handleImeRequests(WPARAM request, LPARAM param, LRESULT *res LL_WARNS("Window") << "*** IMR_QUERYCHARPOSITON called but getPreeditLocation failed." << LL_ENDL; return FALSE; } + fillCharPosition(caret_coord, preedit_bounds, text_control, char_position); *result = 1; @@ -4403,3 +4505,153 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList() #endif // LL_WINDOWS + +inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() + : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) +{ + ThreadPool::start(); +} + +/** + * LogChange is to log changes in status while trying to avoid spamming the + * log with repeated messages, especially in a tight loop. It refuses to log + * a continuous run of identical messages, but logs every time the message + * changes. (It will happily spam when messages quickly bounce back and + * forth.) + */ +class LogChange +{ +public: + LogChange(const std::string& tag): + mTag(tag) + {} + + template <typename... Items> + void always(Items&&... items) + { + // This odd construct ensures that the stringize() call is only + // executed if DEBUG logging is enabled for the passed tag. + LL_DEBUGS(mTag.c_str()); + log(LL_CONT, stringize(std::forward<Items>(items)...)); + LL_ENDL; + } + + template <typename... Items> + void onChange(Items&&... items) + { + LL_DEBUGS(mTag.c_str()); + auto str = stringize(std::forward<Items>(items)...); + if (str != mPrev) + { + log(LL_CONT, str); + } + LL_ENDL; + } + +private: + void log(std::ostream& out, const std::string& message) + { + mPrev = message; + out << message; + } + std::string mTag; + std::string mPrev; +}; + +void LLWindowWin32::LLWindowWin32Thread::run() +{ + sWindowThreadId = std::this_thread::get_id(); + LogChange logger("Window"); + + while (! getQueue().done()) + { + LL_PROFILE_ZONE_SCOPED; + + if (mWindowHandle != 0) + { + MSG msg; + BOOL status; + if (mhDC == 0) + { + LL_PROFILE_ZONE_NAMED("w32t - PeekMessage"); + logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")"); + status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); + } + else + { + LL_PROFILE_ZONE_NAMED("w32t - GetMessage"); + logger.always("GetMessage(", std::hex, mWindowHandle, ")"); + status = GetMessage(&msg, NULL, 0, 0); + } + if (status > 0) + { + logger.always("got MSG (", std::hex, msg.hwnd, ", ", msg.message, + ", ", msg.wParam, ")"); + TranslateMessage(&msg); + DispatchMessage(&msg); + + mMessageQueue.pushFront(msg); + } + } + + { + LL_PROFILE_ZONE_NAMED("w32t - Function Queue"); + logger.onChange("runPending()"); + //process any pending functions + getQueue().runPending(); + } + +#if 0 + { + LL_PROFILE_ZONE_NAMED("w32t - Sleep"); + logger.always("sleep(1)"); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +#endif + } +} + +void LLWindowWin32::post(const std::function<void()>& func) +{ + mFunctionQueue.pushFront(func); +} + +void LLWindowWin32::postMouseButtonEvent(const std::function<void()>& func) +{ + mMouseQueue.pushFront(func); +} + +void LLWindowWin32::kickWindowThread(HWND windowHandle) +{ + if (! windowHandle) + windowHandle = mWindowHandle; + if (windowHandle) + { + // post a nonsense user message to wake up the Window Thread in + // case any functions are pending and no windows events came + // through this frame + WPARAM wparam{ 0xB0B0 }; + LL_DEBUGS("Window") << "PostMessage(" << std::hex << windowHandle + << ", " << WM_DUMMY_ + << ", " << wparam << ")" << std::dec << LL_ENDL; + PostMessage(windowHandle, WM_DUMMY_, wparam, 0x1337); + } +} + +void LLWindowWin32::updateWindowRect() +{ + LL_PROFILE_ZONE_SCOPED; + //called from window thread + RECT rect; + RECT client_rect; + + if (GetWindowRect(mWindowHandle, &rect) && + GetClientRect(mWindowHandle, &client_rect)) + { + post([=] + { + mRect = rect; + mClientRect = client_rect; + }); + } +} diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 0b3d14fb16..9367f49510 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -33,6 +33,10 @@ #include "llwindow.h" #include "llwindowcallbacks.h" #include "lldragdropwin32.h" +#include "llthread.h" +#include "llthreadsafequeue.h" +#include "llmutex.h" +#include "workqueue.h" // Hack for async host by name #define LL_WM_HOST_RESOLVED (WM_APP + 1) @@ -57,9 +61,15 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL); + /*virtual*/ void setTitle(const std::string title); + void* createSharedContext() override; + void makeContextCurrent(void* context) override; + void destroySharedContext(void* context) override; + /*virtual*/ void toggleVSync(bool enable_vsync); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); + /*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta); /*virtual*/ void showCursor(); /*virtual*/ void hideCursor(); /*virtual*/ void showCursorFromMouseMove(); @@ -123,7 +133,7 @@ public: protected: LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, - BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, + BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples); ~LLWindowWin32(); @@ -172,17 +182,24 @@ protected: WCHAR *mWindowTitle; WCHAR *mWindowClassName; - HWND mWindowHandle; // window handle - HGLRC mhRC; // OpenGL rendering context - HDC mhDC; // Windows Device context handle + HWND mWindowHandle = 0; // window handle + HGLRC mhRC = 0; // OpenGL rendering context + HDC mhDC = 0; // Windows Device context handle HINSTANCE mhInstance; // handle to application instance - WNDPROC mWndProc; // user-installable window proc RECT mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() WPARAM mLastSizeWParam; F32 mOverrideAspectRatio; F32 mNativeAspectRatio; HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors + LLCoordWindow mCursorPosition; // mouse cursor position, should only be mutated on main thread + LLMutex mRawMouseMutex; + RAWINPUTDEVICE mRawMouse; + LLCoordWindow mLastCursorPosition; // mouse cursor position from previous frame + LLCoordCommon mRawMouseDelta; // raw mouse delta according to window thread + LLCoordCommon mMouseFrameDelta; // how much the mouse moved between the last two calls to gatherInput + + MASK mMouseMask; static BOOL sIsClassRegistered; // has the window class been registered? @@ -193,7 +210,6 @@ protected: BOOL mCustomGammaSet; LPWSTR mIconResource; - BOOL mMousePositionModified; BOOL mInputProcessingPaused; // The following variables are for Language Text Input control. @@ -221,6 +237,20 @@ protected: BOOL mMouseVanish; + // Cached values of GetWindowRect and GetClientRect to be used by app thread + void updateWindowRect(); + RECT mRect; + RECT mClientRect; + + struct LLWindowWin32Thread; + LLWindowWin32Thread* mWindowThread = nullptr; + LLThreadSafeQueue<std::function<void()>> mFunctionQueue; + LLThreadSafeQueue<std::function<void()>> mMouseQueue; + void post(const std::function<void()>& func); + void postMouseButtonEvent(const std::function<void()>& func); + void recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw_style); + void kickWindowThread(HWND windowHandle=0); + friend class LLWindowManager; }; diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 19508becc3..088502c017 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -247,6 +247,7 @@ public: // generic getter template<typename T> T get(const std::string& name) { + LL_PROFILE_ZONE_SCOPED; LLControlVariable* control = getControl(name); LLSD value; eControlType type = TYPE_COUNT; @@ -405,8 +406,8 @@ public: const T& default_value, const std::string& comment = "Declared In Code") { - mCachedControlPtr = LLControlCache<T>::getInstance(name); - if (mCachedControlPtr.isNull()) + mCachedControlPtr = LLControlCache<T>::getInstance(name).get(); + if (! mCachedControlPtr) { mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment); } @@ -415,8 +416,8 @@ public: LLCachedControl(LLControlGroup& group, const std::string& name) { - mCachedControlPtr = LLControlCache<T>::getInstance(name); - if (mCachedControlPtr.isNull()) + mCachedControlPtr = LLControlCache<T>::getInstance(name).get(); + if (! mCachedControlPtr) { mCachedControlPtr = new LLControlCache<T>(group, name); } diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index 854ba55731..2acce03d08 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -108,9 +108,6 @@ if (DARWIN) LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" ) - ## turns on C++11 using Cmake - target_compile_features(media_plugin_cef PRIVATE cxx_range_for) - add_custom_command(TARGET media_plugin_cef POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "@executable_path/Chromium Embedded Framework" "@executable_path/../../../../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4bce646bf5..ef7c628c71 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -50,6 +50,7 @@ include(OpenSSL) include(PNG) include(TemplateCheck) include(ThreeJS) +include(Tracy) include(UI) include(UnixInstall) include(ViewerMiscLibs) @@ -95,6 +96,7 @@ include_directories( ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLAPPEARANCE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ${TRACY_INCLUDE_DIR} ) include_directories(SYSTEM @@ -282,7 +284,7 @@ set(viewer_SOURCE_FILES llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloaternotificationstabbed.cpp - llfloateroutfitphotopreview.cpp + llfloateroutfitphotopreview.cpp llfloateroutfitsnapshot.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp @@ -395,7 +397,6 @@ set(viewer_SOURCE_FILES llloginhandler.cpp lllogininstance.cpp llmachineid.cpp - llmainlooprepeater.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp @@ -591,11 +592,8 @@ set(viewer_SOURCE_FILES llsyntaxid.cpp llsyswellitem.cpp llsyswellwindow.cpp - lltelemetry.cpp llteleporthistory.cpp llteleporthistorystorage.cpp - lltextureatlas.cpp - lltextureatlasmanager.cpp lltexturecache.cpp lltexturectrl.cpp lltexturefetch.cpp @@ -1036,7 +1034,6 @@ set(viewer_HEADER_FILES llloginhandler.h lllogininstance.h llmachineid.h - llmainlooprepeater.h llmanip.h llmaniprotate.h llmanipscale.h @@ -1225,8 +1222,6 @@ set(viewer_HEADER_FILES lltable.h llteleporthistory.h llteleporthistorystorage.h - lltextureatlas.h - lltextureatlasmanager.h lltexturecache.h lltexturectrl.h lltexturefetch.h @@ -1386,7 +1381,7 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt" "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\n") set_source_files_properties( - llversioninfo.cpp tests/llversioninfo_test.cpp + llversioninfo.cpp tests/llversioninfo_test.cpp PROPERTIES COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake ) @@ -1608,6 +1603,7 @@ if (WINDOWS) ${WINDOWS_LIBRARIES} comdlg32 dxguid + imm32 kernel32 odbc32 odbccp32 @@ -2004,7 +2000,7 @@ endif (WINDOWS) # one of these being libz where you can find four or more versions in play # at once. On Linux, libz can be found at link and run time via a number # of paths: -# +# # => -lfreetype # => libz.so.1 (on install machine, not build) # => -lSDL @@ -2067,6 +2063,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + ${TRACY_LIBRARY} ) if (USE_BUGSPLAT) @@ -2175,7 +2172,7 @@ if (DARWIN) # https://blog.kitware.com/upcoming-in-cmake-2-8-12-osx-rpath-support/ set(CMAKE_MACOSX_RPATH 1) - + set_target_properties( ${VIEWER_BINARY_NAME} PROPERTIES @@ -2377,7 +2374,7 @@ if (LL_TESTS) llworldmap.cpp llworldmipmap.cpp PROPERTIES - LL_TEST_ADDITIONAL_SOURCE_FILES + LL_TEST_ADDITIONAL_SOURCE_FILES tests/llviewertexture_stub.cpp #llviewertexturelist.cpp ) @@ -2411,7 +2408,7 @@ if (LL_TESTS) llworldmap.cpp llworldmipmap.cpp PROPERTIES - LL_TEST_ADDITIONAL_SOURCE_FILES + LL_TEST_ADDITIONAL_SOURCE_FILES tests/llviewertexture_stub.cpp #llviewertexturelist.cpp LL_TEST_ADDITIONAL_LIBRARIES "${BOOST_SYSTEM_LIBRARY}" diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 5e3ec53ea6..826f5ce030 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.5.2 +6.6.0 diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 4e186292f7..7514913d13 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -217,6 +217,14 @@ <string>NoInventoryLibrary</string> </map> + <key>noninteractive</key> + <map> + <key>desc</key> + <string>Run in semi-headless mode where only login and logout need to work.</string> + <key>map-to</key> + <string>NonInteractive</string> + </map> + <key>nonotifications</key> <map> <key>desc</key> diff --git a/indra/newview/app_settings/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml index 662f7e39dd..f64937f443 100644 --- a/indra/newview/app_settings/high_graphics.xml +++ b/indra/newview/app_settings/high_graphics.xml @@ -6,8 +6,6 @@ <RenderAvatarLODFactor value="1.0"/> <!--Default for now--> <RenderAvatarPhysicsLODFactor value="0.9"/> - <!--NO SHADERS--> - <RenderAvatarVP value="TRUE"/> <!--Short Range--> <RenderFarClip value="128"/> <!--Default for now--> diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml index 0ee8e7a059..b31a040d67 100644 --- a/indra/newview/app_settings/low_graphics.xml +++ b/indra/newview/app_settings/low_graphics.xml @@ -6,8 +6,6 @@ <RenderAvatarLODFactor value="0.5"/> <!--Default for now--> <RenderAvatarPhysicsLODFactor value="0.0"/> - <!--NO SHADERS--> - <RenderAvatarVP value="FALSE"/> <!--Short Range--> <RenderFarClip value="64"/> <!--Default for now--> diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml index c89e060307..9c2c17fc60 100644 --- a/indra/newview/app_settings/mid_graphics.xml +++ b/indra/newview/app_settings/mid_graphics.xml @@ -6,8 +6,6 @@ <RenderAvatarLODFactor value="0.5"/> <!--Default for now--> <RenderAvatarPhysicsLODFactor value="0.75"/> - <!--NO SHADERS--> - <RenderAvatarVP value="TRUE"/> <!--Short Range--> <RenderFarClip value="96"/> <!--Default for now--> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 12f435f931..0ccf74e923 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -812,17 +812,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>FramePerSecondLimit</key> - <map> - <key>Comment</key> - <string>Controls upper limit of frames per second</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>120</integer> - </map> <key>BackgroundYieldTime</key> <map> <key>Comment</key> @@ -3409,10 +3398,10 @@ <key>Value</key> <integer>0</integer> </map> - <key>DisableVerticalSync</key> + <key>RenderVSyncEnable</key> <map> <key>Comment</key> - <string>Update frames as fast as possible (FALSE = update frames between display scans)</string> + <string>Update frames between display scans (FALSE = Update frames as fast as possible).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -3585,7 +3574,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>DoubleClickTeleport</key> + <key>DoubleClickTeleport</key> <map> <key>Comment</key> <string>Enable double-click to teleport where allowed (afects minimap and people panel)</string> @@ -3915,6 +3904,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>MainWorkTime</key> + <map> + <key>Comment</key> + <string>Max time per frame devoted to mainloop work queue (in milliseconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.1</real> + </map> <key>QueueInventoryFetchTimeout</key> <map> <key>Comment</key> @@ -7074,6 +7074,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>NonInteractive</key> + <map> + <key>Comment</key> + <string>Run in a semi-headless mode where only logging in and logging out needs to work.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>NonvisibleObjectsInMemoryTime</key> <map> <key>Comment</key> @@ -8682,28 +8693,6 @@ </array> </map> - <key>RenderAlphaBatchFullbrights</key> - <map> - <key>Comment</key> - <string>Render fullbright alpha content more efficiently, but with possible visual differences from prev viewers.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>RenderAlphaBatchEmissives</key> - <map> - <key>Comment</key> - <string>Render emissive alpha content more efficiently, but with possible visual differences from prev viewers.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>RenderAnisotropic</key> <map> <key>Comment</key> @@ -8884,17 +8873,6 @@ <key>Value</key> <real>1.0</real> </map> - <key>RenderAvatarVP</key> - <map> - <key>Comment</key> - <string>Use vertex programs to perform hardware skinning of avatar</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>RenderCompressTextures</key> <map> <key>Comment</key> @@ -8906,7 +8884,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderHiDPI</key> + <key>RenderHiDPI</key> <map> <key>Comment</key> <string>Enable support for HiDPI displays, like Retina (MacOS X ONLY, requires restart)</string> @@ -9875,6 +9853,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderGLMultiThreaded</key> + <map> + <key>Comment</key> + <string>Allow OpenGL to use multiple render contexts (reduces frame stutters from loading textures, doesn't play nice with Intel drivers).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderGlow</key> <map> <key>Comment</key> @@ -10178,7 +10167,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>512</integer> + <integer>4096</integer> </map> <key>RenderNameFadeDuration</key> <map> @@ -11628,7 +11617,7 @@ <string>Boolean</string> <key>Value</key> <integer>0</integer> - </map> + </map> <key>NearbyListShowMap</key> <map> <key>Comment</key> @@ -12722,6 +12711,20 @@ <key>Value</key> <string /> </map> + <key>ThreadPoolSizes</key> + <map> + <key>Comment</key> + <string>Map of size overrides for specific thread pools.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <map> + <key>General</key> + <integer>4</integer> + </map> + </map> <key>ThrottleBandwidthKBPS</key> <map> <key>Comment</key> @@ -14164,17 +14167,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>RenderSynchronousOcclusion</key> - <map> - <key>Comment</key> - <string>Don't let occlusion queries get more than one frame behind (block until they complete).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>RenderDelayVBUpdate</key> <map> <key>Comment</key> @@ -16692,8 +16684,8 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> - </map> + <integer>1</integer> + </map> <key>360CaptureUseInterestListCap</key> <map> <key>Comment</key> @@ -16773,14 +16765,25 @@ </map> <key>ResetUIScaleOnFirstRun</key> <map> - <key>Comment</key> - <string>Resets the UI scale factor on first run due to changed display scaling behavior</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> + <key>Comment</key> + <string>Resets the UI scale factor on first run due to changed display scaling behavior</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>UpdateAppWindowTitleBar</key> + <map> + <key>Comment</key> + <string>Updates the application window title bar with brief information about user/location</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> </map> </map> </llsd> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index dc484317e9..d3a05c34c0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -86,6 +86,14 @@ float getAmbientClamp(); vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance) { + // SL-14895 inverted attenuation work-around + // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct + // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights() + // to recover the `adjusted_radius` value previously being sent as la. + float falloff_factor = (12.0 * fa) - 9.0; + float inverted_la = falloff_factor / la; + // Yes, it makes me want to cry as well. DJH + vec3 col = vec3(0); //get light vector @@ -95,7 +103,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec float dist = length(lv); float da = 1.0; - /*if (dist > la) + /*if (dist > inverted_la) { return col; } @@ -113,9 +121,9 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec return col; }*/ - if (dist > 0.0 && la > 0.0) + if (dist > 0.0 && inverted_la > 0.0) { - dist /= la; + dist /= inverted_la; //normalize light vector lv = normalize(lv); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 506118d381..6a93bc2fd2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -105,9 +105,9 @@ void main() vec4 vert = vec4(position.xyz, 1.0); pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); -#endif +#endif //IS_AVATAR_SKIN -#endif +#endif // HAS_SKIN #ifdef USE_INDEXED_TEX passTextureIndex(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl index ef49b6f4e8..1b16e4eb09 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl @@ -40,11 +40,11 @@ VARYING vec4 post_pos; VARYING float pos_w; VARYING float target_pos_x; VARYING vec2 vary_texcoord0; -VARYING vec4 vertex_color; +uniform vec4 color; void main() { - float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a; + float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * color.a; if (alpha < 0.05) // treat as totally transparent { diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl index d1d7ece6fe..1c5b142ebd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl @@ -30,7 +30,6 @@ uniform float shadow_target_width; mat4 getSkinnedTransform(); void passTextureIndex(); -ATTRIBUTE vec4 diffuse_color; ATTRIBUTE vec3 position; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; @@ -41,7 +40,6 @@ VARYING vec4 post_pos; VARYING float pos_w; VARYING float target_pos_x; VARYING vec2 vary_texcoord0; -VARYING vec4 vertex_color; void main() { @@ -68,7 +66,6 @@ void main() vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vertex_color = diffuse_color; #if !DEPTH_CLAMP post_pos = pos; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl deleted file mode 100644 index 10144f3e16..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file bumpV.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 texture_matrix0; -uniform mat4 modelview_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec2 texcoord0; -ATTRIBUTE vec4 tangent; - -VARYING vec3 vary_mat0; -VARYING vec3 vary_mat1; -VARYING vec3 vary_mat2; -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - -mat4 getObjectSkinnedTransform(); - -void main() -{ - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - mat4 mat = getObjectSkinnedTransform(); - - mat = modelview_matrix * mat; - - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - - vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); - vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz); - vec3 b = cross(n, t) * tangent.w; - - vary_mat0 = vec3(t.x, b.x, n.x); - vary_mat1 = vec3(t.y, b.y, n.y); - vary_mat2 = vec3(t.z, b.z, n.z); - - gl_Position = projection_matrix*vec4(pos, 1.0); - vertex_color = diffuse_color; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index 9f9749394e..d90891aa20 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -39,16 +39,32 @@ VARYING vec3 vary_mat2; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; +#endif + void main() { //transform vertex +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; + gl_Position = projection_matrix*vec4(pos, 1.0); + + vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); + vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz); +#else gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vec3 n = normalize(normal_matrix * normal); vec3 t = normalize(normal_matrix * tangent.xyz); +#endif + vec3 b = cross(n, t) * tangent.w; - + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + vary_mat0 = vec3(t.x, b.x, n.x); vary_mat1 = vec3(t.y, b.y, n.y); vary_mat2 = vec3(t.z, b.z, n.z); diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 3c026796c8..d64bcefade 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -39,14 +39,28 @@ VARYING vec2 vary_texcoord0; void passTextureIndex(); +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; +#endif + void main() { - //transform vertex +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vec4(position.xyz, 1.0); + gl_Position = projection_matrix * pos; + vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); +#else gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_normal = normalize(normal_matrix * normal); +#endif + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; passTextureIndex(); - vary_normal = normalize(normal_matrix * normal); - + vertex_color = diffuse_color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl index 5e4f08b017..08b1147ab0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl @@ -40,15 +40,26 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif void main() { //transform vertex - vec4 vert = vec4(position.xyz, 1.0); - vec4 pos = (modelview_matrix * vert); passTextureIndex(); - gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + + vec4 pos = mat * vec4(position.xyz, 1.0); + gl_Position = projection_matrix * pos; +#else + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); +#endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl index 8f6eb79668..2c139430e7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl @@ -25,7 +25,6 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; -uniform mat4 texture_matrix1; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; @@ -47,19 +46,32 @@ VARYING vec2 vary_texcoord0; VARYING vec3 vary_texcoord1; VARYING vec4 vary_position; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif + void main() { //transform vertex vec4 vert = vec4(position.xyz,1.0); passTextureIndex(); + +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vert; + vary_position = gl_Position = projection_matrix * pos; + vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); +#else vec4 pos = (modelview_matrix * vert); vary_position = gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); - vec3 norm = normalize(normal_matrix * normal); +#endif vec3 ref = reflect(pos.xyz, -norm); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz; + vary_texcoord1 = transpose(normal_matrix) * ref.xyz; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index bdf3546aa5..e71636f2c9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -45,15 +45,26 @@ VARYING vec3 vary_position; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif void main() { //transform vertex vec4 vert = vec4(position.xyz, 1.0); - vec4 pos = (modelview_matrix * vert); passTextureIndex(); +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vert; + gl_Position = projection_matrix * pos; +#else + vec4 pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +#endif #ifdef WATER_FOG vary_position = pos.xyz; diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index e1f7031af6..02d83925ea 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -91,6 +91,14 @@ float getAmbientClamp(); vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance) { + // SL-14895 inverted attenuation work-around + // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct + // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights() + // to recover the `adjusted_radius` value previously being sent as la. + float falloff_factor = (12.0 * fa) - 9.0; + float inverted_la = falloff_factor / la; + // Yes, it makes me want to cry as well. DJH + vec3 col = vec3(0); //get light vector @@ -100,9 +108,9 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float dist = length(lv); float da = 1.0; - dist /= la; + dist /= inverted_la; - if (dist > 0.0 && la > 0.0) + if (dist > 0.0 && inverted_la > 0.0) { //normalize light vector lv = normalize(lv); diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl index 2487110624..2b17aea75a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl @@ -1,8 +1,9 @@ /** - * @file diffuseSkinnedV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * @file shadowAlphaMaskSkinnedV.glsl + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2007, Linden Research, Inc. + * Copyright (C) 2011, 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,38 +23,48 @@ * $/LicenseInfo$ */ -uniform mat4 projection_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; +uniform mat4 projection_matrix; +uniform float shadow_target_width; ATTRIBUTE vec3 position; ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; -VARYING vec3 vary_normal; +VARYING vec4 post_pos; +VARYING float target_pos_x; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +void passTextureIndex(); + mat4 getObjectSkinnedTransform(); void main() { - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - + //transform vertex + vec4 pre_pos = vec4(position.xyz, 1.0); + mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - vec4 norm = vec4(position.xyz, 1.0); - norm.xyz += normal.xyz; - norm.xyz = (mat*norm).xyz; - norm.xyz = normalize(norm.xyz-pos.xyz); + vec4 pos = mat * pre_pos; + pos = projection_matrix * pos; - vary_normal = norm.xyz; - - vertex_color = diffuse_color; + target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x; + + 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 = projection_matrix*vec4(pos, 1.0); + passTextureIndex(); + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + vertex_color = diffuse_color; } diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl index df31b5a79f..bdf8e0854d 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl @@ -1,6 +1,7 @@ /** - * @file simpleSkinnedV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * @file shadowSkinnedV.glsl + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. * @@ -22,44 +23,30 @@ * $/LicenseInfo$ */ -uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; uniform mat4 projection_matrix; ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; +VARYING vec4 post_pos; - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color); -void calcAtmospherics(vec3 inPositionEye); mat4 getObjectSkinnedTransform(); void main() { //transform vertex - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - vec4 norm = vec4(position.xyz, 1.0); - norm.xyz += normal.xyz; - norm.xyz = (mat*norm).xyz; - norm.xyz = normalize(norm.xyz-pos.xyz); - - calcAtmospherics(pos.xyz); + 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 - vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color); - vertex_color = color; - - gl_Position = projection_matrix*vec4(pos, 1.0); - - } diff --git a/indra/newview/app_settings/shaders/class1/objects/emissiveSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl index 9064904191..d9ca6d3a46 100644 --- a/indra/newview/app_settings/shaders/class1/objects/emissiveSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl @@ -1,7 +1,7 @@ /** - * @file emissiveSkinnedV.glsl + * @file treeShadowV.glsl * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. * @@ -23,34 +23,31 @@ * $/LicenseInfo$ */ -uniform mat4 projection_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; - +uniform mat4 projection_matrix; + ATTRIBUTE vec3 position; -ATTRIBUTE vec4 emissive; ATTRIBUTE vec2 texcoord0; -VARYING vec4 vertex_color; +VARYING vec4 post_pos; VARYING vec2 vary_texcoord0; - -void calcAtmospherics(vec3 inPositionEye); mat4 getObjectSkinnedTransform(); void main() { //transform vertex - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - mat4 mat = getObjectSkinnedTransform(); + mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - vertex_color = emissive; - - calcAtmospherics(pos.xyz); - - gl_Position = projection_matrix*vec4(pos, 1.0); + 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); + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; } diff --git a/indra/newview/app_settings/shaders/class1/interface/debugV.glsl b/indra/newview/app_settings/shaders/class1/interface/debugV.glsl index f4d704577a..153998f1d5 100644 --- a/indra/newview/app_settings/shaders/class1/interface/debugV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/debugV.glsl @@ -27,8 +27,21 @@ uniform mat4 modelview_projection_matrix; ATTRIBUTE vec3 position; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; +#endif + void main() { +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vec4(position.xyz,1.0); + gl_Position = projection_matrix * pos; +#else gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); +#endif } diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl index 9bf7b60eb7..0b362cf46c 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl @@ -31,10 +31,23 @@ ATTRIBUTE vec2 texcoord0; VARYING vec2 vary_texcoord0; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; +#endif + void main() { //transform vertex +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vec4(position.xyz,1.0); + gl_Position = projection_matrix * pos; +#else gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); +#endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; } diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionSkinnedV.glsl index eff75435a9..7305065a05 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionSkinnedV.glsl @@ -1,6 +1,7 @@ /** - * @file fullbrightSkinnedV.glsl - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * @file occlusionSkinnedV.glsl + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. * @@ -23,35 +24,17 @@ */ uniform mat4 projection_matrix; -uniform mat4 texture_matrix0; uniform mat4 modelview_matrix; ATTRIBUTE vec3 position; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; -void calcAtmospherics(vec3 inPositionEye); mat4 getObjectSkinnedTransform(); -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; - - void main() { - //transform vertex - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - mat4 mat = getObjectSkinnedTransform(); - mat = modelview_matrix * mat; vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - calcAtmospherics(pos.xyz); - - vertex_color = diffuse_color; - gl_Position = projection_matrix*vec4(pos, 1.0); - - } + diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl index 5fcdf3107c..89be8195f0 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl @@ -56,5 +56,6 @@ void fullbright_lighting() color.rgb = pow(color.rgb, vec3(1.0/texture_gamma)); frag_color = color; + } diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl index a7738087dc..ee9970bc70 100644 --- a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl @@ -33,10 +33,23 @@ ATTRIBUTE vec2 texcoord1; VARYING vec2 vary_texcoord0; VARYING vec2 vary_texcoord1; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; +#endif + void main() { //transform vertex +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vec4(position.xyz, 1.0); + gl_Position = projection_matrix * pos; +#else gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +#endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; } diff --git a/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl index e984deb0c8..d762239e51 100644 --- a/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl @@ -37,20 +37,30 @@ VARYING vec2 vary_texcoord0; void calcAtmospherics(vec3 inPositionEye); - - +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif void main() { //transform vertex passTextureIndex(); + +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + + vec4 pos = mat * vec4(position.xyz, 1.0); + gl_Position = projection_matrix * pos; +#else gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); +#endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); + calcAtmospherics(pos.xyz); vertex_color = emissive; - - } diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl deleted file mode 100644 index 1e244d9dfd..0000000000 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file shinySimpleSkinnedV.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 texture_matrix0; -uniform mat4 texture_matrix1; -uniform mat4 modelview_matrix; -uniform mat4 projection_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; - -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; -VARYING vec3 vary_texcoord1; -VARYING vec4 vary_position; - - -void calcAtmospherics(vec3 inPositionEye); -mat4 getObjectSkinnedTransform(); - -void main() -{ - mat4 mat = getObjectSkinnedTransform(); - - mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - mat4 mvp = modelview_matrix * projection_matrix; - vary_position = mvp * vec4(position, 1.0); - - vec4 norm = vec4(position.xyz, 1.0); - norm.xyz += normal.xyz; - norm.xyz = (mat*norm).xyz; - norm.xyz = normalize(norm.xyz-pos.xyz); - - vec3 ref = reflect(pos.xyz, -norm.xyz); - - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz; - - calcAtmospherics(pos.xyz); - - vertex_color = diffuse_color; - - gl_Position = projection_matrix*vec4(pos, 1.0); - - -} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl index 34bd8d445a..ace2574ac2 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl @@ -25,7 +25,6 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; -uniform mat4 texture_matrix1; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; @@ -46,20 +45,32 @@ VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; VARYING vec3 vary_texcoord1; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif void main() { //transform vertex vec4 vert = vec4(position.xyz,1.0); passTextureIndex(); + +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vert; + gl_Position = projection_matrix * pos; + vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); +#else vec4 pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); - vec3 norm = normalize(normal_matrix * normal); +#endif vec3 ref = reflect(pos.xyz, -norm); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz; + vary_texcoord1 = transpose(normal_matrix) * ref; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl index fc20d3270e..5af42f1fcf 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl @@ -33,26 +33,33 @@ ATTRIBUTE vec2 texcoord0; ATTRIBUTE vec3 normal; ATTRIBUTE vec4 diffuse_color; - void calcAtmospherics(vec3 inPositionEye); - VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif void main() { //transform vertex vec4 vert = vec4(position.xyz,1.0); passTextureIndex(); - vec4 pos = (modelview_matrix * vert); +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vert; + gl_Position = projection_matrix * pos; +#else + vec4 pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +#endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; calcAtmospherics(pos.xyz); vertex_color = diffuse_color; - - } diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl deleted file mode 100644 index 727bae19c0..0000000000 --- a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file shinySimpleSkinnedV.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 texture_matrix0; -uniform mat4 texture_matrix1; -uniform mat4 modelview_matrix; - -ATTRIBUTE vec3 position; -ATTRIBUTE vec3 normal; -ATTRIBUTE vec4 diffuse_color; -ATTRIBUTE vec2 texcoord0; - -VARYING vec4 vertex_color; -VARYING vec2 vary_texcoord0; -VARYING vec3 vary_texcoord1; - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color); -void calcAtmospherics(vec3 inPositionEye); -mat4 getObjectSkinnedTransform(); - -void main() -{ - mat4 mat = getObjectSkinnedTransform(); - - mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; - - vec4 norm = vec4(position.xyz, 1.0); - norm.xyz += normal.xyz; - norm.xyz = (mat*norm).xyz; - norm.xyz = normalize(norm.xyz-pos.xyz); - - vec3 ref = reflect(pos.xyz, -norm.xyz); - - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz; - - calcAtmospherics(pos.xyz); - - vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color); - vertex_color = color; - - gl_Position = projection_matrix*vec4(pos, 1.0); -} diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl index 4ba8194d03..097e42d233 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl @@ -25,7 +25,6 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; -uniform mat4 texture_matrix1; uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; @@ -45,19 +44,32 @@ void calcAtmospherics(vec3 inPositionEye); uniform vec4 origin; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif + void main() { //transform vertex vec4 vert = vec4(position.xyz,1.0); passTextureIndex(); + +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + vec4 pos = mat * vert; + gl_Position = projection_matrix * pos; + vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); +#else vec4 pos = (modelview_matrix * vert); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); - vec3 norm = normalize(normal_matrix * normal); +#endif vec3 ref = reflect(pos.xyz, -norm); - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz; + vary_texcoord0 = (texture_matrix0*vec4(texcoord0,0,1)).xy; + vary_texcoord1 = transpose(normal_matrix) * ref; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl index 9ef7704b70..2025174f7d 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl @@ -44,12 +44,16 @@ void calcAtmospherics(vec3 inPositionEye); VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +uniform mat4 projection_matrix; +#endif + void main() { //transform vertex vec4 vert = vec4(position.xyz,1.0); - gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); passTextureIndex(); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy; @@ -58,11 +62,23 @@ void main() if (no_atmo == 1) { vertex_color = diffuse_color; + gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); } else { +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; + + vec4 pos = mat * vert; + vec3 norm = normalize((mat*vec4(normal.xyz+vert.xyz,1.0)).xyz-pos.xyz); + + gl_Position = projection_matrix * pos; +#else vec4 pos = (modelview_matrix * vert); vec3 norm = normalize(normal_matrix * normal); + gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +#endif calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml index eb2cd356d9..8462df207b 100644 --- a/indra/newview/app_settings/ultra_graphics.xml +++ b/indra/newview/app_settings/ultra_graphics.xml @@ -6,8 +6,6 @@ <RenderAvatarLODFactor value="1.0"/> <!--Default for now--> <RenderAvatarPhysicsLODFactor value="1.0"/> - <!--NO SHADERS--> - <RenderAvatarVP value="TRUE"/> <!--Short Range--> <RenderFarClip value="256"/> <!--Default for now--> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index f1bf8d76c2..4e56141fde 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 33 +version 34 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -70,37 +70,9 @@ RenderShadowDetail 1 2 RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 +RenderGLCoreProfile 1 1 +RenderGLMultiThreaded 1 1 -// -// Low Graphics Settings (fixed function) -// -list LowFixedFunction -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0 -RenderAvatarPhysicsLODFactor 1 0 -RenderAvatarMaxNonImpostors 1 3 -RenderAvatarMaxComplexity 1 25000 -RenderAvatarVP 1 0 -RenderFarClip 1 64 -RenderFlexTimeFactor 1 0 -RenderGlowResolutionPow 1 8 -RenderLocalLights 1 0 -RenderMaxPartCount 1 0 -RenderObjectBump 1 0 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 0 -RenderTerrainLODFactor 1 1 -RenderTransparentWater 1 0 -RenderTreeLODFactor 1 0 -RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 0 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 -RenderShadowDetail 1 0 -WLSkyDetail 1 48 -RenderFSAASamples 1 0 // // Low Graphics Settings @@ -112,7 +84,6 @@ RenderAvatarLODFactor 1 0 RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxNonImpostors 1 3 RenderAvatarMaxComplexity 1 35000 -RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 @@ -142,7 +113,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 RenderAvatarMaxComplexity 1 100000 RenderAvatarPhysicsLODFactor 1 0.75 -RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 @@ -172,7 +142,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 200000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -202,7 +171,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 250000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -232,7 +200,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 300000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -262,7 +229,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 350000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -291,7 +257,6 @@ RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -316,414 +281,45 @@ RenderFSAASamples 1 2 // Class Unknown Hardware (unknown) // list Unknown -RenderVBOEnable 1 0 RenderShadowDetail 1 0 RenderDeferred 1 0 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 // -// Class 0 Hardware (just old) -// -list Class0 -RenderVBOEnable 1 1 - -// -// Class 1 Hardware -// -list Class1 -RenderVBOEnable 1 1 - -// -// Class 2 Hardware -// -list Class2 -RenderVBOEnable 1 1 - -// -// Class 3 Hardware -// -list Class3 -RenderVBOEnable 1 1 - -// -// Class 4 Hardware -// -list Class4 -RenderVBOEnable 1 1 - -// -// Class 5 Hardware -// -list Class5 -RenderVBOEnable 1 1 - -// // VRAM > 512MB // list VRAMGT512 RenderCompressTextures 1 0 // -// No Pixel Shaders available -// -list NoPixelShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 -RenderUseAdvancedAtmospherics 0 0 - -// -// No Vertex Shaders available -// -list NoVertexShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderShadowDetail 0 0 -RenderUseAdvancedAtmospherics 0 0 - -// -// GL_ARB_map_buffer_range exists -// -list MapBufferRange -RenderVBOMappingDisable 1 1 - - -// // "Default" setups for safe, low, medium, high // list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 -RenderAvatarVP 0 0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 80000 RenderObjectBump 0 0 RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 RenderDeferredSSAO 0 0 RenderShadowDetail 0 0 -// -// CPU based feature masks -// - -// 1Ghz or less (equiv) -list CPUSlow -RenderMaxPartCount 1 1024 - -// -// RAM based feature masks -// -list RAM256MB -RenderObjectBump 0 0 - -// -// Graphics card based feature masks -// -list OpenGLPre15 -RenderVBOEnable 1 0 - -list OpenGLPre30 -RenderDeferred 0 0 -RenderMaxTextureIndex 1 1 - list Intel RenderAnisotropic 1 0 -RenderVBOEnable 1 0 RenderFSAASamples 1 0 +RenderGLMultiThreaded 1 0 +RenderGLCoreProfile 1 0 -list GeForce2 -RenderAnisotropic 1 0 -RenderMaxPartCount 1 2048 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 1 - -list SiS -UseOcclusion 0 0 - - -list Intel_830M -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_845G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_855GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_865G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_900 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_915GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_915G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_950 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_965 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -UseOcclusion 0 0 - -list Intel_G33 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_G45 -WindLightUseAtmosShaders 0 0 - -list Intel_Bear_Lake -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Broadwater -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Brookdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Eaglelake -WindLightUseAtmosShaders 0 0 - -list Intel_Montara -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Springdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - - -list ATI_FireGL_5200 -RenderVBOEnable 1 0 -WindLightUseAtmosShaders 0 0 - - -list ATI_Mobility_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_Radeon -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_7500 -RenderVBOEnable 0 0 - -list ATI_Mobility_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - - -/// tweaked ATI to 96 Draw distance - -list ATI_Radeon_9000 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9200 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9500 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - -/// tweaked ATI to 128 draw distance - -list ATI_Radeon_X300 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X400 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X500 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X600 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X700 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1300 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1400 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1500 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1600 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Radeon_X1700 -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 -list ATI_Mobility_Radeon_X1xxx -Disregard128DefaultDrawDistance 1 0 -RenderVBOEnable 1 0 - -list ATI_Radeon_HD_2300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2400 -Disregard128DefaultDrawDistance 1 0 -list ATI_ASUS_AH24xx -Disregard128DefaultDrawDistance 1 0 - - -// Avatar hardware skinning causes invisible avatars -// on various ATI chipsets on drivers before 8.2 - -list ATIOldDriver -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderVBOEnable 1 0 - -// ATI cards generally perform better when not using VBOs for streaming data - -list ATI +// AMD cards generally perform better when not using VBOs for streaming data +// AMD cards also prefer an OpenGL Compatibility Profile Context +list AMD RenderUseStreamVBO 1 0 +RenderGLCoreProfile 1 0 -// Disable vertex buffer objects by default for ATI cards with little video memory -list ATIVramLT256 -RenderVBOEnable 1 0 - -/// Tweaked NVIDIA - -list NVIDIA_GeForce_FX_5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_FX_Go5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5300 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_6100 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6500 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6600 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_G73 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_Go_6100 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6200 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6500 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6600 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6700 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6800 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_7000 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7100 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7500 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7900 -RenderShaderLightingMaxLevel 1 2 - -list NVIDIA_GeForce_Go_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300_LE -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7900 -RenderShaderLightingMaxLevel 1 2 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index bac6fd5708..13ede23a91 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 37 +version 38 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -70,37 +70,8 @@ RenderShadowDetail 1 2 RenderUseStreamVBO 1 1 RenderFSAASamples 1 16 RenderMaxTextureIndex 1 16 - -// -// Low Graphics Settings (fixed function) -// -list LowFixedFunction -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0 -RenderAvatarPhysicsLODFactor 1 0 -RenderAvatarMaxNonImpostors 1 3 -RenderAvatarMaxComplexity 1 25000 -RenderAvatarVP 1 0 -RenderFarClip 1 64 -RenderFlexTimeFactor 1 0 -RenderGlowResolutionPow 1 8 -RenderLocalLights 1 0 -RenderMaxPartCount 1 0 -RenderObjectBump 1 0 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 0 -RenderTerrainLODFactor 1 1 -RenderTransparentWater 1 0 -RenderTreeLODFactor 1 0 -RenderVolumeLODFactor 1 0.5 -WindLightUseAtmosShaders 1 0 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 -RenderShadowDetail 1 0 -WLSkyDetail 1 48 -RenderFSAASamples 1 0 +RenderGLCoreProfile 1 0 +RenderGLMultiThreaded 1 0 // // Low Graphics Settings @@ -112,7 +83,6 @@ RenderAvatarLODFactor 1 0 RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxNonImpostors 1 3 RenderAvatarMaxComplexity 1 35000 -RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 @@ -142,7 +112,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 RenderAvatarMaxComplexity 1 100000 RenderAvatarPhysicsLODFactor 1 0.75 -RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 @@ -172,7 +141,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 200000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -202,7 +170,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 250000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -232,7 +199,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 300000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -262,7 +228,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 350000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -291,7 +256,6 @@ RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -316,73 +280,11 @@ RenderFSAASamples 1 2 // Class Unknown Hardware (unknown) // list Unknown -RenderVBOEnable 1 0 RenderShadowDetail 1 0 RenderDeferred 1 0 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 -// -// Class 0 Hardware (just old) -// -list Class0 -RenderVBOEnable 1 1 - -// -// Class 1 Hardware -// -list Class1 -RenderVBOEnable 1 1 - -// -// Class 2 Hardware -// -list Class2 -RenderVBOEnable 1 1 - -// -// Class 3 Hardware -// -list Class3 -RenderVBOEnable 1 1 - -// -// Class 4 Hardware -// -list Class4 -RenderVBOEnable 1 1 - -// -// Class 5 Hardware -// -list Class5 -RenderVBOEnable 1 1 - -// -// No Pixel Shaders available -// -list NoPixelShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderUseAdvancedAtmospherics 0 0 -RenderShadowDetail 0 0 - -// -// No Vertex Shaders available -// -list NoVertexShaders -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderUseAdvancedAtmospherics 0 0 -RenderShadowDetail 0 0 // // VRAM > 512MB @@ -396,14 +298,12 @@ RenderCompressTextures 1 0 list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 -RenderAvatarVP 0 0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 80000 RenderObjectBump 0 0 RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 @@ -411,31 +311,10 @@ RenderDeferredSSAO 0 0 RenderUseAdvancedAtmospherics 0 0 RenderShadowDetail 0 0 -// -// CPU based feature masks -// - -// 1Ghz or less (equiv) -list CPUSlow -RenderMaxPartCount 1 1024 - -// -// RAM based feature masks -// -list RAM256MB -RenderObjectBump 0 0 - -// -// Graphics card based feature masks -// -list OpenGLPre15 -RenderVBOEnable 1 0 - - list TexUnit8orLess RenderDeferredSSAO 0 0 -list ATI +list AMD RenderDeferredSSAO 1 0 list Intel @@ -443,195 +322,6 @@ RenderAnisotropic 1 0 RenderLocalLights 1 0 RenderFSAASamples 1 0 -list GeForce2 -RenderAnisotropic 1 0 -RenderLocalLights 1 0 -RenderMaxPartCount 1 2048 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 1 - -list Intel_830M -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_845G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_855GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_865G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_900 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_915GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_915G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_950 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderGround 1 0 - -list Intel_965 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -UseOcclusion 0 0 - -list Intel_G33 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Bear_Lake -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Broadwater -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Brookdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_X3100 -WindLightUseAtmosShaders 0 0 - -list Intel_Montara -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Springdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list ATI_Mobility_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_8600 -RenderTextureMemoryMultiple 1 1 -UseOcclusion 0 0 - -/// tweaked ATI to 96 Draw distance - -list ATI_Radeon_9000 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9200 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9500 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - -/// tweaked ATI to 128 draw distance - -list ATI_Radeon_X300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X400 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X500 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X600 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X700 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1400 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1500 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1600 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1700 -Disregard128DefaultDrawDistance 1 0 -list ATI_Mobility_Radeon_X1xxx -Disregard128DefaultDrawDistance 1 0 - -/// Tweaked NVIDIA - -list NVIDIA_GeForce_FX_5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5500 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_FX_Go5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5300 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_6100 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6500 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6600 -Disregard128DefaultDrawDistance 1 0 - - -list NVIDIA_GeForce_Go_6100 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6200 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6500 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6600 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6700 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6800 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_7200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_7300 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_7400 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_Go_7200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_7300 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_7400 -Disregard128DefaultDrawDistance 1 0 - list OSX_10_6_8 RenderDeferred 0 0 diff --git a/indra/newview/installers/darwin/apple-notarize.sh b/indra/newview/installers/darwin/apple-notarize.sh index 466898ecda..e019437924 100755 --- a/indra/newview/installers/darwin/apple-notarize.sh +++ b/indra/newview/installers/darwin/apple-notarize.sh @@ -16,8 +16,9 @@ if [ -f "$CONFIG_FILE" ]; then --password $PASSWORD \ --asc-provider $ASC_PROVIDER \ --file "$zip_file" 2>&1) + echo $res + requestUUID=$(echo $res | awk '/RequestUUID/ { print $NF; }') - echo "Apple Notarization RequestUUID: $requestUUID" if [[ -n $requestUUID ]]; then diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 50e0d1d935..de382d4e23 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1481,7 +1481,7 @@ void LLAgent::resetControlFlags() //----------------------------------------------------------------------------- void LLAgent::setAFK() { - if (!gAgent.getRegion()) + if (gNonInteractive || !gAgent.getRegion()) { // Don't set AFK if we're not talking to a region yet. return; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c9d852686e..89e0da3ea7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -91,7 +91,6 @@ #include "llsdutil_math.h" #include "lllocationhistory.h" #include "llfasttimerview.h" -#include "lltelemetry.h" #include "llvector4a.h" #include "llviewermenufile.h" #include "llvoicechannel.h" @@ -233,11 +232,12 @@ #include "llavatariconctrl.h" #include "llgroupiconctrl.h" #include "llviewerassetstats.h" +#include "workqueue.h" +using namespace LL; // Include for security api initialization #include "llsecapi.h" #include "llmachineid.h" -#include "llmainlooprepeater.h" #include "llcleanup.h" #include "llcoproceduremanager.h" @@ -363,6 +363,10 @@ BOOL gLogoutInProgress = FALSE; BOOL gSimulateMemLeak = FALSE; +// We don't want anyone, especially threads working on the graphics pipeline, +// to have to block due to this WorkQueue being full. +WorkQueue gMainloopWork("mainloop", 1024*1024); + //////////////////////////////////////////////////////////// // Internal globals... that should be removed. static std::string gArgs; @@ -378,42 +382,6 @@ static std::string gLaunchFileOnQuit; // Used on Win32 for other apps to identify our window (eg, win_setup) const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; -//-- LLDeferredTaskList ------------------------------------------------------ - -/** - * A list of deferred tasks. - * - * We sometimes need to defer execution of some code until the viewer gets idle, - * e.g. removing an inventory item from within notifyObservers() may not work out. - * - * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration. - * All tasks are executed only once. - */ -class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList> -{ - LLSINGLETON_EMPTY_CTOR(LLDeferredTaskList); - LOG_CLASS(LLDeferredTaskList); - - friend class LLAppViewer; - typedef boost::signals2::signal<void()> signal_t; - - void addTask(const signal_t::slot_type& cb) - { - mSignal.connect(cb); - } - - void run() - { - if (!mSignal.empty()) - { - mSignal(); - mSignal.disconnect_all_slots(); - } - } - - signal_t mSignal; -}; - //---------------------------------------------------------------------------- // List of entries from strings.xml to always replace @@ -598,14 +566,14 @@ static void settings_to_globals() static void settings_modify() { - LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); - LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - LLPipeline::sRenderDeferred = LLPipeline::sRenderTransparentWater && LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred"); - LLRenderTarget::sUseFBO = LLPipeline::sRenderDeferred && gSavedSettings.getBOOL("RenderAvatarVP"); - LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor"); - LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] - gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; - gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); + LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); + LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred"); + LLRenderTarget::sUseFBO = LLPipeline::sRenderDeferred; + LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor"); + LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; // square lod factor to get exponential range of [1,4] + gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; + gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); } class LLFastTimerLogThread : public LLThread @@ -686,8 +654,7 @@ LLAppViewer::LLAppViewer() mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)), mFastTimerLogThread(NULL), mSettingsLocationList(NULL), - mIsFirstRun(false), - mMinMicroSecPerFrame(0.f) + mIsFirstRun(false) { if(NULL != sInstance) { @@ -856,8 +823,6 @@ bool LLAppViewer::init() LLNotifications::instance(); LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; - writeSystemInfo(); - ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -964,8 +929,8 @@ bool LLAppViewer::init() } LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; - // Initialize the repeater service. - LLMainLoopRepeater::instance().start(); + // Initialize event recorder + LLViewerEventRecorder::createInstance(); // // Initialize the window @@ -974,6 +939,9 @@ bool LLAppViewer::init() initWindow(); LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ; + // writeSystemInfo can be called after window is initialized (gViewerWindow non-null) + writeSystemInfo(); + // initWindow also initializes the Feature List, so now we can initialize this global. LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); @@ -998,19 +966,6 @@ bool LLAppViewer::init() return 0; } - // If we don't have the right shader requirements. - if (!gGLManager.mHasShaderObjects - || !gGLManager.mHasVertexShader - || !gGLManager.mHasFragmentShader) - { - LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedShaderRequirements"); - OSMessageBox( - details.getString(), - LLStringUtil::null, - OSMB_OK); - return 0; - } - // Without SSE2 support we will crash almost immediately, warn here. if (!gSysCPU.hasSSE2()) { @@ -1136,7 +1091,7 @@ bool LLAppViewer::init() { url = LLTrans::getString("NvidiaDriverPage"); } - else if (gGLManager.mIsATI) + else if (gGLManager.mIsAMD) { url = LLTrans::getString("AMDDriverPage"); } @@ -1321,13 +1276,16 @@ bool LLAppViewer::init() joystick = LLViewerJoystick::getInstance(); joystick->setNeedsReset(true); /*----------------------------------------------------------------------*/ - - gSavedSettings.getControl("FramePerSecondLimit")->getSignal()->connect(boost::bind(&LLAppViewer::onChangeFrameLimit, this, _2)); - onChangeFrameLimit(gSavedSettings.getLLSD("FramePerSecondLimit")); - // Load User's bindings loadKeyBindings(); + //LLSimpleton creations + LLEnvironment::createInstance(); + LLEnvironment::getInstance()->initSingleton(); + LLWorld::createInstance(); + LLSelectMgr::createInstance(); + LLViewerCamera::createInstance(); + #if LL_WINDOWS if (!mSecondInstance) { @@ -1360,7 +1318,8 @@ void LLAppViewer::initMaxHeapSize() } static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages"); -static LLTrace::BlockTimerStatHandle FTM_SLEEP("Sleep"); +static LLTrace::BlockTimerStatHandle FTM_SLEEP1("Sleep1"); +static LLTrace::BlockTimerStatHandle FTM_SLEEP2("Sleep2"); static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield"); static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache"); @@ -1421,13 +1380,26 @@ bool LLAppViewer::frame() bool LLAppViewer::doFrame() { + LL_RECORD_BLOCK_TIME(FTM_FRAME); + + if (!LLWorld::instanceExists()) + { + LLWorld::createInstance(); + } + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); LLSD newFrame; - LL_RECORD_BLOCK_TIME(FTM_FRAME); + { + LL_PROFILE_ZONE_NAMED("df LLTrace"); + if (LLFloaterReg::instanceVisible("block_timers")) + { LLTrace::BlockTimer::processTimes(); + } + LLTrace::get_frame_recording().nextPeriod(); LLTrace::BlockTimer::logStats(); + } LLTrace::get_thread_recorder()->pullFromChildren(); @@ -1435,6 +1407,7 @@ bool LLAppViewer::doFrame() LL_CLEAR_CALLSTACKS(); { + LL_PROFILE_ZONE_NAMED( "df processMiscNativeEvents" ) pingMainloopTimeout("Main:MiscNativeWindowEvents"); if (gViewerWindow) @@ -1443,7 +1416,10 @@ bool LLAppViewer::doFrame() gViewerWindow->getWindow()->processMiscNativeEvents(); } + { + LL_PROFILE_ZONE_NAMED( "df gatherInput" ) pingMainloopTimeout("Main:GatherInput"); + } if (gViewerWindow) { @@ -1467,13 +1443,21 @@ bool LLAppViewer::doFrame() } } + { + LL_PROFILE_ZONE_NAMED( "df mainloop" ) // canonical per-frame event mainloop.post(newFrame); + } + + { + LL_PROFILE_ZONE_NAMED( "df suspend" ) // give listeners a chance to run llcoro::suspend(); + } if (!LLApp::isExiting()) { + LL_PROFILE_ZONE_NAMED( "df JoystickKeyboard" ) pingMainloopTimeout("Main:JoystickKeyboard"); // Scan keyboard for movement keys. Command keys and typing @@ -1494,13 +1478,19 @@ bool LLAppViewer::doFrame() // Update state based on messages, user input, object idle. { + { + LL_PROFILE_ZONE_NAMED( "df pauseMainloopTimeout" ) pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! + } LL_RECORD_BLOCK_TIME(FTM_IDLE); idle(); + { + LL_PROFILE_ZONE_NAMED( "df resumeMainloopTimeout" ) resumeMainloopTimeout(); } + } if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) { @@ -1520,49 +1510,51 @@ bool LLAppViewer::doFrame() // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow) { + LL_PROFILE_ZONE_NAMED( "df Display" ) pingMainloopTimeout("Main:Display"); gGLActive = TRUE; display(); - static U64 last_call = 0; - if (!gTeleportDisplay) { - // Frame/draw throttling, controlled by FramePerSecondLimit - U64 elapsed_time = LLTimer::getTotalTime() - last_call; - if (elapsed_time < mMinMicroSecPerFrame) - { - LL_RECORD_BLOCK_TIME(FTM_SLEEP); - // llclamp for when time function gets funky - U64 sleep_time = llclamp(mMinMicroSecPerFrame - elapsed_time, (U64)1, (U64)1e6); - micro_sleep(sleep_time, 0); - } - } - last_call = LLTimer::getTotalTime(); - + LL_PROFILE_ZONE_NAMED( "df Snapshot" ) pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots LLFloaterOutfitSnapshot::update(); gGLActive = FALSE; } } + } + { + LL_PROFILE_ZONE_NAMED( "df pauseMainloopTimeout" ) pingMainloopTimeout("Main:Sleep"); pauseMainloopTimeout(); + } // Sleep and run background threads { - LL_RECORD_BLOCK_TIME(FTM_SLEEP); + //LL_RECORD_BLOCK_TIME(SLEEP2); + LL_PROFILE_ZONE_WARN( "Sleep2" ) // yield some time to the os based on command line option static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1); if(yield_time >= 0) { LL_RECORD_BLOCK_TIME(FTM_YIELD); + LL_PROFILE_ZONE_NUM( yield_time ) ms_sleep(yield_time); } + if (gNonInteractive) + { + S32 non_interactive_ms_sleep_time = 100; + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); + ms_sleep(non_interactive_ms_sleep_time); + } + // yield cooperatively when not running as foreground window // and when not quiting (causes trouble at mac's cleanup stage) if (!LLApp::isExiting() @@ -1570,8 +1562,8 @@ bool LLAppViewer::doFrame() || !gFocusMgr.getAppHasFocus())) { // Sleep if we're not rendering, or the window is minimized. - static LLCachedControl<S32> s_bacground_yeild_time(gSavedSettings, "BackgroundYieldTime", 40); - S32 milliseconds_to_sleep = llclamp((S32)s_bacground_yeild_time, 0, 1000); + static LLCachedControl<S32> s_background_yield_time(gSavedSettings, "BackgroundYieldTime", 40); + S32 milliseconds_to_sleep = llclamp((S32)s_background_yield_time, 0, 1000); // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads // of equal priority on Windows if (milliseconds_to_sleep > 0) @@ -1618,22 +1610,29 @@ bool LLAppViewer::doFrame() total_io_pending += io_pending ; } + + { + LL_PROFILE_ZONE_NAMED( "df gMeshRepo" ) gMeshRepo.update() ; + } if(!total_work_pending) //pause texture fetching threads if nothing to process. { + LL_PROFILE_ZONE_NAMED( "df getTextureCache" ) LLAppViewer::getTextureCache()->pause(); LLAppViewer::getImageDecodeThread()->pause(); LLAppViewer::getTextureFetch()->pause(); } if(!total_io_pending) //pause file threads if nothing to process. { + LL_PROFILE_ZONE_NAMED( "df LLVFSThread" ) LLLFSThread::sLocal->pause(); } //texture fetching debugger if(LLTextureFetchDebugger::isEnabled()) { + LL_PROFILE_ZONE_NAMED( "df tex_fetch_debugger_instance" ) LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); if(tex_fetch_debugger_instance) @@ -1642,8 +1641,10 @@ bool LLAppViewer::doFrame() } } + { + LL_PROFILE_ZONE_NAMED( "df resumeMainloopTimeout" ) resumeMainloopTimeout(); - + } pingMainloopTimeout("Main:End"); } } @@ -1669,7 +1670,7 @@ bool LLAppViewer::doFrame() LL_INFOS() << "Exiting main_loop" << LL_ENDL; } - LLPROFILE_UPDATE(); + LL_PROFILER_FRAME_END return ! LLApp::isRunning(); } @@ -1708,6 +1709,11 @@ void LLAppViewer::flushLFSIO() bool LLAppViewer::cleanup() { + // Since we don't know what functions are going to be queued by + // onCleanup(), we have to assume they might rely on some of the things + // we're about to destroy below. Run them first. + mOnCleanup(); + LLAtmosphere::cleanupClass(); //ditch LLVOAvatarSelf instance @@ -1754,6 +1760,7 @@ bool LLAppViewer::cleanup() LLPluginProcessParent::shutdown(); disconnectViewer(); + LLViewerCamera::deleteSingleton(); LL_INFOS() << "Viewer disconnected" << LL_ENDL; @@ -1947,7 +1954,7 @@ bool LLAppViewer::cleanup() if (LLEnvironment::instanceExists()) { - //Store environment settings if nessesary + //Store environment settings if necessary LLEnvironment::getInstance()->saveToSettings(); } @@ -2138,12 +2145,14 @@ bool LLAppViewer::cleanup() SUBSYSTEM_CLEANUP(LLProxy); LLCore::LLHttp::cleanup(); - LLMainLoopRepeater::instance().stop(); - ll_close_fail_log(); LLError::LLCallStacks::cleanup(); + LLEnvironment::deleteSingleton(); + LLSelectMgr::deleteSingleton(); + LLViewerEventRecorder::deleteSingleton(); + // It's not at first obvious where, in this long sequence, a generic cleanup // call OUGHT to go. So let's say this: as we migrate cleanup from // explicit hand-placed calls into the generic mechanism, eventually @@ -2326,7 +2335,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name() << " - from location " << location_key << LL_ENDL; - LLControlGroup* settings_group = LLControlGroup::getInstance(file.name); + auto settings_group = LLControlGroup::getInstance(file.name); if(!settings_group) { LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL; @@ -2421,6 +2430,38 @@ namespace } } // anonymous namespace +// Set a named control temporarily for this session, as when set via the command line --set option. +// Name can be specified as "<control_group>.<control_name>", with default group being Global. +bool tempSetControl(const std::string& name, const std::string& value) +{ + std::string name_part; + std::string group_part; + LLControlVariable* control = NULL; + + // Name can be further split into ControlGroup.Name, with the default control group being Global + size_t pos = name.find('.'); + if (pos != std::string::npos) + { + group_part = name.substr(0, pos); + name_part = name.substr(pos+1); + LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL; + auto g = LLControlGroup::getInstance(group_part); + if (g) control = g->getControl(name_part); + } + else + { + LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL; + control = gSavedSettings.getControl(name); + } + + if (control) + { + control->setValue(value, false); + return true; + } + return false; +} + bool LLAppViewer::initConfiguration() { //Load settings files list @@ -2471,12 +2512,7 @@ bool LLAppViewer::initConfiguration() #ifndef LL_RELEASE_FOR_DOWNLOAD // provide developer build only overrides for these control variables that are not // persisted to settings.xml - LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow"); - if (c) - { - c->setValue(true, false); - } - c = gSavedSettings.getControl("AllowMultipleViewers"); + LLControlVariable* c = gSavedSettings.getControl("AllowMultipleViewers"); if (c) { c->setValue(true, false); @@ -2582,9 +2618,10 @@ bool LLAppViewer::initConfiguration() disableCrashlogger(); } + gNonInteractive = gSavedSettings.getBOOL("NonInteractive"); // Handle initialization from settings. // Start up the debugging console before handling other options. - if (gSavedSettings.getBOOL("ShowConsoleWindow")) + if (gSavedSettings.getBOOL("ShowConsoleWindow") && !gNonInteractive) { initConsole(); } @@ -2617,31 +2654,7 @@ bool LLAppViewer::initConfiguration() { const std::string& name = *itr; const std::string& value = *(++itr); - std::string name_part; - std::string group_part; - LLControlVariable* control = NULL; - - // Name can be further split into ControlGroup.Name, with the default control group being Global - size_t pos = name.find('.'); - if (pos != std::string::npos) - { - group_part = name.substr(0, pos); - name_part = name.substr(pos+1); - LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL; - LLControlGroup* g = LLControlGroup::getInstance(group_part); - if (g) control = g->getControl(name_part); - } - else - { - LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL; - control = gSavedSettings.getControl(name); - } - - if (control) - { - control->setValue(value, false); - } - else + if (!tempSetControl(name,value)) { LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL; } @@ -2729,6 +2742,19 @@ bool LLAppViewer::initConfiguration() } } + if (gNonInteractive) + { + tempSetControl("AllowMultipleViewers", "TRUE"); + tempSetControl("SLURLPassToOtherInstance", "FALSE"); + tempSetControl("RenderWater", "FALSE"); + tempSetControl("FlyingAtExit", "FALSE"); + tempSetControl("WindowWidth", "1024"); + tempSetControl("WindowHeight", "200"); + LLError::setEnabledLogTypesMask(0); + llassert_always(!gSavedSettings.getBOOL("SLURLPassToOtherInstance")); + } + + // Handle slurl use. NOTE: Don't let SL-55321 reappear. // This initial-SLURL logic, up through the call to // sendURLToOtherInstance(), must precede LLSplashScreen::show() -- @@ -3505,11 +3531,14 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); + if (gViewerWindow) + { std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList(); for (auto res_iter : resolutions) { gDebugInfo["DisplayInfo"].append(res_iter); } + } writeDebugInfo(); // Save out debug_info.log early, in case of crash. } @@ -4251,12 +4280,12 @@ bool LLAppViewer::initCache() { if (mPurgeCache) { - LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); - purgeCache(); + LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); + purgeCache(); // clear the new C++ file system based cache LLDiskCache::getInstance()->clearCache(); - } + } else { // purge excessive files from the new file system based cache @@ -4283,12 +4312,12 @@ bool LLAppViewer::initCache() LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); - return true; + return true; } void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb) { - LLDeferredTaskList::instance().addTask(cb); + gMainloopWork.post(cb); } void LLAppViewer::loadKeyBindings() @@ -4690,6 +4719,20 @@ void LLAppViewer::idle() LLDirPickerThread::clearDead(); F32 dt_raw = idle_timer.getElapsedTimeAndResetF32(); + // Service the WorkQueue we use for replies from worker threads. + // Use function statics for the timeslice setting so we only have to fetch + // and convert MainWorkTime once. + static F32 MainWorkTimeRaw = gSavedSettings.getF32("MainWorkTime"); + static F32Milliseconds MainWorkTimeMs(MainWorkTimeRaw); + // MainWorkTime is specified in fractional milliseconds, but std::chrono + // uses integer representations. What if we want less than a microsecond? + // Use nanoseconds. We're very sure we will never need to specify a + // MainWorkTime that would be larger than we could express in + // std::chrono::nanoseconds. + static std::chrono::nanoseconds MainWorkTimeNanoSec{ + std::chrono::nanoseconds::rep(MainWorkTimeMs.value() * 1000000)}; + gMainloopWork.runFor(MainWorkTimeNanoSec); + // Cap out-of-control frame times // Too low because in menus, swapping, debugger, etc. // Too high because idle called with no objects in view, etc. @@ -5062,9 +5105,6 @@ void LLAppViewer::idle() } } - // Execute deferred tasks. - LLDeferredTaskList::instance().run(); - // Handle shutdown process, for example, // wait for floaters to close, send quit message, // forcibly quit if it has taken too long @@ -5471,19 +5511,6 @@ void LLAppViewer::disconnectViewer() LLUrlEntryParcel::setDisconnected(gDisconnected); } -bool LLAppViewer::onChangeFrameLimit(LLSD const & evt) -{ - if (evt.asInteger() > 0) - { - mMinMicroSecPerFrame = (U64)(1000000.0f / F32(evt.asInteger())); - } - else - { - mMinMicroSecPerFrame = 0; - } - return false; -} - void LLAppViewer::forceErrorLLError() { LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 0f06889d20..d807cf9765 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -50,6 +50,8 @@ #include "lltimer.h" #include "llappcorehttp.h" +#include <boost/signals2.hpp> + class LLCommandLineParser; class LLFrameTimer; class LLPumpIO; @@ -69,13 +71,13 @@ public: LLAppViewer(); virtual ~LLAppViewer(); - /** - * @brief Access to the LLAppViewer singleton. - * - * The LLAppViewer singleton is created in main()/WinMain(). - * So don't use it in pre-entry (static initialization) code. - */ - static LLAppViewer* instance() {return sInstance; } + /** + * @brief Access to the LLAppViewer singleton. + * + * The LLAppViewer singleton is created in main()/WinMain(). + * So don't use it in pre-entry (static initialization) code. + */ + static LLAppViewer* instance() {return sInstance; } // // Main application logic @@ -93,12 +95,12 @@ public: void earlyExit(const std::string& name, const LLSD& substitutions = LLSD()); // Display an error dialog and forcibly quit. void earlyExitNoNotify(); // Do not display error dialog then forcibly quit. - void abortQuit(); // Called to abort a quit request. + void abortQuit(); // Called to abort a quit request. - bool quitRequested() { return mQuitRequested; } - bool logoutRequestSent() { return mLogoutRequestSent; } + bool quitRequested() { return mQuitRequested; } + bool logoutRequestSent() { return mLogoutRequestSent; } bool isSecondInstance() { return mSecondInstance; } - bool isUpdaterMissing() { return mUpdaterNotFound; } + bool isUpdaterMissing() { return mUpdaterNotFound; } void writeDebugInfo(bool isStatic=true); @@ -112,7 +114,7 @@ public: virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. - void checkForCrash(); + void checkForCrash(); // Thread accessors static LLTextureCache* getTextureCache() { return sTextureCache; } @@ -124,37 +126,37 @@ public: static U32 getObjectCacheVersion() ; const std::string& getSerialNumber() { return mSerialNumber; } - + bool getPurgeCache() const { return mPurgeCache; } - + std::string getSecondLifeTitle() const; // The Second Life title. std::string getWindowTitle() const; // The window display name. - void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user. - void badNetworkHandler(); // Cause a crash state due to bad network packet. + void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user. + void badNetworkHandler(); // Cause a crash state due to bad network packet. bool hasSavedFinalSnapshot() { return mSavedFinalSnapshot; } void saveFinalSnapshot(); - void loadNameCache(); - void saveNameCache(); + void loadNameCache(); + void saveNameCache(); void loadExperienceCache(); void saveExperienceCache(); void removeMarkerFiles(); - + void removeDumpDir(); - // LLAppViewer testing helpers. - // *NOTE: These will potentially crash the viewer. Only for debugging. - virtual void forceErrorLLError(); - virtual void forceErrorBreakpoint(); - virtual void forceErrorBadMemoryAccess(); - virtual void forceErrorInfiniteLoop(); - virtual void forceErrorSoftwareException(); - virtual void forceErrorDriverCrash(); - virtual void forceErrorCoroutineCrash(); - virtual void forceErrorThreadCrash(); + // LLAppViewer testing helpers. + // *NOTE: These will potentially crash the viewer. Only for debugging. + virtual void forceErrorLLError(); + virtual void forceErrorBreakpoint(); + virtual void forceErrorBadMemoryAccess(); + virtual void forceErrorInfiniteLoop(); + virtual void forceErrorSoftwareException(); + virtual void forceErrorDriverCrash(); + virtual void forceErrorCoroutineCrash(); + virtual void forceErrorThreadCrash(); // The list is found in app_settings/settings_files.xml // but since they are used explicitly in code, @@ -187,22 +189,32 @@ public: // *NOTE:Mani Fix this for login abstraction!! void handleLoginComplete(); - LLAllocator & getAllocator() { return mAlloc; } + LLAllocator & getAllocator() { return mAlloc; } // On LoginCompleted callback typedef boost::signals2::signal<void (void)> login_completed_signal_t; login_completed_signal_t mOnLoginCompleted; - boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); } + boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) + { + return mOnLoginCompleted.connect(cb); + } void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle + typedef boost::signals2::signal<void()> cleanup_signal_t; + cleanup_signal_t mOnCleanup; + boost::signals2::connection onCleanup(const cleanup_signal_t::slot_type& cb) + { + return mOnCleanup.connect(cb); + } + void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; } void purgeCache(); // Clear the local cache. void purgeCacheImmediate(); //clear local cache immediately. S32 updateTextureThreads(F32 max_time); void loadKeyBindings(); - + // mute/unmute the system's master audio virtual void setMasterSystemAudioMute(bool mute); virtual bool getMasterSystemAudioMute(); @@ -214,7 +226,7 @@ public: // llcorehttp init/shutdown/config information. LLAppCoreHttp & getAppCoreHttp() { return mAppCoreHttp; } - void updateNameLookupUrl(const LLViewerRegion* regionp); + void updateNameLookupUrl(const LLViewerRegion* regionp); protected: virtual bool initWindow(); // Initialize the viewer's window. @@ -225,7 +237,7 @@ protected: virtual bool sendURLToOtherInstance(const std::string& url); virtual bool initParseCommandLine(LLCommandLineParser& clp) - { return true; } // Allow platforms to specify the command line args. + { return true; } // Allow platforms to specify the command line args. virtual std::string generateSerialNumber() = 0; // Platforms specific classes generate this. @@ -253,24 +265,22 @@ private: void processMarkerFiles(); static void recordMarkerVersion(LLAPRFile& marker_file); bool markerIsSameVersion(const std::string& marker_name) const; - - void idle(); - void idleShutdown(); + + void idle(); + void idleShutdown(); // update avatar SLID and display name caches void idleExperienceCache(); void idleNameCache(); - void idleNetwork(); - - void sendLogoutRequest(); - void disconnectViewer(); + void idleNetwork(); - bool onChangeFrameLimit(LLSD const & evt); + void sendLogoutRequest(); + void disconnectViewer(); // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. static LLAppViewer* sInstance; - bool mSecondInstance; // Is this a second instance of the app? + bool mSecondInstance; // Is this a second instance of the app? bool mUpdaterNotFound; // True when attempt to start updater failed std::string mMarkerFileName; @@ -302,8 +312,8 @@ private: boost::optional<U32> mForceGraphicsLevel; - bool mQuitRequested; // User wants to quit, may have modified documents open. - bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim. + bool mQuitRequested; // User wants to quit, may have modified documents open. + bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim. U32 mLastAgentControlFlags; F32 mLastAgentForceUpdate; struct SettingsFiles* mSettingsLocationList; @@ -317,15 +327,12 @@ private: bool mAgentRegionLastAlive; LLUUID mAgentRegionLastID; - LLAllocator mAlloc; + LLAllocator mAlloc; // llcorehttp library init/shutdown helper LLAppCoreHttp mAppCoreHttp; - bool mIsFirstRun; - U64 mMinMicroSecPerFrame; // frame throttling - - + bool mIsFirstRun; }; // consts from viewer.h diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index ee533875b6..a39ec7f51b 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -329,6 +329,11 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, PWSTR pCmdLine, int nCmdShow) { + // Call Tracy first thing to have it allocate memory + // https://github.com/wolfpld/tracy/issues/196 + LL_PROFILER_FRAME_END; + LL_PROFILER_SET_THREAD_NAME("App"); + const S32 MAX_HEAPS = 255; DWORD heap_enable_lfh_error[MAX_HEAPS]; S32 num_heaps = 0; diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 0460bff1b4..30ac35fff7 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -43,14 +43,14 @@ LLBrowserNotification::LLBrowserNotification() bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification) { LLUUID media_id = notification->getPayload()["media_id"].asUUID(); - LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id); + auto media_instance = LLMediaCtrl::getInstance(media_id); if (media_instance) { media_instance->showNotification(notification); } else if (LLViewerMediaFocus::instance().getControlsMediaID() == media_id) { - LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(media_id); + auto impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(media_id); if (impl) { impl->showNotification(notification); diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 6d20b23e9f..9ee9900eba 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -257,7 +257,6 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) LLAvatarName av_name; LLAvatarNameCache::get(agent_id, &av_name); - addChangedMask(LLFriendObserver::ADD, agent_id); LL_DEBUGS() << "Added buddy " << agent_id << ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline") << ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo() @@ -493,6 +492,7 @@ void LLAvatarTracker::notifyObservers() // new masks and ids will be processed later from idle. return; } + LL_PROFILE_ZONE_SCOPED mIsNotifyObservers = TRUE; observer_list_t observers(mObservers); @@ -678,6 +678,7 @@ void LLAvatarTracker::processChangeUserRights(LLMessageSystem* msg, void**) void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) { + LL_PROFILE_ZONE_SCOPED S32 count = msg->getNumberOfBlocksFast(_PREHASH_AgentBlock); BOOL chat_notify = gSavedSettings.getBOOL("ChatOnlineNotification"); @@ -712,8 +713,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) // we were tracking someone who went offline deleteTrackingData(); } - // *TODO: get actual inventory id - gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null); } if(chat_notify) { diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index fab249f988..4a87273372 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -241,7 +241,7 @@ void LLControlAvatar::matchVolumeTransform() if (skin_info) { LL_DEBUGS("BindShape") << getFullname() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL; - bind_rot = LLSkinningUtil::getUnscaledQuaternion(skin_info->mBindShapeMatrix); + bind_rot = LLSkinningUtil::getUnscaledQuaternion(LLMatrix4(skin_info->mBindShapeMatrix)); } #endif setRotation(bind_rot*obj_rot); @@ -299,7 +299,6 @@ void LLControlAvatar::updateVolumeGeom() mRootVolp->mDrawable->makeActive(); gPipeline.markMoved(mRootVolp->mDrawable); gPipeline.markTextured(mRootVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD - mRootVolp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); @@ -308,7 +307,6 @@ void LLControlAvatar::updateVolumeGeom() LLViewerObject* childp = *iter; if (childp && childp->mDrawable.notNull()) { - childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD gPipeline.markMoved(childp->mDrawable); } diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index cb5f9c8a2c..7d4961c598 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -96,11 +96,9 @@ void LLDoNotDisturbNotificationStorage::resetDirty() mDirty = false; } -static LLTrace::BlockTimerStatHandle FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications"); - void LLDoNotDisturbNotificationStorage::saveNotifications() { - LL_RECORD_BLOCK_TIME(FTM_SAVE_DND_NOTIFICATIONS); + LL_PROFILE_ZONE_SCOPED; LLNotificationChannelPtr channelPtr = getCommunicationChannel(); const LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get()); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 507af56cb0..b274fd56b6 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -58,8 +58,6 @@ const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f; const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; const F32 OBJECT_DAMPING_TIME_CONSTANT = 0.06f; -static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound"); - extern bool gShiftFrame; @@ -93,7 +91,6 @@ void LLDrawable::incrementVisible() LLDrawable::LLDrawable(LLViewerObject *vobj, bool new_entry) : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLDRAWABLE), - LLTrace::MemTrackable<LLDrawable, 16>("LLDrawable"), mVObjp(vobj) { init(new_entry); @@ -101,6 +98,8 @@ LLDrawable::LLDrawable(LLViewerObject *vobj, bool new_entry) void LLDrawable::init(bool new_entry) { + LL_PROFILE_ZONE_SCOPED + // mXform mParent = NULL; mRenderType = 0; @@ -150,21 +149,6 @@ void LLDrawable::unload() { LLVOVolume *pVVol = getVOVolume(); pVVol->setNoLOD(); - - for (S32 i = 0; i < getNumFaces(); i++) - { - LLFace* facep = getFace(i); - if (facep->isState(LLFace::RIGGED)) - { - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool(); - if (pool) { - pool->removeRiggedFace(facep); - } - facep->setVertexBuffer(NULL); - } - facep->clearState(LLFace::RIGGED); - } - pVVol->markForUpdate(TRUE); } @@ -261,19 +245,13 @@ BOOL LLDrawable::isLight() const } } -static LLTrace::BlockTimerStatHandle FTM_CLEANUP_DRAWABLE("Cleanup Drawable"); -static LLTrace::BlockTimerStatHandle FTM_DEREF_DRAWABLE("Deref"); -static LLTrace::BlockTimerStatHandle FTM_DELETE_FACES("Faces"); - void LLDrawable::cleanupReferences() { - LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLE); + LL_PROFILE_ZONE_SCOPED; - { - LL_RECORD_BLOCK_TIME(FTM_DELETE_FACES); - std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); - mFaces.clear(); - } + + std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); + mFaces.clear(); gObjectList.removeDrawable(this); @@ -281,12 +259,9 @@ void LLDrawable::cleanupReferences() removeFromOctree(); - { - LL_RECORD_BLOCK_TIME(FTM_DEREF_DRAWABLE); - // Cleanup references to other objects - mVObjp = NULL; - mParent = NULL; - } + // Cleanup references to other objects + mVObjp = NULL; + mParent = NULL; } void LLDrawable::removeFromOctree() @@ -331,14 +306,12 @@ S32 LLDrawable::findReferences(LLDrawable *drawablep) return count; } -static LLTrace::BlockTimerStatHandle FTM_ALLOCATE_FACE("Allocate Face"); - LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerTexture *texturep) { + LL_PROFILE_ZONE_SCOPED LLFace *face; { - LL_RECORD_BLOCK_TIME(FTM_ALLOCATE_FACE); face = new LLFace(this, mVObjp); } @@ -363,13 +336,12 @@ LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerTexture *texturep) LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep) { - LLFace *face; + LL_PROFILE_ZONE_SCOPED - { - LL_RECORD_BLOCK_TIME(FTM_ALLOCATE_FACE); - face = new LLFace(this, mVObjp); - } + LLFace *face; + face = new LLFace(this, mVObjp); + face->setTEOffset(mFaces.size()); face->setTexture(texturep); face->setPoolType(gPipeline.getPoolTypeFromTE(te, texturep)); @@ -387,6 +359,8 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep) LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp) { + LL_PROFILE_ZONE_SCOPED + LLFace *face; face = new LLFace(this, mVObjp); @@ -408,6 +382,8 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp, LLViewerTexture *specularp) { + LL_PROFILE_ZONE_SCOPED + LLFace *face; face = new LLFace(this, mVObjp); @@ -430,6 +406,8 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep, void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerTexture *texturep) { + LL_PROFILE_ZONE_SCOPED + if (newFaces == (S32)mFaces.size()) { return; @@ -453,6 +431,8 @@ void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerText void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewerTexture *texturep) { + LL_PROFILE_ZONE_SCOPED + if (newFaces <= (S32)mFaces.size() && newFaces >= (S32)mFaces.size()/2) { return; @@ -476,6 +456,8 @@ void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewer void LLDrawable::mergeFaces(LLDrawable* src) { + LL_PROFILE_ZONE_SCOPED + U32 face_count = mFaces.size() + src->mFaces.size(); mFaces.reserve(face_count); @@ -509,6 +491,8 @@ void LLDrawable::updateMaterial() void LLDrawable::makeActive() { + LL_PROFILE_ZONE_SCOPED + #if !LL_RELEASE_FOR_DOWNLOAD if (mVObjp.notNull()) { @@ -572,6 +556,8 @@ void LLDrawable::makeActive() void LLDrawable::makeStatic(BOOL warning_enabled) { + LL_PROFILE_ZONE_SCOPED + if (isState(ACTIVE) && !isState(ACTIVE_CHILD) && !mVObjp->isAttachment() && @@ -618,6 +604,8 @@ void LLDrawable::makeStatic(BOOL warning_enabled) // Returns "distance" between target destination and resulting xfrom F32 LLDrawable::updateXform(BOOL undamped) { + LL_PROFILE_ZONE_SCOPED + BOOL damped = !undamped; // Position @@ -769,6 +757,8 @@ void LLDrawable::moveUpdatePipeline(BOOL moved) void LLDrawable::movePartition() { + LL_PROFILE_ZONE_SCOPED + LLSpatialPartition* part = getSpatialPartition(); if (part) { @@ -813,6 +803,8 @@ BOOL LLDrawable::updateMoveUndamped() void LLDrawable::updatePartition() { + LL_PROFILE_ZONE_SCOPED + if (!getVOVolume()) { movePartition(); @@ -830,6 +822,8 @@ void LLDrawable::updatePartition() BOOL LLDrawable::updateMoveDamped() { + LL_PROFILE_ZONE_SCOPED + F32 dist_squared = updateXform(FALSE); mGeneration++; @@ -853,6 +847,8 @@ BOOL LLDrawable::updateMoveDamped() void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { + LL_PROFILE_ZONE_SCOPED + if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) { LL_WARNS() << "Attempted to update distance for non-world camera." << LL_ENDL; @@ -957,6 +953,8 @@ void LLDrawable::updateTexture() BOOL LLDrawable::updateGeometry(BOOL priority) { + LL_PROFILE_ZONE_SCOPED + llassert(mVObjp.notNull()); BOOL res = mVObjp->updateGeometry(this); return res; @@ -1034,6 +1032,8 @@ const LLVector3& LLDrawable::getBounds(LLVector3& min, LLVector3& max) const void LLDrawable::updateSpatialExtents() { + LL_PROFILE_ZONE_SCOPED + if (mVObjp) { const LLVector4a* exts = getSpatialExtents(); @@ -1162,19 +1162,26 @@ void LLDrawable::setGroup(LLViewerOctreeGroup *groupp) LLViewerOctreeEntryData::setGroup(groupp); } +/* +* Get the SpatialPartition this Drawable should use. +* Checks current SpatialPartition assignment and corrects if it is invalid. +*/ LLSpatialPartition* LLDrawable::getSpatialPartition() { + LL_PROFILE_ZONE_SCOPED + LLSpatialPartition* retval = NULL; - + if (!mVObjp || !getVOVolume() || isStatic()) { - retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp); + retval = gPipeline.getSpatialPartition((LLViewerObject*)mVObjp); } else if (isRoot()) { - if (mSpatialBridge) + // determine if the spatial bridge has changed + if (mSpatialBridge) { U32 partition_type = mSpatialBridge->asPartition()->mPartitionType; bool is_hud = mVObjp->isHUDAttachment(); @@ -1191,14 +1198,14 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() { // Was/became part of animesh // remove obsolete bridge - mSpatialBridge->markDead(); + mSpatialBridge->markDead(); setSpatialBridge(NULL); } else if ((partition_type == LLViewerRegion::PARTITION_AVATAR) != is_attachment) { // Was/became part of avatar // remove obsolete bridge - mSpatialBridge->markDead(); + mSpatialBridge->markDead(); setSpatialBridge(NULL); } } @@ -1209,17 +1216,20 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() { setSpatialBridge(new LLHUDBridge(this, getRegion())); } - else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) - { - setSpatialBridge(new LLControlAVBridge(this, getRegion())); - } + else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) + { + setSpatialBridge(new LLControlAVBridge(this, getRegion())); + } // check HUD first, because HUD is also attachment else if (mVObjp->isAttachment()) { + // Attachment + // Use AvatarBridge of root object in attachment linkset setSpatialBridge(new LLAvatarBridge(this, getRegion())); } else { + // Moving linkset, use VolumeBridge of root object in linkset setSpatialBridge(new LLVolumeBridge(this, getRegion())); } } @@ -1247,6 +1257,8 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 dat LLDrawable(root->getVObj(), true), LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB, regionp) { + LL_PROFILE_ZONE_SCOPED + mBridge = this; mDrawable = root; root->setSpatialBridge(this); @@ -1292,12 +1304,11 @@ void LLSpatialBridge::destroyTree() void LLSpatialBridge::updateSpatialExtents() { + LL_PROFILE_ZONE_SCOPED + LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); - { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); - root->rebound(); - } + root->rebound(); const LLVector4a* root_bounds = root->getBounds(); LLVector4a offset; @@ -1392,10 +1403,21 @@ LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) ret.setOrigin(delta); ret.setAxes(lookAt, left_axis, up_axis); - + return ret; } +void LLSpatialBridge::transformExtents(const LLVector4a* src, LLVector4a* dst) +{ + LLMatrix4 mat = mDrawable->getXform()->getWorldMatrix(); + mat.invert(); + + LLMatrix4a world_to_bridge(mat); + + matMulBoundBox(world_to_bridge, src, dst); +} + + void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select) { LLViewerOctreeEntryData::setVisible(); @@ -1455,6 +1477,8 @@ public: void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results, BOOL for_select) { + LL_PROFILE_ZONE_SCOPED + if (!gPipeline.hasRenderType(mDrawableType)) { return; @@ -1552,6 +1576,8 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) { + LL_PROFILE_ZONE_SCOPED + if (mDrawable == NULL) { markDead(); @@ -1723,6 +1749,17 @@ void LLDrawable::updateFaceSize(S32 idx) } } +LLDrawable* LLDrawable::getRoot() +{ + LLDrawable* ret = this; + while (!ret->isRoot()) + { + ret = ret->getParent(); + } + + return ret; +} + LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp) : LLSpatialPartition(0, FALSE, 0, regionp) { diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 14d782d6f2..2372ea01a6 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -59,14 +59,15 @@ const U32 SILHOUETTE_HIGHLIGHT = 0; // All data for new renderer goes into this class. LL_ALIGN_PREFIX(16) -class LLDrawable -: public LLViewerOctreeEntryData, - public LLTrace::MemTrackable<LLDrawable, 16> +class LLDrawable + : public LLViewerOctreeEntryData { + LL_ALIGN_NEW; public: + typedef std::vector<LLFace*> face_list_t; + LLDrawable(const LLDrawable& rhs) - : LLTrace::MemTrackable<LLDrawable, 16>("LLDrawable"), - LLViewerOctreeEntryData(rhs) + : LLViewerOctreeEntryData(rhs) { *this = rhs; } @@ -120,6 +121,7 @@ public: BOOL isAvatar() const { return mVObjp.notNull() && mVObjp->isAvatar(); } BOOL isRoot() const { return !mParent || mParent->isAvatar(); } + LLDrawable* getRoot(); BOOL isSpatialRoot() const { return !mParent || mParent->isAvatar(); } virtual BOOL isSpatialBridge() const { return FALSE; } virtual LLSpatialPartition* asPartition() { return NULL; } @@ -130,6 +132,7 @@ public: inline LLFace* getFace(const S32 i) const; inline S32 getNumFaces() const; + face_list_t& getFaces() { return mFaces; } //void removeFace(const S32 i); // SJB: Avoid using this, it's slow LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep); @@ -253,38 +256,34 @@ public: { IN_REBUILD_Q1 = 0x00000001, IN_REBUILD_Q2 = 0x00000002, - IN_LIGHT_Q = 0x00000004, - EARLY_MOVE = 0x00000008, - MOVE_UNDAMPED = 0x00000010, - ON_MOVE_LIST = 0x00000020, - USE_BACKLIGHT = 0x00000040, - UV = 0x00000080, - UNLIT = 0x00000100, - LIGHT = 0x00000200, - LIGHTING_BUILT = 0x00000400, - REBUILD_VOLUME = 0x00000800, //volume changed LOD or parameters, or vertex buffer changed - REBUILD_TCOORD = 0x00001000, //texture coordinates changed - REBUILD_COLOR = 0x00002000, //color changed - REBUILD_POSITION= 0x00004000, //vertex positions/normals changed + EARLY_MOVE = 0x00000004, + MOVE_UNDAMPED = 0x00000008, + ON_MOVE_LIST = 0x00000010, + UV = 0x00000020, + UNLIT = 0x00000040, + LIGHT = 0x00000080, + REBUILD_VOLUME = 0x00000100, //volume changed LOD or parameters, or vertex buffer changed + REBUILD_TCOORD = 0x00000200, //texture coordinates changed + REBUILD_COLOR = 0x00000400, //color changed + REBUILD_POSITION= 0x00000800, //vertex positions/normals changed REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR, REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR, REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME, - REBUILD_RIGGED = 0x00008000, - ON_SHIFT_LIST = 0x00010000, - BLOCKER = 0x00020000, - ACTIVE = 0x00040000, - DEAD = 0x00080000, - INVISIBLE = 0x00100000, // stay invisible until flag is cleared - NEARBY_LIGHT = 0x00200000, // In gPipeline.mNearbyLightSet - BUILT = 0x00400000, - FORCE_INVISIBLE = 0x00800000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) - REBUILD_SHADOW = 0x02000000, - HAS_ALPHA = 0x04000000, - RIGGED = 0x08000000, - PARTITION_MOVE = 0x10000000, - ANIMATED_CHILD = 0x20000000, - ACTIVE_CHILD = 0x40000000, - FOR_UNLOAD = 0x80000000, //should be unload from memory + REBUILD_RIGGED = 0x00001000, + ON_SHIFT_LIST = 0x00002000, + ACTIVE = 0x00004000, + DEAD = 0x00008000, + INVISIBLE = 0x00010000, // stay invisible until flag is cleared + NEARBY_LIGHT = 0x00020000, // In gPipeline.mNearbyLightSet + BUILT = 0x00040000, + FORCE_INVISIBLE = 0x00080000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) + HAS_ALPHA = 0x00100000, + RIGGED = 0x00200000, //has a rigged face + RIGGED_CHILD = 0x00400000, //has a child with a rigged face + PARTITION_MOVE = 0x00800000, + ANIMATED_CHILD = 0x01000000, + ACTIVE_CHILD = 0x02000000, + FOR_UNLOAD = 0x04000000, //should be unload from memory } EDrawableFlags; public: @@ -298,8 +297,6 @@ public: static F32 sCurPixelAngle; //current pixels per radian private: - typedef std::vector<LLFace*> face_list_t; - U32 mState; S32 mRenderType; LLPointer<LLViewerObject> mVObjp; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index d583a692f9..503ee6d08d 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -50,6 +50,9 @@ #include "lldrawpoolwlsky.h" #include "llglslshader.h" #include "llglcommonfunc.h" +#include "llvoavatar.h" +#include "llviewershadermgr.h" + S32 LLDrawPool::sNumDrawPools = 0; @@ -385,25 +388,48 @@ LLRenderPass::~LLRenderPass() } void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) -{ +{ + LL_PROFILE_ZONE_SCOPED; LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo *pparams = *k; - if (pparams) { + if (pparams) + { pushBatch(*pparams, mask, texture); } } } -void LLRenderPass::renderTexture(U32 type, U32 mask, BOOL batch_textures) +void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) { - pushBatches(type, mask, true, batch_textures); + LL_PROFILE_ZONE_SCOPED; + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + mask |= LLVertexBuffer::MAP_WEIGHT4; + + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo* pparams = *k; + if (pparams) + { + if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) + { + uploadMatrixPalette(*pparams); + lastAvatar = pparams->mAvatar; + lastMeshId = pparams->mSkinInfo->mHash; + } + + pushBatch(*pparams, mask, texture); + } + } } void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { + LL_PROFILE_ZONE_SCOPED; for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; @@ -414,27 +440,74 @@ void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_text } } +void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) +{ + LL_PROFILE_ZONE_SCOPED; + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + mask |= LLVertexBuffer::MAP_WEIGHT4; + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + { + LLDrawInfo* pparams = *i; + if (pparams) + { + if (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; for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { - if (LLGLSLShader::sCurBoundShaderPtr) - { - LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, pparams->mAlphaMaskCutoff); - } - + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); pushBatch(*pparams, mask, texture, batch_textures); } } } +void LLRenderPass::pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) +{ + LL_PROFILE_ZONE_SCOPED; + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + { + LLDrawInfo* pparams = *i; + if (pparams) + { + 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); + } + } +} + void LLRenderPass::applyModelMatrix(const LLDrawInfo& params) { if (params.mModelMatrix != gGLLastMatrix) @@ -452,6 +525,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params) void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { + LL_PROFILE_ZONE_SCOPED; if (!params.mCount) { return; @@ -469,7 +543,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba { if (params.mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); } } } @@ -477,8 +551,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba { //not batching textures or batch has only 1 texture -- might need a texture matrix if (params.mTexture.notNull()) { - params.mTexture->addTextureStats(params.mVSize); - gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + gGL.getTexUnit(0)->bindFast(params.mTexture); if (params.mTextureMatrix) { tex_setup = true; @@ -490,24 +563,20 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); } } } - if (params.mVertexBuffer.notNull()) - { - if (params.mGroup) - { - params.mGroup->rebuildMesh(); - } + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); - - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - } + LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); + + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); if (tex_setup) { @@ -517,7 +586,30 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba } } -void LLRenderPass::renderGroups(U32 type, U32 mask, BOOL texture) +// static +bool LLRenderPass::uploadMatrixPalette(LLDrawInfo& params) { - gPipeline.renderGroups(this, type, mask, texture); + // upload matrix palette to shader + return uploadMatrixPalette(params.mAvatar, params.mSkinInfo); } + +//static +bool LLRenderPass::uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo) +{ + const LLVOAvatar::MatrixPaletteCache& mpc = avatar->updateSkinInfoMatrixPalette(skinInfo); + U32 count = mpc.mMatrixPalette.size(); + + if (count == 0) + { + //skin info not loaded yet, don't render + return false; + } + + LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)&(mpc.mGLMp[0])); + + return true; +} + diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index ecd9bd034f..d4f30fc51a 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -37,6 +37,8 @@ class LLViewerTexture; class LLViewerFetchedTexture; class LLSpatialGroup; class LLDrawInfo; +class LLVOAvatar; +class LLMeshSkinInfo; class LLDrawPool { @@ -125,38 +127,68 @@ protected: class LLRenderPass : public LLDrawPool { public: + // list of possible LLRenderPass types to assign a render batch to + // NOTE: "rigged" variant MUST be non-rigged variant + 1 enum { PASS_SIMPLE = NUM_POOL_TYPES, + PASS_SIMPLE_RIGGED, PASS_GRASS, PASS_FULLBRIGHT, + PASS_FULLBRIGHT_RIGGED, PASS_INVISIBLE, - PASS_INVISI_SHINY, + PASS_INVISIBLE_RIGGED, + PASS_INVISI_SHINY, + PASS_INVISI_SHINY_RIGGED, PASS_FULLBRIGHT_SHINY, + PASS_FULLBRIGHT_SHINY_RIGGED, PASS_SHINY, + PASS_SHINY_RIGGED, PASS_BUMP, + PASS_BUMP_RIGGED, PASS_POST_BUMP, + PASS_POST_BUMP_RIGGED, PASS_MATERIAL, + PASS_MATERIAL_RIGGED, PASS_MATERIAL_ALPHA, + PASS_MATERIAL_ALPHA_RIGGED, PASS_MATERIAL_ALPHA_MASK, // Diffuse texture used as alpha mask + PASS_MATERIAL_ALPHA_MASK_RIGGED, PASS_MATERIAL_ALPHA_EMISSIVE, + PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, PASS_SPECMAP, + PASS_SPECMAP_RIGGED, PASS_SPECMAP_BLEND, + PASS_SPECMAP_BLEND_RIGGED, PASS_SPECMAP_MASK, // Diffuse texture used as alpha mask and specular texture(map) + PASS_SPECMAP_MASK_RIGGED, PASS_SPECMAP_EMISSIVE, + PASS_SPECMAP_EMISSIVE_RIGGED, PASS_NORMMAP, + PASS_NORMMAP_RIGGED, PASS_NORMMAP_BLEND, + PASS_NORMMAP_BLEND_RIGGED, PASS_NORMMAP_MASK, // Diffuse texture used as alpha mask and normal map + PASS_NORMMAP_MASK_RIGGED, PASS_NORMMAP_EMISSIVE, + PASS_NORMMAP_EMISSIVE_RIGGED, PASS_NORMSPEC, - PASS_NORMSPEC_BLEND, + PASS_NORMSPEC_RIGGED, + PASS_NORMSPEC_BLEND, + PASS_NORMSPEC_BLEND_RIGGED, PASS_NORMSPEC_MASK, // Diffuse texture used as alpha mask with normal and specular map + PASS_NORMSPEC_MASK_RIGGED, PASS_NORMSPEC_EMISSIVE, + PASS_NORMSPEC_EMISSIVE_RIGGED, PASS_GLOW, + PASS_GLOW_RIGGED, PASS_ALPHA, PASS_ALPHA_MASK, + PASS_ALPHA_MASK_RIGGED, PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright + PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, PASS_ALPHA_INVISIBLE, + PASS_ALPHA_INVISIBLE_RIGGED, NUM_RENDER_TYPES, }; @@ -169,12 +201,14 @@ public: static void applyModelMatrix(const LLDrawInfo& params); virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); + virtual void pushRiggedBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); virtual void pushMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); + virtual void pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); + static bool uploadMatrixPalette(LLDrawInfo& params); + static bool uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo); virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); - virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE); - virtual void renderTexture(U32 type, U32 mask, BOOL batch_textures = TRUE); - + virtual void renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); }; class LLFacePool : public LLDrawPool diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 4ee08e869a..ee1a640f2d 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -48,34 +48,20 @@ #include "lldrawpoolwater.h" #include "llspatialpartition.h" #include "llglcommonfunc.h" +#include "llvoavatar.h" BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; -static BOOL deferred_render = FALSE; +#define current_shader (LLGLSLShader::sCurBoundShaderPtr) -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETUP("Alpha Setup"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED("Alpha Deferred"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETBUFFER("Alpha SetBuffer"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DRAW("Alpha Draw"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_TEX_BINDS("Alpha Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MATS("Alpha Mat Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GLOW("Alpha Glow Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SHADER_BINDS("Alpha Shader Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS("Alpha Def Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS("Alpha Def Tex Binds"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MESH_REBUILD("Alpha Mesh Rebuild"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_EMISSIVE("Alpha Emissive"); -static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_LIGHT_SETUP("Alpha Light Setup"); +static BOOL deferred_render = FALSE; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : - LLRenderPass(type), current_shader(NULL), target_shader(NULL), - simple_shader(NULL), fullbright_shader(NULL), emissive_shader(NULL), + LLRenderPass(type), target_shader(NULL), mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF), mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF) { - + } LLDrawPoolAlpha::~LLDrawPoolAlpha() @@ -86,232 +72,188 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha() void LLDrawPoolAlpha::prerender() { mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + + // TODO: is this even necessay? These are probably set to never discard + LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f); + LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f); } S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { - if (LLPipeline::sImpostorRender) - { //skip depth buffer filling pass when rendering impostors - return 1; - } - else if (gSavedSettings.getBOOL("RenderDepthOfField")) - { - return 2; - } - else - { - return 1; - } + return 1; } -void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED); - - F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); +// set some common parameters on the given shader to prepare for alpha rendering +static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool deferredEnvironment) +{ + static LLCachedControl<F32> displayGamma(gSavedSettings, "RenderDeferredDisplayGamma"); + F32 gamma = displayGamma; + + // Does this deferred shader need environment uniforms set such as sun_dir, etc. ? + // NOTE: We don't actually need a gbuffer since we are doing forward rendering (for transparency) post deferred rendering + // TODO: bindDeferredShader() probably should have the updating of the environment uniforms factored out into updateShaderEnvironmentUniforms() + // i.e. shaders\class1\deferred\alphaF.glsl + if (deferredEnvironment) + { + gPipeline.bindDeferredShader( *shader ); + } + else + { + shader->bind(); + } + shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0); + shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f)); - emissive_shader = (LLPipeline::sRenderDeferred) ? &gDeferredEmissiveProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + if (LLPipeline::sImpostorRender) + { + shader->setMinimumAlpha(0.5f); + } + else + { + shader->setMinimumAlpha(0.f); + } + if (textureGamma) + { + shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } - emissive_shader->bind(); - emissive_shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0); - emissive_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - emissive_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); + //also prepare rigged variant + if (shader->mRiggedVariant && shader->mRiggedVariant != shader) + { + prepare_alpha_shader(shader->mRiggedVariant, textureGamma, deferredEnvironment); + } +} - if (pass == 0) - { - fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; +void LLDrawPoolAlpha::renderPostDeferred(S32 pass) +{ + LL_PROFILE_ZONE_SCOPED; + deferred_render = TRUE; - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - fullbright_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - fullbright_shader->unbind(); + // first pass, regular forward alpha rendering + { + emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + prepare_alpha_shader(emissive_shader, true, false); - simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : - (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; + fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram; + prepare_alpha_shader(fullbright_shader, true, false); - //prime simple shader (loads shadow relevant uniforms) - gPipeline.bindDeferredShader(*simple_shader); + simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : + (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram; + prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms) + + forwardRender(); + } - simple_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - } - else if (!LLPipeline::sImpostorRender) - { - //update depth buffer sampler - gPipeline.mScreen.flush(); - gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), - 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - gPipeline.mDeferredDepth.bindTarget(); - simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram; - gObjectFullbrightAlphaMaskProgram.bind(); - gObjectFullbrightAlphaMaskProgram.setMinimumAlpha(0.33f); - } + // second pass, render to depth for depth of field effects + if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField")) + { + //update depth buffer sampler + gPipeline.mScreen.flush(); + gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + gPipeline.mDeferredDepth.bindTarget(); + simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram; + + simple_shader->bind(); + simple_shader->setMinimumAlpha(0.33f); + + // mask off color buffer writes as we're only writing to depth buffer + gGL.setColorMask(false, false); + + // If the face is more than 90% transparent, then don't update the Depth buffer for Dof + // We don't want the nearly invisible objects to cause of DoF effects + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, + true); // <--- discard mostly transparent faces + + gPipeline.mDeferredDepth.flush(); + gPipeline.mScreen.bindTarget(); + gGL.setColorMask(true, false); + } - deferred_render = TRUE; - if (mShaderLevel > 0) - { - // Start out with no shaders. - current_shader = target_shader = NULL; - } - gPipeline.enableLightsDynamic(); + deferred_render = FALSE; } -void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED); - - if (pass == 1 && !LLPipeline::sImpostorRender) - { - gPipeline.mDeferredDepth.flush(); - gPipeline.mScreen.bindTarget(); - gObjectFullbrightAlphaMaskProgram.unbind(); - } - - deferred_render = FALSE; - endRenderPass(pass); -} +//set some generic parameters for forward (non-deferred) rendering +static void prepare_forward_shader(LLGLSLShader* shader, F32 minimum_alpha) +{ + shader->bind(); + shader->setMinimumAlpha(minimum_alpha); + shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); -void LLDrawPoolAlpha::renderPostDeferred(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED); - render(pass); + //also prepare rigged variant + if (shader->mRiggedVariant && shader->mRiggedVariant != shader) + { + prepare_forward_shader(shader->mRiggedVariant, minimum_alpha); + } } -void LLDrawPoolAlpha::beginRenderPass(S32 pass) +void LLDrawPoolAlpha::render(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP); - - simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram; + LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); + + simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram : + (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram; - fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram; + fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram : + (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram; - emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram : - (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram : + (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + F32 minimum_alpha = 0.f; if (LLPipeline::sImpostorRender) - { - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.5f); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.5f); - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK - } - } - else - { - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->setMinimumAlpha(0.f); - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.f); - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK - } + { + minimum_alpha = 0.5f; } - gPipeline.enableLightsDynamic(); + prepare_forward_shader(fullbright_shader, minimum_alpha); + prepare_forward_shader(simple_shader, minimum_alpha); - LLGLSLShader::bindNoShader(); - current_shader = NULL; + forwardRender(); } -void LLDrawPoolAlpha::endRenderPass( S32 pass ) +void LLDrawPoolAlpha::forwardRender() { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP); - LLRenderPass::endRenderPass(pass); + gPipeline.enableLightsDynamic(); - if(gPipeline.canUseWindLightShaders()) - { - LLGLSLShader::bindNoShader(); - } -} + LLGLSPipelineAlpha gls_pipeline_alpha; -void LLDrawPoolAlpha::render(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA); + //enable writing to alpha for emissive effects + gGL.setColorMask(true, true); - LLGLSPipelineAlpha gls_pipeline_alpha; + bool write_depth = LLDrawPoolWater::sSkipScreenCopy + // we want depth written so that rendered alpha will + // contribute to the alpha mask used for impostors + || LLPipeline::sImpostorRenderAlphaDepthPass; - if (deferred_render && pass == 1) - { //depth only - gGL.setColorMask(false, false); - } - else - { - gGL.setColorMask(true, true); - } - - bool write_depth = LLDrawPoolWater::sSkipScreenCopy - || (deferred_render && pass == 1) - // we want depth written so that rendered alpha will - // contribute to the alpha mask used for impostors - || LLPipeline::sImpostorRenderAlphaDepthPass; + LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE); - LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE); - - if (deferred_render && pass == 1) - { - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - } - else - { - mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend - mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } - mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression - mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - } + mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend + mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression + mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - if (mShaderLevel > 0) - { - renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass); - } - else - { - renderAlpha(getVertexDataMask(), pass); - } + // If the face is more than 90% transparent, then don't update the Depth buffer for Dof + // We don't want the nearly invisible objects to cause of DoF effects + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2); - gGL.setColorMask(true, false); + gGL.setColorMask(true, false); - if (deferred_render && pass == 1) - { - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } + renderDebugAlpha(); +} +void LLDrawPoolAlpha::renderDebugAlpha() +{ if (sShowDebugAlpha) { - BOOL shaders = gPipeline.canUseVertexShaders(); - if(shaders) - { - gHighlightProgram.bind(); - } - else - { - gPipeline.enableLightsFullbright(); - } + gHighlightProgram.bind(); + gGL.diffuseColor4f(1, 0, 0, 1); + LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f * 1024.f); + gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep); - gGL.diffuseColor4f(1,0,0,1); - - LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; - renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0); + renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0); pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); @@ -327,15 +269,31 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.diffuseColor4f(0, 1, 0, 1); pushBatches(LLRenderPass::PASS_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); - if(shaders) - { - gHighlightProgram.unbind(); - } + gHighlightProgram.mRiggedVariant->bind(); + gGL.diffuseColor4f(1, 0, 0, 1); + + pushRiggedBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + + // Material alpha mask + gGL.diffuseColor4f(0, 0, 1, 1); + pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + + gGL.diffuseColor4f(0, 1, 0, 1); + pushRiggedBatches(LLRenderPass::PASS_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + LLGLSLShader::sCurBoundShaderPtr->unbind(); } } void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; @@ -353,17 +311,37 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) continue; } + bool rigged = (params.mAvatar != nullptr); + gHighlightProgram.bind(rigged); + gGL.diffuseColor4f(1, 0, 0, 1); + + if (rigged) + { + if (lastAvatar != params.mAvatar || + lastMeshId != params.mSkinInfo->mHash) + { + if (!uploadMatrixPalette(params)) + { + continue; + } + lastAvatar = params.mAvatar; + lastMeshId = params.mSkinInfo->mHash; + } + } + LLRenderPass::applyModelMatrix(params); if (params.mGroup) { params.mGroup->rebuildMesh(); } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + params.mVertexBuffer->setBufferFast(rigged ? mask | LLVertexBuffer::MAP_WEIGHT4 : mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); } } } + + // make sure static version of highlight shader is bound before returning + gHighlightProgram.bind(); } inline bool IsFullbright(LLDrawInfo& params) @@ -383,47 +361,41 @@ inline bool IsEmissive(LLDrawInfo& params) inline void Draw(LLDrawInfo* draw, U32 mask) { - draw->mVertexBuffer->setBuffer(mask); + draw->mVertexBuffer->setBufferFast(mask); LLRenderPass::applyModelMatrix(*draw); - draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); - gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode); + draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } -bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader) +bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS); - bool tex_setup = false; if (deferred_render && use_material && current_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS); if (draw->mNormalMap) - { + { draw->mNormalMap->addTextureStats(draw->mVSize); current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap); } - + if (draw->mSpecularMap) { draw->mSpecularMap->addTextureStats(draw->mVSize); current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap); } } - else if (current_shader == simple_shader) + else if (current_shader == simple_shader || current_shader == simple_shader->mRiggedVariant) { - LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(draw->mVSize); - LLViewerFetchedTexture::sWhiteImagep->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); + current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); } - if (use_shaders && draw->mTextureList.size() > 1) + if (draw->mTextureList.size() > 1) { for (U32 i = 0; i < draw->mTextureList.size(); ++i) { if (draw->mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(draw->mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(draw->mTextureList[i]); } } } @@ -431,16 +403,15 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate { //not batching textures or batch has only 1 texture -- might need a texture matrix if (draw->mTexture.notNull()) { - draw->mTexture->addTextureStats(draw->mVSize); - if (use_shaders && use_material) + if (use_material) { current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture); } else { - gGL.getTexUnit(0)->bind(draw->mTexture, TRUE) ; + gGL.getTexUnit(0)->bindFast(draw->mTexture); } - + if (draw->mTextureMatrix) { tex_setup = true; @@ -452,7 +423,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_mate } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); } } @@ -470,160 +441,66 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup) } } -void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples) +void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw) { - gPipeline.enableLightsDynamic(); - simple_shader->bind(); - simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep); - simple_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep); - simple_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); - simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f); - simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : simples) - { - bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader); - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - - Draw(draw, mask); - RestoreTexSetup(tex_setup); - } - simple_shader->unbind(); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); + draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); + draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } -void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights) -{ - gPipeline.enableLightsFullbright(); - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : fullbrights) - { - bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader); - - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - Draw(draw, mask & ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2)); - RestoreTexSetup(tex_setup); - } - fullbright_shader->unbind(); -} - -void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials) +void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives) { - LLGLSLShader::bindNoShader(); - current_shader = NULL; + emissive_shader->bind(); + emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); - gPipeline.enableLightsDynamic(); - bool use_shaders = gPipeline.canUseVertexShaders(); - for (LLDrawInfo* draw : materials) + for (LLDrawInfo* draw : emissives) { - U32 mask = draw->mShaderMask; - - llassert(mask < LLMaterial::SHADER_COUNT); - target_shader = (LLPipeline::sUnderWaterRender) ? &(gDeferredMaterialWaterProgram[mask]) : &(gDeferredMaterialProgram[mask]); - - if (current_shader != target_shader) - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); - if (current_shader) - { - gPipeline.unbindDeferredShader(*current_shader); - } - gPipeline.bindDeferredShader(*target_shader); - current_shader = target_shader; - } - - bool tex_setup = TexSetup(draw, use_shaders, true, current_shader); - - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, draw->mSpecColor.mV[0], draw->mSpecColor.mV[1], draw->mSpecColor.mV[2], draw->mSpecColor.mV[3]); - current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, draw->mEnvIntensity); - current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, draw->mFullbright ? 1.f : 0.f); - - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS); - if (draw->mNormalMap) - { - draw->mNormalMap->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap); - } - - if (draw->mSpecularMap) - { - draw->mSpecularMap->addTextureStats(draw->mVSize); - current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap); - } - } - - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test); - gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - - Draw(draw, mask); + bool tex_setup = TexSetup(draw, false); + drawEmissive(mask, draw); RestoreTexSetup(tex_setup); } } -void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw) -{ - draw->mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); - draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); - gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode); -} - -void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw) +void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives) { - // install glow-accumulating blend mode - gGL.blendFunc( - LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color - LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) - - emissive_shader->bind(); - - drawEmissive(mask, draw); + LLGLSLShader* shader = emissive_shader->mRiggedVariant; + shader->bind(); + shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); - // restore our alpha blend mode - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - - current_shader->bind(); -} - -void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives) -{ - emissive_shader->bind(); - emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; - gPipeline.enableLightsDynamic(); - - // install glow-accumulating blend mode - // don't touch color, add to alpha (glow) - gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE); - bool use_shaders = gPipeline.canUseVertexShaders(); for (LLDrawInfo* draw : emissives) { - bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader); + bool tex_setup = TexSetup(draw, false); + if (lastAvatar != draw->mAvatar || lastMeshId != draw->mSkinInfo->mHash) + { + if (!uploadMatrixPalette(*draw)) + { // failed to upload matrix palette, skip rendering + continue; + } + lastAvatar = draw->mAvatar; + lastMeshId = draw->mSkinInfo->mHash; + } drawEmissive(mask, draw); RestoreTexSetup(tex_setup); } - - // restore our alpha blend mode - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - - emissive_shader->unbind(); } -void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) +void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only) { - BOOL batch_fullbrights = gSavedSettings.getBOOL("RenderAlphaBatchFullbrights"); - BOOL batch_emissives = gSavedSettings.getBOOL("RenderAlphaBatchEmissives"); - BOOL initialized_lighting = FALSE; + LL_PROFILE_ZONE_SCOPED; + BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; - - BOOL use_shaders = gPipeline.canUseVertexShaders(); - - for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + LLGLSLShader* lastAvatarShader = nullptr; + + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { + LL_PROFILE_ZONE_NAMED("renderAlpha - group"); LLSpatialGroup* group = *i; llassert(group); llassert(group->getSpatialPartition()); @@ -631,17 +508,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { - std::vector<LLDrawInfo*> emissives; - std::vector<LLDrawInfo*> fullbrights; + static std::vector<LLDrawInfo*> emissives; + static std::vector<LLDrawInfo*> rigged_emissives; + emissives.resize(0); + rigged_emissives.resize(0); bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow. - - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP); - bool disable_cull = is_particle_or_hud_particle; LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); @@ -649,6 +525,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { + LL_PROFILE_ZONE_NAMED("ra - push batch") LLDrawInfo& params = **k; U32 have_mask = params.mVertexBuffer->getTypeMask() & mask; if (have_mask != mask) @@ -659,29 +536,21 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) continue; } - // Fix for bug - NORSPEC-271 - // If the face is more than 90% transparent, then don't update the Depth buffer for Dof - // We don't want the nearly invisible objects to cause of DoF effects - if(pass == 1 && !LLPipeline::sImpostorRender) + if(depth_only) { + // when updating depth buffer, discard faces that are more than 90% transparent LLFace* face = params.mFace; if(face) { const LLTextureEntry* tep = face->getTextureEntry(); if(tep) - { + { // don't render faces that are more than 90% transparent if(tep->getColor().mV[3] < 0.1f) continue; } } } - if (params.mFullbright && batch_fullbrights) - { - fullbrights.push_back(¶ms); - continue; - } - LLRenderPass::applyModelMatrix(params); LLMaterial* mat = NULL; @@ -696,34 +565,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) // Turn off lighting if it hasn't already been so. if (light_enabled || !initialized_lighting) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP); - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = fullbright_shader; - } - else - { - gPipeline.enableLightsFullbright(); - } + target_shader = fullbright_shader; + light_enabled = FALSE; } } // Turn on lighting if it isn't already. else if (!light_enabled || !initialized_lighting) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP); - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } + target_shader = simple_shader; light_enabled = TRUE; } @@ -739,11 +591,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) target_shader = &(gDeferredMaterialWaterProgram[mask]); } + if (params.mAvatar != nullptr) + { + llassert(target_shader->mRiggedVariant != nullptr); + target_shader = target_shader->mRiggedVariant; + } + if (current_shader != target_shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS); gPipeline.bindDeferredShader(*target_shader); - current_shader = target_shader; } } else if (!params.mFullbright) @@ -755,25 +611,23 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) target_shader = fullbright_shader; } - if(use_shaders && (current_shader != target_shader)) - {// If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SHADER_BINDS); - current_shader = target_shader; - current_shader->bind(); - } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } + if (params.mAvatar != nullptr) + { + target_shader = target_shader->mRiggedVariant; + } + + if (current_shader != target_shader) + {// If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). + target_shader->bind(); + } LLVector4 spec_color(1, 1, 1, 1); F32 env_intensity = 0.0f; F32 brightness = 1.0f; // We have a material. Supply the appropriate data here. - if (use_shaders && mat && deferred_render) + if (mat && deferred_render) { spec_color = params.mSpecColor; env_intensity = params.mEnvIntensity; @@ -782,7 +636,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if (current_shader) { - current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]); + current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]); current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity); current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness); } @@ -792,38 +646,54 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) params.mGroup->rebuildMesh(); } - bool tex_setup = TexSetup(¶ms, use_shaders, use_shaders && (mat != nullptr), current_shader); + if (params.mAvatar != nullptr) + { + if (lastAvatar != params.mAvatar || + lastMeshId != params.mSkinInfo->mHash || + lastAvatarShader != LLGLSLShader::sCurBoundShaderPtr) + { + if (!uploadMatrixPalette(params)) + { + continue; + } + lastAvatar = params.mAvatar; + lastMeshId = params.mSkinInfo->mHash; + lastAvatarShader = LLGLSLShader::sCurBoundShaderPtr; + } + } + + bool tex_setup = TexSetup(¶ms, (mat != nullptr)); { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); - LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); - params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); - + U32 drawMask = mask; + if (params.mFullbright) + { + drawMask &= ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2); + } + if (params.mAvatar != nullptr) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DRAW); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + drawMask |= LLVertexBuffer::MAP_WEIGHT4; } + + params.mVertexBuffer->setBufferFast(drawMask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); } // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls is expensive, but glow must be drawn Z-sorted with alpha. - if (current_shader && - draw_glow_for_this_partition && + if (draw_glow_for_this_partition && params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_EMISSIVE); - - if (batch_emissives) + if (params.mAvatar != nullptr) { - emissives.push_back(¶ms); + rigged_emissives.push_back(¶ms); } else { - drawEmissiveInline(mask, ¶ms); - } + emissives.push_back(¶ms); + } } if (tex_setup) @@ -835,31 +705,67 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) } } - if (batch_fullbrights) + // render emissive faces into alpha channel for bloom effects + if (!depth_only) { - light_enabled = false; - renderFullbrights(mask, fullbrights); - } + gPipeline.enableLightsDynamic(); - if (batch_emissives) - { - light_enabled = true; - renderEmissives(mask, emissives); - } + // install glow-accumulating blend mode + // don't touch color, add to alpha (glow) + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE); - if (current_shader) - { - current_shader->bind(); + bool rebind = false; + LLGLSLShader* lastShader = current_shader; + if (!emissives.empty()) + { + light_enabled = true; + renderEmissives(mask, emissives); + rebind = true; + } + + if (!rigged_emissives.empty()) + { + light_enabled = true; + renderRiggedEmissives(mask, rigged_emissives); + rebind = true; + } + + // restore our alpha blend mode + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + + if (lastShader && rebind) + { + lastShader->bind(); + } } - } + } } gGL.setSceneBlendType(LLRender::BT_ALPHA); - LLVertexBuffer::unbind(); - + LLVertexBuffer::unbind(); + if (!light_enabled) { gPipeline.enableLightsDynamic(); } } + +bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params) +{ + const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo); + U32 count = mpc.mMatrixPalette.size(); + + if (count == 0) + { + //skin info not loaded yet, don't render + return false; + } + + LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)&(mpc.mGLMp[0])); + + return true; +} diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index a069f805e8..1f6909e282 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -51,39 +51,34 @@ public: /*virtual*/ ~LLDrawPoolAlpha(); /*virtual*/ S32 getNumPostDeferredPasses(); - /*virtual*/ void beginPostDeferredPass(S32 pass); - /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); - - /*virtual*/ void beginRenderPass(S32 pass = 0); - /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ S32 getNumPasses() { return 1; } virtual void render(S32 pass = 0); + void forwardRender(); /*virtual*/ void prerender(); + void renderDebugAlpha(); + void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); - void renderAlpha(U32 mask, S32 pass); + void renderAlpha(U32 mask, bool depth_only = false); void renderAlphaHighlight(U32 mask); - + bool uploadMatrixPalette(const LLDrawInfo& params); + static BOOL sShowDebugAlpha; private: - LLGLSLShader* current_shader; LLGLSLShader* target_shader; - LLGLSLShader* simple_shader; - LLGLSLShader* fullbright_shader; - LLGLSLShader* emissive_shader; - void renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples); - void renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights); - void renderMaterials(U32 mask, std::vector<LLDrawInfo*>& fullbrights); - void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives); + // setup by beginFooPass, [0] is static variant, [1] is rigged variant + LLGLSLShader* simple_shader = nullptr; + LLGLSLShader* fullbright_shader = nullptr; + LLGLSLShader* emissive_shader = nullptr; void drawEmissive(U32 mask, LLDrawInfo* draw); - void drawEmissiveInline(U32 mask, LLDrawInfo* draw); - - bool TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader); + void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives); + void renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives); + bool TexSetup(LLDrawInfo* draw, bool use_material); void RestoreTexSetup(bool tex_setup); // our 'normal' alpha blend function for this pass @@ -91,6 +86,9 @@ private: LLRender::eBlendFactor mColorDFactor; LLRender::eBlendFactor mAlphaSFactor; LLRender::eBlendFactor mAlphaDFactor; + + // if true, we're executing a rigged render pass + bool mRigged = false; }; class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index eb0bd0de4e..e1e57ef319 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -103,8 +103,6 @@ S32 normal_channel = -1; S32 specular_channel = -1; S32 cube_channel = -1; -static LLTrace::BlockTimerStatHandle FTM_SHADOW_AVATAR("Avatar Shadow"); - LLDrawPoolAvatar::LLDrawPoolAvatar(U32 type) : LLFacePool(type) { @@ -121,28 +119,27 @@ LLDrawPoolAvatar::~LLDrawPoolAvatar() // virtual BOOL LLDrawPoolAvatar::isDead() { + LL_PROFILE_ZONE_SCOPED + if (!LLFacePool::isDead()) { return FALSE; } - for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) - { - if (mRiggedFace[i].size() > 0) - { - return FALSE; - } - } return TRUE; } S32 LLDrawPoolAvatar::getShaderLevel() const { + LL_PROFILE_ZONE_SCOPED + return (S32) LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); } void LLDrawPoolAvatar::prerender() { + LL_PROFILE_ZONE_SCOPED + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); sShaderLevel = mShaderLevel; @@ -155,20 +152,12 @@ void LLDrawPoolAvatar::prerender() { sBufferUsage = GL_STREAM_DRAW_ARB; } - - if (!mDrawFace.empty()) - { - const LLFace *facep = mDrawFace[0]; - if (facep && facep->getDrawable()) - { - LLVOAvatar* avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - updateRiggedVertexBuffers(avatarp); - } - } } LLMatrix4& LLDrawPoolAvatar::getModelView() { + LL_PROFILE_ZONE_SCOPED + static LLMatrix4 ret; ret.initRows(LLVector4(gGLModelView+0), @@ -187,7 +176,7 @@ LLMatrix4& LLDrawPoolAvatar::getModelView() void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + LL_PROFILE_ZONE_SCOPED; sSkipTransparent = TRUE; is_deferred_render = true; @@ -208,21 +197,12 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) case 2: beginDeferredSkinned(); break; - case 3: - beginDeferredRiggedSimple(); - break; - case 4: - beginDeferredRiggedBump(); - break; - default: - beginDeferredRiggedMaterial(pass-5); - break; } } void LLDrawPoolAvatar::endDeferredPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + LL_PROFILE_ZONE_SCOPED; sSkipTransparent = FALSE; is_deferred_render = false; @@ -243,58 +223,25 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) case 2: endDeferredSkinned(); break; - case 3: - endDeferredRiggedSimple(); - break; - case 4: - endDeferredRiggedBump(); - break; - default: - endDeferredRiggedMaterial(pass-5); - break; } } void LLDrawPoolAvatar::renderDeferred(S32 pass) { + LL_PROFILE_ZONE_SCOPED + render(pass); } S32 LLDrawPoolAvatar::getNumPostDeferredPasses() { - return 10; + return 1; } void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) { - switch (pass) - { - case 0: - beginPostDeferredAlpha(); - break; - case 1: - beginRiggedFullbright(); - break; - case 2: - beginRiggedFullbrightShiny(); - break; - case 3: - beginDeferredRiggedAlpha(); - break; - case 4: - beginRiggedFullbrightAlpha(); - break; - case 9: - beginRiggedGlow(); - break; - default: - beginDeferredRiggedMaterialAlpha(pass-5); - break; - } -} + LL_PROFILE_ZONE_SCOPED -void LLDrawPoolAvatar::beginPostDeferredAlpha() -{ sSkipOpaque = TRUE; sShaderLevel = mShaderLevel; sVertexProgram = &gDeferredAvatarAlphaProgram; @@ -307,80 +254,9 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } -void LLDrawPoolAvatar::beginDeferredRiggedAlpha() -{ - sVertexProgram = &gDeferredSkinnedAlphaProgram; - gPipeline.bindDeferredShader(*sVertexProgram); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - gPipeline.enableLightsDynamic(); -} - -void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass) -{ - switch (pass) - { - case 0: pass = 1; break; - case 1: pass = 5; break; - case 2: pass = 9; break; - default: pass = 13; break; - } - - pass += LLMaterial::SHADER_COUNT; - - sVertexProgram = &gDeferredMaterialProgram[pass]; - - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &(gDeferredMaterialWaterProgram[pass]); - } - - gPipeline.bindDeferredShader(*sVertexProgram); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - gPipeline.enableLightsDynamic(); -} - -void LLDrawPoolAvatar::endDeferredRiggedAlpha() -{ - LLVertexBuffer::unbind(); - gPipeline.unbindDeferredShader(*sVertexProgram); - sDiffuseChannel = 0; - normal_channel = -1; - specular_channel = -1; - sVertexProgram = NULL; -} - void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) { - switch (pass) - { - case 0: - endPostDeferredAlpha(); - break; - case 1: - endRiggedFullbright(); - break; - case 2: - endRiggedFullbrightShiny(); - break; - case 3: - endDeferredRiggedAlpha(); - break; - case 4: - endRiggedFullbrightAlpha(); - break; - case 5: - endRiggedGlow(); - break; - default: - endDeferredRiggedAlpha(); - break; - } -} - -void LLDrawPoolAvatar::endPostDeferredAlpha() -{ + LL_PROFILE_ZONE_SCOPED // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; sSkipOpaque = FALSE; @@ -392,29 +268,17 @@ void LLDrawPoolAvatar::endPostDeferredAlpha() void LLDrawPoolAvatar::renderPostDeferred(S32 pass) { - static const S32 actual_pass[] = - { //map post deferred pass numbers to what render() expects - 2, //skinned - 4, // rigged fullbright - 6, //rigged fullbright shiny - 7, //rigged alpha - 8, //rigged fullbright alpha - 9, //rigged material alpha 1 - 10,//rigged material alpha 2 - 11,//rigged material alpha 3 - 12,//rigged material alpha 4 - 13, //rigged glow - }; - - S32 p = actual_pass[pass]; + LL_PROFILE_ZONE_SCOPED + is_post_deferred_render = true; if (LLPipeline::sImpostorRender) { //HACK for impostors so actual pass ends up being proper pass - p -= 2; + render(0); + } + else + { + render(2); } - - is_post_deferred_render = true; - render(p); is_post_deferred_render = false; } @@ -427,7 +291,7 @@ S32 LLDrawPoolAvatar::getNumShadowPasses() void LLDrawPoolAvatar::beginShadowPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); + LL_PROFILE_ZONE_SCOPED; if (pass == SHADOW_PASS_AVATAR_OPAQUE) { @@ -439,7 +303,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram->bind(); } - gGL.diffuseColor4f(1,1,1,1); + gGL.diffuseColor4f(1, 1, 1, 1); } else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND) { @@ -459,7 +323,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram->bind(); } - gGL.diffuseColor4f(1,1,1,1); + gGL.diffuseColor4f(1, 1, 1, 1); } else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK) { @@ -479,69 +343,13 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) sVertexProgram->bind(); } - gGL.diffuseColor4f(1,1,1,1); - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) - { - sVertexProgram = &gDeferredAttachmentAlphaShadowProgram; - - // bind diffuse tex so we can reference the alpha channel... - S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); - sDiffuseChannel = 0; - if (loc != -1) - { - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) - { - sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram; - - // bind diffuse tex so we can reference the alpha channel... - S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); - sDiffuseChannel = 0; - if (loc != -1) - { - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - - if ((sShaderLevel > 0)) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - } - - gGL.diffuseColor4f(1,1,1,1); - } - else // SHADOW_PASS_ATTACHMENT_OPAQUE - { - sVertexProgram = &gDeferredAttachmentShadowProgram; - S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP); - sDiffuseChannel = 0; - if (loc != -1) - { - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - sVertexProgram->bind(); + gGL.diffuseColor4f(1, 1, 1, 1); } } void LLDrawPoolAvatar::endShadowPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); - - if (pass == SHADOW_PASS_ATTACHMENT_OPAQUE) - { - LLVertexBuffer::unbind(); - } + LL_PROFILE_ZONE_SCOPED; if (sShaderLevel > 0) { @@ -554,7 +362,7 @@ void LLDrawPoolAvatar::endShadowPass(S32 pass) void LLDrawPoolAvatar::renderShadow(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR); + LL_PROFILE_ZONE_SCOPED; if (mDrawFace.empty()) { @@ -574,10 +382,9 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance(); BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor(); - if (oa == LLVOAvatar::AOA_INVISIBLE || - (impostor && oa == LLVOAvatar::AOA_JELLYDOLL)) + if (impostor || (oa == LLVOAvatar::AOA_INVISIBLE)) { - // No shadows for jellydolled or invisible avs. + // No shadows for impostored (including jellydolled) or invisible avs. return; } @@ -601,79 +408,23 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) avatarp->renderSkinned(); LLDrawPoolAvatar::sSkipOpaque = false; } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) // rigged alpha - { - LLDrawPoolAvatar::sSkipOpaque = true; - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); - renderRigged(avatarp, RIGGED_ALPHA); - renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); - renderRigged(avatarp, RIGGED_GLOW); - renderRigged(avatarp, RIGGED_SPECMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); - LLDrawPoolAvatar::sSkipOpaque = false; - } - else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) // rigged alpha mask - { - LLDrawPoolAvatar::sSkipOpaque = true; - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); - renderRigged(avatarp, RIGGED_NORMMAP_MASK); - renderRigged(avatarp, RIGGED_SPECMAP_MASK); - renderRigged(avatarp, RIGGED_NORMSPEC_MASK); - renderRigged(avatarp, RIGGED_GLOW); - LLDrawPoolAvatar::sSkipOpaque = false; - } - else // rigged opaque (SHADOW_PASS_ATTACHMENT_OPAQUE - { - LLDrawPoolAvatar::sSkipTransparent = true; - renderRigged(avatarp, RIGGED_MATERIAL); - renderRigged(avatarp, RIGGED_SPECMAP); - renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMMAP); - renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMSPEC); - renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); - renderRigged(avatarp, RIGGED_SIMPLE); - renderRigged(avatarp, RIGGED_FULLBRIGHT); - renderRigged(avatarp, RIGGED_SHINY); - renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); - renderRigged(avatarp, RIGGED_GLOW); - renderRigged(avatarp, RIGGED_DEFERRED_BUMP); - renderRigged(avatarp, RIGGED_DEFERRED_SIMPLE); - LLDrawPoolAvatar::sSkipTransparent = false; - } } S32 LLDrawPoolAvatar::getNumPasses() { - if (LLPipeline::sImpostorRender) - { - return 8; - } - else - { - return 10; - } + return 3; } S32 LLDrawPoolAvatar::getNumDeferredPasses() { - if (LLPipeline::sImpostorRender) - { - return 19; - } - else - { - return 21; - } + return 3; } void LLDrawPoolAvatar::render(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + LL_PROFILE_ZONE_SCOPED; if (LLPipeline::sImpostorRender) { renderAvatars(NULL, pass+2); @@ -685,7 +436,7 @@ void LLDrawPoolAvatar::render(S32 pass) void LLDrawPoolAvatar::beginRenderPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + LL_PROFILE_ZONE_SCOPED; //reset vertex buffer mappings LLVertexBuffer::unbind(); @@ -705,27 +456,6 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) case 2: beginSkinned(); break; - case 3: - beginRiggedSimple(); - break; - case 4: - beginRiggedFullbright(); - break; - case 5: - beginRiggedShinySimple(); - break; - case 6: - beginRiggedFullbrightShiny(); - break; - case 7: - beginRiggedAlpha(); - break; - case 8: - beginRiggedFullbrightAlpha(); - break; - case 9: - beginRiggedGlow(); - break; } if (pass == 0) @@ -736,7 +466,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) void LLDrawPoolAvatar::endRenderPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + LL_PROFILE_ZONE_SCOPED; if (LLPipeline::sImpostorRender) { @@ -754,43 +484,21 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) case 2: endSkinned(); break; - case 3: - endRiggedSimple(); - break; - case 4: - endRiggedFullbright(); - break; - case 5: - endRiggedShinySimple(); - break; - case 6: - endRiggedFullbrightShiny(); - break; - case 7: - endRiggedAlpha(); - break; - case 8: - endRiggedFullbrightAlpha(); - break; - case 9: - endRiggedGlow(); - break; } } void LLDrawPoolAvatar::beginImpostor() { + LL_PROFILE_ZONE_SCOPED + if (!LLPipeline::sReflectionRender) { LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); LLVOAvatar::sNumVisibleAvatars = 0; } - if (LLGLSLShader::sNoFixedFunction) - { gImpostorProgram.bind(); gImpostorProgram.setMinimumAlpha(0.01f); - } gPipeline.enableLightsFullbright(); sDiffuseChannel = 0; @@ -798,16 +506,17 @@ void LLDrawPoolAvatar::beginImpostor() void LLDrawPoolAvatar::endImpostor() { - if (LLGLSLShader::sNoFixedFunction) - { + LL_PROFILE_ZONE_SCOPED + gImpostorProgram.unbind(); - } gPipeline.enableLightsDynamic(); } void LLDrawPoolAvatar::beginRigid() { - if (gPipeline.canUseVertexShaders()) + LL_PROFILE_ZONE_SCOPED + + if (gPipeline.shadersLoaded()) { if (LLPipeline::sUnderWaterRender) { @@ -840,6 +549,8 @@ void LLDrawPoolAvatar::beginRigid() void LLDrawPoolAvatar::endRigid() { + LL_PROFILE_ZONE_SCOPED + sShaderLevel = mShaderLevel; if (sVertexProgram != NULL) { @@ -849,6 +560,8 @@ void LLDrawPoolAvatar::endRigid() void LLDrawPoolAvatar::beginDeferredImpostor() { + LL_PROFILE_ZONE_SCOPED + if (!LLPipeline::sReflectionRender) { LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); @@ -865,6 +578,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor() void LLDrawPoolAvatar::endDeferredImpostor() { + LL_PROFILE_ZONE_SCOPED + sShaderLevel = mShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); @@ -876,6 +591,8 @@ void LLDrawPoolAvatar::endDeferredImpostor() void LLDrawPoolAvatar::beginDeferredRigid() { + LL_PROFILE_ZONE_SCOPED + sVertexProgram = &gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); @@ -892,6 +609,8 @@ void LLDrawPoolAvatar::beginDeferredRigid() void LLDrawPoolAvatar::endDeferredRigid() { + LL_PROFILE_ZONE_SCOPED + sShaderLevel = mShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->unbind(); @@ -901,6 +620,8 @@ void LLDrawPoolAvatar::endDeferredRigid() void LLDrawPoolAvatar::beginSkinned() { + LL_PROFILE_ZONE_SCOPED + if (sShaderLevel > 0) { if (LLPipeline::sUnderWaterRender) @@ -943,7 +664,7 @@ void LLDrawPoolAvatar::beginSkinned() } else { - if(gPipeline.canUseVertexShaders()) + if(gPipeline.shadersLoaded()) { // software skinning, use a basic shader for windlight. // TODO: find a better fallback method for software skinning. @@ -959,14 +680,13 @@ void LLDrawPoolAvatar::beginSkinned() } } - if (LLGLSLShader::sNoFixedFunction) - { sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); - } } void LLDrawPoolAvatar::endSkinned() { + LL_PROFILE_ZONE_SCOPED + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done if (sShaderLevel > 0) { @@ -978,7 +698,7 @@ void LLDrawPoolAvatar::endSkinned() } else { - if(gPipeline.canUseVertexShaders()) + if(gPipeline.shadersLoaded()) { // software skinning, use a basic shader for windlight. // TODO: find a better fallback method for software skinning. @@ -989,424 +709,10 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } -void LLDrawPoolAvatar::beginRiggedSimple() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectSimpleWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectSimpleProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectSimpleNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectSimpleNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sDiffuseChannel = 0; - sVertexProgram->bind(); - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } -} - -void LLDrawPoolAvatar::endRiggedSimple() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->unbind(); - sVertexProgram = NULL; - } -} - -void LLDrawPoolAvatar::beginRiggedAlpha() -{ - beginRiggedSimple(); -} - -void LLDrawPoolAvatar::endRiggedAlpha() -{ - endRiggedSimple(); -} - - -void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() -{ - beginRiggedFullbright(); -} - -void LLDrawPoolAvatar::endRiggedFullbrightAlpha() -{ - endRiggedFullbright(); -} - -void LLDrawPoolAvatar::beginRiggedGlow() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectEmissiveWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectEmissiveProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectEmissiveNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectEmissiveNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sDiffuseChannel = 0; - sVertexProgram->bind(); - - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, LLPipeline::sRenderDeferred ? 2.2f : 1.1f); - - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - - F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); - sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - } -} - -void LLDrawPoolAvatar::endRiggedGlow() -{ - endRiggedFullbright(); -} - -void LLDrawPoolAvatar::beginRiggedFullbright() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; - } - else - { - if (LLPipeline::sRenderDeferred) - { - sVertexProgram = &gDeferredSkinnedFullbrightProgram; - } - else - { - sVertexProgram = &gSkinnedObjectFullbrightProgram; - } - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectFullbrightNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sDiffuseChannel = 0; - sVertexProgram->bind(); - - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else if (LLPipeline::sRenderDeferred) - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); - sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - } - else - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } -} - -void LLDrawPoolAvatar::endRiggedFullbright() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->unbind(); - sVertexProgram = NULL; - } -} - -void LLDrawPoolAvatar::beginRiggedShinySimple() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; - } - else - { - sVertexProgram = &gSkinnedObjectShinySimpleProgram; - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectShinyNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectShinyNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->bind(); - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - } -} - -void LLDrawPoolAvatar::endRiggedShinySimple() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - sVertexProgram->unbind(); - sVertexProgram = NULL; - } -} - -void LLDrawPoolAvatar::beginRiggedFullbrightShiny() -{ - if (sShaderLevel > 0) - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; - } - else - { - if (LLPipeline::sRenderDeferred) - { - sVertexProgram = &gDeferredSkinnedFullbrightShinyProgram; - } - else - { - sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; - } - } - } - else - { - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram; - } - else - { - sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram; - } - } - - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - sVertexProgram->bind(); - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else if (LLPipeline::sRenderDeferred) - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); - sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f)); - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - else - { - sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } -} - -void LLDrawPoolAvatar::endRiggedFullbrightShiny() -{ - LLVertexBuffer::unbind(); - if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) - { - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); - sVertexProgram->unbind(); - sVertexProgram = NULL; - } -} - - -void LLDrawPoolAvatar::beginDeferredRiggedSimple() -{ - sVertexProgram = &gDeferredSkinnedDiffuseProgram; - sDiffuseChannel = 0; - sVertexProgram->bind(); - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } -} - -void LLDrawPoolAvatar::endDeferredRiggedSimple() -{ - LLVertexBuffer::unbind(); - sVertexProgram->unbind(); - sVertexProgram = NULL; -} - -void LLDrawPoolAvatar::beginDeferredRiggedBump() -{ - sVertexProgram = &gDeferredSkinnedBumpProgram; - sVertexProgram->bind(); - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); -} - -void LLDrawPoolAvatar::endDeferredRiggedBump() -{ - LLVertexBuffer::unbind(); - sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->unbind(); - normal_channel = -1; - sDiffuseChannel = 0; - sVertexProgram = NULL; -} - -void LLDrawPoolAvatar::beginDeferredRiggedMaterial(S32 pass) -{ - if (pass == 1 || - pass == 5 || - pass == 9 || - pass == 13) - { //skip alpha passes - return; - } - sVertexProgram = &gDeferredMaterialProgram[pass+LLMaterial::SHADER_COUNT]; - - if (LLPipeline::sUnderWaterRender) - { - sVertexProgram = &(gDeferredMaterialWaterProgram[pass+LLMaterial::SHADER_COUNT]); - } - - sVertexProgram->bind(); - if (LLPipeline::sRenderingHUDs) - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); -} - -void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass) -{ - if (pass == 1 || - pass == 5 || - pass == 9 || - pass == 13) - { - return; - } - - LLVertexBuffer::unbind(); - sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - sVertexProgram->unbind(); - normal_channel = -1; - sDiffuseChannel = 0; - sVertexProgram = NULL; -} - void LLDrawPoolAvatar::beginDeferredSkinned() { + LL_PROFILE_ZONE_SCOPED + sShaderLevel = mShaderLevel; sVertexProgram = &gDeferredAvatarProgram; sRenderingSkinned = TRUE; @@ -1428,6 +734,8 @@ void LLDrawPoolAvatar::beginDeferredSkinned() void LLDrawPoolAvatar::endDeferredSkinned() { + LL_PROFILE_ZONE_SCOPED + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; sVertexProgram->unbind(); @@ -1439,13 +747,8 @@ void LLDrawPoolAvatar::endDeferredSkinned() gGL.getTexUnit(0)->activate(); } -static LLTrace::BlockTimerStatHandle FTM_RENDER_AVATARS("renderAvatars"); - - void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_AVATARS); - if (pass == -1) { for (S32 i = 1; i < getNumPasses(); i++) @@ -1485,6 +788,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } + LL_RECORD_BLOCK_TIME(FTM_RENDER_CHARACTERS); + if (!single_avatar && !avatarp->isFullyLoaded() ) { if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) @@ -1565,142 +870,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } - if (pass == 3) - { - if (is_deferred_render) - { - renderDeferredRiggedSimple(avatarp); - } - else - { - renderRiggedSimple(avatarp); - - if (LLPipeline::sRenderDeferred) - { //render "simple" materials - renderRigged(avatarp, RIGGED_MATERIAL); - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK); - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMMAP); - renderRigged(avatarp, RIGGED_NORMMAP_MASK); - renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_SPECMAP); - renderRigged(avatarp, RIGGED_SPECMAP_MASK); - renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE); - renderRigged(avatarp, RIGGED_NORMSPEC); - renderRigged(avatarp, RIGGED_NORMSPEC_MASK); - renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE); - } - } - return; - } - - if (pass == 4) - { - if (is_deferred_render) - { - renderDeferredRiggedBump(avatarp); - } - else - { - renderRiggedFullbright(avatarp); - } - - return; - } - - if (is_deferred_render && pass >= 5 && pass <= 21) - { - S32 p = pass-5; - - if (p != 1 && - p != 5 && - p != 9 && - p != 13) - { - renderDeferredRiggedMaterial(avatarp, p); - } - return; - } - - - - - if (pass == 5) - { - renderRiggedShinySimple(avatarp); - - return; - } - - if (pass == 6) - { - renderRiggedFullbrightShiny(avatarp); - return; - } - - if (pass >= 7 && pass < 13) - { - if (pass == 7) - { - renderRiggedAlpha(avatarp); - - if (LLPipeline::sRenderDeferred && !is_post_deferred_render) - { //render transparent materials under water - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - renderRigged(avatarp, RIGGED_MATERIAL_ALPHA); - renderRigged(avatarp, RIGGED_SPECMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMMAP_BLEND); - renderRigged(avatarp, RIGGED_NORMSPEC_BLEND); - - gGL.setColorMask(true, false); - } - return; - } - - if (pass == 8) - { - renderRiggedFullbrightAlpha(avatarp); - return; - } - - if (LLPipeline::sRenderDeferred && is_post_deferred_render) - { - S32 p = 0; - switch (pass) - { - case 9: p = 1; break; - case 10: p = 5; break; - case 11: p = 9; break; - case 12: p = 13; break; - } - - { - LLGLEnable blend(GL_BLEND); - renderDeferredRiggedMaterial(avatarp, p); - } - return; - } - else if (pass == 9) - { - renderRiggedGlow(avatarp); - return; - } - } - - if (pass == 13) - { - renderRiggedGlow(avatarp); - - return; - } - if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) { LLMatrix4 rot_mat; @@ -1732,748 +901,15 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } -void LLDrawPoolAvatar::getRiggedGeometry( - LLFace* face, - LLPointer<LLVertexBuffer>& buffer, - U32 data_mask, - const LLMeshSkinInfo* skin, - LLVolume* volume, - const LLVolumeFace& vol_face) -{ - face->setGeomIndex(0); - face->setIndicesIndex(0); - - if (face->getTextureIndex() != FACE_DO_NOT_BATCH_TEXTURES) - { - face->setDrawInfo(NULL); - } - - //rigged faces do not batch textures - face->setTextureIndex(FACE_DO_NOT_BATCH_TEXTURES); - - if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable()) - { - // make a new buffer - if (sShaderLevel > 0) - { - buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB); - } - else - { - buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB); - } - - if (!buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true)) - { - LL_WARNS("LLDrawPoolAvatar") << "Failed to allocate Vertex Buffer to " - << vol_face.mNumVertices << " vertices and " - << vol_face.mNumIndices << " indices" << LL_ENDL; - // allocate dummy triangle - buffer->allocateBuffer(1, 3, true); - memset((U8*)buffer->getMappedData(), 0, buffer->getSize()); - memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize()); - } - } - else - { - //resize existing buffer - if(!buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices)) - { - LL_WARNS("LLDrawPoolAvatar") << "Failed to resize Vertex Buffer to " - << vol_face.mNumVertices << " vertices and " - << vol_face.mNumIndices << " indices" << LL_ENDL; - // allocate dummy triangle - buffer->resizeBuffer(1, 3); - memset((U8*)buffer->getMappedData(), 0, buffer->getSize()); - memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize()); - } - } - - face->setSize(buffer->getNumVerts(), buffer->getNumIndices()); - face->setVertexBuffer(buffer); - - U16 offset = 0; - - LLMatrix4 mat_vert = skin->mBindShapeMatrix; - glh::matrix4f m((F32*) mat_vert.mMatrix); - m = m.inverse().transpose(); - - F32 mat3[] = - { m.m[0], m.m[1], m.m[2], - m.m[4], m.m[5], m.m[6], - m.m[8], m.m[9], m.m[10] }; - - LLMatrix3 mat_normal(mat3); - - //let getGeometryVolume know if alpha should override shiny - U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture()); - - if (type == LLDrawPool::POOL_ALPHA) - { - face->setPoolType(LLDrawPool::POOL_ALPHA); - } - else - { - face->setPoolType(mType); // either POOL_AVATAR or POOL_CONTROL_AV - } - - //LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL; - - // Let getGeometryVolume know if a texture matrix is in play - if (face->mTextureMatrix) - { - face->setState(LLFace::TEXTURE_ANIM); - } - else - { - face->clearState(LLFace::TEXTURE_ANIM); - } - face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); - - buffer->flush(); -} - -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer( - LLVOAvatar* avatar, - LLFace* face, - const LLMeshSkinInfo* skin, - LLVolume* volume, - LLVolumeFace& vol_face) -{ - LLVector4a* weights = vol_face.mWeights; - if (!weights) - { - return; - } - - LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer(); - LLDrawable* drawable = face->getDrawable(); - - if (drawable->getVOVolume() && drawable->getVOVolume()->isNoLOD()) - { - return; - } - - const U32 max_joints = LLSkinningUtil::getMaxJointCount(); - -#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - #define CONDITION_WEIGHT(f) ((U8)llclamp((S32)f, (S32)0, (S32)max_joints-1)) - LLVector4a* just_weights = vol_face.mJustWeights; - // we need to calculate the separated indices and store just the matrix weights for this vol... - if (!vol_face.mJointIndices) - { - // not very consty after all... - vol_face.allocateJointIndices(vol_face.mNumVertices); - just_weights = vol_face.mJustWeights; - - U8* joint_indices_cursor = vol_face.mJointIndices; - for (int i = 0; i < vol_face.mNumVertices; i++) - { - F32* w = weights[i].getF32ptr(); - F32* w_ = just_weights[i].getF32ptr(); - - F32 w0 = floorf(w[0]); - F32 w1 = floorf(w[1]); - F32 w2 = floorf(w[2]); - F32 w3 = floorf(w[3]); - - joint_indices_cursor[0] = CONDITION_WEIGHT(w0); - joint_indices_cursor[1] = CONDITION_WEIGHT(w1); - joint_indices_cursor[2] = CONDITION_WEIGHT(w2); - joint_indices_cursor[3] = CONDITION_WEIGHT(w3); - - // remove joint portion of combined weight - w_[0] = w[0] - w0; - w_[1] = w[1] - w1; - w_[2] = w[2] - w2; - w_[3] = w[3] - w3; - - joint_indices_cursor += 4; - } - } -#endif - - // FIXME ugly const cast - LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin)); - - U32 data_mask = face->getRiggedVertexBufferDataMask(); - - if (!vol_face.mWeightsScrubbed) - { - LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin); - vol_face.mWeightsScrubbed = TRUE; - } - - if (buffer.isNull() || - buffer->getTypeMask() != data_mask || - buffer->getNumVerts() != vol_face.mNumVertices || - buffer->getNumIndices() != vol_face.mNumIndices || - (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) - { - if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) - { - //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* facep = drawable->getFace(i); - U32 face_data_mask = facep->getRiggedVertexBufferDataMask(); - if (face_data_mask) - { - LLPointer<LLVertexBuffer> cur_buffer = facep->getVertexBuffer(); - const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i); - getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face); - } - } - drawable->clearState(LLDrawable::REBUILD_ALL); - - buffer = face->getVertexBuffer(); - } - else - { - //just rebuild this face - getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face); - } - } - - if (buffer.isNull() || - buffer->getNumVerts() != vol_face.mNumVertices || - buffer->getNumIndices() != vol_face.mNumIndices) - { - // Allocation failed - return; - } - - if (!buffer.isNull() && - sShaderLevel <= 0 && - face->mLastSkinTime < avatar->getLastSkinTime()) - { - //perform software vertex skinning for this face - LLStrider<LLVector3> position; - LLStrider<LLVector3> normal; - - bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - buffer->getVertexStrider(position); - - if (has_normal) - { - buffer->getNormalStrider(normal); - } - - LLVector4a* pos = (LLVector4a*) position.get(); - - LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; - - //build matrix palette - LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); - LLSkinningUtil::checkSkinWeights(weights, buffer->getNumVerts(), skin); - - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); - -#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - U8* joint_indices_cursor = vol_face.mJointIndices; - // fast path with joint indices separate from weights - if (joint_indices_cursor) - { - LLMatrix4a src[4]; - for (U32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - //LLMatrix4a final_mat_correct; - - F32* jw = just_weights[j].getF32ptr(); - - LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src); - - joint_indices_cursor += 4; - - LLVector4a& v = vol_face.mPositions[j]; - - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - - if (norm) - { - LLVector4a& n = vol_face.mNormals[j]; - bind_shape_matrix.rotate(n, t); - final_mat.rotate(t, dst); - dst.normalize3fast(); - norm[j] = dst; - } - } - } - // slow path with joint indices calculated from weights - else -#endif - { - for (U32 j = 0; j < buffer->getNumVerts(); ++j) - { - LLMatrix4a final_mat; - LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints); - - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - - if (norm) - { - LLVector4a& n = vol_face.mNormals[j]; - bind_shape_matrix.rotate(n, t); - final_mat.rotate(t, dst); - //dst.normalize3fast(); - norm[j] = dst; - } - } - } - } -} - -void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) -{ - if (!avatar->shouldRenderRigged()) - { - return; - } - - stop_glerror(); - - for (U32 i = 0; i < mRiggedFace[type].size(); ++i) - { - LLFace* face = mRiggedFace[type][i]; - - S32 offset = face->getIndicesStart(); - U32 count = face->getIndicesCount(); - - U16 start = face->getGeomStart(); - U16 end = start + face->getGeomCount()-1; - - LLDrawable* drawable = face->getDrawable(); - if (!drawable) - { - continue; - } - - LLVOVolume* vobj = drawable->getVOVolume(); - - if (!vobj) - { - continue; - } - - LLVolume* volume = vobj->getVolume(); - S32 te = face->getTEOffset(); - - if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) - { - continue; - } - - const LLMeshSkinInfo* skin = vobj->getSkinInfo(); - if (!skin) - { - continue; - } - - //stop_glerror(); - - //const LLVolumeFace& vol_face = volume->getVolumeFace(te); - //updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); - - //stop_glerror(); - - U32 data_mask = LLFace::getRiggedDataMask(type); - - LLVertexBuffer* buff = face->getVertexBuffer(); - - const LLTextureEntry* tex_entry = face->getTextureEntry(); - LLMaterial* mat = tex_entry ? tex_entry->getMaterialParams().get() : nullptr; - - if (LLDrawPoolAvatar::sShadowPass >= 0) - { - bool is_alpha_blend = false; - bool is_alpha_mask = false; - - LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP); - if (tex) - { - if (tex->getIsAlphaMask()) - { - is_alpha_mask = true; - } - } - - if (tex) - { - LLGLenum image_format = tex->getPrimaryFormat(); - if (!is_alpha_mask && (image_format == GL_RGBA || image_format == GL_ALPHA)) - { - is_alpha_blend = true; - } - } - - if (tex_entry) - { - if (tex_entry->getAlpha() <= 0.99f) - { - is_alpha_blend = true; - } - } - - if (mat) - { - switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode())) - { - case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: - { - is_alpha_mask = true; - is_alpha_blend = false; - } - break; - - case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: - { - is_alpha_blend = true; - is_alpha_mask = false; - } - break; - - case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: - case LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT: - case LLMaterial::DIFFUSE_ALPHA_MODE_NONE: - default: - is_alpha_blend = false; - is_alpha_mask = false; - break; - } - } - - // if this is alpha mask content and we're doing opaques or a non-alpha-mask shadow pass... - if (is_alpha_mask && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_MASK)) - { - return; - } - - // if this is alpha blend content and we're doing opaques or a non-alpha-blend shadow pass... - if (is_alpha_blend && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_BLEND)) - { - return; - } - - // if this is opaque content and we're skipping opaques... - if (!is_alpha_mask && !is_alpha_blend && LLDrawPoolAvatar::sSkipOpaque) - { - return; - } - } - - if (buff) - { - if (sShaderLevel > 0) - { - // upload matrix palette to shader - LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - U32 count = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count, skin, avatar); - - stop_glerror(); - - F32 mp[LL_MAX_JOINTS_PER_MESH_OBJECT*12]; - - for (U32 i = 0; i < count; ++i) - { - F32* m = (F32*) mat[i].mMatrix[0].getF32ptr(); - - U32 idx = i*12; - - mp[idx+0] = m[0]; - mp[idx+1] = m[1]; - mp[idx+2] = m[2]; - mp[idx+3] = m[12]; - - mp[idx+4] = m[4]; - mp[idx+5] = m[5]; - mp[idx+6] = m[6]; - mp[idx+7] = m[13]; - - mp[idx+8] = m[8]; - mp[idx+9] = m[9]; - mp[idx+10] = m[10]; - mp[idx+11] = m[14]; - } - - LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, - count, - FALSE, - (GLfloat*) mp); - - stop_glerror(); - } - else - { - data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; - } - - /*if (glow) - { - gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); - }*/ - - if (mat) - { - //order is important here LLRender::DIFFUSE_MAP should be last, becouse it change - //(gGL).mCurrTextureUnitIndex - LLViewerTexture* specular = NULL; - if (LLPipeline::sImpostorRender) - { - specular = LLViewerTextureManager::findFetchedTexture(gBlackSquareID, TEX_LIST_STANDARD); - llassert(NULL != specular); - } - else - { - specular = face->getTexture(LLRender::SPECULAR_MAP); - } - if (specular) - { - gGL.getTexUnit(specular_channel)->bind(specular); - } - - gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP), false, true); - - - LLColor4 col = mat->getSpecularLightColor(); - F32 spec = mat->getSpecularLightExponent()/255.f; - - F32 env = mat->getEnvironmentIntensity()/255.f; - - if (mat->getSpecularID().isNull()) - { - env = tex_entry->getShiny()*0.25f; - col.set(env,env,env,0); - spec = env; - } - - BOOL fullbright = tex_entry->getFullbright(); - - sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f); - sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec); - sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env); - - if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - F32 cutoff = mat->getAlphaMaskCutoff()/255.f; - sVertexProgram->setMinimumAlpha(cutoff); - } - else - { - sVertexProgram->setMinimumAlpha(0.f); - } - - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - LLViewerTexture* tex = face->getTexture(i); - if (tex) - { - tex->addTextureStats(avatar->getPixelArea()); - } - } - } - else - { - gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); - sVertexProgram->setMinimumAlpha(0.f); - if (normal_channel > -1) - { - LLDrawPoolBump::bindBumpMap(face, normal_channel); - } - } - - if (face->mTextureMatrix && vobj->mTexAnimMode) - { - U32 tex_index = gGL.getCurrentTexUnitIndex(); - - if (tex_index <= 1) - { - gGL.matrixMode(LLRender::eMatrixMode(LLRender::MM_TEXTURE0 + tex_index)); - gGL.pushMatrix(); - gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix); - } - - buff->setBuffer(data_mask); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); - - if (tex_index <= 1) - { - gGL.matrixMode(LLRender::eMatrixMode(LLRender::MM_TEXTURE0 + tex_index)); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - } - else - { - buff->setBuffer(data_mask); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); - } - - gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); - } - } -} - -void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); -} - -void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_DEFERRED_BUMP); -} - -void LLDrawPoolAvatar::renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass) -{ - renderRigged(avatar, pass); -} - static LLTrace::BlockTimerStatHandle FTM_RIGGED_VBO("Rigged VBO"); -void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar) -{ - LL_RECORD_BLOCK_TIME(FTM_RIGGED_VBO); - - //update rigged vertex buffers - for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type) - { - for (U32 i = 0; i < mRiggedFace[type].size(); ++i) - { - LLFace* face = mRiggedFace[type][i]; - LLDrawable* drawable = face->getDrawable(); - if (!drawable) - { - continue; - } - - LLVOVolume* vobj = drawable->getVOVolume(); - - if (!vobj || vobj->isNoLOD()) - { - continue; - } - - LLVolume* volume = vobj->getVolume(); - S32 te = face->getTEOffset(); - - if (!volume || volume->getNumVolumeFaces() <= te) - { - continue; - } - - const LLMeshSkinInfo* skin = vobj->getSkinInfo(); - if (!skin) - { - continue; - } - - stop_glerror(); - - LLVolumeFace& vol_face = volume->getVolumeFace(te); - updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); - } - } -} - -void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_SIMPLE); -} - -void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_FULLBRIGHT); -} - - -void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_SHINY); -} - -void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) -{ - renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY); -} - -void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) -{ - if (!mRiggedFace[RIGGED_ALPHA].empty()) - { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - renderRigged(avatar, RIGGED_ALPHA); - gGL.setColorMask(true, false); - } -} - -void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) -{ - if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) - { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); - gGL.setColorMask(true, false); - } -} - -void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) -{ - if (!mRiggedFace[RIGGED_GLOW].empty()) - { - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.flush(); - - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.setColorMask(false, true); - - renderRigged(avatar, RIGGED_GLOW, true); - - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } -} - - - //----------------------------------------------------------------------------- // getDebugTexture() //----------------------------------------------------------------------------- LLViewerTexture *LLDrawPoolAvatar::getDebugTexture() { + LL_PROFILE_ZONE_SCOPED + if (mReferences.empty()) { return NULL; @@ -2495,68 +931,12 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const return LLColor3(0.f, 1.f, 0.f); } -void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) -{ - llassert (facep->isState(LLFace::RIGGED)); - llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV); - if (facep->getPool() && facep->getPool() != this) - { - LL_ERRS() << "adding rigged face that's already in another pool" << LL_ENDL; - } - if (type >= NUM_RIGGED_PASSES) - { - LL_ERRS() << "Invalid rigged face type." << LL_ENDL; - } - if (facep->getRiggedIndex(type) != -1) - { - LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL; - } - - facep->setRiggedIndex(type, mRiggedFace[type].size()); - facep->setPool(this); - mRiggedFace[type].push_back(facep); -} - -void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep) -{ - llassert (facep->isState(LLFace::RIGGED)); - llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV); - if (facep->getPool() != this) - { - LL_ERRS() << "Tried to remove a rigged face from the wrong pool" << LL_ENDL; - } - facep->setPool(NULL); - - for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) - { - S32 index = facep->getRiggedIndex(i); - - if (index > -1) - { - if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep) - { - facep->setRiggedIndex(i,-1); - mRiggedFace[i].erase(mRiggedFace[i].begin()+index); - for (U32 j = index; j < mRiggedFace[i].size(); ++j) - { //bump indexes down for faces referenced after erased face - mRiggedFace[i][j]->setRiggedIndex(i, j); - } - } - else - { - LL_ERRS() << "Face reference data corrupt for rigged type " << i - << ((mRiggedFace[i].size() <= index) ? "; wrong index (out of bounds)" : (mRiggedFace[i][index] != facep) ? "; wrong face pointer" : "") - << LL_ENDL; - } - } - } -} LLVertexBufferAvatar::LLVertexBufferAvatar() : LLVertexBuffer(sDataMask, GL_STREAM_DRAW_ARB) //avatars are always stream draw due to morph targets { - + LL_PROFILE_ZONE_SCOPED } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 92a8538958..21add39b21 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -28,14 +28,18 @@ #define LL_LLDRAWPOOLAVATAR_H #include "lldrawpool.h" +#include "llmodel.h" + +#include <unordered_map> class LLVOAvatar; +class LLVOVolume; class LLGLSLShader; class LLFace; -class LLMeshSkinInfo; class LLVolume; class LLVolumeFace; +extern U32 gFrameCount; class LLDrawPoolAvatar : public LLFacePool { @@ -58,119 +62,11 @@ public: ~LLDrawPoolAvatar(); /*virtual*/ BOOL isDead(); - typedef enum - { - RIGGED_MATERIAL=0, - RIGGED_MATERIAL_ALPHA, - RIGGED_MATERIAL_ALPHA_MASK, - RIGGED_MATERIAL_ALPHA_EMISSIVE, - RIGGED_SPECMAP, - RIGGED_SPECMAP_BLEND, - RIGGED_SPECMAP_MASK, - RIGGED_SPECMAP_EMISSIVE, - RIGGED_NORMMAP, - RIGGED_NORMMAP_BLEND, - RIGGED_NORMMAP_MASK, - RIGGED_NORMMAP_EMISSIVE, - RIGGED_NORMSPEC, - RIGGED_NORMSPEC_BLEND, - RIGGED_NORMSPEC_MASK, - RIGGED_NORMSPEC_EMISSIVE, - RIGGED_SIMPLE, - RIGGED_FULLBRIGHT, - RIGGED_SHINY, - RIGGED_FULLBRIGHT_SHINY, - RIGGED_GLOW, - RIGGED_ALPHA, - RIGGED_FULLBRIGHT_ALPHA, - RIGGED_DEFERRED_BUMP, - RIGGED_DEFERRED_SIMPLE, - NUM_RIGGED_PASSES, - RIGGED_UNKNOWN, - } eRiggedPass; - - typedef enum - { - RIGGED_MATERIAL_MASK = - LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_MATERIAL_ALPHA_VMASK = RIGGED_MATERIAL_MASK, - RIGGED_MATERIAL_ALPHA_MASK_MASK = RIGGED_MATERIAL_MASK, - RIGGED_MATERIAL_ALPHA_EMISSIVE_MASK = RIGGED_MATERIAL_MASK, - RIGGED_SPECMAP_VMASK = - LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_TEXCOORD2 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_SPECMAP_BLEND_MASK = RIGGED_SPECMAP_VMASK, - RIGGED_SPECMAP_MASK_MASK = RIGGED_SPECMAP_VMASK, - RIGGED_SPECMAP_EMISSIVE_MASK = RIGGED_SPECMAP_VMASK, - RIGGED_NORMMAP_VMASK = - LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TANGENT | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_TEXCOORD1 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_NORMMAP_BLEND_MASK = RIGGED_NORMMAP_VMASK, - RIGGED_NORMMAP_MASK_MASK = RIGGED_NORMMAP_VMASK, - RIGGED_NORMMAP_EMISSIVE_MASK = RIGGED_NORMMAP_VMASK, - RIGGED_NORMSPEC_VMASK = - LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TANGENT | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_TEXCOORD1 | - LLVertexBuffer::MAP_TEXCOORD2 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_NORMSPEC_BLEND_MASK = RIGGED_NORMSPEC_VMASK, - RIGGED_NORMSPEC_MASK_MASK = RIGGED_NORMSPEC_VMASK, - RIGGED_NORMSPEC_EMISSIVE_MASK = RIGGED_NORMSPEC_VMASK, - RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_FULLBRIGHT_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_SHINY_MASK = RIGGED_SIMPLE_MASK, - RIGGED_FULLBRIGHT_SHINY_MASK = RIGGED_SIMPLE_MASK, - RIGGED_GLOW_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_EMISSIVE | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_ALPHA_MASK = RIGGED_SIMPLE_MASK, - RIGGED_FULLBRIGHT_ALPHA_MASK = RIGGED_FULLBRIGHT_MASK, - RIGGED_DEFERRED_BUMP_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_TANGENT | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - RIGGED_DEFERRED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4, - } eRiggedDataMask; - typedef enum { SHADOW_PASS_AVATAR_OPAQUE, SHADOW_PASS_AVATAR_ALPHA_BLEND, SHADOW_PASS_AVATAR_ALPHA_MASK, - SHADOW_PASS_ATTACHMENT_ALPHA_BLEND, - SHADOW_PASS_ATTACHMENT_ALPHA_MASK, - SHADOW_PASS_ATTACHMENT_OPAQUE, NUM_SHADOW_PASSES } eShadowPass; @@ -211,78 +107,19 @@ typedef enum void endImpostor(); void endSkinned(); - void beginDeferredImpostor(); - void beginDeferredRigid(); - void beginDeferredSkinned(); - - void endDeferredImpostor(); - void endDeferredRigid(); - void endDeferredSkinned(); - - void beginPostDeferredAlpha(); - void endPostDeferredAlpha(); - - void beginRiggedSimple(); - void beginRiggedFullbright(); - void beginRiggedFullbrightShiny(); - void beginRiggedShinySimple(); - void beginRiggedAlpha(); - void beginRiggedFullbrightAlpha(); - void beginRiggedGlow(); - void beginDeferredRiggedAlpha(); - void beginDeferredRiggedMaterial(S32 pass); - void beginDeferredRiggedMaterialAlpha(S32 pass); + void beginDeferredRigid(); + void beginDeferredImpostor(); + void beginDeferredSkinned(); - void endRiggedSimple(); - void endRiggedFullbright(); - void endRiggedFullbrightShiny(); - void endRiggedShinySimple(); - void endRiggedAlpha(); - void endRiggedFullbrightAlpha(); - void endRiggedGlow(); - void endDeferredRiggedAlpha(); - void endDeferredRiggedMaterial(S32 pass); - void endDeferredRiggedMaterialAlpha(S32 pass); - - void beginDeferredRiggedSimple(); - void beginDeferredRiggedBump(); - - void endDeferredRiggedSimple(); - void endDeferredRiggedBump(); - - void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face); - void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, - LLFace* facep, - const LLMeshSkinInfo* skin, - LLVolume* volume, - LLVolumeFace& vol_face); - void updateRiggedVertexBuffers(LLVOAvatar* avatar); - - void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); - void renderRiggedSimple(LLVOAvatar* avatar); - void renderRiggedAlpha(LLVOAvatar* avatar); - void renderRiggedFullbrightAlpha(LLVOAvatar* avatar); - void renderRiggedFullbright(LLVOAvatar* avatar); - void renderRiggedShinySimple(LLVOAvatar* avatar); - void renderRiggedFullbrightShiny(LLVOAvatar* avatar); - void renderRiggedGlow(LLVOAvatar* avatar); - void renderDeferredRiggedSimple(LLVOAvatar* avatar); - void renderDeferredRiggedBump(LLVOAvatar* avatar); - void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass); - - - - void addRiggedFace(LLFace* facep, U32 type); - void removeRiggedFace(LLFace* facep); - - std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES]; + void endDeferredRigid(); + void endDeferredImpostor(); + void endDeferredSkinned(); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. - static BOOL sSkipOpaque; static BOOL sSkipTransparent; static S32 sShadowPass; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 14069fa6c2..b01450bba9 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -47,6 +47,7 @@ #include "pipeline.h" #include "llspatialpartition.h" #include "llviewershadermgr.h" +#include "llmodel.h" //#include "llimagebmp.h" //#include "../tools/imdebug/imdebug.h" @@ -199,32 +200,7 @@ void LLDrawPoolBump::prerender() // static S32 LLDrawPoolBump::numBumpPasses() { - if (gSavedSettings.getBOOL("RenderObjectBump")) - { - if (mShaderLevel > 1) - { - if (LLPipeline::sImpostorRender) - { - return 2; - } - else - { - return 3; - } - } - else if (LLPipeline::sImpostorRender) - { - return 1; - } - else - { - return 2; - } - } - else - { - return 0; - } + return 1; } S32 LLDrawPoolBump::getNumPasses() @@ -232,140 +208,79 @@ S32 LLDrawPoolBump::getNumPasses() return numBumpPasses(); } -void LLDrawPoolBump::beginRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - switch( pass ) - { - case 0: - beginShiny(); - break; - case 1: - if (mShaderLevel > 1) - { - beginFullbrightShiny(); - } - else - { - beginBump(); - } - break; - case 2: - beginBump(); - break; - default: - llassert(0); - break; - } -} - void LLDrawPoolBump::render(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - - if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE)) - { - return; - } - - switch( pass ) - { - case 0: - renderShiny(); - break; - case 1: - if (mShaderLevel > 1) - { - renderFullbrightShiny(); - } - else - { - renderBump(); - } - break; - case 2: - renderBump(); - break; - default: - llassert(0); - break; - } -} + LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); -void LLDrawPoolBump::endRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - switch( pass ) - { - case 0: - endShiny(); - break; - case 1: - if (mShaderLevel > 1) - { - endFullbrightShiny(); - } - else - { - endBump(); - } - break; - case 2: - endBump(); - break; - default: - llassert(0); - break; - } + if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE)) + { + return; + } + + for (int i = 0; i < 2; ++i) + { + mRigged = i == 1; + + // first pass -- shiny + beginShiny(); + renderShiny(); + endShiny(); - //to cleanup texture channels - LLRenderPass::endRenderPass(pass); + //second pass -- fullbright shiny + if (mShaderLevel > 1) + { + beginFullbrightShiny(); + renderFullbrightShiny(); + endFullbrightShiny(); + } + + //third pass -- bump + beginBump(); + renderBump(LLRenderPass::PASS_BUMP); + endBump(); + } } + //static -void LLDrawPoolBump::beginShiny(bool invisible) +void LLDrawPoolBump::beginShiny() { LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) - { - return; - } - + mShiny = TRUE; sVertexMask = VERTEX_MASK_SHINY; // Second pass: environment map - if (!invisible && mShaderLevel > 1) + if (mShaderLevel > 1) { sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } - if (getShaderLevel() > 0) + if (LLPipeline::sUnderWaterRender) { - if (LLPipeline::sUnderWaterRender) - { - shader = &gObjectShinyWaterProgram; - } - else - { - shader = &gObjectShinyProgram; - } - shader->bind(); - if (LLPipeline::sRenderingHUDs) - { - shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } + shader = &gObjectShinyWaterProgram; } else { - shader = NULL; + shader = &gObjectShinyProgram; } - bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible); + if (mRigged) + { + llassert(shader->mRiggedVariant); + shader = shader->mRiggedVariant; + } + + shader->bind(); + if (LLPipeline::sRenderingHUDs) + { + shader->uniform1i(LLShaderMgr::NO_ATMO, 1); + } + else + { + shader->uniform1i(LLShaderMgr::NO_ATMO, 0); + } + + bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel); if (mShaderLevel > 1) { //indexed texture rendering, channel 0 is always diffuse @@ -374,12 +289,12 @@ void LLDrawPoolBump::beginShiny(bool invisible) } //static -void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) +void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel) { LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - if (!invisible && shader ) + if (shader ) { LLMatrix4 mat; mat.initRows(LLVector4(gGLModelView+0), @@ -391,19 +306,16 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); if (shader_level > 1) { - cube_map->setMatrix(1); // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for // the cube map in the one pass shiny shaders cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); cube_map->enableTexture(cube_channel); - cube_map->enableTextureCoords(1); diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } else { cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); diffuse_channel = -1; - cube_map->setMatrix(0); cube_map->enable(cube_channel); } gGL.getTexUnit(cube_channel)->bind(cube_map); @@ -415,49 +327,50 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di diffuse_channel = -1; gGL.getTexUnit(0)->disable(); cube_map->enable(0); - cube_map->setMatrix(0); gGL.getTexUnit(0)->bind(cube_map); - - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_ALPHA); } } } -void LLDrawPoolBump::renderShiny(bool invisible) +void LLDrawPoolBump::renderShiny() { LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) - { - return; - } - + if( gSky.mVOSkyp->getCubeMap() ) { LLGLEnable blend_enable(GL_BLEND); - if (!invisible && mShaderLevel > 1) + if (mShaderLevel > 1) { - LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + if (mRigged) + { + LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_SHINY_RIGGED, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } + else + { + LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } } - else if (!invisible) + else { - renderGroups(LLRenderPass::PASS_SHINY, sVertexMask); + if (mRigged) + { + gPipeline.renderRiggedGroups(this, LLRenderPass::PASS_SHINY_RIGGED, sVertexMask, TRUE); + } + else + { + gPipeline.renderGroups(this, LLRenderPass::PASS_SHINY, sVertexMask, TRUE); + } } - //else // invisible (deprecated) - //{ - //renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask); - //} } } //static -void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) +void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel) { LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - if (!invisible && shader_level > 1) + if (shader_level > 1) { shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); @@ -472,29 +385,14 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& // Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0 // MAINT-755 cube_map->disable(); - cube_map->restoreMatrix(); - } - - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.getTexUnit(diffuse_channel)->disable(); - gGL.getTexUnit(cube_channel)->disable(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } } -void LLDrawPoolBump::endShiny(bool invisible) +void LLDrawPoolBump::endShiny() { LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) - { - return; - } - unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible); + unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel); if (shader) { shader->unbind(); @@ -508,11 +406,7 @@ void LLDrawPoolBump::endShiny(bool invisible) void LLDrawPoolBump::beginFullbrightShiny() { LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) - { - return; - } - + sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; // Second pass: environment map @@ -533,6 +427,12 @@ void LLDrawPoolBump::beginFullbrightShiny() } } + if (mRigged) + { + llassert(shader->mRiggedVariant); + shader = shader->mRiggedVariant; + } + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { @@ -553,15 +453,13 @@ void LLDrawPoolBump::beginFullbrightShiny() LLVector3 vec = LLVector3(gShinyOrigin) * mat; LLVector4 vec4(vec, gShinyOrigin.mV[3]); - shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); + shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); - cube_map->setMatrix(1); // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for // the cube map in the one pass shiny shaders gGL.getTexUnit(1)->disable(); cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); cube_map->enableTexture(cube_channel); - cube_map->enableTextureCoords(1); diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); gGL.getTexUnit(cube_channel)->bind(cube_map); @@ -579,10 +477,6 @@ void LLDrawPoolBump::beginFullbrightShiny() void LLDrawPoolBump::renderFullbrightShiny() { LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) - { - return; - } if( gSky.mVOSkyp->getCubeMap() ) { @@ -590,11 +484,25 @@ void LLDrawPoolBump::renderFullbrightShiny() if (mShaderLevel > 1) { - LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + if (mRigged) + { + LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } + else + { + LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } } else { - LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask); + if (mRigged) + { + LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, sVertexMask); + } + else + { + LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask); + } } } } @@ -602,31 +510,14 @@ void LLDrawPoolBump::renderFullbrightShiny() void LLDrawPoolBump::endFullbrightShiny() { LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY)) - { - return; - } LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { cube_map->disable(); - cube_map->restoreMatrix(); - - /*if (diffuse_channel != 0) - { - shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);*/ - shader->unbind(); - //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } - //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - diffuse_channel = -1; cube_channel = 0; mShiny = FALSE; @@ -677,6 +568,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel) //static BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel) { + LL_PROFILE_ZONE_SCOPED; //Note: texture atlas does not support bump texture now. LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; if(!tex) @@ -693,7 +585,7 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi break; case BE_BRIGHTNESS: case BE_DARKNESS: - bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); + bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); break; default: @@ -709,12 +601,13 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi { if (channel == -2) { - gGL.getTexUnit(1)->bind(bump); - gGL.getTexUnit(0)->bind(bump); + gGL.getTexUnit(1)->bindFast(bump); + gGL.getTexUnit(0)->bindFast(bump); } else { - gGL.getTexUnit(channel)->bind(bump); + // NOTE: do not use bindFast here (see SL-16222) + gGL.getTexUnit(channel)->bind(bump); } return TRUE; @@ -724,53 +617,22 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi } //static -void LLDrawPoolBump::beginBump(U32 pass) +void LLDrawPoolBump::beginBump() { - if (!gPipeline.hasRenderBatches(pass)) - { - return; - } - sVertexMask = VERTEX_MASK_BUMP; LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); // Optional second pass: emboss bump map stop_glerror(); - if (LLGLSLShader::sNoFixedFunction) - { - gObjectBumpProgram.bind(); - } - else - { - // TEXTURE UNIT 0 - // Output.rgb = texture at texture coord 0 - gGL.getTexUnit(0)->activate(); - - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + shader = &gObjectBumpProgram; - // TEXTURE UNIT 1 - gGL.getTexUnit(1)->activate(); - - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + if (mRigged) + { + llassert(shader->mRiggedVariant); + shader = shader->mRiggedVariant; + } - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - - // src = tex0 + (1 - tex1) - 0.5 - // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5 - // = (1 + bump0 - bump1) / 2 - - - // Blend: src * dst + dst * src - // = 2 * src * dst - // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst] - // = (1 + bump0 - bump1) * dst.rgb - // = dst.rgb + dst.rgb * (bump0 - bump1) - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); - } + shader->bind(); gGL.setSceneBlendType(LLRender::BT_MULT_X2); stop_glerror(); @@ -779,11 +641,6 @@ void LLDrawPoolBump::beginBump(U32 pass) //static void LLDrawPoolBump::renderBump(U32 pass) { - if (!gPipeline.hasRenderBatches(pass)) - { - return; - } - LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); LLGLDisable fog(GL_FOG); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL); @@ -798,28 +655,9 @@ void LLDrawPoolBump::renderBump(U32 pass) //static void LLDrawPoolBump::endBump(U32 pass) { - if (!gPipeline.hasRenderBatches(pass)) - { - return; - } - - if (LLGLSLShader::sNoFixedFunction) - { - gObjectBumpProgram.unbind(); - } - else - { - // Disable texture blending on unit 1 - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + gObjectBumpProgram.unbind(); - // Disable texture blending on unit 0 - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } - - gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } S32 LLDrawPoolBump::getNumDeferredPasses() @@ -834,101 +672,81 @@ S32 LLDrawPoolBump::getNumDeferredPasses() } } -void LLDrawPoolBump::beginDeferredPass(S32 pass) -{ - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) - { - return; - } - LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - mShiny = TRUE; - gDeferredBumpProgram.bind(); - diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP); - gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE); -} - -void LLDrawPoolBump::endDeferredPass(S32 pass) -{ - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) - { - return; - } - LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - mShiny = FALSE; - gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP); - gDeferredBumpProgram.unbind(); - gGL.getTexUnit(0)->activate(); -} - void LLDrawPoolBump::renderDeferred(S32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) - { - return; - } LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - U32 type = LLRenderPass::PASS_BUMP; - LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); + mShiny = TRUE; + for (int i = 0; i < 2; ++i) + { + bool rigged = i == 1; + gDeferredBumpProgram.bind(rigged); + diffuse_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + bump_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::BUMP_MAP); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE); - U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; - - for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) - { - LLDrawInfo& params = **i; + U32 type = rigged ? LLRenderPass::PASS_BUMP_RIGGED : LLRenderPass::PASS_BUMP; + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff); - LLDrawPoolBump::bindBumpMap(params, bump_channel); - pushBatch(params, mask, TRUE); - } -} + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; -void LLDrawPoolBump::beginPostDeferredPass(S32 pass) -{ - switch (pass) - { - case 0: - beginFullbrightShiny(); - break; - case 1: - beginBump(LLRenderPass::PASS_POST_BUMP); - break; - } -} + LLVOAvatar* avatar = nullptr; + U64 skin = 0; -void LLDrawPoolBump::endPostDeferredPass(S32 pass) -{ - switch (pass) - { - case 0: - endFullbrightShiny(); - break; - case 1: - endBump(LLRenderPass::PASS_POST_BUMP); - break; - } + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + { + LLDrawInfo& params = **i; + + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff); + LLDrawPoolBump::bindBumpMap(params, bump_channel); + + if (rigged) + { + if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash) + { + uploadMatrixPalette(params); + avatar = params.mAvatar; + skin = params.mSkinInfo->mHash; + } + pushBatch(params, mask | LLVertexBuffer::MAP_WEIGHT4, TRUE, FALSE); + } + else + { + pushBatch(params, mask, TRUE, FALSE); + } + } - //to disable texture channels - LLRenderPass::endRenderPass(pass); + LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::BUMP_MAP); + LLGLSLShader::sCurBoundShaderPtr->unbind(); + gGL.getTexUnit(0)->activate(); + } + + mShiny = FALSE; } + void LLDrawPoolBump::renderPostDeferred(S32 pass) { - switch (pass) - { - case 0: - renderFullbrightShiny(); - break; - case 1: - renderBump(LLRenderPass::PASS_POST_BUMP); - break; - } + for (int i = 0; i < 2; ++i) + { // two passes -- static and rigged + mRigged = (i == 1); + + // render shiny + beginFullbrightShiny(); + renderFullbrightShiny(); + endFullbrightShiny(); + + //render bump + beginBump(); + renderBump(LLRenderPass::PASS_POST_BUMP); + endBump(); + } } + //////////////////////////////////////////////////////////////// // List of bump-maps created from other textures. @@ -1061,6 +879,7 @@ void LLBumpImageList::updateImages() // Note: the caller SHOULD NOT keep the pointer that this function returns. It may be updated as more data arrives. LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code ) { + LL_PROFILE_ZONE_SCOPED; llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) ); LLViewerTexture* bump = NULL; @@ -1113,11 +932,10 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText } -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_STANDARD_LOADED("Bump Standard Callback"); - // static void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { + LL_PROFILE_ZONE_SCOPED; LLUUID* source_asset_id = (LLUUID*)userdata; LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS ); if( final ) @@ -1137,22 +955,17 @@ void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerFetchedTextu } } -static LLTrace::BlockTimerStatHandle FTM_BUMP_GEN_NORMAL("Generate Normal Map"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_CREATE_TEXTURE("Create GL Normal Map"); - void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { if (success && LLPipeline::sRenderDeferred) { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_STANDARD_LOADED); + LL_PROFILE_ZONE_SCOPED; LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); { - LL_RECORD_BLOCK_TIME(FTM_BUMP_GEN_NORMAL); generateNormalMapFromAlpha(src, nrm_image); } src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); { - LL_RECORD_BLOCK_TIME(FTM_BUMP_CREATE_TEXTURE); src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image); } } @@ -1213,28 +1026,18 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr } } - -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_LOADED("Bump Source Loaded"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_ENTRIES_UPDATE("Entries Update"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_MIN_MAX("Min/Max"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_RGB2LUM("RGB to Luminance"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_RESCALE("Rescale"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_GEN_NORMAL("Generate Normal"); -static LLTrace::BlockTimerStatHandle FTM_BUMP_SOURCE_CREATE("Bump Source Create"); - // static void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code ) { if( success ) { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_LOADED); + LL_PROFILE_ZONE_SCOPED; bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries ); bump_image_map_t::iterator iter = entries_list.find(source_asset_id); { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_ENTRIES_UPDATE); if (iter == entries_list.end() || iter->second.isNull() || iter->second->getWidth() != src->getWidth() || @@ -1277,7 +1080,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI case 1: case 2: { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_MIN_MAX); if( src_data_size == dst_data_size * src_components ) { for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components ) @@ -1303,7 +1105,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI case 3: case 4: { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_RGB2LUM); if( src_data_size == dst_data_size * src_components ) { for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components ) @@ -1336,7 +1137,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI if( maximum > minimum ) { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_RESCALE); U8 bias_and_scale_lut[256]; F32 twice_one_over_range = 2.f / (maximum - minimum); S32 i; @@ -1372,7 +1172,6 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI if (!LLPipeline::sRenderDeferred) { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_CREATE); bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); bump->createGLTexture(0, dst_image); } @@ -1383,13 +1182,11 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump->getGLTexture()->setAllowCompression(false); { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_CREATE); bump->setExplicitFormat(GL_RGBA8, GL_ALPHA); bump->createGLTexture(0, dst_image); } { - LL_RECORD_BLOCK_TIME(FTM_BUMP_SOURCE_GEN_NORMAL); gPipeline.mScreen.bindTarget(); LLGLDepthTest depth(GL_FALSE); @@ -1481,8 +1278,17 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI void LLDrawPoolBump::renderBump(U32 type, U32 mask) { - LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); + LLVOAvatar* avatar = nullptr; + U64 skin = 0; + + if (mRigged) + { // nudge type enum and include skinweights for rigged pass + type += 1; + mask |= LLVertexBuffer::MAP_WEIGHT4; + } + + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { @@ -1490,6 +1296,21 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) if (LLDrawPoolBump::bindBumpMap(params)) { + if (mRigged) + { + if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash) + { + if (uploadMatrixPalette(params)) + { + avatar = params.mAvatar; + skin = params.mSkinInfo->mHash; + } + else + { + continue; + } + } + } pushBatch(params, mask, FALSE); } } @@ -1497,6 +1318,7 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { + LL_PROFILE_ZONE_SCOPED; applyModelMatrix(params); bool tex_setup = false; @@ -1507,7 +1329,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL { if (params.mTextureList[i].notNull()) { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); } } } @@ -1522,13 +1344,6 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL } else { - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.getTexUnit(1)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - } - gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); @@ -1545,8 +1360,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL { if (params.mTexture.notNull()) { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture); - params.mTexture->addTextureStats(params.mVSize); + gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture); } else { @@ -1559,10 +1373,10 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL { params.mGroup->rebuildMesh(); } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - if (tex_setup) + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + + if (tex_setup) { if (mShiny) { @@ -1570,12 +1384,6 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL } else { - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.getTexUnit(1)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - } gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); } @@ -1588,7 +1396,7 @@ void LLDrawPoolInvisible::render(S32 pass) { //render invisiprims LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE); - if (gPipeline.canUseVertexShaders()) + if (gPipeline.shadersLoaded()) { gOcclusionProgram.bind(); } @@ -1600,48 +1408,8 @@ void LLDrawPoolInvisible::render(S32 pass) gGL.setColorMask(true, false); glStencilMask(0xFFFFFFFF); - if (gPipeline.canUseVertexShaders()) + if (gPipeline.shadersLoaded()) { gOcclusionProgram.unbind(); } - - if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) - { - beginShiny(true); - renderShiny(true); - endShiny(true); - } -} - -void LLDrawPoolInvisible::beginDeferredPass(S32 pass) -{ - beginRenderPass(pass); -} - -void LLDrawPoolInvisible::endDeferredPass( S32 pass ) -{ - endRenderPass(pass); -} - -void LLDrawPoolInvisible::renderDeferred( S32 pass ) -{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff -#if 0 - LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE); - - U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; - glStencilMask(0); - glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE); - gGL.setColorMask(false, false); - pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE); - gGL.setColorMask(true, true); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glStencilMask(0xFFFFFFFF); - - if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) - { - beginShiny(true); - renderShiny(true); - endShiny(true); - } -#endif } diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 476b1d41b7..38744a7d98 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -32,6 +32,8 @@ #include "lltextureentry.h" #include "lluuid.h" +#include <unordered_map> + class LLImageRaw; class LLSpatialGroup; class LLDrawInfo; @@ -46,52 +48,47 @@ public: static U32 sVertexMask; BOOL mShiny; - virtual U32 getVertexDataMask() { return sVertexMask; } + virtual U32 getVertexDataMask() override { return sVertexMask; } LLDrawPoolBump(); - virtual void render(S32 pass = 0); - virtual void beginRenderPass( S32 pass ); - virtual void endRenderPass( S32 pass ); - virtual S32 getNumPasses(); - /*virtual*/ void prerender(); - /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); + virtual void render(S32 pass = 0) override; + virtual S32 getNumPasses() override; + /*virtual*/ void prerender() override; + void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE) override; void renderBump(U32 type, U32 mask); - void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture); + void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) override; S32 numBumpPasses(); - void beginShiny(bool invisible = false); - void renderShiny(bool invisible = false); - void endShiny(bool invisible = false); + void beginShiny(); + void renderShiny(); + void endShiny(); void beginFullbrightShiny(); void renderFullbrightShiny(); void endFullbrightShiny(); - void beginBump(U32 pass = LLRenderPass::PASS_BUMP); + void beginBump(); void renderBump(U32 pass = LLRenderPass::PASS_BUMP); void endBump(U32 pass = LLRenderPass::PASS_BUMP); - static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); - static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); + static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel); + static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel); - virtual S32 getNumDeferredPasses(); - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); + virtual S32 getNumDeferredPasses() override; + /*virtual*/ void renderDeferred(S32 pass) override; - virtual S32 getNumPostDeferredPasses() { return 2; } - /*virtual*/ void beginPostDeferredPass(S32 pass); - /*virtual*/ void endPostDeferredPass(S32 pass); - /*virtual*/ void renderPostDeferred(S32 pass); + virtual S32 getNumPostDeferredPasses() override { return 1; } + /*virtual*/ void renderPostDeferred(S32 pass) override; static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); static BOOL bindBumpMap(LLFace* face, S32 channel = -2); private: static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel); + bool mRigged = false; // if true, doing a rigged pass }; @@ -161,17 +158,17 @@ private: static void onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump ); private: - typedef std::map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t; + typedef std::unordered_map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t; bump_image_map_t mBrightnessEntries; bump_image_map_t mDarknessEntries; }; extern LLBumpImageList gBumpImageList; -class LLDrawPoolInvisible : public LLDrawPoolBump +class LLDrawPoolInvisible : public LLRenderPass { public: - LLDrawPoolInvisible() : LLDrawPoolBump(LLDrawPool::POOL_INVISIBLE) { } + LLDrawPoolInvisible() : LLRenderPass(LLDrawPool::POOL_INVISIBLE) { } enum { @@ -186,11 +183,6 @@ public: virtual void beginRenderPass( S32 pass ) { } virtual void endRenderPass( S32 pass ) { } virtual S32 getNumPasses() {return 1;} - - virtual S32 getNumDeferredPasses() { return 1; } - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); }; diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 05b0c1f1a9..fd5850084b 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -31,6 +31,7 @@ #include "llviewershadermgr.h" #include "pipeline.h" #include "llglcommonfunc.h" +#include "llvoavatar.h" S32 diffuse_channel = -1; @@ -47,11 +48,18 @@ void LLDrawPoolMaterials::prerender() S32 LLDrawPoolMaterials::getNumDeferredPasses() { - return 12; + // 12 render passes times 2 (one for each rigged and non rigged) + return 12*2; } void LLDrawPoolMaterials::beginDeferredPass(S32 pass) { + bool rigged = false; + if (pass >= 12) + { + rigged = true; + pass -= 12; + } U32 shader_idx[] = { 0, //LLRenderPass::PASS_MATERIAL, @@ -72,13 +80,22 @@ void LLDrawPoolMaterials::beginDeferredPass(S32 pass) 15, //LLRenderPass::PASS_NORMSPEC_GLOW, }; - mShader = &(gDeferredMaterialProgram[shader_idx[pass]]); - - if (LLPipeline::sUnderWaterRender) - { - mShader = &(gDeferredMaterialWaterProgram[shader_idx[pass]]); - } - + U32 idx = shader_idx[pass]; + + if (LLPipeline::sUnderWaterRender) + { + mShader = &(gDeferredMaterialWaterProgram[idx]); + } + else + { + mShader = &(gDeferredMaterialProgram[idx]); + } + + if (rigged) + { + llassert(mShader->mRiggedVariant != nullptr); + mShader = mShader->mRiggedVariant; + } mShader->bind(); if (LLPipeline::sRenderingHUDs) @@ -106,6 +123,7 @@ void LLDrawPoolMaterials::endDeferredPass(S32 pass) void LLDrawPoolMaterials::renderDeferred(S32 pass) { + LL_PROFILE_ZONE_SCOPED; static const U32 type_list[] = { LLRenderPass::PASS_MATERIAL, @@ -126,9 +144,20 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) LLRenderPass::PASS_NORMSPEC_EMISSIVE, }; + bool rigged = false; + if (pass >= 12) + { + rigged = true; + pass -= 12; + } + llassert(pass < sizeof(type_list)/sizeof(U32)); U32 type = type_list[pass]; + if (rigged) + { + type += 1; + } U32 mask = mShader->mAttributeMask; @@ -157,7 +186,10 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) mShader->setMinimumAlpha(params.mAlphaMaskCutoff); mShader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f); - pushBatch(params, mask, TRUE); + { + LL_PROFILE_ZONE_SCOPED; + pushMaterialsBatch(params, mask, rigged); + } } } @@ -171,49 +203,37 @@ void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex) mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex); } -void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) +void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool rigged) { + LL_PROFILE_ZONE_SCOPED; applyModelMatrix(params); bool tex_setup = false; - if (batch_textures && params.mTextureList.size() > 1) + //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTextureMatrix) { - for (U32 i = 0; i < params.mTextureList.size(); ++i) + //if (mShiny) { - if (params.mTextureList[i].notNull()) - { - gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); - } + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); } - } - else - { //not batching textures or batch has only 1 texture -- might need a texture matrix - if (params.mTextureMatrix) - { - //if (mShiny) - { - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - } - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; - tex_setup = true; - } + tex_setup = true; + } - if (mShaderLevel > 1 && texture) + if (mShaderLevel > 1) + { + if (params.mTexture.notNull()) { - if (params.mTexture.notNull()) - { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture); - params.mTexture->addTextureStats(params.mVSize); - } - else - { - gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); - } + gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture); + } + else + { + gGL.getTexUnit(diffuse_channel)->unbindFast(LLTexUnit::TT_TEXTURE); } } @@ -222,11 +242,29 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, params.mGroup->rebuildMesh(); } + // upload matrix palette to shader + if (rigged) + { + const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo); + U32 count = mpc.mMatrixPalette.size(); + + if (count == 0) + { + //skin info not loaded yet, don't render + return; + } + + mShader->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + count, + FALSE, + (GLfloat*)&(mpc.mGLMp[0])); + } + LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + params.mVertexBuffer->setBufferFast(mask); + params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + if (tex_setup) { gGL.getTexUnit(0)->activate(); diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h index eae1aba87c..8a3ad923df 100644 --- a/indra/newview/lldrawpoolmaterials.h +++ b/indra/newview/lldrawpoolmaterials.h @@ -55,21 +55,21 @@ public: LLVertexBuffer::MAP_TANGENT }; - /*virtual*/ U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + U32 getVertexDataMask() override { return VERTEX_DATA_MASK; } - /*virtual*/ void render(S32 pass = 0) { } - /*virtual*/ S32 getNumPasses() {return 0;} - /*virtual*/ void prerender(); + void render(S32 pass = 0) override { } + S32 getNumPasses() override {return 0;} + void prerender() override; - /*virtual*/ S32 getNumDeferredPasses(); - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); + S32 getNumDeferredPasses() override; + void beginDeferredPass(S32 pass) override; + void endDeferredPass(S32 pass) override; + void renderDeferred(S32 pass) override; void bindSpecularMap(LLViewerTexture* tex); void bindNormalMap(LLViewerTexture* tex); - /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); + void pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool rigged); }; #endif //LL_LLDRAWPOOLMATERIALS_H diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index f211cf6e27..4ada753355 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -38,71 +38,54 @@ #include "llrender.h" static LLGLSLShader* simple_shader = NULL; -static LLGLSLShader* fullbright_shader = NULL; static LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple"); static LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS_DEFERRED("Deferred Grass"); -void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) + +static void setup_simple_shader(LLGLSLShader* shader) { - gDeferredEmissiveProgram.bind(); - gDeferredEmissiveProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + shader->bind(); + if (LLPipeline::sRenderingHUDs) - { - gDeferredEmissiveProgram.uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - gDeferredEmissiveProgram.uniform1i(LLShaderMgr::NO_ATMO, 0); - } + { + shader->uniform1i(LLShaderMgr::NO_ATMO, 1); + } + else + { + shader->uniform1i(LLShaderMgr::NO_ATMO, 0); + } } -static LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW_PUSH("Glow Push"); - -void LLDrawPoolGlow::renderPostDeferred(S32 pass) +static void setup_glow_shader(LLGLSLShader* shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW); - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.flush(); - /// Get rid of z-fighting with non-glow pass. - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.setColorMask(false, true); - - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW_PUSH); - pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - } - - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + setup_simple_shader(shader); + if (LLPipeline::sRenderDeferred && !LLPipeline::sRenderingHUDs) + { + shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); + } + else + { + shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f); + } } -void LLDrawPoolGlow::endPostDeferredPass(S32 pass) +static void setup_fullbright_shader(LLGLSLShader* shader) { - gDeferredEmissiveProgram.unbind(); - LLRenderPass::endRenderPass(pass); + setup_glow_shader(shader); + shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); } -S32 LLDrawPoolGlow::getNumPasses() + +void LLDrawPoolGlow::renderPostDeferred(S32 pass) { - if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) - { - return 1; - } - else - { - return 0; - } + LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW); + render(&gDeferredEmissiveProgram); } -void LLDrawPoolGlow::render(S32 pass) +void LLDrawPoolGlow::render(LLGLSLShader* shader) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW); + LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW); LLGLEnable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); gGL.flush(); @@ -111,51 +94,33 @@ void LLDrawPoolGlow::render(S32 pass) glPolygonOffset(-1.0f, -1.0f); gGL.setSceneBlendType(LLRender::BT_ADD); - U32 shader_level = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); - - //should never get here without basic shaders enabled - llassert(shader_level > 0); - - LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; - shader->bind(); - if (LLPipeline::sRenderDeferred) - { - shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - } - else - { - shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f); - } - - if (LLPipeline::sRenderingHUDs) - { - shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.setColorMask(false, true); - pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - if (shader_level > 0 && fullbright_shader) - { - shader->unbind(); - } + //first pass -- static objects + setup_glow_shader(shader); + pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + + // second pass -- rigged objects + shader = shader->mRiggedVariant; + setup_glow_shader(shader); + pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } -void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) +S32 LLDrawPoolGlow::getNumPasses() { - //gGL.diffuseColor4ubv(params.mGlowColor.mV); - LLRenderPass::pushBatch(params, mask, texture, batch_textures); + return 1; } +void LLDrawPoolGlow::render(S32 pass) +{ + LL_PROFILE_ZONE_SCOPED; + LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram; + render(shader); +} LLDrawPoolSimple::LLDrawPoolSimple() : LLRenderPass(POOL_SIMPLE) @@ -167,100 +132,73 @@ void LLDrawPoolSimple::prerender() mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } -void LLDrawPoolSimple::beginRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); - - if (LLPipeline::sImpostorRender) - { - simple_shader = &gObjectSimpleImpostorProgram; - } - else if (LLPipeline::sUnderWaterRender) - { - simple_shader = &gObjectSimpleWaterProgram; - } - else - { - simple_shader = &gObjectSimpleProgram; - } - - if (mShaderLevel > 0) - { - simple_shader->bind(); - - if (LLPipeline::sRenderingHUDs) - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } - else - { - // don't use shaders! - if (gGLManager.mHasShaderObjects) - { - LLGLSLShader::bindNoShader(); - } - } -} - -void LLDrawPoolSimple::endRenderPass(S32 pass) +S32 LLDrawPoolSimple::getNumPasses() { - LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); - stop_glerror(); - LLRenderPass::endRenderPass(pass); - stop_glerror(); - if (mShaderLevel > 0) - { - simple_shader->unbind(); - } + return 1; } void LLDrawPoolSimple::render(S32 pass) { + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); + LLGLDisable blend(GL_BLEND); + LLGLSLShader* shader = nullptr; + if (LLPipeline::sImpostorRender) + { + shader = &gObjectSimpleImpostorProgram; + } + else if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectSimpleWaterProgram; + } + else + { + shader = &gObjectSimpleProgram; + } + { //render simple - LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE); + gPipeline.enableLightsDynamic(); - if (mShaderLevel > 0) - { - U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX; - - pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE); - - if (LLPipeline::sRenderDeferred) - { //if deferred rendering is enabled, bump faces aren't registered as simple - //render bump faces here as simple so bump faces will appear under water - pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_MATERIAL, mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_SPECMAP, mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_NORMMAP, mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE); - } - } - else - { - LLGLDisable alpha_test(GL_ALPHA_TEST); - renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); - } - + U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX; + + // first pass -- static objects + { + setup_simple_shader(shader); + pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE); + + if (LLPipeline::sRenderDeferred) + { //if deferred rendering is enabled, bump faces aren't registered as simple + //render bump faces here as simple so bump faces will appear under water + pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_MATERIAL, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_SPECMAP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMMAP, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE); + } + } + + //second pass, rigged + { + shader = shader->mRiggedVariant; + setup_simple_shader(shader); + pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, mask, TRUE, TRUE); + + if (LLPipeline::sRenderDeferred) + { //if deferred rendering is enabled, bump faces aren't registered as simple + //render bump faces here as simple so bump faces will appear under water + pushRiggedBatches(LLRenderPass::PASS_BUMP_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_MATERIAL_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_SPECMAP_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_NORMMAP_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_RIGGED, mask, TRUE, TRUE); + } + } } } - - - - - - - - static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK("Alpha Mask"); LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() : @@ -273,85 +211,36 @@ void LLDrawPoolAlphaMask::prerender() mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } -void LLDrawPoolAlphaMask::beginRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); - - if (LLPipeline::sUnderWaterRender) - { - simple_shader = &gObjectSimpleWaterAlphaMaskProgram; - } - else - { - simple_shader = &gObjectSimpleAlphaMaskProgram; - } - - if (mShaderLevel > 0) - { - simple_shader->bind(); - - if (LLPipeline::sRenderingHUDs) - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } - else - { - // don't use shaders! - if (gGLManager.mHasShaderObjects) - { - LLGLSLShader::bindNoShader(); - } - } -} - -void LLDrawPoolAlphaMask::endRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); - stop_glerror(); - LLRenderPass::endRenderPass(pass); - stop_glerror(); - if (mShaderLevel > 0) - { - simple_shader->unbind(); - } -} - void LLDrawPoolAlphaMask::render(S32 pass) { LLGLDisable blend(GL_BLEND); - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); + LL_PROFILE_ZONE_SCOPED; - if (mShaderLevel > 0) - { - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.33f); + LLGLSLShader* shader = nullptr; + if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectSimpleWaterAlphaMaskProgram; + } + else + { + shader = &gObjectSimpleAlphaMaskProgram; + } - if (LLPipeline::sRenderingHUDs) - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } + // render static + setup_simple_shader(shader); + pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - } - else - { - LLGLEnable test(GL_ALPHA_TEST); - pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK - } + // render rigged + setup_simple_shader(shader->mRiggedVariant); + pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushRiggedMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushRiggedMaskBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushRiggedMaskBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + pushRiggedMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() : @@ -364,166 +253,70 @@ void LLDrawPoolFullbrightAlphaMask::prerender() mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } -void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass) +void LLDrawPoolFullbrightAlphaMask::render(S32 pass) { LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); - if (LLPipeline::sUnderWaterRender) - { - simple_shader = &gObjectFullbrightWaterAlphaMaskProgram; - } - else - { - simple_shader = &gObjectFullbrightAlphaMaskProgram; - } - - if (mShaderLevel > 0) - { - simple_shader->bind(); - - if (LLPipeline::sRenderingHUDs) - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } - else - { - // don't use shaders! - if (gGLManager.mHasShaderObjects) - { - LLGLSLShader::bindNoShader(); - } - } -} - -void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); - stop_glerror(); - LLRenderPass::endRenderPass(pass); - stop_glerror(); - if (mShaderLevel > 0) - { - simple_shader->unbind(); - } -} + LLGLSLShader* shader = nullptr; + if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectFullbrightWaterAlphaMaskProgram; + } + else + { + shader = &gObjectFullbrightAlphaMaskProgram; + } -void LLDrawPoolFullbrightAlphaMask::render(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK); + // render static + setup_fullbright_shader(shader); + pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - if (mShaderLevel > 0) - { - if (simple_shader) - { - simple_shader->bind(); - simple_shader->setMinimumAlpha(0.33f); - - if (LLPipeline::sRenderingHUDs) - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - } - else - { - simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - if (LLPipeline::sRenderDeferred) - { - simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - } - else - { - simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - } - } - } - pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - //LLGLSLShader::bindNoShader(); - } - else - { - LLGLEnable test(GL_ALPHA_TEST); - gPipeline.enableLightsFullbright(); - pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE); - gPipeline.enableLightsDynamic(); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK - } + // render rigged + setup_fullbright_shader(shader->mRiggedVariant); + pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } //=============================== //DEFERRED IMPLEMENTATION //=============================== -void LLDrawPoolSimple::beginDeferredPass(S32 pass) +S32 LLDrawPoolSimple::getNumDeferredPasses() { - LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); - gDeferredDiffuseProgram.bind(); - - if (LLPipeline::sRenderingHUDs) - { - gDeferredDiffuseProgram.uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - gDeferredDiffuseProgram.uniform1i(LLShaderMgr::NO_ATMO, 0); - } -} - -void LLDrawPoolSimple::endDeferredPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); - LLRenderPass::endRenderPass(pass); - - gDeferredDiffuseProgram.unbind(); + return 1; } void LLDrawPoolSimple::renderDeferred(S32 pass) { + LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); LLGLDisable blend(GL_BLEND); LLGLDisable alpha_test(GL_ALPHA_TEST); - { //render simple - LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED); - pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - } + //render static + setup_simple_shader(&gDeferredDiffuseProgram); + pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + + //render rigged + setup_simple_shader(gDeferredDiffuseProgram.mRiggedVariant); + pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask"); -void LLDrawPoolAlphaMask::beginDeferredPass(S32 pass) -{ - -} - -void LLDrawPoolAlphaMask::endDeferredPass(S32 pass) -{ - -} void LLDrawPoolAlphaMask::renderDeferred(S32 pass) { LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_DEFERRED); - gDeferredDiffuseAlphaMaskProgram.bind(); - gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f); + LLGLSLShader* shader = &gDeferredDiffuseAlphaMaskProgram; - if (LLPipeline::sRenderingHUDs) - { - gDeferredDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - gDeferredDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0); - } + //render static + setup_simple_shader(shader); + pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); - gDeferredDiffuseAlphaMaskProgram.unbind(); + //render rigged + setup_simple_shader(shader->mRiggedVariant); + pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } - // grass drawpool LLDrawPoolGrass::LLDrawPoolGrass() : LLRenderPass(POOL_GRASS) @@ -566,12 +359,8 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) } else { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - // don't use shaders! - if (gGLManager.mHasShaderObjects) - { - LLGLSLShader::bindNoShader(); - } + gGL.flush(); + LLGLSLShader::bindNoShader(); } } @@ -586,7 +375,7 @@ void LLDrawPoolGrass::endRenderPass(S32 pass) } else { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); } } @@ -599,7 +388,7 @@ void LLDrawPoolGrass::render(S32 pass) LLGLEnable test(GL_ALPHA_TEST); gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass - LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); + LLRenderPass::pushBatches(LLRenderPass::PASS_GRASS, getVertexDataMask()); } } @@ -630,7 +419,7 @@ void LLDrawPoolGrass::renderDeferred(S32 pass) } //render grass - LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); + LLRenderPass::pushBatches(LLRenderPass::PASS_GRASS, getVertexDataMask()); } } @@ -646,77 +435,31 @@ void LLDrawPoolFullbright::prerender() mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } -void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) -{ - if (LLPipeline::sUnderWaterRender) - { - gDeferredFullbrightWaterProgram.bind(); - } - else - { - gDeferredFullbrightProgram.bind(); - - if (LLPipeline::sRenderingHUDs) - { - gDeferredFullbrightProgram.uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - gDeferredFullbrightProgram.uniform1i(LLShaderMgr::NO_ATMO, 0); - } - } - -} void LLDrawPoolFullbright::renderPostDeferred(S32 pass) { LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; - pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); -} -void LLDrawPoolFullbright::endPostDeferredPass(S32 pass) -{ - if (LLPipeline::sUnderWaterRender) - { - gDeferredFullbrightWaterProgram.unbind(); - } - else - { - gDeferredFullbrightProgram.unbind(); - } - LLRenderPass::endRenderPass(pass); -} - -void LLDrawPoolFullbright::beginRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); - - if (LLPipeline::sUnderWaterRender) - { - fullbright_shader = &gObjectFullbrightWaterProgram; - } - else - { - fullbright_shader = &gObjectFullbrightProgram; - } -} - -void LLDrawPoolFullbright::endRenderPass(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); - LLRenderPass::endRenderPass(pass); - - stop_glerror(); - - if (mShaderLevel > 0) - { - fullbright_shader->unbind(); - } + LLGLSLShader* shader = nullptr; + if (LLPipeline::sUnderWaterRender) + { + shader = &gDeferredFullbrightWaterProgram; + } + else + { + shader = &gDeferredFullbrightProgram; + } - stop_glerror(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; + + // render static + setup_fullbright_shader(shader); + pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); + + // render rigged + setup_fullbright_shader(shader->mRiggedVariant); + pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE); } void LLDrawPoolFullbright::render(S32 pass) @@ -725,41 +468,34 @@ void LLDrawPoolFullbright::render(S32 pass) gGL.setSceneBlendType(LLRender::BT_ALPHA); stop_glerror(); + LLGLSLShader* shader = nullptr; + if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectFullbrightWaterProgram; + } + else + { + shader = &gObjectFullbrightProgram; + } - if (mShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); - fullbright_shader->uniform1f(LLViewerShaderMgr::TEXTURE_GAMMA, 1.f); - if (LLPipeline::sRenderingHUDs) - { - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, 0); - } + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; - U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; - pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask, TRUE, TRUE); - pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask, TRUE, TRUE); - } - else - { - gPipeline.enableLightsFullbright(); - U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; - renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); - pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask); - pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask); - pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask); - pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask); - } - - stop_glerror(); + // render static + setup_fullbright_shader(shader); + pushBatches(LLRenderPass::PASS_FULLBRIGHT, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, mask, TRUE, TRUE); + pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, mask, TRUE, TRUE); + + // render rigged + setup_fullbright_shader(shader->mRiggedVariant); + pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, mask, TRUE, TRUE); + pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, mask, TRUE, TRUE); } S32 LLDrawPoolFullbright::getNumPasses() @@ -767,65 +503,40 @@ S32 LLDrawPoolFullbright::getNumPasses() return 1; } - -void LLDrawPoolFullbrightAlphaMask::beginPostDeferredPass(S32 pass) +void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass) { - + LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); + + LLGLSLShader* shader = nullptr; if (LLPipeline::sRenderingHUDs) { - gObjectFullbrightAlphaMaskProgram.bind(); - gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - gObjectFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1); + shader = &gObjectFullbrightAlphaMaskProgram; } - else if (LLPipeline::sRenderDeferred) - { + else if (LLPipeline::sRenderDeferred) + { if (LLPipeline::sUnderWaterRender) - { - gDeferredFullbrightAlphaMaskWaterProgram.bind(); - gDeferredFullbrightAlphaMaskWaterProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - gDeferredFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1); - } - else - { - gDeferredFullbrightAlphaMaskProgram.bind(); - gDeferredFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); - gDeferredFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0); - } + { + shader = &gDeferredFullbrightAlphaMaskWaterProgram; + } + else + { + shader = &gDeferredFullbrightAlphaMaskProgram; + } } else { - gObjectFullbrightAlphaMaskProgram.bind(); - gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f); - gObjectFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0); - } -} + shader = &gObjectFullbrightAlphaMaskProgram; + } -void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass) -{ - LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT); LLGLDisable blend(GL_BLEND); U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; - pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE); + + // render static + setup_fullbright_shader(shader); + pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE); + + // render rigged + setup_fullbright_shader(shader->mRiggedVariant); + pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, fullbright_mask, TRUE, TRUE); } -void LLDrawPoolFullbrightAlphaMask::endPostDeferredPass(S32 pass) -{ - if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred) - { - gObjectFullbrightAlphaMaskProgram.unbind(); - } - else - { - if (LLPipeline::sUnderWaterRender) - { - gDeferredFullbrightAlphaMaskWaterProgram.unbind(); - } - else - { - gDeferredFullbrightAlphaMaskProgram.unbind(); - } - } - LLRenderPass::endRenderPass(pass); -} - - diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index 608ad9e1eb..cccbe5e495 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -29,6 +29,8 @@ #include "lldrawpool.h" +class LLGLSLShader; + class LLDrawPoolSimple : public LLRenderPass { public: @@ -39,22 +41,17 @@ public: LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR }; - virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + virtual U32 getVertexDataMask() override { return VERTEX_DATA_MASK; } LLDrawPoolSimple(); - /*virtual*/ S32 getNumDeferredPasses() { return 1; } - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); + S32 getNumDeferredPasses() override; + void renderDeferred(S32 pass) override; - /*virtual*/ void beginRenderPass(S32 pass); - /*virtual*/ void endRenderPass(S32 pass); /// We need two passes so we can handle emissive materials separately. - /*virtual*/ S32 getNumPasses() { return 1; } - /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void prerender(); - + S32 getNumPasses() override; + void render(S32 pass = 0) override; + void prerender() override; }; class LLDrawPoolGrass : public LLRenderPass @@ -99,13 +96,9 @@ public: LLDrawPoolAlphaMask(); /*virtual*/ S32 getNumDeferredPasses() { return 1; } - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); /*virtual*/ void renderDeferred(S32 pass); /*virtual*/ S32 getNumPasses() { return 1; } - /*virtual*/ void beginRenderPass(S32 pass); - /*virtual*/ void endRenderPass(S32 pass); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); @@ -125,13 +118,9 @@ public: LLDrawPoolFullbrightAlphaMask(); /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass); - /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); /*virtual*/ S32 getNumPasses() { return 1; } - /*virtual*/ void beginRenderPass(S32 pass); - /*virtual*/ void endRenderPass(S32 pass); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); }; @@ -151,12 +140,8 @@ public: LLDrawPoolFullbright(); /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass); - /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); - /*virtual*/ void beginRenderPass(S32 pass); - /*virtual*/ void endRenderPass(S32 pass); /*virtual*/ S32 getNumPasses(); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); @@ -180,14 +165,13 @@ public: virtual void prerender() { } /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass); - /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); + void render(LLGLSLShader* shader); + /*virtual*/ S32 getNumPasses(); void render(S32 pass = 0); - void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); }; diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index b6f55e800a..3a1efec91b 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -76,22 +76,8 @@ void LLDrawPoolSky::render(S32 pass) } - if (LLGLSLShader::sNoFixedFunction) - { //just use the UI shader (generic single texture no lighting) - gOneTextureNoColorProgram.bind(); - } - else - { - // don't use shaders! - if (gGLManager.mHasShaderObjects) - { - // Ironically, we must support shader objects to be - // able to use this call. - LLGLSLShader::bindNoShader(); - } - mShader = NULL; - } - + //just use the UI shader (generic single texture no lighting) + gOneTextureNoColorProgram.bind(); LLGLSPipelineDepthTestSkyBox gls_skybox(true, false); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 37dc80e2b7..adea1909a3 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -343,8 +343,6 @@ void LLDrawPoolTerrain::renderFullShader() LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - ((LLSettingsVOWater*)pwater.get())->updateShader(shader); - // // detail texture 1 // @@ -469,8 +467,6 @@ void LLDrawPoolTerrain::renderFull4TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - // // Stage 1: Generate alpha ramp for detail0/detail1 transition // @@ -479,10 +475,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); - // Care about alpha only - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // // Stage 2: Interpolate detail1 with existing based on ramp // @@ -497,8 +489,6 @@ void LLDrawPoolTerrain::renderFull4TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(2)->setTextureColorBlend(LLTexUnit::TBO_LERP_PREV_ALPHA, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_TEX_COLOR); - // // Stage 3: Modulate with primary (vertex) color for lighting // @@ -506,9 +496,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->activate(); - // Set alpha texture and do lighting modulation - gGL.getTexUnit(3)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(0)->activate(); // GL_BLEND disabled by default @@ -529,8 +516,6 @@ void LLDrawPoolTerrain::renderFull4TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - // // Stage 1: Generate alpha ramp for detail2/detail3 transition // @@ -543,10 +528,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.loadIdentity(); gGL.translatef(-2.f, 0.f, 0.f); - // Care about alpha only - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // // Stage 2: Interpolate detail2 with existing based on ramp // @@ -561,8 +542,6 @@ void LLDrawPoolTerrain::renderFull4TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(2)->setTextureColorBlend(LLTexUnit::TBO_LERP_PREV_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); - // // Stage 3: Generate alpha ramp for detail1/detail2 transition // @@ -576,10 +555,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.translatef(-1.f, 0.f, 0.f); gGL.matrixMode(LLRender::MM_MODELVIEW); - // Set alpha texture and do lighting modulation - gGL.getTexUnit(3)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(3)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - gGL.getTexUnit(0)->activate(); { LLGLEnable blend(GL_BLEND); @@ -629,8 +604,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } void LLDrawPoolTerrain::renderFull2TU() @@ -669,8 +642,6 @@ void LLDrawPoolTerrain::renderFull2TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - drawLoop(); //---------------------------------------------------------------------------- @@ -684,11 +655,6 @@ void LLDrawPoolTerrain::renderFull2TU() glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); - // Care about alpha only - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - - // // Stage 1: Write detail1 // @@ -703,9 +669,6 @@ void LLDrawPoolTerrain::renderFull2TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); - gGL.getTexUnit(0)->activate(); { LLGLEnable blend(GL_BLEND); @@ -725,10 +688,6 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.translatef(-1.f, 0.f, 0.f); gGL.matrixMode(LLRender::MM_MODELVIEW); - // Care about alpha only - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // // Stage 1: Write detail2 // @@ -743,9 +702,6 @@ void LLDrawPoolTerrain::renderFull2TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); - { LLGLEnable blend(GL_BLEND); drawLoop(); @@ -765,10 +721,6 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.translatef(-2.f, 0.f, 0.f); gGL.matrixMode(LLRender::MM_MODELVIEW); - // Care about alpha only - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // Stage 1: Write detail3 gGL.getTexUnit(1)->bind(detail_texture3p); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); @@ -781,9 +733,6 @@ void LLDrawPoolTerrain::renderFull2TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); - gGL.getTexUnit(0)->activate(); { LLGLEnable blend(GL_BLEND); @@ -816,7 +765,6 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } @@ -839,22 +787,8 @@ void LLDrawPoolTerrain::renderSimple() tp0.setVec(tscale, 0.f, 0.0f, -1.f*(origin_agent.mV[0]/256.f)); tp1.setVec(0.f, tscale, 0.0f, -1.f*(origin_agent.mV[1]/256.f)); - if (LLGLSLShader::sNoFixedFunction) - { - sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); - sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); - } - else - { - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - } - - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); + sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); + sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); drawLoop(); @@ -863,15 +797,9 @@ void LLDrawPoolTerrain::renderSimple() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - } gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } //============================================================================ @@ -922,6 +850,7 @@ void LLDrawPoolTerrain::renderOwnership() void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures) { + LL_PROFILE_ZONE_SCOPED; LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(mTexturep) ; if (tex && textures.find(tex) != textures.end()) { diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 0d5195bdbf..facfb235c9 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -42,7 +42,6 @@ S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; -static LLTrace::BlockTimerStatHandle FTM_SHADOW_TREE("Tree Shadow"); LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) : LLFacePool(POOL_TREE), @@ -69,7 +68,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) shader = &gTreeProgram; } - if (gPipeline.canUseVertexShaders()) + if (gPipeline.shadersLoaded()) { shader->bind(); shader->setMinimumAlpha(0.5f); @@ -78,23 +77,24 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) else { gPipeline.enableLightsDynamic(); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + gGL.flush(); } } void LLDrawPoolTree::render(S32 pass) { - LL_RECORD_BLOCK_TIME(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES); + LL_PROFILE_ZONE_SCOPED; if (mDrawFace.empty()) { return; } - LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); + LLGLState test(GL_ALPHA_TEST, 0); + + gGL.getTexUnit(sDiffTex)->bindFast(mTexturep); + gPipeline.touchTexture(mTexturep, 1024.f * 1024.f); // <=== keep Linden tree textures at full res - gGL.getTexUnit(sDiffTex)->bind(mTexturep); - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { @@ -117,9 +117,8 @@ void LLDrawPoolTree::render(S32 pass) gPipeline.mMatrixOpCount++; } - buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); - gPipeline.addTrianglesDrawn(buff->getNumIndices()); + buff->setBufferFast(LLDrawPoolTree::VERTEX_DATA_MASK); + buff->drawRangeFast(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); } } } @@ -135,7 +134,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass) if (mShaderLevel <= 0) { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); } } @@ -153,6 +152,7 @@ void LLDrawPoolTree::beginDeferredPass(S32 pass) void LLDrawPoolTree::renderDeferred(S32 pass) { + LL_PROFILE_ZONE_SCOPED; render(pass); } @@ -168,7 +168,7 @@ void LLDrawPoolTree::endDeferredPass(S32 pass) //============================================ void LLDrawPoolTree::beginShadowPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_TREE); + LL_PROFILE_ZONE_SCOPED; glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), gSavedSettings.getF32("RenderDeferredTreeShadowBias")); @@ -187,7 +187,7 @@ void LLDrawPoolTree::renderShadow(S32 pass) void LLDrawPoolTree::endShadowPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_TREE); + LL_PROFILE_ZONE_SCOPED; glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"), gSavedSettings.getF32("RenderDeferredSpotShadowBias")); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index aa426cd785..62706feae3 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -50,8 +50,6 @@ #include "llsettingssky.h" #include "llsettingswater.h" -static float sTime; - BOOL deferred_render = FALSE; BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; @@ -137,8 +135,16 @@ void LLDrawPoolWater::endPostDeferredPass(S32 pass) void LLDrawPoolWater::renderDeferred(S32 pass) { LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER); + + if (!LLPipeline::sRenderTransparentWater) + { + // Will render opaque water without use of ALM + render(pass); + return; + } + deferred_render = TRUE; - shade(); + renderWater(); deferred_render = FALSE; } @@ -174,7 +180,7 @@ void LLDrawPoolWater::render(S32 pass) if ((mShaderLevel > 0) && !sSkipScreenCopy) { - shade(); + renderWater(); return; } @@ -233,9 +239,6 @@ void LLDrawPoolWater::render(S32 pass) glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_ALPHA); - gGL.getTexUnit(0)->activate(); glClearStencil(1); @@ -293,8 +296,6 @@ void LLDrawPoolWater::render(S32 pass) gGL.matrixMode(LLRender::MM_MODELVIEW); LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { @@ -311,8 +312,6 @@ void LLDrawPoolWater::render(S32 pass) } } - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - gSky.mVOSkyp->getCubeMap()->disable(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -330,29 +329,30 @@ void LLDrawPoolWater::render(S32 pass) glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); renderReflection(refl_face); } - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } // for low end hardware void LLDrawPoolWater::renderOpaqueLegacyWater() { - LLVOSky *voskyp = gSky.mVOSkyp; + LL_PROFILE_ZONE_SCOPED; + LLVOSky *voskyp = gSky.mVOSkyp; + + if (voskyp == NULL) + { + return; + } LLGLSLShader* shader = NULL; - if (LLGLSLShader::sNoFixedFunction) + if (LLPipeline::sUnderWaterRender) { - if (LLPipeline::sUnderWaterRender) - { - shader = &gObjectSimpleNonIndexedTexGenWaterProgram; - } - else - { - shader = &gObjectSimpleNonIndexedTexGenProgram; - } - - shader->bind(); + shader = &gObjectSimpleNonIndexedTexGenWaterProgram; } + else + { + shader = &gObjectSimpleNonIndexedTexGenProgram; + } + + shader->bind(); stop_glerror(); @@ -438,12 +438,12 @@ void LLDrawPoolWater::renderOpaqueLegacyWater() } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } void LLDrawPoolWater::renderReflection(LLFace* face) { + LL_PROFILE_ZONE_SCOPED; LLVOSky *voskyp = gSky.mVOSkyp; if (!voskyp) @@ -470,330 +470,245 @@ void LLDrawPoolWater::renderReflection(LLFace* face) face->renderIndexed(); } -void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp) +void LLDrawPoolWater::renderWater() { - F32 water_height = LLEnvironment::instance().getWaterHeight(); - F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; - F32 eyedepth = camera_height - water_height; - bool underwater = eyedepth <= 0.0f; - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - shader->bind(); - -// bind textures for water rendering - if (deferred_render) - { - if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { - glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); - shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); - } - } - - LLColor4 specular(psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor()); - shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV); + LL_PROFILE_ZONE_SCOPED; + if (!deferred_render) + { + gGL.setColorMask(true, true); + } - sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f; - - S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); - - if (reftex > -1) - { - gGL.getTexUnit(reftex)->activate(); - gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); - gGL.getTexUnit(0)->activate(); - } + LLGLDisable blend(GL_BLEND); - //bind normal map - S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); + LLColor3 light_diffuse(0, 0, 0); + F32 light_exp = 0.0f; - LLViewerTexture* tex_a = mWaterNormp[0]; - LLViewerTexture* tex_b = mWaterNormp[1]; + LLEnvironment & environment = LLEnvironment::instance(); + LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + LLVector3 light_dir = environment.getLightDirection(); + bool sun_up = environment.getIsSunUp(); + bool moon_up = environment.getIsMoonUp(); + bool has_normal_mips = gSavedSettings.getBOOL("RenderWaterMipNormal"); + bool underwater = LLViewerCamera::getInstance()->cameraUnderWater(); - F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor(); - - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - - if (tex_a && (!tex_b || (tex_a == tex_b))) - { - gGL.getTexUnit(bumpTex)->bind(tex_a); - blend_factor = 0; // only one tex provided, no blending - } - else if (tex_b && !tex_a) + if (sun_up) { - gGL.getTexUnit(bumpTex)->bind(tex_b); - blend_factor = 0; // only one tex provided, no blending + light_diffuse += psky->getSunlightColor(); } - else if (tex_b != tex_a) + // moonlight is several orders of magnitude less bright than sunlight, + // so only use this color when the moon alone is showing + else if (moon_up) { - gGL.getTexUnit(bumpTex)->bind(tex_a); - gGL.getTexUnit(bumpTex2)->bind(tex_b); + light_diffuse += psky->getMoonlightColor(); } - - // bind reflection texture from RenderTarget - S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); - F32 screenRes[] = - { - 1.f/gGLViewport[2], - 1.f/gGLViewport[3] - }; - - S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - stop_glerror(); - -// set uniforms for water rendering - shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); - shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); - - LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f); - F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); - if (screentex > -1) - { - shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); - gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - } - - if (mShaderLevel == 1) + // Apply magic numbers translating light direction into intensities + light_dir.normalize(); + F32 ground_proj_sq = light_dir.mV[0] * light_dir.mV[0] + light_dir.mV[1] * light_dir.mV[1]; + light_exp = llmax(32.f, 256.f * powf(ground_proj_sq, 16.0f)); + if (0.f < light_diffuse.normalize()) // Normalizing a color? Puzzling... { - //F32 fog_density_slider_value = param_mgr->mDensitySliderValue; - //sWaterFogColor.mV[3] = fog_density_slider_value; - fog_color.mV[VW] = log(fog_density) / log(2); - } - - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); + light_diffuse *= (1.5f + (6.f * ground_proj_sq)); + } - //shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix); - shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth); - shader->uniform1f(LLShaderMgr::WATER_TIME, sTime); - shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); - shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); - shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); - if (LLEnvironment::instance().isCloudScrollPaused()) + // set up normal maps filtering + for (auto norm_map : mWaterNormp) { - static const std::array<F32, 2> zerowave{ {0.0f, 0.0f} }; - - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data()); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data()); + if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); } - else + + LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor()); + F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f; + bool edge = false; + LLGLSLShader *shader = nullptr; + do // twice through, once with normal shader bound & once with edge shader bound { - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); - } - shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); + // select shader + if (underwater && LLPipeline::sWaterReflections) + { + shader = deferred_render ? &gDeferredUnderWaterProgram : &gUnderWaterProgram; + } + else + { + if (edge && !deferred_render) + { + shader = &gWaterEdgeProgram; + } + else + { + shader = deferred_render ? &gDeferredWaterProgram : &gWaterProgram; + } + } + shader->bind(); - shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); - shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); + // bind textures for water rendering + S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); + if (reftex > -1) + { + gGL.getTexUnit(reftex)->activate(); + gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); + gGL.getTexUnit(0)->activate(); + } - F32 sunAngle = llmax(0.f, light_dir.mV[1]); - F32 scaledAngle = 1.f - sunAngle; + // bind normal map + S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); + S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); - shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); - shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle); - shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); + LLViewerTexture *tex_a = mWaterNormp[0]; + LLViewerTexture *tex_b = mWaterNormp[1]; - LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm(); - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); - shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); + F32 blend_factor = pwater->getBlendFactor(); - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); - } - else - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); - } - - { - LLGLDisable cullface(GL_CULL_FACE); + gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - if (edge) + if (tex_a && (!tex_b || (tex_a == tex_b))) { - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (face) - { - LLVOWater* water = (LLVOWater*) face->getViewerObject(); - gGL.getTexUnit(diffTex)->bind(face->getTexture()); - - if (water) - { - bool edge_patch = water->getIsEdgePatch(); - if (edge_patch) - { - //sNeedsReflectionUpdate = TRUE; - face->renderIndexed(); - } - } - } - } + gGL.getTexUnit(bumpTex)->bind(tex_a); + blend_factor = 0; // only one tex provided, no blending } - else + else if (tex_b && !tex_a) { - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (face) - { - LLVOWater* water = (LLVOWater*) face->getViewerObject(); - gGL.getTexUnit(diffTex)->bind(face->getTexture()); - - if (water) - { - bool edge_patch = water->getIsEdgePatch(); - if (!edge_patch) - { - sNeedsReflectionUpdate = TRUE; - sNeedsDistortionUpdate = TRUE; - face->renderIndexed(); - } - } - } - } + gGL.getTexUnit(bumpTex)->bind(tex_b); + blend_factor = 0; // only one tex provided, no blending + } + else if (tex_b != tex_a) + { + gGL.getTexUnit(bumpTex)->bind(tex_a); + gGL.getTexUnit(bumpTex2)->bind(tex_b); } - } - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); + // bind reflection texture from RenderTarget + S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); + F32 screenRes[] = {1.f / gGLViewport[2], 1.f / gGLViewport[3]}; - shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); - shader->disableTexture(LLShaderMgr::BUMP_MAP); - shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); - shader->disableTexture(LLShaderMgr::WATER_REFTEX); - shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); + S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - shader->unbind(); -} + // set uniforms for shader + if (deferred_render) + { + if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) + { + glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); + shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); + } + } -void LLDrawPoolWater::shade() -{ - if (!deferred_render) - { - gGL.setColorMask(true, true); - } + shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); + shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); - LLVOSky *voskyp = gSky.mVOSkyp; + LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f); + F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); - if(voskyp == NULL) - { - return; - } + if (screentex > -1) + { + shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); + gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); + } - LLGLDisable blend(GL_BLEND); + if (mShaderLevel == 1) + { + fog_color.mV[VW] = log(fog_density) / log(2); + } - LLColor3 light_diffuse(0,0,0); - F32 light_exp = 0.0f; - LLVector3 light_dir; + F32 water_height = environment.getWaterHeight(); + F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; + shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height); + shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time); + shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV); + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); - light_dir = environment.getLightDirection(); - light_dir.normalize(); + shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); + shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); + if (LLEnvironment::instance().isCloudScrollPaused()) + { + static const std::array<F32, 2> zerowave {{0.0f, 0.0f}}; - bool sun_up = environment.getIsSunUp(); - bool moon_up = environment.getIsMoonUp(); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data()); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data()); + } + else + { + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); + } + shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - if (sun_up) - { - light_diffuse += voskyp->getSun().getColorCached(); - } - // moonlight is several orders of magnitude less bright than sunlight, - // so only use this color when the moon alone is showing - else if (moon_up) - { - light_diffuse += psky->getMoonDiffuse(); - } + shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); + shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); - light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f); + F32 sunAngle = llmax(0.f, light_dir.mV[1]); + F32 scaledAngle = 1.f - sunAngle; - light_diffuse.normalize(); - light_diffuse *= (light_exp + 0.25f); + shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); + shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle); + shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); - light_exp *= light_exp; - light_exp *= light_exp; - light_exp *= light_exp; - light_exp *= light_exp; - light_exp *= 256.f; - light_exp = light_exp > 32.f ? light_exp : 32.f; + LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm(); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); + shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); - light_diffuse *= 6.f; + if (LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); + } + else + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); + } - LLGLSLShader* shader = nullptr; - LLGLSLShader* edge_shader = nullptr; + LLGLDisable cullface(GL_CULL_FACE); - F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight(); - - if (eyedepth < 0.f && LLPipeline::sWaterReflections) - { - if (deferred_render) - { - shader = &gDeferredUnderWaterProgram; - } - else + LLVOWater *water = nullptr; + for (LLFace *const &face : mDrawFace) { - shader = &gUnderWaterProgram; - } - } - else if (deferred_render) - { - shader = &gDeferredWaterProgram; - edge_shader = nullptr; - } - else - { - shader = &gWaterProgram; - edge_shader = &gWaterEdgeProgram; - } + if (!face) continue; + water = static_cast<LLVOWater *>(face->getViewerObject()); + if (!water) continue; - if (mWaterNormp[0]) - { - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT); - } - } + gGL.getTexUnit(diffTex)->bind(face->getTexture()); - if (mWaterNormp[1]) - { - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_POINT); - } - } + if (edge == (bool) water->getIsEdgePatch()) + { + face->renderIndexed(); + + // Note non-void water being drawn, updates required + if (!edge) // SL-16461 remove !LLPipeline::sUseOcclusion check + { + sNeedsReflectionUpdate = TRUE; + sNeedsDistortionUpdate = TRUE; + } + } + } - shade2(false, shader, light_diffuse, light_dir, light_exp); - shade2(true, edge_shader ? edge_shader : shader, light_diffuse, light_dir, light_exp); + shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); + shader->disableTexture(LLShaderMgr::BUMP_MAP); + shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); + shader->disableTexture(LLShaderMgr::WATER_REFTEX); + shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - if (!deferred_render) - { - gGL.setColorMask(true, false); - } + // clean up + shader->unbind(); + gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); + + edge = !edge; + } while (!edge); + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + if (!deferred_render) + { + gGL.setColorMask(true, false); + } } LLViewerTexture *LLDrawPoolWater::getDebugTexture() diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index a5d163e0d7..6f2fc3271d 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -78,8 +78,7 @@ public: /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderReflection(LLFace* face); - void shade(); - void shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp); + void renderWater(); void setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId); void setOpaqueTexture(const LLUUID& opaqueTextureId); diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 0c3d8f3098..80a65947f6 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -182,8 +182,6 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca sky_shader->bindTexture(LLShaderMgr::RAINBOW_MAP, rainbow_tex); sky_shader->bindTexture(LLShaderMgr::HALO_MAP, halo_tex); - ((LLSettingsVOSky*)psky.get())->updateShader(sky_shader); - F32 moisture_level = (float)psky->getSkyMoistureLevel(); F32 droplet_radius = (float)psky->getSkyDropletRadius(); F32 ice_level = (float)psky->getSkyIceLevel(); @@ -268,33 +266,14 @@ void LLDrawPoolWLSky::renderStars(const LLVector3& camPosLocal) const gGL.pushMatrix(); gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]); gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); - if (LLGLSLShader::sNoFixedFunction) - { - gCustomAlphaProgram.bind(); - gCustomAlphaProgram.uniform1f(sCustomAlpha, star_alpha.mV[3]); - } - else - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); - } + gCustomAlphaProgram.bind(); + gCustomAlphaProgram.uniform1f(sCustomAlpha, star_alpha.mV[3]); gSky.mVOWLSkyp->drawStars(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.popMatrix(); - - if (LLGLSLShader::sNoFixedFunction) - { - gCustomAlphaProgram.unbind(); - } - else - { - // and disable the combiner states - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } + gCustomAlphaProgram.unbind(); } void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const @@ -406,8 +385,6 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance); cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor()); - ((LLSettingsVOSky*)psky.get())->updateShader(cloudshader); - /// Render the skydome renderDome(camPosLocal, camHeightLocal, cloudshader); @@ -462,8 +439,6 @@ void LLDrawPoolWLSky::renderSkyClouds(const LLVector3& camPosLocal, F32 camHeigh cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance); cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor()); - ((LLSettingsVOSky*)psky.get())->updateShader(cloudshader); - /// Render the skydome renderDome(camPosLocal, camHeightLocal, cloudshader); @@ -485,7 +460,7 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN]; F32 blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor(); - bool can_use_vertex_shaders = gPipeline.canUseVertexShaders(); + bool can_use_vertex_shaders = gPipeline.shadersLoaded(); bool can_use_windlight_shaders = gPipeline.canUseWindLightShaders(); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 8b8273d183..63e7887d81 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -119,10 +119,13 @@ BOOL LLViewerDynamicTexture::render() void LLViewerDynamicTexture::preRender(BOOL clear_depth) { gPipeline.allocatePhysicsBuffer(); - llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth())); - llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight())); + if (!gNonInteractive) + { + llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth())); + llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight())); + } - if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsATI) + if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD) { //using offscreen render target, just use the bottom left corner mOrigin.set(0, 0); } @@ -209,7 +212,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } - bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsATI; + bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsAMD; if (use_fbo) { diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index 4bd74a8425..caedf928c3 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -35,16 +35,8 @@ class LLViewerDynamicTexture : public LLViewerTexture { + LL_ALIGN_NEW public: - void* operator new(size_t size) - { - return LLTrace::MemTrackable<LLTexture>::aligned_new<16>(size); - } - - void operator delete(void* ptr, size_t size) - { - LLTrace::MemTrackable<LLTexture>::aligned_delete<16>(ptr, size); - } enum { diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index cc2b1cc42c..4bec7fa111 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -105,7 +105,6 @@ namespace //--------------------------------------------------------------------- LLTrace::BlockTimerStatHandle FTM_ENVIRONMENT_UPDATE("Update Environment Tick"); - LLTrace::BlockTimerStatHandle FTM_SHADER_PARAM_UPDATE("Update Shader Parameters"); LLSettingsBase::Seconds DEFAULT_UPDATE_THRESHOLD(10.0); const LLSettingsBase::Seconds MINIMUM_SPANLENGTH(0.01f); @@ -825,7 +824,6 @@ std::string env_selection_to_string(LLEnvironment::EnvSelection_t sel) #undef RTNENUM } - //------------------------------------------------------------------------- LLEnvironment::LLEnvironment(): mCloudScrollDelta(), @@ -879,6 +877,7 @@ void LLEnvironment::cleanupSingleton() LLEnvironment::~LLEnvironment() { + cleanupSingleton(); } bool LLEnvironment::canEdit() const @@ -1471,6 +1470,7 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getSharedEnvironmentInstance() void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool forced) { + LL_PROFILE_ZONE_SCOPED; DayInstance::ptr_t pinstance = getSelectedEnvironmentInstance(); if ((mCurrentEnvironment != pinstance) || forced) @@ -1488,6 +1488,8 @@ void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool f { mCurrentEnvironment = pinstance; } + + updateSettingsUniforms(); } } @@ -1614,6 +1616,8 @@ void LLEnvironment::update(const LLViewerCamera * cam) stop_glerror(); + updateSettingsUniforms(); + // *TODO: potential optimization - this block may only need to be // executed some of the time. For example for water shaders only. { @@ -1648,10 +1652,16 @@ void LLEnvironment::updateCloudScroll() } // static -void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLSettingsBase::ptr_t &psetting) +void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, const LLSettingsBase::ptr_t &psetting) { - LL_RECORD_BLOCK_TIME(FTM_SHADER_PARAM_UPDATE); + LL_PROFILE_ZONE_SCOPED; + + for (int i = 0; i < LLGLSLShader::SG_COUNT; ++i) + { + uniforms[i].clear(); + } + LLShaderUniforms* shader = &uniforms[LLGLSLShader::SG_ANY]; //_WARNS("RIDER") << "----------------------------------------------------------------" << LL_ENDL; LLSettingsBase::parammapping_t params = psetting->getParameterMap(); for (auto &it: params) @@ -1694,7 +1704,7 @@ void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLS { LLVector4 vect4(value); //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << vect4 << LL_ENDL; - shader->uniform4fv(it.second.getShaderKey(), 1, vect4.mV); + shader->uniform4fv(it.second.getShaderKey(), vect4 ); break; } @@ -1707,17 +1717,30 @@ void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLS default: break; } - stop_glerror(); } //_WARNS("RIDER") << "----------------------------------------------------------------" << LL_ENDL; - psetting->applySpecial(shader); + psetting->applySpecial(uniforms); +} + +void LLEnvironment::updateShaderUniforms(LLGLSLShader* shader) +{ + LL_PROFILE_ZONE_SCOPED; + + // apply uniforms that should be applied to all shaders + mSkyUniforms[LLGLSLShader::SG_ANY].apply(shader); + mWaterUniforms[LLGLSLShader::SG_ANY].apply(shader); + + // apply uniforms specific to the given shader's shader group + auto group = shader->mShaderGroup; + mSkyUniforms[group].apply(shader); + mWaterUniforms[group].apply(shader); } -void LLEnvironment::updateShaderUniforms(LLGLSLShader *shader) +void LLEnvironment::updateSettingsUniforms() { - updateGLVariablesForSettings(shader, mCurrentEnvironment->getWater()); - updateGLVariablesForSettings(shader, mCurrentEnvironment->getSky()); + updateGLVariablesForSettings(mWaterUniforms, mCurrentEnvironment->getWater()); + updateGLVariablesForSettings(mSkyUniforms, mCurrentEnvironment->getSky()); } void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envinfo, LLSettingsBase::Seconds transition) @@ -2634,6 +2657,7 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::DayInstance::clone() const bool LLEnvironment::DayInstance::applyTimeDelta(const LLSettingsBase::Seconds& delta) { + LL_PROFILE_ZONE_SCOPED; ptr_t keeper(shared_from_this()); // makes sure that this does not go away while it is being worked on. bool changed(false); diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index 7cbf2d25bb..0ec06402f8 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -38,20 +38,21 @@ #include "llatmosphere.h" +#include "llglslshader.h" + #include <boost/signals2.hpp> //------------------------------------------------------------------------- class LLViewerCamera; -class LLGLSLShader; class LLParcel; //------------------------------------------------------------------------- -class LLEnvironment : public LLSingleton<LLEnvironment> +class LLEnvironment : public LLSimpleton<LLEnvironment> { - LLSINGLETON_C11(LLEnvironment); LOG_CLASS(LLEnvironment); - public: + LLEnvironment(); + static const F64Seconds TRANSITION_INSTANT; static const F64Seconds TRANSITION_FAST; static const F64Seconds TRANSITION_DEFAULT; @@ -114,7 +115,7 @@ public: typedef std::array<F32, 4> altitude_list_t; typedef std::vector<F32> altitudes_vect_t; - virtual ~LLEnvironment(); + ~LLEnvironment(); bool canEdit() const; bool isExtendedEnvironmentEnabled() const; @@ -131,9 +132,14 @@ public: void update(const LLViewerCamera * cam); - static void updateGLVariablesForSettings(LLGLSLShader *shader, const LLSettingsBase::ptr_t &psetting); + static void updateGLVariablesForSettings(LLShaderUniforms* uniforms, const LLSettingsBase::ptr_t &psetting); + + // apply current sky settings to given shader void updateShaderUniforms(LLGLSLShader *shader); + // prepare settings to be applied to shaders (call whenever settings are updated) + void updateSettingsUniforms(); + void setSelectedEnvironment(EnvSelection_t env, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false); EnvSelection_t getSelectedEnvironment() const { return mSelectedEnvironment; } @@ -234,6 +240,11 @@ public: void handleEnvironmentPush(LLSD &message); + //cached uniform values from LLSD values + LLShaderUniforms mWaterUniforms[LLGLSLShader::SG_COUNT]; + LLShaderUniforms mSkyUniforms[LLGLSLShader::SG_COUNT]; + // ======================================================================================= + class DayInstance: public std::enable_shared_from_this<DayInstance> { public: @@ -288,6 +299,7 @@ public: LLSettingsDay::ptr_t mDayCycle; LLSettingsSky::ptr_t mSky; LLSettingsWater::ptr_t mWater; + S32 mSkyTrack; bool mInitialized; @@ -325,9 +337,10 @@ public: DayInstance::ptr_t getSelectedEnvironmentInstance(); DayInstance::ptr_t getSharedEnvironmentInstance(); + void initSingleton(); + protected: - virtual void initSingleton() override; - virtual void cleanupSingleton() override; + void cleanupSingleton(); private: diff --git a/indra/newview/llexperiencelog.cpp b/indra/newview/llexperiencelog.cpp index ee5d561927..c441fbc09f 100644 --- a/indra/newview/llexperiencelog.cpp +++ b/indra/newview/llexperiencelog.cpp @@ -149,10 +149,6 @@ std::string LLExperienceLog::getPermissionString( const LLSD& message, const std { buf.str(entry); } - else - { - buf.str(); - } } if(buf.str().empty()) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4a802ad9aa..54a043482b 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -56,6 +56,7 @@ #include "llviewertexture.h" #include "llvoavatar.h" #include "llsculptidsize.h" +#include "llmeshrepository.h" #if LL_LINUX // Work-around spurious used before init warning on Vector4a @@ -71,6 +72,7 @@ static LLStaticHashedString sColorIn("color_in"); BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE + #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) /* @@ -127,6 +129,7 @@ void planarProjection(LLVector2 &tc, const LLVector4a& normal, void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) { + LL_PROFILE_ZONE_SCOPED; mLastUpdateTime = gFrameTimeSeconds; mLastMoveTime = 0.f; mLastSkinTime = gFrameTimeSeconds; @@ -196,14 +199,7 @@ void LLFace::destroy() if (mDrawPoolp) { - if (this->isState(LLFace::RIGGED) && (mDrawPoolp->getType() == LLDrawPool::POOL_CONTROL_AV || mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR)) - { - ((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this); - } - else - { - mDrawPoolp->removeFace(this); - } + mDrawPoolp->removeFace(this); mDrawPoolp = NULL; } @@ -241,6 +237,8 @@ void LLFace::setPool(LLFacePool* pool) void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep) { + LL_PROFILE_ZONE_SCOPED + if (!new_pool) { LL_ERRS() << "Setting pool to null!" << LL_ENDL; @@ -320,6 +318,8 @@ void LLFace::setSpecularMap(LLViewerTexture* tex) void LLFace::dirtyTexture() { + LL_PROFILE_ZONE_SCOPED + LLDrawable* drawablep = getDrawable(); if (mVObjp.notNull() && mVObjp->getVolume()) @@ -535,6 +535,8 @@ void LLFace::updateCenterAgent() void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) { + LL_PROFILE_ZONE_SCOPED + if (mDrawablep == NULL || mDrawablep->getSpatialGroup() == NULL) { return; @@ -585,6 +587,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords); } gGL.syncMatrices(); + LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x00FF00 ); glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } @@ -605,6 +608,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) void renderFace(LLDrawable* drawable, LLFace *face) { + LL_PROFILE_ZONE_SCOPED + LLVOVolume* vobj = drawable->getVOVolume(); if (vobj) { @@ -648,7 +653,7 @@ void LLFace::renderOneWireframe(const LLColor4 &color, F32 fogCfx, bool wirefram glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); glFogfv(GL_FOG_COLOR, fogCol.mV); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); { gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); renderFace(mDrawablep, this); @@ -891,6 +896,8 @@ bool less_than_max_mag(const LLVector4a& vec) BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, const LLMatrix4& mat_vert_in, BOOL global_volume) { + LL_PROFILE_ZONE_SCOPED + //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED)) { @@ -1195,12 +1202,10 @@ bool LLFace::canRenderAsMask() } -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_VOLUME("Volume VB Cache"); - //static void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_VOLUME); + LL_PROFILE_ZONE_SCOPED; U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL; @@ -1262,41 +1267,13 @@ void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) } } -static LLTrace::BlockTimerStatHandle FTM_FACE_GET_GEOM("Face Geom"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_POSITION("Position"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_NORMAL("Normal"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_TEXTURE("Texture"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_COLOR("Color"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_EMISSIVE("Emissive"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_WEIGHTS("Weights"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_TANGENT("Binormal"); - -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK("Face Feedback"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_POSITION("Feedback Position"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_NORMAL("Feedback Normal"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_TEXTURE("Feedback Texture"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_COLOR("Feedback Color"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_EMISSIVE("Feedback Emissive"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_FEEDBACK_BINORMAL("Feedback Binormal"); - -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_INDEX("Index"); -static LLTrace::BlockTimerStatHandle FTM_FACE_GEOM_INDEX_TAIL("Tail"); -static LLTrace::BlockTimerStatHandle FTM_FACE_POSITION_STORE("Pos"); -static LLTrace::BlockTimerStatHandle FTM_FACE_TEXTURE_INDEX_STORE("TexIdx"); -static LLTrace::BlockTimerStatHandle FTM_FACE_POSITION_PAD("Pad"); -static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_DEFAULT("Default"); -static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK("Quick"); -static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK_NO_XFORM("No Xform"); -static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK_XFORM("Xform"); -static LLTrace::BlockTimerStatHandle FTM_FACE_TEX_QUICK_PLANAR("Quick Planar"); - BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in, const U16 &index_offset, bool force_rebuild) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GET_GEOM); + LL_PROFILE_ZONE_SCOPED; llassert(verify()); if (volume.getNumVolumeFaces() <= f) { @@ -1304,7 +1281,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, return FALSE; } - const LLVolumeFace &vf = volume.getVolumeFace(f); + bool rigged = isState(RIGGED); + + const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mNumVertices; S32 num_indices = (S32) vf.mNumIndices; @@ -1437,7 +1416,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, // INDICES if (full_rebuild) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_INDEX); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - indices"); mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, map_range); volatile __m128i* dst = (__m128i*) indicesp.get(); @@ -1453,7 +1432,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_INDEX_TAIL); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - indices tail"); U16* idx = (U16*) dst; for (S32 i = end*8; i < num_indices; ++i) @@ -1468,9 +1447,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - LLMatrix4a mat_normal; - mat_normal.loadu(mat_norm_in); - F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; bool do_xform = false; if (rebuild_tcoord) @@ -1505,6 +1481,45 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } + const LLMeshSkinInfo* skin = nullptr; + LLMatrix4a mat_vert; + LLMatrix4a mat_normal; + + // prepare mat_vert + if (rebuild_pos) + { + if (rigged) + { //override with bind shape matrix if rigged + skin = mSkinInfo; + mat_vert = skin->mBindShapeMatrix; + } + else + { + mat_vert.loadu(mat_vert_in); + } + } + + if (rebuild_normal || rebuild_tangent) + { //override mat_normal with inverse of skin->mBindShapeMatrix + LL_PROFILE_ZONE_NAMED("getGeometryVolume - norm mat override"); + if (rigged) + { + if (skin == nullptr) + { + skin = mSkinInfo; + } + + //TODO -- cache this (check profile marker above)? + glh::matrix4f m((F32*) skin->mBindShapeMatrix.getF32ptr()); + m = m.inverse().transpose(); + mat_normal.loadu(m.m); + } + else + { + mat_normal.loadu(mat_norm_in); + } + } + static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); #ifdef GL_TRANSFORM_FEEDBACK_BUFFER @@ -1516,7 +1531,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, !volume.isUnique()) //source volume is NOT flexi { //use transform feedback to pack vertex buffer //gGLDebugLoggingEnabled = TRUE; - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_FEEDBACK); + + LL_PROFILE_ZONE_NAMED("getGeometryVolume - transform feedback"); LLGLEnable discard(GL_RASTERIZER_DISCARD); LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get(); @@ -1534,7 +1550,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_pos) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_FEEDBACK_POSITION); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tf position"); gTransformPositionProgram.bind(); mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); @@ -1559,7 +1575,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_color) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_FEEDBACK_COLOR); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tf color"); gTransformColorProgram.bind(); mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount); @@ -1575,7 +1591,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_emissive) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_FEEDBACK_EMISSIVE); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tf emissive"); gTransformColorProgram.bind(); mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); @@ -1596,7 +1612,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_normal) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_FEEDBACK_NORMAL); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tf normal"); gTransformNormalProgram.bind(); mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); @@ -1609,7 +1625,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tangent) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_TANGENT); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tf tangent"); gTransformTangentProgram.bind(); mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TANGENT, mGeomIndex, mGeomCount); @@ -1622,7 +1638,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tcoord) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_FEEDBACK_TEXTURE); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tf tcoord"); gTransformTexCoordProgram.bind(); mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); @@ -1661,7 +1677,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tcoord) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_TEXTURE); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tcoord"); //bump setup LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); @@ -1757,7 +1773,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, do_xform = false; } - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE || isState(LLFace::RIGGED)) + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) // || isState(LLFace::RIGGED)) { //don't override texture transform during tc bake tex_mode = 0; } @@ -1784,18 +1800,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (texgen != LLTextureEntry::TEX_GEN_PLANAR) { - LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - texgen"); if (!do_tex_mat) { if (!do_xform) { - LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK_NO_XFORM); + LL_PROFILE_ZONE_NAMED("ggv - texgen 1"); S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; LLVector4a::memcpyNonAliased16((F32*) tex_coords0.get(), (F32*) vf.mTexCoords, tc_size); } else { - LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK_XFORM); + LL_PROFILE_ZONE_NAMED("ggv - texgen 2"); F32* dst = (F32*) tex_coords0.get(); LLVector4a* src = (LLVector4a*) vf.mTexCoords; @@ -1835,9 +1851,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, for (S32 i = 0; i < num_vertices; i++) { LLVector2 tc(vf.mTexCoords[i]); - //LLVector4a& norm = vf.mNormals[i]; - //LLVector4a& center = *(vf.mCenter); - + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); tmp = tmp * *mTextureMatrix; tc.mV[0] = tmp.mV[0]; @@ -1848,7 +1862,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { //no bump, tex gen planar - LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_QUICK_PLANAR); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - texgen planar"); if (do_tex_mat) { for (S32 i = 0; i < num_vertices; i++) @@ -1893,7 +1907,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } else { //bump mapped or has material, just do the whole expensive loop - LL_RECORD_BLOCK_TIME(FTM_FACE_TEX_DEFAULT); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - texgen default"); std::vector<LLVector2> bump_tc; @@ -2051,14 +2065,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a* end = src+num_vertices; //LLVector4a* end_64 = end-4; - //LL_RECORD_TIME_BLOCK(FTM_FACE_GEOM_POSITION); llassert(num_vertices > 0); mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); - LLMatrix4a mat_vert; - mat_vert.loadu(mat_vert_in); - + F32* dst = (F32*) vert.get(); F32* end_f32 = dst+mGeomCount*4; @@ -2088,53 +2099,19 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a tmp; - { - //LL_RECORD_TIME_BLOCK(FTM_FACE_POSITION_STORE); - - /*if (num_vertices > 4) - { //more than 64 bytes - while (src < end_64) - { - _mm_prefetch((char*)src + 64, _MM_HINT_T0); - _mm_prefetch((char*)dst + 64, _MM_HINT_T0); - - mat_vert.affineTransform(*src, res0); - tmp.setSelectWithMask(mask, texIdx, res0); - tmp.store4a((F32*) dst); - - mat_vert.affineTransform(*(src+1), res1); - tmp.setSelectWithMask(mask, texIdx, res1); - tmp.store4a((F32*) dst+4); - - mat_vert.affineTransform(*(src+2), res2); - tmp.setSelectWithMask(mask, texIdx, res2); - tmp.store4a((F32*) dst+8); - - mat_vert.affineTransform(*(src+3), res3); - tmp.setSelectWithMask(mask, texIdx, res3); - tmp.store4a((F32*) dst+12); - - dst += 16; - src += 4; - } - }*/ - - while (src < end) - { - mat_vert.affineTransform(*src++, res0); - tmp.setSelectWithMask(mask, texIdx, res0); - tmp.store4a((F32*) dst); - dst += 4; - } + + while (src < end) + { + mat_vert.affineTransform(*src++, res0); + tmp.setSelectWithMask(mask, texIdx, res0); + tmp.store4a((F32*) dst); + dst += 4; } - + + while (dst < end_f32) { - //LL_RECORD_TIME_BLOCK(FTM_FACE_POSITION_PAD); - while (dst < end_f32) - { - res0.store4a((F32*) dst); - dst += 4; - } + res0.store4a((F32*) dst); + dst += 4; } if (map_range) @@ -2143,10 +2120,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - if (rebuild_normal) { - //LL_RECORD_TIME_BLOCK(FTM_FACE_GEOM_NORMAL); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - normal"); + mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range); F32* normals = (F32*) norm.get(); LLVector4a* src = vf.mNormals; @@ -2168,7 +2145,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_tangent) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_TANGENT); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - tangent"); mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount, map_range); F32* tangents = (F32*) tangent.get(); @@ -2201,7 +2178,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_weights && vf.mWeights) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_WEIGHTS); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - weight"); mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, map_range); F32* weights = (F32*) wght.get(); LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); @@ -2213,7 +2190,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_COLOR); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - color"); mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, map_range); LLVector4a src; @@ -2244,7 +2221,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_emissive) { - LL_RECORD_BLOCK_TIME(FTM_FACE_GEOM_EMISSIVE); + LL_PROFILE_ZONE_NAMED("getGeometryVolume - emissive"); LLStrider<LLColor4U> emissive; mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount, map_range); @@ -2375,6 +2352,8 @@ F32 LLFace::getTextureVirtualSize() BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { + LL_PROFILE_ZONE_SCOPED + //VECTORIZE THIS //get area of circle around face LLVector4a center; @@ -2654,6 +2633,8 @@ const LLMatrix4& LLFace::getRenderMatrix() const S32 LLFace::renderElements(const U16 *index_array) const { + LL_PROFILE_ZONE_SCOPED + S32 ret = 0; if (isState(GLOBAL)) @@ -2673,6 +2654,8 @@ S32 LLFace::renderElements(const U16 *index_array) const S32 LLFace::renderIndexed() { + LL_PROFILE_ZONE_SCOPED + if(mDrawablep == NULL || mDrawPoolp == NULL) { return 0; @@ -2683,6 +2666,8 @@ S32 LLFace::renderIndexed() S32 LLFace::renderIndexed(U32 mask) { + LL_PROFILE_ZONE_SCOPED + if (mVertexBuffer.isNull()) { return 0; @@ -2760,56 +2745,6 @@ void LLFace::clearVertexBuffer() mVertexBuffer = NULL; } -//static -U32 LLFace::getRiggedDataMask(U32 type) -{ - static const U32 rigged_data_mask[] = { - LLDrawPoolAvatar::RIGGED_MATERIAL_MASK, - LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_VMASK, - LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_MASK_MASK, - LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_EMISSIVE_MASK, - LLDrawPoolAvatar::RIGGED_SPECMAP_VMASK, - LLDrawPoolAvatar::RIGGED_SPECMAP_BLEND_MASK, - LLDrawPoolAvatar::RIGGED_SPECMAP_MASK_MASK, - LLDrawPoolAvatar::RIGGED_SPECMAP_EMISSIVE_MASK, - LLDrawPoolAvatar::RIGGED_NORMMAP_VMASK, - LLDrawPoolAvatar::RIGGED_NORMMAP_BLEND_MASK, - LLDrawPoolAvatar::RIGGED_NORMMAP_MASK_MASK, - LLDrawPoolAvatar::RIGGED_NORMMAP_EMISSIVE_MASK, - LLDrawPoolAvatar::RIGGED_NORMSPEC_VMASK, - LLDrawPoolAvatar::RIGGED_NORMSPEC_BLEND_MASK, - LLDrawPoolAvatar::RIGGED_NORMSPEC_MASK_MASK, - LLDrawPoolAvatar::RIGGED_NORMSPEC_EMISSIVE_MASK, - LLDrawPoolAvatar::RIGGED_SIMPLE_MASK, - LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK, - LLDrawPoolAvatar::RIGGED_SHINY_MASK, - LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK, - LLDrawPoolAvatar::RIGGED_GLOW_MASK, - LLDrawPoolAvatar::RIGGED_ALPHA_MASK, - LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK, - LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK, - LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK, - }; - - llassert(type < sizeof(rigged_data_mask)/sizeof(U32)); - - return rigged_data_mask[type]; -} - -U32 LLFace::getRiggedVertexBufferDataMask() const -{ - U32 data_mask = 0; - for (U32 i = 0; i < mRiggedIndex.size(); ++i) - { - if (mRiggedIndex[i] > -1) - { - data_mask |= LLFace::getRiggedDataMask(i); - } - } - - return data_mask; -} - S32 LLFace::getRiggedIndex(U32 type) const { if (mRiggedIndex.empty()) @@ -2822,19 +2757,7 @@ S32 LLFace::getRiggedIndex(U32 type) const return mRiggedIndex[type]; } -void LLFace::setRiggedIndex(U32 type, S32 index) +U64 LLFace::getSkinHash() { - if (mRiggedIndex.empty()) - { - mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES); - for (U32 i = 0; i < mRiggedIndex.size(); ++i) - { - mRiggedIndex[i] = -1; - } - } - - llassert(type < mRiggedIndex.size()); - - mRiggedIndex[type] = index; + return mSkinInfo ? mSkinInfo->mHash : 0; } - diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 3611539ff8..79f50f2273 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -47,18 +47,18 @@ class LLTextureEntry; class LLVertexProgram; class LLViewerTexture; class LLGeometryManager; -class LLTextureAtlasSlot; class LLDrawInfo; +class LLMeshSkinInfo; const F32 MIN_ALPHA_SIZE = 1024.f; const F32 MIN_TEX_ANIM_SIZE = 512.f; const U8 FACE_DO_NOT_BATCH_TEXTURES = 255; -class LLFace : public LLTrace::MemTrackableNonVirtual<LLFace, 16> +class alignas(16) LLFace { + LL_ALIGN_NEW public: LLFace(const LLFace& rhs) - : LLTrace::MemTrackableNonVirtual<LLFace, 16>("LLFace") { *this = rhs; } @@ -85,8 +85,8 @@ public: public: LLFace(LLDrawable* drawablep, LLViewerObject* objp) - : LLTrace::MemTrackableNonVirtual<LLFace, 16>("LLFace") { + LL_PROFILE_ZONE_SCOPED; init(drawablep, objp); } ~LLFace() { destroy(); } @@ -228,11 +228,7 @@ public: void setVertexBuffer(LLVertexBuffer* buffer); void clearVertexBuffer(); //sets mVertexBuffer to NULL LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } - U32 getRiggedVertexBufferDataMask() const; S32 getRiggedIndex(U32 type) const; - void setRiggedIndex(U32 type, S32 index); - - static U32 getRiggedDataMask(U32 type); void notifyAboutCreatingTexture(LLViewerTexture *texture); void notifyAboutMissingAsset(LLViewerTexture *texture); @@ -261,6 +257,11 @@ public: LLMatrix4* mSpecMapMatrix; LLMatrix4* mNormalMapMatrix; LLDrawInfo* mDrawInfo; + LLVOAvatar* mAvatar = nullptr; + LLMeshSkinInfo* mSkinInfo = nullptr; + + // return mSkinInfo->mHash or 0 if mSkinInfo is null + U64 getSkinHash(); private: LLPointer<LLVertexBuffer> mVertexBuffer; @@ -271,10 +272,10 @@ private: LLColor4 mFaceColor; // overrides material color if state |= USE_FACE_COLOR U16 mGeomCount; // vertex count for this face - U16 mGeomIndex; // index into draw pool + U16 mGeomIndex; // starting index into mVertexBuffer's vertex array U8 mTextureIndex; // index of texture channel to use for pseudo-atlasing U32 mIndicesCount; - U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) + U32 mIndicesIndex; // index into mVertexBuffer's index array S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; LLXformMatrix* mXform; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 239d162101..1605e4133d 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -716,7 +716,6 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t //====================================== buffer.clear(); - gGL.color3fv(base_col.mV); U32 count = 0; U32 total_count = base_execution.size(); @@ -1019,11 +1018,9 @@ void LLFastTimerView::printLineStats() } } -static LLTrace::BlockTimerStatHandle FTM_DRAW_LINE_GRAPH("Draw line graph"); - void LLFastTimerView::drawLineGraph() { - LL_RECORD_BLOCK_TIME(FTM_DRAW_LINE_GRAPH); + LL_PROFILE_ZONE_SCOPED; //draw line graph history gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLLocalClipRect clip(mGraphRect); @@ -1062,6 +1059,7 @@ void LLFastTimerView::drawLineGraph() F32Seconds cur_max(0); U32 cur_max_calls = 0; + for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); it != LLTrace::end_block_timer_tree_df(); ++it) @@ -1096,6 +1094,7 @@ void LLFastTimerView::drawLineGraph() F32 call_scale_factor = (F32)mGraphRect.getHeight() / (F32)max_calls; F32 time_scale_factor = (F32)mGraphRect.getHeight() / max_time.value(); F32 hz_scale_factor = (F32) mGraphRect.getHeight() / (1.f / max_time.value()); + for (U32 j = mRecording.getNumRecordedPeriods(); j > 0; j--) @@ -1103,7 +1102,7 @@ void LLFastTimerView::drawLineGraph() LLTrace::Recording& recording = mRecording.getPrevRecording(j); F32Seconds time = llmax(recording.getSum(*idp), F64Seconds(0.000001)); U32 calls = recording.getSum(idp->callCount()); - + if (is_hover_timer) { //normalize to highlighted timer @@ -1450,6 +1449,7 @@ void LLFastTimerView::updateTotalTime() void LLFastTimerView::drawBars() { + LL_PROFILE_ZONE_SCOPED; LLLocalClipRect clip(mBarRect); S32 bar_height = mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2); @@ -1527,11 +1527,9 @@ void LLFastTimerView::drawBars() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); - F32Seconds LLFastTimerView::updateTimerBarWidths(LLTrace::BlockTimerStatHandle* time_block, TimerBarRow& row, S32 history_index, U32& bar_index) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_TIMER_BAR_WIDTHS); + LL_PROFILE_ZONE_SCOPED; const F32Seconds self_time = history_index == -1 ? mRecording.getPeriodMean(time_block->selfTime(), RUNNING_AVERAGE_WIDTH) : mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()); @@ -1555,11 +1553,9 @@ F32Seconds LLFastTimerView::updateTimerBarWidths(LLTrace::BlockTimerStatHandle* return full_time; } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_TIMER_BAR_FRACTIONS("Update timer bar fractions"); - S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::BlockTimerStatHandle* time_block, TimerBarRow& row, S32 timer_bar_index) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_TIMER_BAR_FRACTIONS); + LL_PROFILE_ZONE_SCOPED; TimerBar& timer_bar = row.mBars[timer_bar_index]; const F32Seconds bar_time = timer_bar.mTotalTime - timer_bar.mSelfTime; @@ -1620,6 +1616,7 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::BlockTimerStatHandle* time_b S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, bool visible, S32 bar_index) { + LL_PROFILE_ZONE_SCOPED; TimerBar& timer_bar = row.mBars[bar_index]; LLTrace::BlockTimerStatHandle* time_block = timer_bar.mTimeBlock; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index e6bbe234b3..3240f169b3 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -520,7 +520,6 @@ void LLFeatureManager::initSingleton() void LLFeatureManager::applyRecommendedSettings() { - loadGPUClass(); // apply saved settings // cap the level at 2 (high) U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); @@ -607,22 +606,6 @@ void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures) // if we're passed an invalid level, default to "Low" std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low"); - if (features == "Low") - { -#if LL_DARWIN - // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac - // systems which support them instead of falling back to fixed-function unnecessarily - // MAINT-2157 - if (gGLManager.mGLVersion < 2.1f) -#else - // only use fixed function by default if GL version < 3.0 or this is an intel graphics chip - if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel) -#endif - { - // same as Low, but with "Basic Shaders" disabled - features = "LowFixedFunction"; - } - } maskFeatures(features); @@ -670,46 +653,18 @@ void LLFeatureManager::applyBaseMasks() } // now all those wacky ones - if (!gGLManager.mHasFragmentShader) - { - maskFeatures("NoPixelShaders"); - } - if (!gGLManager.mHasVertexShader || !mGPUSupported) - { - maskFeatures("NoVertexShaders"); - } if (gGLManager.mIsNVIDIA) { maskFeatures("NVIDIA"); } - if (gGLManager.mIsGF2or4MX) - { - maskFeatures("GeForce2"); - } - if (gGLManager.mIsATI) - { - maskFeatures("ATI"); - } - if (gGLManager.mHasATIMemInfo && gGLManager.mVRAM < 256) + if (gGLManager.mIsAMD) { - maskFeatures("ATIVramLT256"); - } - if (gGLManager.mATIOldDriver) - { - maskFeatures("ATIOldDriver"); - } - if (gGLManager.mIsGFFX) - { - maskFeatures("GeForceFX"); + maskFeatures("AMD"); } if (gGLManager.mIsIntel) { maskFeatures("Intel"); } - if (gGLManager.mGLVersion < 1.5f) - { - maskFeatures("OpenGLPre15"); - } if (gGLManager.mGLVersion < 3.f) { maskFeatures("OpenGLPre30"); @@ -749,17 +704,6 @@ void LLFeatureManager::applyBaseMasks() //LL_INFOS() << "Masking features from gpu table match: " << gpustr << LL_ENDL; maskFeatures(gpustr); - // now mask cpu type ones - if (gSysMemory.getPhysicalMemoryKB() <= U32Megabytes(256)) - { - maskFeatures("RAM256MB"); - } - - if (gSysCPU.getMHz() < 1100) - { - maskFeatures("CPUSlow"); - } - if (isSafe()) { maskFeatures("safe"); @@ -774,11 +718,9 @@ LLSD LLFeatureManager::getRecommendedSettingsMap() LLSD map(LLSD::emptyMap()); - loadGPUClass(); U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); LL_INFOS("RenderInit") << "Getting the map of recommended settings for level " << level << LL_ENDL; - applyBaseMasks(); std::string features(isValidGraphicsLevel(level) ? getNameForGraphicsLevel(level) : "Low"); maskFeatures(features); diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index e075a311c2..0b0567b687 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -47,9 +47,6 @@ static const F32 SEC_PER_FLEXI_FRAME = 1.f / 60.f; // 60 flexi updates per secon /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; std::vector<LLVolumeImplFlexible*> LLVolumeImplFlexible::sInstanceList; -static LLTrace::BlockTimerStatHandle FTM_FLEXIBLE_REBUILD("Rebuild"); -static LLTrace::BlockTimerStatHandle FTM_DO_FLEXIBLE_UPDATE("Flexible Update"); - // LLFlexibleObjectData::pack/unpack now in llprimitive.cpp //----------------------------------------------- @@ -95,7 +92,7 @@ LLVolumeImplFlexible::~LLVolumeImplFlexible() //static void LLVolumeImplFlexible::updateClass() { - LL_RECORD_BLOCK_TIME(FTM_DO_FLEXIBLE_UPDATE); + LL_PROFILE_ZONE_SCOPED; U64 virtual_frame_num = LLTimer::getElapsedSeconds() / SEC_PER_FLEXI_FRAME; for (std::vector<LLVolumeImplFlexible*>::iterator iter = sInstanceList.begin(); @@ -429,7 +426,7 @@ inline S32 log2(S32 x) void LLVolumeImplFlexible::doFlexibleUpdate() { - LL_RECORD_BLOCK_TIME(FTM_DO_FLEXIBLE_UPDATE); + LL_PROFILE_ZONE_SCOPED; LLVolume* volume = mVO->getVolume(); LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) @@ -720,13 +717,12 @@ void LLVolumeImplFlexible::doFlexibleUpdate() mLastSegmentRotation = parentSegmentRotation; } -static LLTrace::BlockTimerStatHandle FTM_FLEXI_PREBUILD("Flexi Prebuild"); void LLVolumeImplFlexible::preRebuild() { if (!mUpdated) { - LL_RECORD_BLOCK_TIME(FTM_FLEXI_PREBUILD); + LL_PROFILE_ZONE_SCOPED; doFlexibleRebuild(false); } } @@ -752,6 +748,7 @@ void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped) BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) { + LL_PROFILE_ZONE_SCOPED; LLVOVolume *volume = (LLVOVolume*)mVO; if (mVO->isAttachment()) @@ -789,7 +786,6 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) if (mRenderRes > -1) { - LL_RECORD_BLOCK_TIME(FTM_DO_FLEXIBLE_UPDATE); doFlexibleUpdate(); } @@ -809,7 +805,6 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME); volume->dirtySpatialGroup(); { - LL_RECORD_BLOCK_TIME(FTM_FLEXIBLE_REBUILD); doFlexibleRebuild(volume->mVolumeChanged); } volume->genBBoxes(isVolumeGlobal()); diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 687d820a18..a3037ed651 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1087,10 +1087,7 @@ BOOL LLPreviewAnimation::render() gGL.pushMatrix(); gGL.loadIdentity(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); LLGLSUIDefault def; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 028c922a4d..89ba687d25 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -664,10 +664,7 @@ BOOL LLImagePreviewAvatar::render() LLGLSUIDefault def; gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); gl_rect_2d_simple( mFullWidth, mFullHeight ); @@ -866,10 +863,7 @@ BOOL LLImagePreviewSculpted::render() gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); gl_rect_2d_simple( mFullWidth, mFullHeight ); @@ -903,10 +897,7 @@ BOOL LLImagePreviewSculpted::render() gPipeline.enableLightsAvatar(); - if (LLGLSLShader::sNoFixedFunction) - { - gObjectPreviewProgram.bind(); - } + gObjectPreviewProgram.bind(); gPipeline.enableLightsPreview(); gGL.pushMatrix(); @@ -920,10 +911,7 @@ BOOL LLImagePreviewSculpted::render() gGL.popMatrix(); - if (LLGLSLShader::sNoFixedFunction) - { - gObjectPreviewProgram.unbind(); - } + gObjectPreviewProgram.unbind(); return TRUE; } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 9c84fa1991..112ece0fbf 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -723,7 +723,8 @@ void LLFloaterIMContainer::setMinimized(BOOL b) } void LLFloaterIMContainer::setVisible(BOOL visible) -{ LLFloaterIMNearbyChat* nearby_chat; +{ + LLFloaterIMNearbyChat* nearby_chat; if (visible) { // Make sure we have the Nearby Chat present when showing the conversation container @@ -758,22 +759,25 @@ void LLFloaterIMContainer::setVisible(BOOL visible) LLFloaterIMSessionTab::addToHost(LLUUID()); } - // We need to show/hide all the associated conversations that have been torn off - // (and therefore, are not longer managed by the multifloater), - // so that they show/hide with the conversations manager. - conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - for (;widget_it != mConversationsWidgets.end(); ++widget_it) - { - LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); - if (widget) - { - LLFloater* session_floater = widget->getSessionFloater(); - if (session_floater != nearby_chat) - { - widget->setVisibleIfDetached(visible); - } - } - } + if (!LLFloater::isQuitRequested()) + { + // We need to show/hide all the associated conversations that have been torn off + // (and therefore, are not longer managed by the multifloater), + // so that they show/hide with the conversations manager. + conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + for (; widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + LLFloater* session_floater = widget->getSessionFloater(); + if (session_floater != nearby_chat) + { + widget->setVisibleIfDetached(visible); + } + } + } + } // Now, do the normal multifloater show/hide LLMultiFloater::setVisible(visible); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index d6bb0ec872..c907dfc969 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1370,31 +1370,31 @@ void LLFloaterModelPreview::clearAvatarTab() } void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides) - { +{ S32 display_lod = mModelPreview->mPreviewLOD; if (mModelPreview->mModel[display_lod].empty()) - { + { mSelectedJointName.clear(); return; - } + } // Joints will be listed as long as they are listed in mAlternateBindMatrix // even if they are for some reason identical to defaults. // Todo: Are overrides always identical for all lods? They normally are, but there might be situations where they aren't. if (mJointOverrides[display_lod].empty()) - { + { // populate map for (LLModelLoader::scene::iterator iter = mModelPreview->mScene[display_lod].begin(); iter != mModelPreview->mScene[display_lod].end(); ++iter) - { + { for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) - { + { LLModelInstance& instance = *model_iter; LLModel* model = instance.mModel; const LLMeshSkinInfo *skin = &model->mSkinInfo; U32 joint_count = LLSkinningUtil::getMeshJointCount(skin); U32 bind_count = highlight_overrides ? skin->mAlternateBindMatrix.size() : 0; // simply do not include overrides if data is not needed if (bind_count > 0 && bind_count != joint_count) - { + { std::ostringstream out; out << "Invalid joint overrides for model " << model->getName(); out << ". Amount of joints " << joint_count; @@ -1403,68 +1403,68 @@ void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides) addStringToLog(out.str(), true); // Disable overrides for this model bind_count = 0; - } + } if (bind_count > 0) - { + { for (U32 j = 0; j < joint_count; ++j) - { - const LLVector3& joint_pos = skin->mAlternateBindMatrix[j].getTranslation(); + { + const LLVector3& joint_pos = LLVector3(skin->mAlternateBindMatrix[j].getTranslation()); LLJointOverrideData &data = mJointOverrides[display_lod][skin->mJointNames[j]]; LLJoint* pJoint = LLModelPreview::lookupJointByName(skin->mJointNames[j], mModelPreview); if (pJoint) - { + { // see how voavatar uses aboveJointPosThreshold if (pJoint->aboveJointPosThreshold(joint_pos)) - { + { // valid override if (data.mPosOverrides.size() > 0 && (data.mPosOverrides.begin()->second - joint_pos).lengthSquared() > (LL_JOINT_TRESHOLD_POS_OFFSET * LL_JOINT_TRESHOLD_POS_OFFSET)) - { + { // File contains multiple meshes with conflicting joint offsets // preview may be incorrect, upload result might wary (depends onto // mesh_id that hasn't been generated yet). data.mHasConflicts = true; - } + } data.mPosOverrides[model->getName()] = joint_pos; - } - else - { + } + else + { // default value, it won't be accounted for by avatar data.mModelsNoOverrides.insert(model->getName()); - } - } - } - } - else - { + } + } + } + } + else + { for (U32 j = 0; j < joint_count; ++j) - { + { LLJointOverrideData &data = mJointOverrides[display_lod][skin->mJointNames[j]]; data.mModelsNoOverrides.insert(model->getName()); } } - } - } - } + } + } + } LLPanel *panel = mTabContainer->getPanelByName("rigging_panel"); LLScrollListCtrl *joints_list = panel->getChild<LLScrollListCtrl>("joints_list"); if (joints_list->isEmpty()) - { + { // Populate table - std::map<std::string, std::string> joint_alias_map; + std::map<std::string, std::string> joint_alias_map; mModelPreview->getJointAliases(joint_alias_map); - + S32 conflicts = 0; joint_override_data_map_t::iterator joint_iter = mJointOverrides[display_lod].begin(); joint_override_data_map_t::iterator joint_end = mJointOverrides[display_lod].end(); while (joint_iter != joint_end) - { + { const std::string& listName = joint_iter->first; - + LLScrollListItem::Params item_params; item_params.value(listName); @@ -1472,38 +1472,38 @@ void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides) cell_params.font = LLFontGL::getFontSansSerif(); cell_params.value = listName; if (joint_alias_map.find(listName) == joint_alias_map.end()) - { + { // Missing names cell_params.color = LLColor4::red; - } + } if (joint_iter->second.mHasConflicts) - { + { // Conflicts cell_params.color = LLColor4::orange; conflicts++; - } + } if (highlight_overrides && joint_iter->second.mPosOverrides.size() > 0) - { + { cell_params.font.style = "BOLD"; - } + } item_params.columns.add(cell_params); joints_list->addRow(item_params, ADD_BOTTOM); joint_iter++; - } + } joints_list->selectFirstItem(); LLScrollListItem *selected = joints_list->getFirstSelected(); if (selected) -{ + { mSelectedJointName = selected->getValue().asString(); - } + } LLTextBox *joint_conf_descr = panel->getChild<LLTextBox>("conflicts_description"); joint_conf_descr->setTextArg("[CONFLICTS]", llformat("%d", conflicts)); joint_conf_descr->setTextArg("[JOINTS_COUNT]", llformat("%d", mJointOverrides[display_lod].size())); - } - } + } +} //----------------------------------------------------------------------------- // addStringToLogTab() diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index da01457126..b7d3701e4a 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1196,14 +1196,11 @@ void LLFloaterPreference::refreshEnabledState() //Deferred/SSAO/Shadows BOOL bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump"); - BOOL transparent_water = LLFeatureManager::getInstance()->isFeatureAvailable("RenderTransparentWater") && gSavedSettings.getBOOL("RenderTransparentWater"); BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && bumpshiny && - transparent_water && shaders && gGLManager.mHasFramebufferObject && - gSavedSettings.getBOOL("RenderAvatarVP") && (ctrl_wind_light->get()) ? TRUE : FALSE; ctrl_deferred->setEnabled(enabled); @@ -1224,37 +1221,14 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() ctrl_reflections->setEnabled(reflections); reflections_text->setEnabled(reflections); - // Transparent Water - LLCheckBoxCtrl* transparent_water_ctrl = getChild<LLCheckBoxCtrl>("TransparentWater"); - // Bump & Shiny LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny"); bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE); // Avatar Mode - // Enable Avatar Shaders - LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram"); // Avatar Render Mode - LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth"); - - bool avatar_vp_enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"); - if (LLViewerShaderMgr::sInitialized) - { - S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel; - avatar_vp_enabled = (max_avatar_shader > 0) ? TRUE : FALSE; - } - - ctrl_avatar_vp->setEnabled(avatar_vp_enabled); - - if (gSavedSettings.getBOOL("RenderAvatarVP") == FALSE) - { - ctrl_avatar_cloth->setEnabled(FALSE); - } - else - { - ctrl_avatar_cloth->setEnabled(TRUE); - } + getChild<LLCheckBoxCtrl>("AvatarCloth")->setEnabled(TRUE); // Vertex Shaders, Global Shader Enable // SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code @@ -1277,9 +1251,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && - ((transparent_water_ctrl && transparent_water_ctrl->get()) ? TRUE : FALSE) && gGLManager.mHasFramebufferObject && - gSavedSettings.getBOOL("RenderAvatarVP") && (ctrl_wind_light->get()) ? TRUE : FALSE; ctrl_deferred->setEnabled(enabled); @@ -1378,7 +1350,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings() { LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections"); LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText"); - LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram"); LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth"); LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders"); LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); @@ -1454,30 +1425,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings() reflections_text->setEnabled(FALSE); } - // disabled av - if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) - { - ctrl_avatar_vp->setEnabled(FALSE); - ctrl_avatar_vp->setValue(FALSE); - - ctrl_avatar_cloth->setEnabled(FALSE); - ctrl_avatar_cloth->setValue(FALSE); - - //deferred needs AvatarVP, disable deferred - ctrl_shadows->setEnabled(FALSE); - ctrl_shadows->setValue(0); - shadows_text->setEnabled(FALSE); - - ctrl_ssao->setEnabled(FALSE); - ctrl_ssao->setValue(FALSE); - - ctrl_dof->setEnabled(FALSE); - ctrl_dof->setValue(FALSE); - - ctrl_deferred->setEnabled(FALSE); - ctrl_deferred->setValue(FALSE); - } - // disabled cloth if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) { diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 23fd6d9c8e..ceab472c55 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -159,7 +159,7 @@ LLFloater* LLFloaterWebContent::create( Params p) //static void LLFloaterWebContent::closeRequest(const std::string &uuid) { - LLFloaterWebContent* floaterp = instance_tracker_t::getInstance(uuid); + auto floaterp = instance_tracker_t::getInstance(uuid); if (floaterp) { floaterp->closeFloater(false); @@ -169,7 +169,7 @@ void LLFloaterWebContent::closeRequest(const std::string &uuid) //static void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) { - LLFloaterWebContent* floaterp = instance_tracker_t::getInstance(uuid); + auto floaterp = instance_tracker_t::getInstance(uuid); if (floaterp) { floaterp->geometryChanged(x, y, width, height); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 698c15bd2d..175f1849cf 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -791,10 +791,7 @@ void LLViewerObjectList::renderObjectBeacons() LLGLSUIDefault gls_ui; - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -882,10 +879,7 @@ void LLViewerObjectList::renderObjectBeacons() void LLSky::renderSunMoonBeacons(const LLVector3& pos_agent, const LLVector3& direction, LLColor4 color) { LLGLSUIDefault gls_ui; - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLVector3 pos_end; @@ -993,9 +987,8 @@ private: //----------------------------------------------------------------------------- F32 gpu_benchmark() { - if (!gGLManager.mHasShaderObjects || !gGLManager.mHasTimerQuery) - { // don't bother benchmarking the fixed function - // or venerable drivers which don't support accurate timing anyway + if (!gGLManager.mHasTimerQuery) + { // don't bother benchmarking venerable drivers which don't support accurate timing anyway // and are likely to be correctly identified by the GPU table already. return -1.f; } @@ -1091,7 +1084,7 @@ F32 gpu_benchmark() delete [] pixels; //make a dummy triangle to draw with - LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); + LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, GL_STREAM_DRAW_ARB); if (!buff->allocateBuffer(3, 0, true)) { @@ -1101,7 +1094,6 @@ F32 gpu_benchmark() } LLStrider<LLVector3> v; - LLStrider<LLVector2> tc; if (! buff->getVertexStrider(v)) { @@ -1123,6 +1115,16 @@ F32 gpu_benchmark() // ensure matched pair of bind() and unbind() calls ShaderBinder binder(gBenchmarkProgram); +#ifdef GL_ARB_vertex_array_object + U32 glarray = 0; + + if (LLRender::sGLCoreProfile) + { + glGenVertexArrays(1, &glarray); + glBindVertexArray(glarray); + } +#endif + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); glFinish(); @@ -1155,6 +1157,15 @@ F32 gpu_benchmark() } } +#ifdef GL_ARB_vertex_array_object + if (LLRender::sGLCoreProfile) + { + glBindVertexArray(0); + glDeleteVertexArrays(1, &glarray); + } +#endif + + std::sort(results.begin(), results.end()); F32 gbps = results[results.size()/2]; diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 32f88b49ac..7f65153879 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -944,12 +944,10 @@ static void formatDateString(std::string &date_string) } } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_MEMBERS_REPLY("Process Group Members"); - // static void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_MEMBERS_REPLY); + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupMembersReply" << LL_ENDL; LLUUID agent_id; @@ -1054,12 +1052,10 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data) LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_PROPERTIES_REPLY("Process Group Properties"); - //static void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_PROPERTIES_REPLY); + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupPropertiesReply" << LL_ENDL; if (!msg) @@ -1139,11 +1135,10 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data) LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES); } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_ROLE_DATA_REPLY("Process Group Role Data"); // static void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_ROLE_DATA_REPLY); + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleDataReply" << LL_ENDL; LLUUID agent_id; @@ -1227,11 +1222,10 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data) LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA); } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_ROLE_MEMBERS_REPLY("Process Group Role Members"); // static void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_ROLE_MEMBERS_REPLY); + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleMembersReply" << LL_ENDL; LLUUID agent_id; diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 9d49c30a49..8e296321d2 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -224,6 +224,7 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector4a& start, const LLVector4 void LLHUDNameTag::render() { + LL_PROFILE_ZONE_SCOPED; if (sDisplayText) { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -322,8 +323,6 @@ void LLHUDNameTag::renderText(BOOL for_select) // Render label { - //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin(); segment_iter != mLabelSegments.end(); ++segment_iter ) { @@ -731,6 +730,7 @@ void LLHUDNameTag::updateSize() void LLHUDNameTag::updateAll() { + LL_PROFILE_ZONE_SCOPED; // iterate over all text objects, calculate their restoration forces, // and add them to the visible set if they are on screen and close enough sVisibleTextObjects.clear(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 7c957ac712..9d8bf7f51c 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -188,9 +188,6 @@ void LLHUDText::renderText() F32 y_offset = (F32)mOffsetY; // Render label - { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } // Render text { @@ -573,7 +570,6 @@ void LLHUDText::renderAllHUD() { LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); { LLGLEnable color_mat(GL_COLOR_MATERIAL); @@ -591,7 +587,6 @@ void LLHUDText::renderAllHUD() LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); } void LLHUDText::shiftAll(const LLVector3& offset) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 1059324a16..f5358ba5f2 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1229,7 +1229,6 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id, if (!session) { - LL_WARNS() << "session " << session_id << "does not exist " << LL_ENDL; return NULL; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 81b55c1073..3609c5e457 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5740,14 +5740,14 @@ class LLCallingCardObserver : public LLFriendObserver public: LLCallingCardObserver(LLCallingCardBridge* bridge) : mBridgep(bridge) {} virtual ~LLCallingCardObserver() { mBridgep = NULL; } - virtual void changed(U32 mask) - { - mBridgep->refreshFolderViewItem(); - if (mask & LLFriendObserver::ONLINE) - { - mBridgep->checkSearchBySuffixChanges(); - } - } + virtual void changed(U32 mask) + { + if (mask & LLFriendObserver::ONLINE) + { + mBridgep->refreshFolderViewItem(); + mBridgep->checkSearchBySuffixChanges(); + } + } protected: LLCallingCardBridge* mBridgep; }; @@ -5761,14 +5761,15 @@ LLCallingCardBridge::LLCallingCardBridge(LLInventoryPanel* inventory, const LLUUID& uuid ) : LLItemBridge(inventory, root, uuid) { - mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); + mObserver = new LLCallingCardObserver(this); + LLAvatarTracker::instance().addParticularFriendObserver(getItem()->getCreatorUUID(), mObserver); } LLCallingCardBridge::~LLCallingCardBridge() { - LLAvatarTracker::instance().removeObserver(mObserver); - delete mObserver; + LLAvatarTracker::instance().removeParticularFriendObserver(getItem()->getCreatorUUID(), mObserver); + + delete mObserver; } void LLCallingCardBridge::refreshFolderViewItem() diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 3b5ba24b9f..707ff2b7b6 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -48,8 +48,6 @@ #include "llclipboard.h" #include "lltrans.h" -LLTrace::BlockTimerStatHandle FT_FILTER_CLIPBOARD("Filter Clipboard"); - LLInventoryFilter::FilterOps::FilterOps(const Params& p) : mFilterObjectTypes(p.object_types), mFilterCategoryTypes(p.category_types), @@ -506,7 +504,7 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const { if (LLClipboard::instance().isCutMode()) { - LL_RECORD_BLOCK_TIME(FT_FILTER_CLIPBOARD); + LL_PROFILE_ZONE_SCOPED; LLUUID current_id = object_id; LLInventoryObject *current_object = gInventory.getObject(object_id); while (current_id.notNull() && current_object) diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 1dc1aa395e..23129f7d44 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -133,11 +133,9 @@ void LLInventoryItemsList::idle(void* user_data) } } -LLTrace::BlockTimerStatHandle FTM_INVENTORY_ITEMS_REFRESH("Inventory List Refresh"); - void LLInventoryItemsList::refresh() { - LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH); + LL_PROFILE_ZONE_SCOPED; switch (mRefreshState) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 05d9fec701..7c241c3283 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -674,10 +674,9 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve } // Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849) -static LLTrace::BlockTimerStatHandle FTM_REFRESH("Inventory Refresh"); void LLInventoryPanel::modelChanged(U32 mask) { - LL_RECORD_BLOCK_TIME(FTM_REFRESH); + LL_PROFILE_ZONE_SCOPED; if (mViewsInitialized != VIEWS_INITIALIZED) return; @@ -1692,10 +1691,9 @@ void LLInventoryPanel::removeItemID(const LLUUID& id) } } -LLTrace::BlockTimerStatHandle FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) { - LL_RECORD_BLOCK_TIME(FTM_GET_ITEM_BY_ID); + LL_PROFILE_ZONE_SCOPED; std::map<LLUUID, LLFolderViewItem*>::iterator map_it; map_it = mItemMap.find(id); diff --git a/indra/newview/lllegacyatmospherics.cpp b/indra/newview/lllegacyatmospherics.cpp index a2acb3efe2..1364067949 100644 --- a/indra/newview/lllegacyatmospherics.cpp +++ b/indra/newview/lllegacyatmospherics.cpp @@ -202,17 +202,11 @@ void LLAtmospherics::init() mInitialized = true; } -LLColor4 LLAtmospherics::calcSkyColorInDir(AtmosphericsVars& vars, const LLVector3 &dir, bool isShiny) -{ - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - return calcSkyColorInDir(psky, vars, dir, isShiny); -} - // This cubemap is used as "environmentMap" in indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl -LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const LLVector3 &dir, bool isShiny) +LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const LLVector3 &dir, bool isShiny, bool low_end) { - F32 sky_saturation = 0.25f; - F32 land_saturation = 0.1f; + const F32 sky_saturation = 0.25f; + const F32 land_saturation = 0.1f; if (isShiny && dir.mV[VZ] < -0.02f) { @@ -227,7 +221,7 @@ LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, Atm } F32 greyscale_sat = brightness * (1.0f - land_saturation); desat_fog = desat_fog * land_saturation + smear(greyscale_sat); - if (!gPipeline.canUseWindLightShaders()) + if (low_end) { col = LLColor4(desat_fog, 0.f); } @@ -258,8 +252,7 @@ LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, Atm return LLColor4(sky_color, 0.0f); } - bool low_end = !gPipeline.canUseWindLightShaders(); - LLColor3 sky_color = low_end ? vars.hazeColor * 2.0f : psky->gammaCorrect(vars.hazeColor * 2.0f); + LLColor3 sky_color = low_end ? vars.hazeColor * 2.0f : psky->gammaCorrect(vars.hazeColor * 2.0f, vars.gamma); return LLColor4(sky_color, 0.0f); } @@ -270,11 +263,12 @@ LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, Atm // indra\newview\lllegacyatmospherics.cpp void LLAtmospherics::calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVector3 & Pn, AtmosphericsVars& vars) { - LLColor3 blue_density = vars.blue_density; - LLColor3 blue_horizon = vars.blue_horizon; - F32 haze_horizon = vars.haze_horizon; - F32 haze_density = vars.haze_density; - F32 density_multiplier = vars.density_multiplier; + const LLColor3 blue_density = vars.blue_density; + const LLColor3 blue_horizon = vars.blue_horizon; + const F32 haze_horizon = vars.haze_horizon; + const F32 haze_density = vars.haze_density; + const F32 density_multiplier = vars.density_multiplier; + F32 max_y = vars.max_y; LLVector4 sun_norm = vars.sun_norm; @@ -313,7 +307,7 @@ void LLAtmospherics::calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVect // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes LLColor3 light_atten = vars.light_atten; - LLColor3 light_transmittance = psky->getLightTransmittance(Plen); + LLColor3 light_transmittance = psky->getLightTransmittanceFast(vars.total_density, vars.density_multiplier, Plen); (void)light_transmittance; // silence Clang warn-error // Calculate relative weights @@ -389,12 +383,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG)) { - if (!LLGLSLShader::sNoFixedFunction) - { - glFogf(GL_FOG_DENSITY, 0); - glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV); - glFogf(GL_FOG_END, 1000000.f); - } return; } @@ -436,12 +424,16 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + // NOTE: This is very similar to LLVOSky::cacheEnvironment() + // Differences: + // vars.sun_norm + // vars.sunlight // invariants across whole sky tex process... - vars.blue_density = psky->getBlueDensity(); + vars.blue_density = psky->getBlueDensity(); vars.blue_horizon = psky->getBlueHorizon(); vars.haze_density = psky->getHazeDensity(); vars.haze_horizon = psky->getHazeHorizon(); - vars.density_multiplier = psky->getDensityMultiplier(); + vars.density_multiplier = psky->getDensityMultiplier(); vars.distance_multiplier = psky->getDistanceMultiplier(); vars.max_y = psky->getMaxY(); vars.sun_norm = LLEnvironment::instance().getSunDirectionCFR(); @@ -456,9 +448,9 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) vars.total_density = psky->getTotalDensity(); vars.gamma = psky->getGamma(); - res_color[0] = calcSkyColorInDir(vars, tosun); - res_color[1] = calcSkyColorInDir(vars, perp_tosun); - res_color[2] = calcSkyColorInDir(vars, tosun_45); + res_color[0] = calcSkyColorInDir(psky, vars, tosun); + res_color[1] = calcSkyColorInDir(psky, vars, perp_tosun); + res_color[2] = calcSkyColorInDir(psky, vars, tosun_45); sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]); @@ -486,10 +478,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) if (camera_height > water_height) { LLColor4 fog(render_fog_color); - if (!LLGLSLShader::sNoFixedFunction) - { - glFogfv(GL_FOG_COLOR, fog.mV); - } mGLFogCol = fog; if (hide_clip_plane) @@ -497,19 +485,11 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) // For now, set the density to extend to the cull distance. const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f))) fog_density = f_log/fog_distance; - if (!LLGLSLShader::sNoFixedFunction) - { - glFogi(GL_FOG_MODE, GL_EXP2); - } } else { const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f)) fog_density = (f_log)/fog_distance; - if (!LLGLSLShader::sNoFixedFunction) - { - glFogi(GL_FOG_MODE, GL_EXP); - } } } else @@ -535,12 +515,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) // set the density based on what the shaders use fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale"); - - if (!LLGLSLShader::sNoFixedFunction) - { - glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV); - glFogi(GL_FOG_MODE, GL_EXP2); - } } mFogColor = sky_fog_color; @@ -548,13 +522,6 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in) LLDrawPoolWater::sWaterFogEnd = fog_distance*2.2f; - if (!LLGLSLShader::sNoFixedFunction) - { - LLGLSFog gls_fog; - glFogf(GL_FOG_END, fog_distance*2.2f); - glFogf(GL_FOG_DENSITY, fog_density); - glHint(GL_FOG_HINT, GL_NICEST); - } stop_glerror(); } diff --git a/indra/newview/lllegacyatmospherics.h b/indra/newview/lllegacyatmospherics.h index 03c8efb91a..d48f3040c3 100644 --- a/indra/newview/lllegacyatmospherics.h +++ b/indra/newview/lllegacyatmospherics.h @@ -257,13 +257,11 @@ public: void setCloudDensity(F32 cloud_density) { mCloudDensity = cloud_density; } void setWind ( const LLVector3& wind ) { mWind = wind.length(); } - LLColor4 calcSkyColorInDir(AtmosphericsVars& vars, const LLVector3& dir, bool isShiny = false); - LLColor4 calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const LLVector3& dir, bool isShiny = false); + LLColor4 calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const LLVector3& dir, bool isShiny = false, const bool low_end = false); -protected: +protected: void calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVector3 & Pn, AtmosphericsVars& vars); - LLColor3 getHazeColor(LLSettingsSky::ptr_t psky, AtmosphericsVars& vars, F32 costheta, F32 cloud_shadow); LLHaze mHaze; F32 mHazeConcentration; diff --git a/indra/newview/llmainlooprepeater.cpp b/indra/newview/llmainlooprepeater.cpp deleted file mode 100644 index 6736e9a950..0000000000 --- a/indra/newview/llmainlooprepeater.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file llmachineid.cpp - * @brief retrieves unique machine ids - * - * $LicenseInfo:firstyear=2009&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$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llapr.h" -#include "llevents.h" -#include "llmainlooprepeater.h" - - - -// LLMainLoopRepeater -//----------------------------------------------------------------------------- - - -LLMainLoopRepeater::LLMainLoopRepeater(void): - mQueue(0) -{ - ; // No op. -} - - -void LLMainLoopRepeater::start(void) -{ - if(mQueue != 0) return; - - mQueue = new LLThreadSafeQueue<LLSD>(1024); - mMainLoopConnection = LLEventPumps::instance(). - obtain("mainloop").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1)); - mRepeaterConnection = LLEventPumps::instance(). - obtain("mainlooprepeater").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMessage, this, _1)); -} - - -void LLMainLoopRepeater::stop(void) -{ - mMainLoopConnection.release(); - mRepeaterConnection.release(); - - delete mQueue; - mQueue = 0; -} - - -bool LLMainLoopRepeater::onMainLoop(LLSD const &) -{ - LLSD message; - while(mQueue->tryPopBack(message)) { - std::string pump = message["pump"].asString(); - if(pump.length() == 0 ) continue; // No pump. - LLEventPumps::instance().obtain(pump).post(message["payload"]); - } - return false; -} - - -bool LLMainLoopRepeater::onMessage(LLSD const & event) -{ - try { - mQueue->pushFront(event); - } catch(LLThreadSafeQueueError & e) { - LL_WARNS() << "could not repeat message (" << e.what() << ")" << - event.asString() << LL_ENDL; - } - return false; -} diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h deleted file mode 100644 index 2ec3a74e4a..0000000000 --- a/indra/newview/llmainlooprepeater.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file llmainlooprepeater.h - * @brief a service for repeating messages on the main loop. - * - * $LicenseInfo:firstyear=2010&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$ - */ - -#ifndef LL_LLMAINLOOPREPEATER_H -#define LL_LLMAINLOOPREPEATER_H - - -#include "llsd.h" -#include "llthreadsafequeue.h" - - -// -// A service which creates the pump 'mainlooprepeater' to which any thread can -// post a message that will be re-posted on the main loop. -// -// The posted message should contain two map elements: pump and payload. The -// pump value is a string naming the pump to which the message should be -// re-posted. The payload value is what will be posted to the designated pump. -// -class LLMainLoopRepeater: - public LLSingleton<LLMainLoopRepeater> -{ - LLSINGLETON(LLMainLoopRepeater); -public: - // Start the repeater service. - void start(void); - - // Stop the repeater service. - void stop(void); - -private: - LLTempBoundListener mMainLoopConnection; - LLTempBoundListener mRepeaterConnection; - LLThreadSafeQueue<LLSD> * mQueue; - - bool onMainLoop(LLSD const &); - bool onMessage(LLSD const & event); -}; - - -#endif diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 7c942e8b53..452762b09d 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -157,10 +157,7 @@ void LLManipRotate::render() } else { - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } + gDebugProgram.bind(); LLGLEnable cull_face(GL_CULL_FACE); LLGLDepthTest gls_depth(GL_FALSE); @@ -213,10 +210,7 @@ void LLManipRotate::render() } gGL.popMatrix(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); } gGL.translatef( center.mV[VX], center.mV[VY], center.mV[VZ] ); @@ -234,10 +228,7 @@ void LLManipRotate::render() gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } + gDebugProgram.bind(); if (mManipPart == LL_ROT_Z) { @@ -355,11 +346,7 @@ void LLManipRotate::render() } - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - + gUIProgram.bind(); } gGL.popMatrix(); gGL.popMatrix(); diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 8736d3b51f..0b2a1ef389 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1565,11 +1565,6 @@ void LLManipTranslate::renderSnapGuides() LLGLEnable stipple(GL_LINE_STIPPLE); gGL.flush(); - if (!LLGLSLShader::sNoFixedFunction) - { - glLineStipple(1, 0x3333); - } - switch (mManipPart) { case LL_YZ_PLANE: @@ -1633,7 +1628,7 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal, LLQuaternion grid_rotation, LLColor4 inner_color) { - if (!gSavedSettings.getBOOL("GridCrossSections") || !LLGLSLShader::sNoFixedFunction) + if (!gSavedSettings.getBOOL("GridCrossSections")) { return; } diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 52b9fb40ae..11aa607393 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -580,11 +580,9 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content) } } -static LLTrace::BlockTimerStatHandle FTM_MATERIALS_IDLE("Idle Materials"); - void LLMaterialMgr::onIdle(void*) { - LL_RECORD_BLOCK_TIME(FTM_MATERIALS_IDLE); + LL_PROFILE_ZONE_SCOPED; LLMaterialMgr* instancep = LLMaterialMgr::getInstance(); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 8080e43383..61418ba547 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1972,7 +1972,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat LLMeshSkinInfo info(skin); info.mMeshID = mesh_id; - // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL; + // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL; { LLMutexLock lock(mMutex); mSkinInfoQ.push_back(info); @@ -4070,29 +4070,28 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj) { - LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); - - if (mesh_id.notNull()) - { - skin_map::iterator iter = mSkinMap.find(mesh_id); - if (iter != mSkinMap.end()) - { - return &(iter->second); - } - - //no skin info known about given mesh, try to fetch it - { - LLMutexLock lock(mMeshMutex); - //add volume to list of loading meshes - skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); - if (iter == mLoadingSkins.end()) - { //no request pending for this skin info - mPendingSkinRequests.push(mesh_id); - } - mLoadingSkins[mesh_id].insert(requesting_obj->getID()); - } - } + LL_PROFILE_ZONE_SCOPED; + if (mesh_id.notNull()) + { + skin_map::iterator iter = mSkinMap.find(mesh_id); + if (iter != mSkinMap.end()) + { + return &(iter->second); + } + //no skin info known about given mesh, try to fetch it + if (requesting_obj != nullptr) + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); + if (iter == mLoadingSkins.end()) + { //no request pending for this skin info + mPendingSkinRequests.push(mesh_id); + } + mLoadingSkins[mesh_id].insert(requesting_obj->getID()); + } + } return NULL; } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 441264d42f..1989350303 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -27,6 +27,7 @@ #ifndef LL_MESH_REPOSITORY_H #define LL_MESH_REPOSITORY_H +#include <unordered_map> #include "llassettype.h" #include "llmodel.h" #include "lluuid.h" @@ -584,7 +585,7 @@ public: S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); static S32 getActualMeshLOD(LLSD& header, S32 lod); - const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj); + const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr); LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id); void fetchPhysicsShape(const LLUUID& mesh_id); bool hasPhysicsShape(const LLUUID& mesh_id); @@ -612,7 +613,7 @@ public: typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map; mesh_load_map mLoadingMeshes[4]; - typedef std::map<LLUUID, LLMeshSkinInfo> skin_map; + typedef std::unordered_map<LLUUID, LLMeshSkinInfo> skin_map; skin_map mSkinMap; typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 5a8c1b474a..5d81d2c9b3 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -559,7 +559,7 @@ void LLModelPreview::rebuildUploadData() bool upload_skinweights = fmp && fmp->childGetValue("upload_skin").asBoolean(); if (upload_skinweights && high_lod_model->mSkinInfo.mJointNames.size() > 0) { - LLQuaternion bind_rot = LLSkinningUtil::getUnscaledQuaternion(high_lod_model->mSkinInfo.mBindShapeMatrix); + LLQuaternion bind_rot = LLSkinningUtil::getUnscaledQuaternion(LLMatrix4(high_lod_model->mSkinInfo.mBindShapeMatrix)); LLQuaternion identity; if (!bind_rot.isEqualEps(identity, 0.01)) { @@ -1380,6 +1380,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe S32 buf_positions_copied = 0; S32 buf_indices_copied = 0; indices_idx_shift = 0; + S32 valid_faces = 0; // Crude method to copy indices back into face for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx) @@ -1478,6 +1479,8 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe U32 tex_size = (buf_positions_copied * sizeof(LLVector2) + 0xF)&~0xF; LLVector4a::memcpyNonAliased16((F32*)new_face.mTexCoords, (F32*)buffer_tex_coords, tex_size); + + valid_faces++; } indices_idx_shift += face.mNumVertices; @@ -1490,7 +1493,7 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe ll_aligned_free_16(buffer_indices); ll_aligned_free_32(combined_indices); - if (new_indices < 3) + if (new_indices < 3 || valid_faces == 0) { // Model should have at least one visible triangle @@ -1691,12 +1694,6 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d end = which_lod; } - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - if (shader) - { - shader->unbind(); - } - for (S32 lod = start; lod >= end; --lod) { if (which_lod == -1) @@ -1740,7 +1737,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d // but combine all submodels with origin model as well if (model_meshopt_mode == MESH_OPTIMIZER_COMBINE) { - // Run meshoptimizer for each model/object, up to 8 faces in one model + // Run meshoptimizer for each model/object, up to 8 faces in one model. // Ideally this should run not per model, // but combine all submodels with origin model as well @@ -1762,10 +1759,15 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true); } + + LL_INFOS() << "Model " << target_model->getName() + << " lod " << which_lod + << " simplified using per face method." << LL_ENDL; } if (model_meshopt_mode == MESH_OPTIMIZER_AUTO) { + // Switches between 'combine' method and 'per model sloppy' based on combine's result. F32 allowed_ratio_drift = 2.f; F32 res_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); @@ -1776,25 +1778,44 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); } - LL_INFOS() << "Model " << target_model->getName() - << " lod " << which_lod - << " per model method overflow, defaulting to per face." << LL_ENDL; } else if (res_ratio * allowed_ratio_drift < indices_decimator) { // Try sloppy variant if normal one failed to simplify model enough. res_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); - LL_INFOS() << "Model " << target_model->getName() - << " lod " << which_lod - << " sloppily simplified using per model method." << LL_ENDL; + + // Sloppy has a tendecy to error into lower side, so a request for 100 + // triangles turns into ~70, so check for significant difference from target decimation + F32 sloppy_ratio_drift = 1.4f; + if (lod_mode == LIMIT_TRIANGLES + && (res_ratio > indices_decimator * sloppy_ratio_drift || res_ratio < 0)) + { + // Apply a correction to compensate. + + // (indices_decimator / res_ratio) by itself is likely to overshoot to a differend + // side due to overal lack of precision, and we don't need an ideal result, which + // likely does not exist, just a better one, so a partial correction is enough. + F32 sloppy_decimator = indices_decimator * (indices_decimator / res_ratio + 1) / 2; + res_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + } if (res_ratio < 0) { // Sloppy variant failed to generate triangles. // Can happen with models that are too simple as is. - // Fallback to normal method. + // Fallback to normal method or use lower decimator. genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + + LL_INFOS() << "Model " << target_model->getName() + << " lod " << which_lod + << " simplified using per model method." << LL_ENDL; + } + else + { + LL_INFOS() << "Model " << target_model->getName() + << " lod " << which_lod + << " sloppily simplified using per model method." << LL_ENDL; } } else @@ -1846,12 +1867,6 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d } mResourceCost = calcResourceCost(); - - LLVertexBuffer::unbind(); - if (shader) - { - shader->bind(); - } } void LLModelPreview::updateStatusMessages() @@ -2652,6 +2667,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) *(index_strider++) = vf.mIndices[i]; } + vb->flush(); + mVertexBuffer[lod][mdl].push_back(vb); vertex_count += num_vertices; @@ -2877,8 +2894,6 @@ BOOL LLModelPreview::render() LLMutexLock lock(this); mNeedsUpdate = FALSE; - bool use_shaders = LLGLSLShader::sNoFixedFunction; - bool edges = mViewOption["show_edges"]; bool joint_overrides = mViewOption["show_joint_overrides"]; bool joint_positions = mViewOption["show_joint_positions"]; @@ -2896,10 +2911,8 @@ BOOL LLModelPreview::render() LLGLDisable fog(GL_FOG); { - if (use_shaders) - { - gUIProgram.bind(); - } + gUIProgram.bind(); + //clear background to grey gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); @@ -2918,10 +2931,7 @@ BOOL LLModelPreview::render() gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.popMatrix(); - if (use_shaders) - { - gUIProgram.unbind(); - } + gUIProgram.unbind(); } LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; @@ -3074,10 +3084,7 @@ BOOL LLModelPreview::render() refresh(); } - if (use_shaders) - { - gObjectPreviewProgram.bind(); - } + gObjectPreviewProgram.bind(); gGL.loadIdentity(); gPipeline.enableLightsPreview(); @@ -3137,6 +3144,11 @@ BOOL LLModelPreview::render() genBuffers(mPreviewLOD, skin_weight); } + if (physics && mVertexBuffer[LLModel::LOD_PHYSICS].empty()) + { + genBuffers(LLModel::LOD_PHYSICS, false); + } + if (!skin_weight) { for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) @@ -3198,6 +3210,7 @@ BOOL LLModelPreview::render() glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLineWidth(1.f); } + buffer->flush(); } gGL.popMatrix(); } @@ -3278,7 +3291,7 @@ BOOL LLModelPreview::render() } gGL.diffuseColor4ubv(hull_colors[i].mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions); if (explode > 0.f) { @@ -3291,11 +3304,6 @@ BOOL LLModelPreview::render() if (render_mesh) { - if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) - { - genBuffers(LLModel::LOD_PHYSICS, false); - } - U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); if (pass > 0){ for (U32 i = 0; i < num_models; ++i) @@ -3315,6 +3323,8 @@ BOOL LLModelPreview::render() glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLineWidth(1.f); + + buffer->flush(); } } } @@ -3359,11 +3369,6 @@ BOOL LLModelPreview::render() if (physics.mHull.empty()) { - if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) - { - genBuffers(LLModel::LOD_PHYSICS, false); - } - U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); for (U32 v = 0; v < num_models; ++v) { @@ -3390,6 +3395,8 @@ BOOL LLModelPreview::render() buffer->draw(LLRender::POINTS, 3, i); } } + + buffer->flush(); } } } @@ -3450,7 +3457,7 @@ BOOL LLModelPreview::render() LLJoint *joint = getPreviewAvatar()->getJoint(skin->mJointNums[j]); if (joint) { - const LLVector3& jointPos = skin->mAlternateBindMatrix[j].getTranslation(); + const LLVector3& jointPos = LLVector3(skin->mAlternateBindMatrix[j].getTranslation()); if (joint->aboveJointPosThreshold(jointPos)) { bool override_changed; @@ -3492,11 +3499,10 @@ BOOL LLModelPreview::render() //build matrix palette LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT]; - LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, joint_count, + LLSkinningUtil::initSkinningMatrixPalette(mat, joint_count, skin, getPreviewAvatar()); - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); + const LLMatrix4a& bind_shape_matrix = skin->mBindShapeMatrix; U32 max_joints = LLSkinningUtil::getMaxJointCount(); for (U32 j = 0; j < buffer->getNumVerts(); ++j) { @@ -3579,10 +3585,7 @@ BOOL LLModelPreview::render() } } - if (use_shaders) - { - gObjectPreviewProgram.unbind(); - } + gObjectPreviewProgram.unbind(); gGL.popMatrix(); diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 9361acfc49..48d6d362eb 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -225,8 +225,12 @@ private: // Count amount of original models, excluding sub-models static U32 countRootModels(LLModelLoader::model_list models); - // functions for meshoptimizer, return reached simplification ratio + // Merges faces into single mesh, simplifies using mesh optimizer, + // then splits back into faces. + // Returns reached simplification ratio. -1 in case of a failure. F32 genMeshOptimizerPerModel(LLModel *base_model, LLModel *target_model, F32 indices_ratio, F32 error_threshold, bool sloppy); + // Simplifies specified face using mesh optimizer. + // Returns reached simplification ratio. -1 in case of a failure. F32 genMeshOptimizerPerFace(LLModel *base_model, LLModel *target_model, U32 face_idx, F32 indices_ratio, F32 error_threshold, bool sloppy); protected: diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 112da55682..937f36b6fc 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -147,6 +147,7 @@ void LLNetMap::setScale( F32 scale ) void LLNetMap::draw() { + LL_PROFILE_ZONE_SCOPED; static LLFrameTimer map_timer; static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white); @@ -258,7 +259,7 @@ void LLNetMap::draw() gGL.end(); // Draw water - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, ABOVE_WATERLINE_ALPHA / 255.f); + gGL.flush(); { if (regionp->getLand().getWaterTexture()) { @@ -275,7 +276,7 @@ void LLNetMap::draw() gGL.end(); } } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); } // Redraw object layer periodically diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index a9678b1e93..d9359d20cf 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -166,14 +166,14 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) /*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p) { - LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); + auto panelp = LLToastNotifyPanel::getInstance(p->getID()); if (panelp) { // // HACK: if we're dealing with a notification embedded in IM, update it // otherwise remove its toast // - if (dynamic_cast<LLIMToastNotifyPanel*>(panelp)) + if (dynamic_cast<LLIMToastNotifyPanel*>(panelp.get())) { panelp->updateNotification(); } diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index ba831ab2ed..d896c409d7 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -69,7 +69,8 @@ void LLScriptHandler::initChannel() //-------------------------------------------------------------------------- void LLScriptHandler::addToastWithNotification(const LLNotificationPtr& notification) { - LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + LL_PROFILE_ZONE_SCOPED + LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); LLToast::Params p; p.notif_id = notification->getID(); diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index f95ab9928d..20cf4df56b 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -47,11 +47,9 @@ LLPersistentNotificationStorage::~LLPersistentNotificationStorage() { } -static LLTrace::BlockTimerStatHandle FTM_SAVE_NOTIFICATIONS("Save Notifications"); - void LLPersistentNotificationStorage::saveNotifications() { - LL_RECORD_BLOCK_TIME(FTM_SAVE_NOTIFICATIONS); + LL_PROFILE_ZONE_SCOPED; boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); if (!history_channel) @@ -90,11 +88,9 @@ void LLPersistentNotificationStorage::saveNotifications() writeNotifications(output); } -static LLTrace::BlockTimerStatHandle FTM_LOAD_NOTIFICATIONS("Load Notifications"); - void LLPersistentNotificationStorage::loadNotifications() { - LL_RECORD_BLOCK_TIME(FTM_LOAD_NOTIFICATIONS); + LL_PROFILE_ZONE_SCOPED; LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL; diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index f48ce680fd..30ca7ae539 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -453,6 +453,7 @@ F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local, const BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; // Skip if disabled globally. if (!gSavedSettings.getBOOL("AvatarPhysics")) { diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index f9baf5fbd3..2e44dc1459 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -271,7 +271,7 @@ void LLSceneMonitor::capture() static LLCachedControl<F32> scene_load_sample_time(gSavedSettings, "SceneLoadingMonitorSampleTime"); static bool force_capture = true; - bool enabled = LLGLSLShader::sNoFixedFunction && (monitor_enabled || mDebugViewerVisible); + bool enabled = monitor_enabled || mDebugViewerVisible; if(mEnabled != enabled) { if(mEnabled) @@ -332,9 +332,6 @@ bool LLSceneMonitor::needsUpdate() const return mDiffState == NEED_DIFF; } -static LLTrace::BlockTimerStatHandle FTM_GENERATE_SCENE_LOAD_DITHER_TEXTURE("Generate Scene Load Dither Texture"); -static LLTrace::BlockTimerStatHandle FTM_SCENE_LOAD_IMAGE_DIFF("Scene Load Image Diff"); - static LLStaticHashedString sDitherScale("dither_scale"); static LLStaticHashedString sDitherScaleS("dither_scale_s"); static LLStaticHashedString sDitherScaleT("dither_scale_t"); @@ -356,14 +353,12 @@ void LLSceneMonitor::compare() return; } - LL_RECORD_BLOCK_TIME(FTM_SCENE_LOAD_IMAGE_DIFF); mDiffState = EXECUTE_DIFF; S32 width = gViewerWindow->getWindowWidthRaw(); S32 height = gViewerWindow->getWindowHeightRaw(); if(!mDiff) { - LL_RECORD_BLOCK_TIME(FTM_GENERATE_SCENE_LOAD_DITHER_TEXTURE); mDiff = new LLRenderTarget(); mDiff->allocate(width, height, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true); @@ -371,7 +366,6 @@ void LLSceneMonitor::compare() } else if(mDiff->getWidth() != width || mDiff->getHeight() != height) { - LL_RECORD_BLOCK_TIME(FTM_GENERATE_SCENE_LOAD_DITHER_TEXTURE); mDiff->resize(width, height); generateDitheringTexture(width, height); } @@ -427,8 +421,6 @@ void LLSceneMonitor::calcDiffAggregate() { #ifdef LL_WINDOWS - LL_RECORD_BLOCK_TIME(FTM_SCENE_LOAD_IMAGE_DIFF); - if(mDiffState != EXECUTE_DIFF && !mDebugViewerVisible) { return; @@ -481,8 +473,6 @@ void LLSceneMonitor::calcDiffAggregate() static LLTrace::EventStatHandle<> sFramePixelDiff("FramePixelDifference"); void LLSceneMonitor::fetchQueryResult() { - LL_RECORD_BLOCK_TIME(FTM_SCENE_LOAD_IMAGE_DIFF); - // also throttle timing here, to avoid going below sample time due to phasing with frame capture static LLCachedControl<F32> scene_load_sample_time_control(gSavedSettings, "SceneLoadingMonitorSampleTime"); F32Seconds scene_load_sample_time = (F32Seconds)scene_load_sample_time_control(); @@ -729,13 +719,6 @@ void LLSceneMonitorView::onTeleportFinished() void LLSceneMonitorView::onVisibilityChange(BOOL visible) { - if (!LLGLSLShader::sNoFixedFunction && visible) - { - visible = false; - // keep Scene monitor and its view in sycn - setVisible(false); - LL_WARNS("SceneMonitor") << "Incompatible graphical settings, Scene Monitor can't be turned on" << LL_ENDL; - } LLSceneMonitor::getInstance()->setDebugViewerVisible(visible); } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 681787bcbe..17f2970f99 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -49,10 +49,9 @@ using namespace LLNotificationsUI; bool LLScreenChannel::mWasStartUpToastShown = false; -LLTrace::BlockTimerStatHandle FTM_GET_CHANNEL_RECT("Calculate Notification Channel Region"); LLRect LLScreenChannelBase::getChannelRect() { - LL_RECORD_BLOCK_TIME(FTM_GET_CHANNEL_RECT); + LL_PROFILE_ZONE_SCOPED; if (mFloaterSnapRegion == NULL) { @@ -259,7 +258,8 @@ void LLScreenChannel::updatePositionAndSize(LLRect new_world_rect) //-------------------------------------------------------------------------- void LLScreenChannel::addToast(const LLToast::Params& p) { - bool store_toast = false, show_toast = false; + LL_PROFILE_ZONE_SCOPED + bool store_toast = false, show_toast = false; if (mDisplayToastsAlways) { diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index cd3a4dfd11..c6bb2f19dd 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -138,11 +138,9 @@ void LLScriptEditor::initKeywords() mKeywords.initialize(LLSyntaxIdLSL::getInstance()->getKeywordsXML()); } -LLTrace::BlockTimerStatHandle FTM_SYNTAX_HIGHLIGHTING("Syntax Highlighting"); - void LLScriptEditor::loadKeywords() { - LL_RECORD_BLOCK_TIME(FTM_SYNTAX_HIGHLIGHTING); + LL_PROFILE_ZONE_SCOPED; mKeywords.processTokens(); segment_vec_t segment_list; @@ -160,7 +158,7 @@ void LLScriptEditor::updateSegments() { if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly) { - LL_RECORD_BLOCK_TIME(FTM_SYNTAX_HIGHLIGHTING); + LL_PROFILE_ZONE_SCOPED; // HACK: No non-ascii keywords for now segment_vec_t segment_list; mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b0a566755f..b3d3e9e0da 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -209,8 +209,6 @@ void LLSelectMgr::cleanupGlobals() LLSelectMgr::getInstance()->clearSelections(); } -// Build time optimization, generate this function once here -template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance(); //----------------------------------------------------------------------------- // LLSelectMgr() //----------------------------------------------------------------------------- @@ -5896,8 +5894,6 @@ void LLSelectMgr::updateSilhouettes() LLViewerObject* objectp = *iter; objectp->clearChanged(LLXform::MOVED | LLXform::SILHOUETTE); } - - //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector<LLViewerObject*>& changed_objects) @@ -6622,7 +6618,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) glFogfv(GL_FOG_COLOR, fogCol.mV); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); gGL.begin(LLRender::LINES); { gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 2b00fa1595..ce0316e610 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -407,11 +407,8 @@ private: LLObjectSelectionHandle mSelectedObjects; }; -class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr> +class LLSelectMgr : public LLEditMenuHandler, public LLSimpleton<LLSelectMgr> { - LLSINGLETON(LLSelectMgr); - ~LLSelectMgr(); - public: static BOOL sRectSelectInclusive; // do we need to surround an object to pick it? static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded? @@ -437,6 +434,9 @@ public: LLCachedControl<bool> mDebugSelectMgr; public: + LLSelectMgr(); + ~LLSelectMgr(); + static void cleanupGlobals(); // LLEditMenuHandler interface diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 58cbe0e20a..6415da4e4a 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -637,6 +637,7 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA //------------------------------------------------------------------------- void LLSettingsVOSky::updateSettings() { + LL_PROFILE_ZONE_SCOPED; LLSettingsSky::updateSettings(); LLVector3 sun_direction = getSunDirection(); LLVector3 moon_direction = getMoonDirection(); @@ -665,55 +666,56 @@ void LLSettingsVOSky::updateSettings() void LLSettingsVOSky::applySpecial(void *ptarget, bool force) { - LLGLSLShader *shader = (LLGLSLShader *)ptarget; - + LL_PROFILE_ZONE_SCOPED LLVector4 light_direction = LLEnvironment::instance().getClampedLightNorm(); - if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT) + LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_DEFAULT]; { - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV); - shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, light_direction); + shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, LLViewerCamera::getInstance()->getOrigin()); } - else if (shader->mShaderGroup == LLGLSLShader::SG_SKY) + + shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_SKY]; { - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, light_direction); - // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate") - LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]); - LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() ); + // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate") + LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]); + LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() ); - // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll - // Keep in Sync! - // * indra\newview\llsettingsvo.cpp - // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl - // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl - cloud_scroll[0] = -cloud_scroll[0]; - vect_c_p_d1 += cloud_scroll; - shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV); + // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll + // Keep in Sync! + // * indra\newview\llsettingsvo.cpp + // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl + // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl + cloud_scroll[0] = -cloud_scroll[0]; + vect_c_p_d1 += cloud_scroll; + shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, vect_c_p_d1); - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - LLColor4 sunDiffuse = psky->getSunlightColor(); - LLColor4 moonDiffuse = psky->getMoonlightColor(); + LLVector4 sunDiffuse = LLVector4(psky->getSunlightColor().mV); + LLVector4 moonDiffuse = LLVector4(psky->getMoonlightColor().mV); - shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, sunDiffuse.mV); - shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, moonDiffuse.mV); + shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); + shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); - LLColor4 cloud_color(psky->getCloudColor(), 1.0); - shader->uniform4fv(LLShaderMgr::CLOUD_COLOR, 1, cloud_color.mV); + LLVector4 cloud_color(LLVector3(psky->getCloudColor().mV), 1.0); + shader->uniform4fv(LLShaderMgr::CLOUD_COLOR, cloud_color); } + shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_ANY]; shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength); LLColor4 ambient(getTotalAmbient()); - shader->uniform4fv(LLShaderMgr::AMBIENT, 1, ambient.mV); + shader->uniform4fv(LLShaderMgr::AMBIENT, LLVector4(ambient.mV)); shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, getIsSunUp() ? 1 : 0); shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, getSunMoonGlowFactor()); shader->uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, getDensityMultiplier()); shader->uniform1f(LLShaderMgr::DISTANCE_MULTIPLIER, getDistanceMultiplier()); - F32 g = getGamma(); + F32 g = getGamma(); F32 display_gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma"); shader->uniform1f(LLShaderMgr::GAMMA, g); @@ -907,11 +909,13 @@ LLSD LLSettingsVOWater::convertToLegacy(const LLSettingsWater::ptr_t &pwater) //------------------------------------------------------------------------- void LLSettingsVOWater::applySpecial(void *ptarget, bool force) { - LLGLSLShader *shader = (LLGLSLShader *)ptarget; + LL_PROFILE_ZONE_SCOPED LLEnvironment& env = LLEnvironment::instance(); - if (force || (shader->mShaderGroup == LLGLSLShader::SG_WATER)) + auto group = LLGLSLShader::SG_WATER; + LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[group]; + { F32 water_height = env.getWaterHeight(); @@ -935,7 +939,7 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); - shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, waterPlane.mV); + shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, waterPlane.mV); LLVector4 light_direction = env.getClampedLightNorm(); @@ -950,18 +954,19 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, waterFogDensity); LLColor4 fog_color(env.getCurrentWater()->getWaterFogColor(), 0.0f); - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, fog_color.mV); F32 blend_factor = env.getCurrentWater()->getBlendFactor(); shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); // update to normal lightnorm, water shader itself will use rotated lightnorm as necessary - shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, light_direction.mV); + shader->uniform4fv(LLShaderMgr::LIGHTNORM, light_direction.mV); } } void LLSettingsVOWater::updateSettings() { + LL_PROFILE_ZONE_SCOPED; // base class clears dirty flag so as to not trigger recursive update LLSettingsBase::updateSettings(); diff --git a/indra/newview/llsettingsvo.h b/indra/newview/llsettingsvo.h index a1baf02fe7..05ec0e9275 100644 --- a/indra/newview/llsettingsvo.h +++ b/indra/newview/llsettingsvo.h @@ -101,8 +101,6 @@ public: bool isAdvanced() const { return m_isAdvanced; } - virtual void updateShader(LLGLSLShader* shader) { applySpecial(shader, true); } - protected: LLSettingsVOSky(); @@ -135,8 +133,6 @@ public: static LLSD convertToLegacy(const ptr_t &); - virtual void updateShader(LLGLSLShader* shader) { applySpecial(shader, true); } - protected: LLSettingsVOWater(); diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp index e02b21f036..dc12de29fb 100644 --- a/indra/newview/llskinningutil.cpp +++ b/indra/newview/llskinningutil.cpp @@ -35,7 +35,6 @@ #include "llrigginginfo.h" #define DEBUG_SKINNING LL_DEBUG -#define MAT_USE_SSE 1 void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, const LLMeshSkinInfo *skin) { @@ -120,36 +119,26 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin skin->mInvalidJointsScrubbed = true; } -#define MAT_USE_SSE 1 - void LLSkinningUtil::initSkinningMatrixPalette( - LLMatrix4* mat, + LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar) { + LL_PROFILE_ZONE_SCOPED; + initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar); + + LLMatrix4a world[LL_CHARACTER_MAX_ANIMATED_JOINTS]; + for (U32 j = 0; j < count; ++j) { S32 joint_num = skin->mJointNums[j]; - LLJoint *joint = NULL; - if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS) - { - joint = avatar->getJoint(joint_num); - } - llassert(joint); + LLJoint *joint = avatar->getJoint(joint_num); + if (joint) { -#ifdef MAT_USE_SSE - LLMatrix4a bind, world, res; - bind.loadu(skin->mInvBindMatrix[j]); - world.loadu(joint->getWorldMatrix()); - matMul(bind,world,res); - memcpy(mat[j].mMatrix,res.mMatrix,16*sizeof(float)); -#else - mat[j] = skin->mInvBindMatrix[j]; - mat[j] *= joint->getWorldMatrix(); -#endif + world[j] = joint->getWorldMatrix4a(); } else { @@ -159,16 +148,27 @@ void LLSkinningUtil::initSkinningMatrixPalette( // rendering should be disabled unless all joints are // valid. In other cases of skinned rendering, invalid // joints should already have been removed during scrubInvalidJoints(). - LL_WARNS_ONCE("Avatar") << avatar->getFullname() - << " rigged to invalid joint name " << skin->mJointNames[j] - << " num " << skin->mJointNums[j] << LL_ENDL; - LL_WARNS_ONCE("Avatar") << avatar->getFullname() - << " avatar build state: isBuilt() " << avatar->isBuilt() - << " mInitFlags " << avatar->mInitFlags << LL_ENDL; + LL_WARNS_ONCE("Avatar") << avatar->getFullname() + << " rigged to invalid joint name " << skin->mJointNames[j] + << " num " << skin->mJointNums[j] << LL_ENDL; + LL_WARNS_ONCE("Avatar") << avatar->getFullname() + << " avatar build state: isBuilt() " << avatar->isBuilt() + << " mInitFlags " << avatar->mInitFlags << LL_ENDL; #endif dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin); } } + + //NOTE: pointer striders used here as a micro-optimization over vector/array lookups + const LLMatrix4a* invBind = &(skin->mInvBindMatrix[0]); + const LLMatrix4a* w = world; + LLMatrix4a* m = mat; + LLMatrix4a* end = m + count; + + while (m < end) + { + matMulUnsafe(*(invBind++), *(w++), *(m++)); + } } void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin) @@ -212,7 +212,7 @@ void LLSkinningUtil::scrubSkinWeights(LLVector4a* weights, U32 num_vertices, con void LLSkinningUtil::getPerVertexSkinMatrix( F32* weights, - LLMatrix4a* mat, + const LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints) @@ -270,6 +270,7 @@ void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar) { if (!skin->mJointNumsInitialized) { + LL_PROFILE_ZONE_SCOPED; for (U32 j = 0; j < skin->mJointNames.size(); ++j) { #if DEBUG_SKINNING @@ -357,13 +358,11 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a rig_info_tab[joint_num].setIsRiggedTo(true); // FIXME could precompute these matMuls. - LLMatrix4a bind_shape; - LLMatrix4a inv_bind; + const LLMatrix4a& bind_shape = skin->mBindShapeMatrix; + const LLMatrix4a& inv_bind = skin->mInvBindMatrix[joint_index]; LLMatrix4a mat; LLVector4a pos_joint_space; - bind_shape.loadu(skin->mBindShapeMatrix); - inv_bind.loadu(skin->mInvBindMatrix[joint_index]); matMul(bind_shape, inv_bind, mat); mat.affineTransform(pos, pos_joint_space); @@ -426,3 +425,4 @@ LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4) bind_rot.normalize(); return bind_rot; } + diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h index efe7c85997..807418f983 100644 --- a/indra/newview/llskinningutil.h +++ b/indra/newview/llskinningutil.h @@ -42,10 +42,10 @@ namespace LLSkinningUtil S32 getMaxJointCount(); U32 getMeshJointCount(const LLMeshSkinInfo *skin); void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin); - void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); + void initSkinningMatrixPalette(LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar); void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin); - void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); + void getPerVertexSkinMatrix(F32* weights, const LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints); LL_FORCE_INLINE void getPerVertexSkinMatrixWithIndices( F32* weights, diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index efa4a7fd66..1869370ac7 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -51,13 +51,9 @@ #include "llphysicsshapebuilderutil.h" #include "llvoavatar.h" #include "llvolumemgr.h" -#include "lltextureatlas.h" #include "llviewershadermgr.h" #include "llcontrolavatar.h" -static LLTrace::BlockTimerStatHandle FTM_FRUSTUM_CULL("Frustum Culling"); -static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound Partition"); - extern bool gShiftFrame; static U32 sZombieGroups = 0; @@ -131,129 +127,6 @@ LLSpatialGroup::~LLSpatialGroup() sNodeCount--; clearDrawMap(); - clearAtlasList() ; -} - -BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp) -{ - S8 type = atlasp->getComponents() - 1 ; - for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter) - { - if(atlasp == *iter) - { - return TRUE ; - } - } - return FALSE ; -} - -void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level) -{ - if(!hasAtlas(atlasp)) - { - mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ; - atlasp->addSpatialGroup(this) ; - } - - --recursive_level; - if(recursive_level)//levels propagating up. - { - LLSpatialGroup* parent = getParent() ; - if(parent) - { - parent->addAtlas(atlasp, recursive_level) ; - } - } -} - -void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level) -{ - mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ; - if(remove_group) - { - atlasp->removeSpatialGroup(this) ; - } - - --recursive_level; - if(recursive_level)//levels propagating up. - { - LLSpatialGroup* parent = getParent() ; - if(parent) - { - parent->removeAtlas(atlasp, recursive_level) ; - } - } -} - -void LLSpatialGroup::clearAtlasList() -{ - std::list<LLTextureAtlas*>::iterator iter ; - for(S8 i = 0 ; i < 4 ; i++) - { - if(mAtlasList[i].size() > 0) - { - for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter) - { - ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ; - } - mAtlasList[i].clear() ; - } - } -} - -LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level) -{ - S8 type = ncomponents - 1 ; - if(mAtlasList[type].size() > 0) - { - for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter) - { - if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved)) - { - return *iter ; - } - } - } - - --recursive_level; - if(recursive_level) - { - LLSpatialGroup* parent = getParent() ; - if(parent) - { - return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ; - } - } - return NULL ; -} - -void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp) -{ - mCurUpdatingSlotp = slotp; - - //if(!hasAtlas(mCurUpdatingSlotp->getAtlas())) - //{ - // addAtlas(mCurUpdatingSlotp->getAtlas()) ; - //} -} - -LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level) -{ - if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep) - { - return mCurUpdatingSlotp ; - } - - //--recursive_level ; - //if(recursive_level) - //{ - // LLSpatialGroup* parent = getParent() ; - // if(parent) - // { - // return parent->getCurUpdatingSlot(imagep, recursive_level) ; - // } - //} - return NULL ; } void LLSpatialGroup::clearDrawMap() @@ -345,6 +218,7 @@ void LLSpatialGroup::validateDrawMap() BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) { + LL_PROFILE_ZONE_SCOPED; drawablep->updateSpatialExtents(); OctreeNode* parent = mOctreeNode->getOctParent(); @@ -409,11 +283,6 @@ void LLSpatialGroup::rebuildMesh() } } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VBO("VBO Rebuilt"); -static LLTrace::BlockTimerStatHandle FTM_ADD_GEOMETRY_COUNT("Add Geometry"); -static LLTrace::BlockTimerStatHandle FTM_CREATE_VB("Create VB"); -static LLTrace::BlockTimerStatHandle FTM_GET_GEOMETRY("Get Geometry"); - void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) @@ -427,7 +296,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; } - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VBO); + LL_PROFILE_ZONE_SCOPED; group->clearDrawMap(); @@ -435,15 +304,12 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) U32 index_count = 0; U32 vertex_count = 0; - { - LL_RECORD_BLOCK_TIME(FTM_ADD_GEOMETRY_COUNT); - addGeometryCount(group, vertex_count, index_count); - } - + addGeometryCount(group, vertex_count, index_count); + if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node { - LL_RECORD_BLOCK_TIME(FTM_CREATE_VB); + group->mBuilt = 1.f; if (group->mVertexBuffer.isNull() || !group->mVertexBuffer->isWriteable() || @@ -458,7 +324,6 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->mVertexBuffer = NULL; group->mBufferMap.clear(); } - stop_glerror(); } else { @@ -471,13 +336,11 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->mVertexBuffer = NULL; group->mBufferMap.clear(); } - stop_glerror(); } } if (group->mVertexBuffer) { - LL_RECORD_BLOCK_TIME(FTM_GET_GEOMETRY); getGeometry(group); } } @@ -503,7 +366,9 @@ LLSpatialGroup* LLSpatialGroup::getParent() } BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) - { +{ + LL_PROFILE_ZONE_SCOPED + if(!drawablep) { return FALSE; @@ -591,6 +456,8 @@ public: void LLSpatialGroup::setState(U32 state, S32 mode) { + LL_PROFILE_ZONE_SCOPED + llassert(state <= LLSpatialGroup::STATE_MASK); if (mode > STATE_MODE_SINGLE) @@ -638,6 +505,8 @@ public: void LLSpatialGroup::clearState(U32 state, S32 mode) { + LL_PROFILE_ZONE_SCOPED + llassert(state <= LLSpatialGroup::STATE_MASK); if (mode > STATE_MODE_SINGLE) @@ -673,11 +542,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO mDistance(0.f), mDepth(0.f), mLastUpdateDistance(-1.f), - mLastUpdateTime(gFrameTimeSeconds), - mAtlasList(4), - mCurUpdatingTime(0), - mCurUpdatingSlotp(NULL), - mCurUpdatingTexture (NULL) + mLastUpdateTime(gFrameTimeSeconds) { ll_assert_aligned(this,16); @@ -724,6 +589,8 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) { + LL_PROFILE_ZONE_SCOPED + LLVector4a eye; LLVector4a origin; origin.load3(camera.getOrigin().mV); @@ -815,6 +682,8 @@ F32 LLSpatialGroup::getUpdateUrgency() const BOOL LLSpatialGroup::changeLOD() { + LL_PROFILE_ZONE_SCOPED + if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) { //a rebuild is going to happen, update distance and LoD @@ -907,6 +776,8 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { + LL_PROFILE_ZONE_SCOPED + if (child->getListenerCount() == 0) { new LLSpatialGroup(child, getSpatialPartition()); @@ -983,6 +854,7 @@ LLSpatialPartition::~LLSpatialPartition() LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) { + LL_PROFILE_ZONE_SCOPED; drawablep->updateSpatialExtents(); //keep drawable from being garbage collected @@ -1008,6 +880,7 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) { + LL_PROFILE_ZONE_SCOPED; if (!curp->removeObject(drawablep)) { OCT_ERRS << "Failed to remove drawable from octree!" << LL_ENDL; @@ -1024,6 +897,7 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) { + LL_PROFILE_ZONE_SCOPED; // sanity check submitted by open source user bushing Spatula // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) if (!drawablep) @@ -1477,12 +1351,12 @@ void LLSpatialPartition::resetVertexBuffers() BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) { + LL_PROFILE_ZONE_SCOPED; LLVector4a visMina, visMaxa; visMina.load3(visMin.mV); visMaxa.load3(visMax.mV); { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } @@ -1504,11 +1378,11 @@ BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) { + LL_PROFILE_ZONE_SCOPED; #if LL_OCTREE_PARANOIA_CHECK ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); #endif { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } @@ -1525,37 +1399,32 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) { + LL_PROFILE_ZONE_SCOPED; #if LL_OCTREE_PARANOIA_CHECK ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); #endif - { - LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - } + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); #if LL_OCTREE_PARANOIA_CHECK ((LLSpatialGroup*)mOctree->getListener(0))->validate(); #endif - if (LLPipeline::sShadowRender) - { - LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); - LLOctreeCullShadow culler(&camera); - culler.traverse(mOctree); - } - else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) - { - LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); - LLOctreeCullNoFarClip culler(&camera); - culler.traverse(mOctree); - } - else - { - LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); - LLOctreeCull culler(&camera); - culler.traverse(mOctree); - } + if (LLPipeline::sShadowRender) + { + LLOctreeCullShadow culler(&camera); + culler.traverse(mOctree); + } + else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) + { + LLOctreeCullNoFarClip culler(&camera); + culler.traverse(mOctree); + } + else + { + LLOctreeCull culler(&camera); + culler.traverse(mOctree); + } return 0; } @@ -1728,10 +1597,14 @@ void renderOctree(LLSpatialGroup* group) gGL.flush(); glLineWidth(1.f); gGL.flush(); + + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) + if(!drawable || drawable->getNumFaces() == 0) { continue; } @@ -1742,6 +1615,27 @@ void renderOctree(LLSpatialGroup* group) gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); } + LLFace* face = drawable->getFace(0); + bool rigged = face->isState(LLFace::RIGGED); + gDebugProgram.bind(rigged); + + gGL.diffuseColor4f(1, 0, 0, 1); + + if (rigged) + { + gGL.pushMatrix(); + gGL.loadMatrix(gGLModelView); + if (lastAvatar != face->mAvatar || + lastMeshId != face->mSkinInfo->mHash) + { + if (!LLRenderPass::uploadMatrixPalette(face->mAvatar, face->mSkinInfo)) + { + continue; + } + lastAvatar = face->mAvatar; + lastMeshId = face->mSkinInfo->mHash; + } + } for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* face = drawable->getFace(j); @@ -1760,19 +1654,25 @@ void renderOctree(LLSpatialGroup* group) continue; } - face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX); + face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX | (rigged ? LLVertexBuffer::MAP_WEIGHT4 : 0)); //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, // (face->mExtents[1]-face->mExtents[0])*0.5f); face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); } } + if (rigged) + { + gGL.popMatrix(); + } + if (!group->getSpatialPartition()->isBridge()) { gGL.popMatrix(); } } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gDebugProgram.bind(); // make sure non-rigged variant is bound gGL.diffuseColor4f(1,1,1,1); } } @@ -2374,7 +2274,12 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo if (!decomp->mBaseHullMesh.empty()) { gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else { @@ -2394,13 +2299,11 @@ void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLCo void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color) { gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glPolygonOffset(3.f, 3.f); glLineWidth(3.f); gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions); glLineWidth(1.f); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } @@ -2455,6 +2358,9 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) gGL.pushMatrix(); gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); + LLGLEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(3.f, 3.f); + if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) { LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); @@ -2482,12 +2388,12 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) { //decomp has physics mesh, render that mesh gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); gGL.diffuseColor4fv(line_color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else { //no mesh or decomposition, render base hull @@ -2613,9 +2519,9 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) gGL.diffuseColor4fv(line_color.mV); LLVertexBuffer::unbind(); - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); - - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + llassert(LLGLSLShader::sCurBoundShader != 0); + + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); gGL.diffuseColor4fv(color.mV); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -2695,16 +2601,22 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) if (phys_volume->mHullPoints && phys_volume->mHullIndices) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); + llassert(LLGLSLShader::sCurBoundShader != 0); LLVertexBuffer::unbind(); glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); gGL.diffuseColor4fv(line_color.mV); gGL.syncMatrices(); - glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + { + LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x20FF20 ) + glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + } gGL.diffuseColor4fv(color.mV); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + { + LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x40FF40 ) + glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + } } else { @@ -2896,8 +2808,27 @@ void renderBatchSize(LLDrawInfo* params) { LLGLEnable offset(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.f, 1.f); - gGL.diffuseColor4ubv((GLubyte*) &(params->mDebugColor)); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); + LLGLSLShader* old_shader = LLGLSLShader::sCurBoundShaderPtr; + U32 mask = LLVertexBuffer::MAP_VERTEX; + bool bind = false; + if (params->mAvatar) + { + gGL.pushMatrix(); + gGL.loadMatrix(gGLModelView); + bind = true; + old_shader->mRiggedVariant->bind(); + LLRenderPass::uploadMatrixPalette(*params); + mask |= LLVertexBuffer::MAP_WEIGHT4; + } + + gGL.diffuseColor4ubv((GLubyte*)&(params->mDebugColor)); + pushVerts(params, mask); + + if (bind) + { + gGL.popMatrix(); + old_shader->bind(); + } } void renderShadowFrusta(LLDrawInfo* params) @@ -3222,6 +3153,7 @@ void renderRaycast(LLDrawable* drawablep) gGL.diffuseColor4f(0,1,1,0.5f); glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions); gGL.syncMatrices(); + LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x60FF60 ); glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); } @@ -3774,10 +3706,7 @@ void LLSpatialPartition::renderDebug() return; } - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } + gDebugProgram.bind(); if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { @@ -3826,10 +3755,7 @@ void LLSpatialPartition::renderDebug() glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.unbind(); - } + gDebugProgram.unbind(); } void LLSpatialGroup::drawObjectBox(LLColor4 col) @@ -4023,8 +3949,7 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, LLViewerTexture* texture, LLVertexBuffer* buffer, bool selected, BOOL fullbright, U8 bump, BOOL particle, F32 part_size) -: LLTrace::MemTrackableNonVirtual<LLDrawInfo, 16>("LLDrawInfo"), - mVertexBuffer(buffer), +: mVertexBuffer(buffer), mTexture(texture), mTextureMatrix(NULL), mModelMatrix(NULL), @@ -4054,7 +3979,8 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, { mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); - mDebugColor = (rand() << 16) + rand(); + mDebugColor = (rand() << 16) + rand(); + ((U8*)&mDebugColor)[3] = 200; } LLDrawInfo::~LLDrawInfo() @@ -4080,6 +4006,11 @@ void LLDrawInfo::validate() mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); } +U64 LLDrawInfo::getSkinHash() +{ + return mSkinInfo ? mSkinInfo->mHash : 0; +} + LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) { return new LLVertexBuffer(type_mask, usage); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 919f386d29..666c025347 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -41,6 +41,7 @@ #include "llviewercamera.h" #include "llvector4a.h" #include <queue> +#include <unordered_map> #define SG_STATE_INHERIT_MASK (OCCLUDED) #define SG_INITIAL_STATE_MASK (DIRTY | GEOM_DIRTY) @@ -49,20 +50,18 @@ class LLViewerOctreePartition; class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; -class LLTextureAtlas; -class LLTextureAtlasSlot; class LLViewerRegion; void pushVerts(LLFace* face, U32 mask); -class LLDrawInfo : public LLRefCount, public LLTrace::MemTrackableNonVirtual<LLDrawInfo, 16> +class LLDrawInfo : public LLRefCount { + LL_ALIGN_NEW; protected: ~LLDrawInfo(); public: LLDrawInfo(const LLDrawInfo& rhs) - : LLTrace::MemTrackableNonVirtual<LLDrawInfo, 16>("LLDrawInfo") { *this = rhs; } @@ -81,12 +80,19 @@ public: void validate(); + // return mSkinHash->mHash, or 0 if mSkinHash is null + U64 getSkinHash(); + LLVector4a mExtents[2]; LLPointer<LLVertexBuffer> mVertexBuffer; LLPointer<LLViewerTexture> mTexture; std::vector<LLPointer<LLViewerTexture> > mTextureList; + // virtual size of mTexture and mTextureList textures + // used to update the decode priority of textures in this DrawInfo + std::vector<F32> mTextureListVSize; + S32 mDebugColor; const LLMatrix4* mTextureMatrix; const LLMatrix4* mModelMatrix; @@ -119,6 +125,8 @@ public: F32 mAlphaMaskCutoff; U8 mDiffuseAlphaMode; bool mSelected; + LLVOAvatar* mAvatar = nullptr; + LLMeshSkinInfo* mSkinInfo = nullptr; struct CompareTexture @@ -216,10 +224,10 @@ public: typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t; typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t; typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; - typedef std::map<U32, drawmap_elem_t > draw_map_t; + typedef std::unordered_map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t; - typedef std::map<U32, buffer_texture_map_t> buffer_map_t; + typedef std::unordered_map<LLFace*, buffer_list_t> buffer_texture_map_t; + typedef std::unordered_map<U32, buffer_texture_map_t> buffer_map_t; struct CompareDistanceGreater { @@ -298,49 +306,15 @@ public: virtual void handleDestruction(const TreeNode* node); virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); -//------------------- -//for atlas use -//------------------- - //atlas - void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;} - U32 getCurUpdatingTime() const { return mCurUpdatingTime ;} - - void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ; - LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level = 3) ; - - void setCurUpdatingTexture(LLViewerTexture* tex){ mCurUpdatingTexture = tex ;} - LLViewerTexture* getCurUpdatingTexture() const { return mCurUpdatingTexture ;} - - BOOL hasAtlas(LLTextureAtlas* atlasp) ; - LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ; - void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ; - void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ; - void clearAtlasList() ; - public: - LL_ALIGN_16(LLVector4a mViewAngle); LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3() - -private: - U32 mCurUpdatingTime ; - //do not make the below two to use LLPointer - //because mCurUpdatingTime invalidates them automatically. - LLTextureAtlasSlot* mCurUpdatingSlotp ; - LLViewerTexture* mCurUpdatingTexture ; - - std::vector< std::list<LLTextureAtlas*> > mAtlasList ; -//------------------- -//end for atlas use -//------------------- protected: virtual ~LLSpatialGroup(); - static S32 sLODSeed; - public: bridge_list_t mBridgeList; buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers @@ -465,8 +439,11 @@ public: virtual void cleanupReferences(); virtual LLSpatialPartition* asPartition() { return this; } + //transform agent space camera into this Spatial Bridge's coordinate frame virtual LLCamera transformCamera(LLCamera& camera); - + + //transform agent space bounding box into this Spatial Bridge's coordinate frame + void transformExtents(const LLVector4a* src, LLVector4a* dst); LLDrawable* mDrawable; }; @@ -646,7 +623,7 @@ class LLVolumeGeometryManager: public LLGeometryManager virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); - U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE); + U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL rigged = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); private: @@ -654,13 +631,13 @@ private: void freeFaces(); static int32_t sInstanceCount; - static LLFace** sFullbrightFaces; - static LLFace** sBumpFaces; - static LLFace** sSimpleFaces; - static LLFace** sNormFaces; - static LLFace** sSpecFaces; - static LLFace** sNormSpecFaces; - static LLFace** sAlphaFaces; + static LLFace** sFullbrightFaces[2]; + static LLFace** sBumpFaces[2]; + static LLFace** sSimpleFaces[2]; + static LLFace** sNormFaces[2]; + static LLFace** sSpecFaces[2]; + static LLFace** sNormSpecFaces[2]; + static LLFace** sAlphaFaces[2]; }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 54f3e6305c..da8d5152b4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -35,6 +35,7 @@ #else # include <sys/stat.h> // mkdir() #endif +#include <memory> // std::unique_ptr #include "llviewermedia_streamingaudio.h" #include "llaudioengine.h" @@ -178,7 +179,6 @@ #include "pipeline.h" #include "llappviewer.h" #include "llfasttimerview.h" -#include "lltelemetry.h" #include "llfloatermap.h" #include "llweb.h" #include "llvoiceclient.h" @@ -205,6 +205,9 @@ #include "llstacktrace.h" +#include "threadpool.h" + + #if LL_WINDOWS #include "lldxhardware.h" #endif @@ -252,9 +255,9 @@ static bool mBenefitsSuccessfullyInit = false; const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds -boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState")); -boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener()); -boost::scoped_ptr<LLViewerStats::PhaseMap> LLStartUp::sPhases(new LLViewerStats::PhaseMap); +std::unique_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState")); +std::unique_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener()); +std::unique_ptr<LLViewerStats::PhaseMap> LLStartUp::sPhases(new LLViewerStats::PhaseMap); // // local function declaration @@ -529,8 +532,6 @@ bool idle_startup() } #if LL_WINDOWS - LLPROFILE_STARTUP(); - // On the windows dev builds, unpackaged, the message.xml file will // be located in indra/build-vc**/newview/<config>/app_settings. std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml"); @@ -1484,6 +1485,21 @@ bool idle_startup() gAgentCamera.resetCamera(); display_startup(); + // start up the ThreadPool we'll use for textures et al. + { + LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") }; + LLSD sizeSpec{ poolSizes["General"] }; + LLSD::Integer poolSize{ sizeSpec.isInteger()? sizeSpec.asInteger() : 3 }; + LL_DEBUGS("ThreadPool") << "Instantiating General pool with " + << poolSize << " threads" << LL_ENDL; + // We don't want anyone, especially the main thread, to have to block + // due to this ThreadPool being full. + auto pool = new LL::ThreadPool("General", poolSize, 1024*1024); + pool->start(); + // Once we start shutting down, destroy this ThreadPool. + LLAppViewer::instance()->onCleanup([pool](){ delete pool; }); + } + // Initialize global class data needed for surfaces (i.e. textures) LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; // Initialize all of the viewer object classes for the first time (doing things like texture fetches. diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 116aeb36a7..fe8e215f76 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -27,7 +27,7 @@ #ifndef LL_LLSTARTUP_H #define LL_LLSTARTUP_H -#include <boost/scoped_ptr.hpp> +#include <memory> // unique_ptr class LLViewerTexture ; class LLEventPump; @@ -130,9 +130,9 @@ private: static std::string startupStateToString(EStartupState state); static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState - static boost::scoped_ptr<LLEventPump> sStateWatcher; - static boost::scoped_ptr<LLStartupListener> sListener; - static boost::scoped_ptr<LLViewerStats::PhaseMap> sPhases; + static std::unique_ptr<LLEventPump> sStateWatcher; + static std::unique_ptr<LLStartupListener> sListener; + static std::unique_ptr<LLViewerStats::PhaseMap> sPhases; }; diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index cb356726e6..ea36e1d7be 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -1214,6 +1214,7 @@ F32 LLSurface::getWaterHeight() const BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y, const F32 width, const F32 height) { + LL_PROFILE_ZONE_SCOPED if (!getWaterTexture()) { return FALSE; diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 5e056944e9..aeefcd6fb8 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -728,6 +728,7 @@ BOOL LLSurfacePatch::updateTexture() void LLSurfacePatch::updateGL() { + LL_PROFILE_ZONE_SCOPED F32 meters_per_grid = getSurface()->getMetersPerGrid(); F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); diff --git a/indra/newview/lltelemetry.cpp b/indra/newview/lltelemetry.cpp deleted file mode 100644 index 0c63e2fede..0000000000 --- a/indra/newview/lltelemetry.cpp +++ /dev/null @@ -1,145 +0,0 @@ - /** - * @file lltelemetry.cpp - * @brief Wrapper for Rad Game Tools Telemetry - * - * $LicenseInfo:firstyear=2020&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2020, 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$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "lltelemetry.h" - -#if LLPROFILE_USE_RAD_TELEMETRY_PROFILER - #if LL_WINDOWS - #include "llwin32headers.h" - - // build-vc120-64\packages\lib\release - // build-vc150-64\packages\lib\release - #ifdef _MSC_VER - #pragma comment(lib,"rad_tm_win64.lib") - #else - #pragma message "NOTE: Rad GameTools Telemetry requested but non-MSVC compiler not yet supported on Windows" - #endif - #endif // LL_WINDOWS - - #if LL_DARWIN - #pragma message "NOTE: Rad Game Tools Telemetry requested but not yet supported on Darwin" - #endif - - #if LL_LINUX - #pragma message "NOTE: Rad Game Tools Telemetry requested but not yet supported on Linux" - #endif - -// -// local consts -// -static const tm_int32 TELEMETRY_BUFFER_SIZE = 8 * 1024 * 1024; - -// -// local globals -// -static char *gTelemetryBufferPtr = NULL; // Telemetry - -static const char *tm_status[ TMERR_INIT_NETWORKING_FAILED + 1 ] = -{ - "Telemetry pass: connected" // TM_OK - , "Telemetry FAIL: disabled via #define NTELEMETRY" // TMERR_DISABLED - , "Telemetry FAIL: invalid paramater" // TMERR_INVALID_PARAM - , "Telemetry FAIL: DLL not found" // TMERR_NULL_API - , "Telemetry FAIL: out of resources" // TMERR_OUT_OF_RESOURCES - , "Telemetry FAIL: tmInitialize() not called" // TMERR_UNINITIALIZED - , "Telemetry FAIL: bad hostname" // TMERR_BAD_HOSTNAME - , "Telemetry FAIL: couldn't connect to server" // TMERR_COULD_NOT_CONNECT - , "Telemetry FAIL: unknown network error" // TMERR_UNKNOWN_NETWORK - , "Telemetry FAIL: tmShutdown() already called" // TMERR_ALREADY_SHUTDOWN - , "Telemetry FAIL: memory buffer too small" // TMERR_ARENA_TOO_SMALL - , "Telemetry FAIL: server handshake error" // TMERR_BAD_HANDSHAKE - , "Telemetry FAIL: unaligned parameters" // TMERR_UNALIGNED - , "Telemetry FAIL: network not initialized" // TMERR_NETWORK_NOT_INITIALIZED -- WSAStartup not called before tmOpen() - , "Telemetry FAIL: bad version" // TMERR_BAD_VERSION - , "Telemetry FAIL: timer too large" // TMERR_BAD_TIMER - , "Telemetry FAIL: tmOpen() already called" // TMERR_ALREADY_OPENED - , "Telemetry FAIL: tmInitialize() already called" // TMERR_ALREADY_INITIALIZED - , "Telemetry FAIL: could't open file" // TMERR_FILE_OPEN_FAILED - , "Telemetry FAIL: tmOpen() failed networking" // TMERR_INIT_NETWORKING_FAILED -}; - -// -// exported functionality -// - -void telemetry_shutdown() -{ - #if LL_WINDOWS - if (gTelemetryBufferPtr) - { - tmClose(0); - tmShutdown(); - - delete[] gTelemetryBufferPtr; - gTelemetryBufferPtr = NULL; - } - #endif -} - -void telemetry_startup() -{ - #if LL_WINDOWS - tmLoadLibrary(TM_RELEASE); // Loads .dll - - gTelemetryBufferPtr = new char[ TELEMETRY_BUFFER_SIZE ]; - tmInitialize(TELEMETRY_BUFFER_SIZE, gTelemetryBufferPtr); - - tm_error telemetry_status = tmOpen( - 0, // unused - "SecondLife", // app name - __DATE__ " " __TIME__, // build identifier - "localhost", // server name (or filename) - TMCT_TCP, // connection type (or TMCT_FILE) - 4719, // port - TMOF_INIT_NETWORKING, // open flags - 250 ); // timeout ms - - if (telemetry_status == TMERR_UNKNOWN) - { - LL_ERRS() << "Telemetry FAIL: unknown error" << LL_ENDL; - } - else if (telemetry_status && (telemetry_status <= TMERR_INIT_NETWORKING_FAILED)) - { - LL_INFOS() << tm_status[ telemetry_status ] << LL_ENDL; - free(gTelemetryBufferPtr); - gTelemetryBufferPtr = NULL; - } - #endif // LL_WINDOWS -} - -// Called after we render a frame -void telemetry_update() -{ - #if LL_WINDOWS - if (gTelemetryBufferPtr) - { - tmTick(0); - } - #endif -} -#endif // LLPROFILE_USE_RAD_TELEMETRY_PROFILER diff --git a/indra/newview/lltelemetry.h b/indra/newview/lltelemetry.h deleted file mode 100644 index a73e5fcfa2..0000000000 --- a/indra/newview/lltelemetry.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file lltelemetry.h - * @brief Wrapper for Rad Game Tools Telemetry - * - * $LicenseInfo:firstyear=2020&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2020, 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$ - */ - -/* -To use: - -1. Uncomment #define LLPROFILE_USE_RAD_TELEMETRY_PROFILER below - -2. Include this header file - #include "lltelemetry.h" - -3. Add zones to the functions you wish to profile - void onFoo() - { - LLPROFILE_ZONE("Foo"); - } -*/ -//#define LLPROFILE_USE_RAD_TELEMETRY_PROFILER 1 - -// Default NO local telemetry profiling -#ifndef LLPROFILE_USE_RAD_TELEMETRY_PROFILER - #define LLPROFILE_USE_RAD_TELEMETRY_PROFILER 0 - #define LLPROFILE_SHUTDOWN( ...) {} - #define LLPROFILE_STARTUP( ...) {} - #define LLPROFILE_UPDATE( ...) {} - - #define LLPROFILE_AUTO_CPU_MARKER_COLOR(r, g, b) - #define LLPROFILE_ENTER(name) - #define LLPROFILE_ENTER_FORMAT(format, ...) - #define LLPROFILE_FUNCTION - #define LLPROFILE_LEAVE() - #define LLPROFILE_THREAD_NAME(name) - #define LLPROFILE_ZONE(name) - #define LLPROFILE_ZONE_FORMAT(format, ...) -#else - #include <rad_tm.h> - - #define LLPROFILE_SHUTDOWN telemetry_shutdown - #define LLPROFILE_STARTUP telemetry_startup - #define LLPROFILE_UPDATE telemetry_update - - #define LLPROFILE_AUTO_CPU_MARKER_COLOR(r, g, b) tmZoneColor(r, g, b) - #define LLPROFILE_ENTER(name) tmEnter(0, 0, name) - #define LLPROFILE_ENTER_FORMAT(format, ...) tmEnter(0, 0, format, __VA_ARGS__) - #define LLPROFILE_FUNCTION tmFunction(0, 0) - #define LLPROFILE_LEAVE() tmLeave(0) - #define LLPROFILE_THREAD_NAME(name) tmThreadName(0, 0, name) - #define LLPROFILE_ZONE(name) tmZone(0, 0, name) - #define LLPROFILE_ZONE_FORMAT(format, ...) tmZone(0, 0, format, __VA_ARGS__) -#endif // LLPROFILE_USE_RAD_TELEMETRY_PROFILER - -// -// exported functionality -// - -extern void telemetry_startup(); -extern void telemetry_shutdown(); -extern void telemetry_update(); // called after every frame update diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp index 3c3c1c96ef..3ece12931c 100644 --- a/indra/newview/llteleporthistory.cpp +++ b/indra/newview/llteleporthistory.cpp @@ -39,6 +39,11 @@ #include "llviewerregion.h" #include "llworldmap.h" #include "llagentui.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llavatarname.h" +#include "llavatarnamecache.h" + ////////////////////////////////////////////////////////////////////////////// // LLTeleportHistoryItem @@ -113,6 +118,20 @@ void LLTeleportHistory::handleLoginComplete() updateCurrentLocation(gAgent.getPositionGlobal()); } +static void on_avatar_name_update_title(const LLAvatarName& av_name) +{ + if (gAgent.getRegion() && gViewerWindow && gViewerWindow->getWindow()) + { + std::string region = gAgent.getRegion()->getName(); + std::string username = av_name.getUserName(); + + // this first pass simply displays username and region name + // but could easily be extended to include other details like + // X/Y/Z location within a region etc. + std::string new_title = STRINGIZE(username << " @ " << region); + gViewerWindow->getWindow()->setTitle(new_title); + } +} void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos) { @@ -174,6 +193,14 @@ void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos) if (!mGotInitialUpdate) mGotInitialUpdate = true; + // update Viewer window title with username and region name + // if we are in "non-interactive mode" (SL-15999) or the debug + // setting to allow it is enabled (may be useful in other situations) + if (gNonInteractive || gSavedSettings.getBOOL("UpdateAppWindowTitleBar")) + { + LLAvatarNameCache::get(gAgent.getID(), boost::bind(&on_avatar_name_update_title, _2)); + } + // Signal the interesting party that we've changed. onHistoryChanged(); } diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp deleted file mode 100644 index 1c8e4f796e..0000000000 --- a/indra/newview/lltextureatlas.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/** - * @file lltextureatlas.cpp - * @brief LLTextureAtlas class implementation. - * - * $LicenseInfo:firstyear=2002&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$ - */ -#include "llviewerprecompiledheaders.h" -#include "linden_common.h" -#include "llerror.h" -#include "llimage.h" -#include "llmath.h" -#include "llgl.h" -#include "llrender.h" -#include "lltextureatlas.h" - -//------------------- -S16 LLTextureAtlas::sMaxSubTextureSize = 64 ; -S16 LLTextureAtlas::sSlotSize = 32 ; - -#ifndef DEBUG_ATLAS -#define DEBUG_ATLAS 0 -#endif - -#ifndef DEBUG_USAGE_BITS -#define DEBUG_USAGE_BITS 0 -#endif -//************************************************************************************************************** -LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) : - LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE), - mAtlasDim(atlas_dim), - mNumSlotsReserved(0), - mMaxSlotsInAtlas(atlas_dim * atlas_dim) -{ - generateEmptyUsageBits() ; - - //generate an empty texture - generateGLTexture() ; - LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents); - createGLTexture(0, image_raw, 0); - image_raw = NULL; -} - -LLTextureAtlas::~LLTextureAtlas() -{ - if(mSpatialGroupList.size() > 0) - { - LL_ERRS() << "Not clean up the spatial groups!" << LL_ENDL ; - } - releaseUsageBits() ; -} - -//virtual -S8 LLTextureAtlas::getType() const -{ - return 0; //LLViewerTexture::ATLAS_TEXTURE ; -} - -void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset) -{ - xoffset = (F32)col / mAtlasDim ; - yoffset = (F32)row / mAtlasDim ; -} - -void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) -{ - xscale = (F32)w / (mAtlasDim * sSlotSize) ; - yscale = (F32)h / (mAtlasDim * sSlotSize) ; -} - -//insert a texture piece into the atlas -LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) -{ - if(!getTexName()) - { - return 0 ; - } - - S32 w = raw_image->getWidth() ; - S32 h = raw_image->getHeight() ; - if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize) - { - //size overflow - return 0 ; - } - - BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName()); - if (!res) - { - LL_ERRS() << "bindTexture failed" << LL_ENDL; - } - - GLint xoffset = sSlotSize * slot_col ; - GLint yoffset = sSlotSize * slot_row ; - - if(!source_gl_tex->preAddToAtlas(discard_level, raw_image)) - { - return 0 ; - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h, - mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData()); - - source_gl_tex->postAddToAtlas() ; - return getTexName(); -} - -//release a sub-texture slot from the atlas -void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width) -{ - unmarkUsageBits(slot_width, slot_col, slot_row) ; - mNumSlotsReserved -= slot_width * slot_width ; -} - -BOOL LLTextureAtlas::isEmpty() const -{ - return !mNumSlotsReserved ; -} - -BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const -{ - return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ; -} -F32 LLTextureAtlas::getFullness() const -{ - return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ; -} - -void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp) -{ - if(groupp && !hasSpatialGroup(groupp)) - { - mSpatialGroupList.push_back(groupp); - } -} - -void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp) -{ - if(groupp) - { - mSpatialGroupList.remove(groupp); - } -} - -void LLTextureAtlas::clearSpatialGroup() -{ - mSpatialGroupList.clear(); -} -void LLTextureAtlas::removeLastSpatialGroup() -{ - mSpatialGroupList.pop_back() ; -} - -LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup() -{ - if(mSpatialGroupList.size() > 0) - { - return mSpatialGroupList.back() ; - } - return NULL ; -} - -BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp) -{ - for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter) - { - if(*iter == groupp) - { - return TRUE ; - } - } - return FALSE ; -} - -//-------------------------------------------------------------------------------------- -//private -void LLTextureAtlas::generateEmptyUsageBits() -{ - S32 col_len = (mAtlasDim + 7) >> 3 ; - mUsageBits = new U8*[mAtlasDim] ; - *mUsageBits = new U8[mAtlasDim * col_len] ; - - mUsageBits[0] = *mUsageBits ; - for(S32 i = 1 ; i < mAtlasDim ; i++) - { - mUsageBits[i] = mUsageBits[i-1] + col_len ; - - for(S32 j = 0 ; j < col_len ; j++) - { - //init by 0 for all bits. - mUsageBits[i][j] = 0 ; - } - } - - //do not forget mUsageBits[0]! - for(S32 j = 0 ; j < col_len ; j++) - { - //init by 0 for all bits. - mUsageBits[0][j] = 0 ; - } - - mTestBits = NULL ; -#if DEBUG_USAGE_BITS - //------------ - //test - mTestBits = new U8*[mAtlasDim] ; - *mTestBits = new U8[mAtlasDim * mAtlasDim] ; - mTestBits[0] = *mTestBits ; - for(S32 i = 1 ; i < mAtlasDim ; i++) - { - mTestBits[i] = mTestBits[i-1] + mAtlasDim ; - - for(S32 j = 0 ; j < mAtlasDim ; j++) - { - //init by 0 for all bits. - mTestBits[i][j] = 0 ; - } - } - - for(S32 j = 0 ; j < mAtlasDim ; j++) - { - //init by 0 for all bits. - mTestBits[0][j] = 0 ; - } -#endif -} - -void LLTextureAtlas::releaseUsageBits() -{ - if(mUsageBits) - { - delete[] *mUsageBits ; - delete[] mUsageBits ; - } - mUsageBits = NULL ; - - //test - if( mTestBits) - { - delete[] *mTestBits; - delete[] mTestBits; - } - mTestBits = NULL ; -} - -void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) -{ - S16 x = col >> 3 ; - - for(S8 i = 0 ; i < bits_len ; i++) - { - mUsageBits[row + i][x] |= mask ; - } - -#if DEBUG_USAGE_BITS - //test - for(S8 i = row ; i < row + bits_len ; i++) - { - for(S8 j = col ; j < col + bits_len ; j++) - { - mTestBits[i][j] = 1 ; - } - } -#endif -} - -void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row) -{ - S16 x = col >> 3 ; - U8 mask = 1 ; - for(S8 i = 1 ; i < bits_len ; i++) - { - mask |= (1 << i) ; - } - mask <<= (col & 7) ; - mask = ~mask ; - - for(S8 i = 0 ; i < bits_len ; i++) - { - mUsageBits[row + i][x] &= mask ; - } - -#if DEBUG_USAGE_BITS - //test - for(S8 i = row ; i < row + bits_len ; i++) - { - for(S8 j = col ; j < col + bits_len ; j++) - { - mTestBits[i][j] = 0 ; - } - } -#endif -} - -//return true if any of bits in the range marked. -BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) -{ - BOOL ret = FALSE ; - S16 x = col >> 3 ; - - for(S8 i = 0 ; i < bits_len ; i++) - { - if(mUsageBits[row + i][x] & mask) - { - ret = TRUE ; - break ; - //return TRUE ; - } - } - -#if DEBUG_USAGE_BITS - //test - BOOL ret2 = FALSE ; - for(S8 i = row ; i < row + bits_len ; i++) - { - for(S8 j = col ; j < col + bits_len ; j++) - { - if(mTestBits[i][j]) - { - ret2 = TRUE ; - } - } - } - - if(ret != ret2) - { - LL_ERRS() << "bits map corrupted." << LL_ENDL ; - } -#endif - return ret ;//FALSE ; -} - -//---------------------------------------------------------------------- -// -//index order: Z order, i.e.: -// |-----|-----|-----|-----| -// | 10 | 11 | 14 | 15 | -// |-----|-----|-----|-----| -// | 8 | 9 | 12 | 13 | -// |-----|-----|-----|-----| -// | 2 | 3 | 6 | 7 | -// |-----|-----|-----|-----| -// | 0 | 1 | 4 | 5 | -// |-----|-----|-----|-----| -void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row) -{ - col = 0 ; - row = 0 ; - - S16 index_copy = index ; - for(S16 i = 0 ; index_copy && i < 16 ; i += 2) - { - col |= ((index & (1 << i)) >> i) << (i >> 1) ; - row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ; - index_copy >>= 2 ; - } -} -void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index) -{ - index = 0 ; - S16 col_copy = col ; - S16 row_copy = row ; - for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++) - { - index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ; - col_copy >>= 1 ; - row_copy >>= 1 ; - } -} -//---------------------------------------------------------------------- -//return TRUE if succeeds. -BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row) -{ - S16 index_step = bits_len * bits_len ; - - U8 mask = 1 ; - for(S8 i = 1 ; i < bits_len ; i++) - { - mask |= (1 << i) ; - } - - U8 cur_mask ; - for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step) - { - getPositionFromIndex(index, col, row) ; - - cur_mask = mask << (col & 7) ; - if(!areUsageBitsMarked(bits_len, cur_mask, col, row)) - { - markUsageBits(bits_len, cur_mask, col, row) ; - mNumSlotsReserved += bits_len * bits_len ; - - return TRUE ; - } - } - - return FALSE ; -} diff --git a/indra/newview/lltextureatlas.h b/indra/newview/lltextureatlas.h deleted file mode 100644 index 6b36eb7fe4..0000000000 --- a/indra/newview/lltextureatlas.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file lltextureatlas.h - * @brief LLTextureAtlas base class. - * - * $LicenseInfo:firstyear=2002&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$ - */ - - -#ifndef LL_TEXTUREATLAS_H -#define LL_TEXTUREATLAS_H - -#include "llviewertexture.h" -class LLSpatialGroup ; - -class LLTextureAtlas : public LLViewerTexture -{ -protected: - /*virtual*/ ~LLTextureAtlas() ; - -public: - LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ; - - /*virtual*/ S8 getType() const; - - LLGLuint insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ; - void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width); - - BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ; - void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ; - void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ; - - BOOL isEmpty() const ; - BOOL isFull(S8 to_be_reserved = 1) const ; - F32 getFullness() const ; - - void addSpatialGroup(LLSpatialGroup* groupp) ; - void removeSpatialGroup(LLSpatialGroup* groupp) ; - LLSpatialGroup* getLastSpatialGroup() ; - void removeLastSpatialGroup() ; - BOOL hasSpatialGroup(LLSpatialGroup* groupp) ; - void clearSpatialGroup() ; - std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;} -private: - void generateEmptyUsageBits() ; - void releaseUsageBits() ; - - void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ; - void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ; - - void getPositionFromIndex(S16 index, S16& col, S16& row) ; - void getIndexFromPosition(S16 col, S16 row, S16& index) ; - BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ; - -private: - S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas. - S16 mNumSlotsReserved ; - S16 mMaxSlotsInAtlas ; - U8 **mUsageBits ; - std::list<LLSpatialGroup*> mSpatialGroupList ; - -public: - //debug use only - U8 **mTestBits ; - -public: - static S16 sMaxSubTextureSize ; - static S16 sSlotSize ; -}; - -#endif - diff --git a/indra/newview/lltextureatlasmanager.cpp b/indra/newview/lltextureatlasmanager.cpp deleted file mode 100644 index ca9d6da4db..0000000000 --- a/indra/newview/lltextureatlasmanager.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/** - * @file lltextureatlasmanager.cpp - * @brief LLTextureAtlasManager class implementation. - * - * $LicenseInfo:firstyear=2002&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$ - */ -#include "llviewerprecompiledheaders.h" -#include "linden_common.h" -#include "llerror.h" -#include "llmath.h" -#include "lltextureatlas.h" -#include "lltextureatlasmanager.h" -#include "llspatialpartition.h" - -const S8 MAX_NUM_EMPTY_ATLAS = 2 ; -const F32 MIN_ATLAS_FULLNESS = 0.6f ; - -//********************************************************************************************* -//implementation of class LLTextureAtlasInfo -//********************************************************************************************* -LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) : - mAtlasp(atlasp), - mGroupp(groupp), - mCol(col), - mRow(row), - mReservedSlotWidth(slot_width), - mValid(FALSE), - mUpdatedTime(0), - mTexCoordOffset(xoffset, yoffset), - mTexCoordScale(1.f, 1.f) -{ - llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ; -} - -LLTextureAtlasSlot::~LLTextureAtlasSlot() -{ - if(mAtlasp) - { - mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ; - if(mAtlasp->isEmpty()) - { - LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ; - } - mAtlasp = NULL ; - } -} - -//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp) -//{ -// mAtlasp = atlasp ; -//} -//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row) -//{ -// mCol = col ; -// mRow = row ; -//} -//void LLTextureAtlasSlot::setSlotWidth(S8 width) -//{ -// //slot is a square with each edge length a power-of-two number -// mReservedSlotWidth = width ; -//} -//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset) -//{ -// mTexCoordOffset.mV[0] = xoffset ; -// mTexCoordOffset.mV[1] = yoffset ; -//} - -void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp) -{ - mGroupp = groupp ; -} -void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale) -{ - mTexCoordScale.mV[0] = xscale ; - mTexCoordScale.mV[1] = yscale ; -} -//********************************************************************************************* -//END of implementation of class LLTextureAtlasInfo -//********************************************************************************************* - -//********************************************************************************************* -//implementation of class LLTextureAtlasManager -//********************************************************************************************* -LLTextureAtlasManager::LLTextureAtlasManager() : - mAtlasMap(4), - mEmptyAtlasMap(4) -{ -} - -LLTextureAtlasManager::~LLTextureAtlasManager() -{ - for(S32 i = 0 ; i < 4 ; i++) - { - for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j) - { - *j = NULL ; - } - for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j) - { - *j = NULL ; - } - - mAtlasMap[i].clear() ; - mEmptyAtlasMap[i].clear() ; - } - mAtlasMap.clear() ; - mEmptyAtlasMap.clear() ; -} - -//return TRUE if qualified -BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) -{ - if(ncomponents < 1 || ncomponents > 4) - { - return FALSE ; - } - //only support GL_TEXTURE_2D - if(GL_TEXTURE_2D != target) - { - return FALSE ; - } - //real image size overflows - if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize) - { - return FALSE ; - } - - //if non-power-of-two number - if((w & (w - 1)) || (h & (h - 1))) - { - return FALSE ; - } - - return TRUE ; -} - -void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp) -{ - LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ; - while(groupp) - { - groupp->removeAtlas(atlasp, FALSE) ; - atlasp->removeLastSpatialGroup() ; - - groupp = atlasp->getLastSpatialGroup() ; - } - - S8 type = atlasp->getComponents() - 1 ; - //insert to the empty list - if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS) - { - mEmptyAtlasMap[type].push_back(atlasp) ; - } - - //delete the atlasp - mAtlasMap[type].remove(atlasp) ; -} - -// -//this function reserves an appropriate slot from atlas pool for an image. -//return non-NULL if succeeds. -//Note: -//1, this function does not check if the image this slot assigned for qualifies for atlas or not, -// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function. -//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway. -//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching. -// -LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, - LLSpatialGroup* groupp, LLViewerTexture* imagep) -{ - if(!groupp) - { - //do not insert to atlas if does not have a group. - return NULL ; - } - - //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8. - if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize) - { - sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ; - } - S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ; - if(bits_len < 1) - { - bits_len = 1 ; - } - - S16 col = -1, row = -1; - S8 total_bits = bits_len * bits_len ; - - //insert to the atlas reserved by the same spatial group - LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ; - if(atlasp.notNull()) - { - if(!atlasp->getNextAvailableSlot(bits_len, col, row)) - { - //failed - atlasp = NULL ; - } - } - - //search an atlas to fit for 'size' - if(!atlasp) - { - S8 atlas_index = ncomponents - 1 ; - ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ; - for(; iter != mAtlasMap[atlas_index].end(); ++iter) - { - LLTextureAtlas* cur = (LLTextureAtlas*)*iter ; - if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary. - { - if(cur->getNextAvailableSlot(bits_len, col, row)) - { - atlasp = cur ; - groupp->addAtlas(atlasp) ; - break ; - } - } - } - } - - //create a new atlas if necessary - if(!atlasp) - { - if(mEmptyAtlasMap[ncomponents - 1].size() > 0) - { - //there is an empty one - atlasp = mEmptyAtlasMap[ncomponents - 1].back() ; - mEmptyAtlasMap[ncomponents - 1].pop_back() ; - } - else - { - atlasp = new LLTextureAtlas(ncomponents, 16) ; - } - mAtlasMap[ncomponents - 1].push_back(atlasp) ; - atlasp->getNextAvailableSlot(bits_len, col, row) ; - groupp->addAtlas(atlasp) ; - } - - F32 xoffset, yoffset ; - atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ; - LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ; - - return slot_infop ; -} - -//********************************************************************************************* -//END of implementation of class LLTextureAtlasManager -//********************************************************************************************* diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h deleted file mode 100644 index 1b8df708c6..0000000000 --- a/indra/newview/lltextureatlasmanager.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file lltextureatlasmanager.h - * @brief LLTextureAtlasManager base class. - * - * $LicenseInfo:firstyear=2002&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$ - */ - - -#ifndef LL_TEXTUREATLASMANAGER_H -#define LL_TEXTUREATLASMANAGER_H - -#include "llmemory.h" - -class LLSpatialGroup ; -class LLViewerTexture ; - -//just use it as a structure. -class LLTextureAtlasSlot : public LLRefCount -{ -public: - LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ; - -protected: - virtual ~LLTextureAtlasSlot(); - -public: - - // - //do not allow to change those values - // - //void setAtlas(LLTextureAtlas* atlasp) ; - //void setSlotPos(S16 col, S16 row) ; - //void setSlotWidth(S8 width) ; - //void setTexCoordOffset(F32 xoffser, F32 yoffset) ; - // - - void setSpatialGroup(LLSpatialGroup* groupp) ; - void setTexCoordScale(F32 xscale, F32 yscale) ; - void setValid() {mValid = TRUE ;} - - LLTextureAtlas* getAtlas()const {return mAtlasp;} - LLSpatialGroup* getSpatialGroup() const {return mGroupp ;} - S16 getSlotCol()const {return mCol;} - S16 getSlotRow()const {return mRow;} - S8 getSlotWidth()const{return mReservedSlotWidth;} - BOOL isValid()const { return mValid;} - const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;} - const LLVector2* getTexCoordScale() const {return &mTexCoordScale;} - - void setUpdatedTime(U32 t) {mUpdatedTime = t;} - U32 getUpdatedTime()const {return mUpdatedTime;} - -private: - LLTextureAtlas* mAtlasp; - S16 mCol ;//col of the slot - S16 mRow ;//row of the slot - S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number - LLSpatialGroup* mGroupp ; - BOOL mValid ; - - LLVector2 mTexCoordOffset ; - LLVector2 mTexCoordScale ; - - U32 mUpdatedTime ; -} ; - -class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager> -{ - LLSINGLETON(LLTextureAtlasManager); - ~LLTextureAtlasManager(); - typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ; - -public: - - LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, - LLSpatialGroup* groupp, LLViewerTexture* imagep) ; - void releaseAtlas(LLTextureAtlas* atlasp); - - BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ; - -private: - std::vector<ll_texture_atlas_list_t> mAtlasMap ; - std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately. -}; - -#endif diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index f64db7beb5..73a25397fd 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -314,6 +314,7 @@ private: // Threads: Ttc virtual void completed(bool success) { + LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { @@ -338,6 +339,7 @@ private: // Threads: Ttc virtual void completed(bool success) { + LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { @@ -362,6 +364,7 @@ private: // Threads: Tid virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) { + LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { @@ -1139,6 +1142,11 @@ void LLTextureFetchWorker::startWork(S32 param) // Threads: Ttf bool LLTextureFetchWorker::doWork(S32 param) { + LL_PROFILE_ZONE_SCOPED; + if (gNonInteractive) + { + return true; + } static const LLCore::HttpStatus http_not_found(HTTP_NOT_FOUND); // 404 static const LLCore::HttpStatus http_service_unavail(HTTP_SERVICE_UNAVAILABLE); // 503 static const LLCore::HttpStatus http_not_sat(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE); // 416; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 100d5ee713..d43da93c61 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -114,7 +114,8 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount) LLToastPanel* LLToastPanel::buidPanelFromNotification( const LLNotificationPtr& notification) { - LLToastPanel* res = NULL; + LL_PROFILE_ZONE_SCOPED + LLToastPanel* res = NULL; //process tip toast panels if ("notifytip" == notification->getType()) diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index f01b374db1..6216899dc6 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -529,8 +529,8 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask) const F32 RADIANS_PER_PIXEL_X = 0.01f; const F32 RADIANS_PER_PIXEL_Y = 0.01f; - S32 dx = x - (gViewerWindow->getWorldViewWidthScaled() / 2); - S32 dy = y - (gViewerWindow->getWorldViewHeightScaled() / 2); + S32 dx = gViewerWindow->getCurrentMouseDX(); + S32 dy = gViewerWindow->getCurrentMouseDY(); if (dx != 0 || dy != 0) { diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 06a2caf75b..b2e8348ffd 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -195,10 +195,7 @@ BOOL LLVisualParamHint::render() gGL.pushMatrix(); gGL.loadIdentity(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); LLGLSUIDefault gls_ui; //LLGLState::verify(TRUE); @@ -247,11 +244,11 @@ BOOL LLVisualParamHint::render() { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)gAgentAvatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - gGL.setAlphaRejectSettings(LLRender::CF_ALWAYS); + gGL.flush(); gGL.setSceneBlendType(LLRender::BT_REPLACE); avatarPoolp->renderAvatars(gAgentAvatarp); // renders only one avatar gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); } gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight); mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 27a87ee1a0..5d8e80cc41 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -81,9 +81,6 @@ glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height return glh::matrix4f(m); } -// Build time optimization, generate this once in .cpp file -template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance(); - LLViewerCamera::LLViewerCamera() : LLCamera() { calcProjection(getFar()); diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index fb07a3fb2d..549778a841 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -38,25 +38,11 @@ class LLViewerObject; const BOOL FOR_SELECTION = TRUE; const BOOL NOT_FOR_SELECTION = FALSE; -// Build time optimization, generate this once in .cpp file -#ifndef LLVIEWERCAMERA_CPP -extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance(); -#endif - -LL_ALIGN_PREFIX(16) -class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera> +class alignas(16) LLViewerCamera : public LLCamera, public LLSimpleton<LLViewerCamera> { - LLSINGLETON(LLViewerCamera); + LL_ALIGN_NEW public: - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } + LLViewerCamera(); typedef enum { @@ -141,7 +127,7 @@ protected: S16 mZoomSubregion; public: -} LL_ALIGN_POSTFIX(16); +}; #endif // LL_LLVIEWERCAMERA_H diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index bc425123e1..e53f988c6e 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -107,10 +107,14 @@ static bool handleRenderAvatarMouselookChanged(const LLSD& newvalue) static bool handleRenderFarClipChanged(const LLSD& newvalue) { - F32 draw_distance = (F32) newvalue.asReal(); + if (LLStartUp::getStartupState() >= STATE_STARTED) + { + F32 draw_distance = (F32)newvalue.asReal(); gAgentCamera.mDrawDistance = draw_distance; LLWorld::getInstance()->setLandFarClip(draw_distance); return true; + } + return false; } static bool handleTerrainDetailChanged(const LLSD& newvalue) @@ -162,17 +166,6 @@ static bool handleSetShaderChanged(const LLSD& newvalue) return true; } -static bool handleAvatarVPChanged(const LLSD& newvalue) -{ - LLRenderTarget::sUseFBO = newvalue.asBoolean() - && gSavedSettings.getBOOL("RenderObjectBump") - && gSavedSettings.getBOOL("RenderTransparentWater") - && gSavedSettings.getBOOL("RenderDeferred"); - - handleSetShaderChanged(LLSD()); - return true; -} - static bool handleRenderPerfTestChanged(const LLSD& newvalue) { bool status = !newvalue.asBoolean(); @@ -212,10 +205,6 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue) bool handleRenderTransparentWaterChanged(const LLSD& newvalue) { - LLRenderTarget::sUseFBO = newvalue.asBoolean() - && gSavedSettings.getBOOL("RenderObjectBump") - && gSavedSettings.getBOOL("RenderAvatarVP") - && gSavedSettings.getBOOL("RenderDeferred"); if (gPipeline.isInit()) { gPipeline.updateRenderTransparentWater(); @@ -269,6 +258,14 @@ static bool handleAnisotropicChanged(const LLSD& newvalue) return true; } +static bool handleVSyncChanged(const LLSD& newvalue) +{ +#if LL_WINDOWS + gViewerWindow->getWindow()->toggleVSync(newvalue.asBoolean()); +#endif + return true; +} + static bool handleVolumeLODChanged(const LLSD& newvalue) { LLVOVolume::sLODFactor = llclamp((F32) newvalue.asReal(), 0.01f, MAX_LOD_FACTOR); @@ -391,7 +388,7 @@ static bool handleJoystickChanged(const LLSD& newvalue) static bool handleUseOcclusionChanged(const LLSD& newvalue) { - LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery && LLGLSLShader::sNoFixedFunction + LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0; return true; } @@ -468,10 +465,7 @@ static bool handleRenderDeferredChanged(const LLSD& newvalue) // static bool handleRenderBumpChanged(const LLSD& newval) { - LLRenderTarget::sUseFBO = newval.asBoolean() - && gSavedSettings.getBOOL("RenderTransparentWater") - && gSavedSettings.getBOOL("RenderAvatarVP") - && gSavedSettings.getBOOL("RenderDeferred"); + LLRenderTarget::sUseFBO = newval.asBoolean() && gSavedSettings.getBOOL("RenderDeferred"); if (gPipeline.isInit()) { gPipeline.updateRenderBump(); @@ -665,7 +659,6 @@ void settings_setup_listeners() gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); - gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleAvatarVPChanged, _2)); gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleWindowResized, _2)); gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); @@ -696,6 +689,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleRenderBumpChanged, _2)); gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("RenderVSyncEnable")->getSignal()->connect(boost::bind(&handleVSyncChanged, _2)); gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderDebugGL")->getSignal()->connect(boost::bind(&handleRenderDebugGLChanged, _2)); gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2)); diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp index 3443bb644a..8820f9ec56 100644 --- a/indra/newview/llviewercontrollistener.cpp +++ b/indra/newview/llviewercontrollistener.cpp @@ -127,7 +127,7 @@ struct Info LLEventAPI::Response response; std::string groupname; - LLControlGroup* group; + LLControlGroup::ptr_t group; std::string key; LLControlVariable* control; }; @@ -187,7 +187,7 @@ void LLViewerControlListener::groups(LLSD const & request) struct CollectVars: public LLControlGroup::ApplyFunctor { - CollectVars(LLControlGroup* g): + CollectVars(LLControlGroup::ptr_t g): mGroup(g) {} @@ -200,7 +200,7 @@ struct CollectVars: public LLControlGroup::ApplyFunctor ("comment", control->getComment())); } - LLControlGroup* mGroup; + LLControlGroup::ptr_t mGroup; LLSD vars; }; @@ -210,7 +210,7 @@ void LLViewerControlListener::vars(LLSD const & request) // control name. Response response(LLSD(), request); std::string groupname(request["group"]); - LLControlGroup* group(LLControlGroup::getInstance(groupname)); + auto group(LLControlGroup::getInstance(groupname)); if (! group) { return response.error(STRINGIZE("Unrecognized group '" << groupname << "'")); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 109dc93261..c84a8c70fa 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -124,7 +124,8 @@ void display_startup() if ( !gViewerWindow || !gViewerWindow->getActive() || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() ) + || gViewerWindow->getWindow()->getMinimized() + || gNonInteractive) { return; } @@ -165,8 +166,6 @@ void display_startup() if (gViewerWindow) gViewerWindow->setup2DRender(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - gGL.color4f(1,1,1,1); if (gViewerWindow) gViewerWindow->draw(); @@ -208,9 +207,11 @@ void display_update_camera() // Write some stats to LL_INFOS() void display_stats() { + LL_PROFILE_ZONE_SCOPED F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency"); if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq) { + LL_PROFILE_ZONE_NAMED("DS - FPS"); F32 fps = gRecentFrameCount / fps_log_freq; LL_INFOS() << llformat("FPS: %.02f", fps) << LL_ENDL; gRecentFrameCount = 0; @@ -219,6 +220,7 @@ void display_stats() F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) { + LL_PROFILE_ZONE_NAMED("DS - Memory"); gMemoryAllocated = U64Bytes(LLMemory::getCurrentRSS()); U32Megabytes memory = gMemoryAllocated; LL_INFOS() << "MEMORY: " << memory << LL_ENDL; @@ -228,6 +230,7 @@ void display_stats() F32 asset_storage_log_freq = gSavedSettings.getF32("AssetStorageLogFrequency"); if (asset_storage_log_freq > 0.f && gAssetStorageLogTime.getElapsedTimeF32() >= asset_storage_log_freq) { + LL_PROFILE_ZONE_NAMED("DS - Asset Storage"); gAssetStorageLogTime.reset(); gAssetStorage->logAssetStorageInfo(); } @@ -309,7 +312,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // Attempting to draw into a minimized window causes a GL error. JC if ( !gViewerWindow->getActive() || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() ) + || gViewerWindow->getWindow()->getMinimized() + || gNonInteractive) { // Clean up memory the pools may have allocated if (rebuild) @@ -572,8 +576,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); - LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); - LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); + if (LLViewerCamera::instanceExists()) + { + LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); + LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); + } ////////////////////////// // @@ -630,6 +637,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (!gDisconnected) { + LL_PROFILE_ZONE_NAMED("display - 1"); LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { //don't draw hud objects in this frame @@ -675,21 +683,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) stop_glerror(); - S32 water_clip = 0; - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && - (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || - gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER))) - { - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - water_clip = -1; - } - else - { - water_clip = 1; - } - } - LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); //Increment drawable frame counter @@ -707,21 +700,20 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); static LLCullResult result; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater(); - gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); + gPipeline.updateCull(*LLViewerCamera::getInstance(), result); stop_glerror(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - + LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); { + LL_PROFILE_ZONE_NAMED("display - 2") if (gResizeScreenTexture) { gResizeScreenTexture = FALSE; @@ -733,7 +725,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); if (!for_snapshot) { @@ -747,7 +738,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); glh::matrix4f proj = get_current_projection(); glh::matrix4f mod = get_current_modelview(); @@ -766,17 +756,16 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); } glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } LLGLState::checkStates(); - LLGLState::checkClientArrays(); //if (!for_snapshot) { + LL_PROFILE_ZONE_NAMED("display - 3") LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); gPipeline.generateHighlight(*LLViewerCamera::getInstance()); @@ -784,7 +773,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } LLGLState::checkStates(); - LLGLState::checkClientArrays(); ////////////////////////////////////// // @@ -800,13 +788,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_CLASS); - LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); - LLTrace::CountStatHandle<>* angular_velocity_stat = LLViewerCamera::getAngularVelocityStat(); - LLViewerTexture::updateClass(LLTrace::get_frame_recording().getPeriodMeanPerSec(*velocity_stat), - LLTrace::get_frame_recording().getPeriodMeanPerSec(*angular_velocity_stat)); + LLViewerTexture::updateClass(); } - { LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_BUMP); gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. @@ -825,10 +809,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLImageGL::deleteDeadTextures(); stop_glerror(); }*/ - } + } LLGLState::checkStates(); - LLGLState::checkClientArrays(); /////////////////////////////////// // @@ -840,6 +823,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); { + LL_PROFILE_ZONE_NAMED("display - 3") LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); @@ -859,7 +843,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLSceneMonitor::getInstance()->fetchQueryResult(); LLGLState::checkStates(); - LLGLState::checkClientArrays(); LLPipeline::sUseOcclusion = occlusion; @@ -918,7 +901,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; LLGLState::checkStates(); - LLGLState::checkClientArrays(); stop_glerror(); @@ -948,9 +930,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) && !gRestoreGL) { + LL_PROFILE_ZONE_NAMED("display - 4") LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - if (gSavedSettings.getBOOL("RenderDepthPrePass") && LLGLSLShader::sNoFixedFunction) + if (gSavedSettings.getBOOL("RenderDepthPrePass")) { gGL.setColorMask(false, false); @@ -1259,7 +1242,7 @@ bool setup_hud_matrices(const LLRect& screen_region) void render_ui(F32 zoom_factor, int subfield) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); LLGLState::checkStates(); @@ -1274,7 +1257,6 @@ void render_ui(F32 zoom_factor, int subfield) if(LLSceneMonitor::getInstance()->needsUpdate()) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_SCENE_MON); gGL.pushMatrix(); gViewerWindow->setup2DRender(); LLSceneMonitor::getInstance()->compare(); @@ -1282,55 +1264,61 @@ void render_ui(F32 zoom_factor, int subfield) gGL.popMatrix(); } - // Finalize scene - gPipeline.renderFinalize(); + // Finalize scene + gPipeline.renderFinalize(); - LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD); - render_hud_elements(); - render_hud_attachments(); - - LLGLSDefault gls_default; - LLGLSUIDefault gls_ui; { - gPipeline.disableLights(); - } + // SL-15709 + // NOTE: Tracy only allows one ZoneScoped per function. + // Solutions are: + // 1. Use a new scope + // 2. Use named zones + // 3. Use transient zones + LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD); + render_hud_elements(); + render_hud_attachments(); - { - gGL.color4f(1,1,1,1); - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + LLGLSDefault gls_default; + LLGLSUIDefault gls_ui; { - if (!gDisconnected) + gPipeline.disableLights(); + } + + { + gGL.color4f(1,1,1,1); + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D); - render_ui_3d(); + if (!gDisconnected) + { + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D); + render_ui_3d(); + LLGLState::checkStates(); + } + else + { + render_disconnected_background(); + } + + LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D); + render_ui_2d(); LLGLState::checkStates(); } - else - { - render_disconnected_background(); - } + gGL.flush(); - LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D); - render_ui_2d(); - LLGLState::checkStates(); - } - gGL.flush(); - - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_DEBUG_TEXT); gViewerWindow->setup2DRender(); gViewerWindow->updateDebugText(); gViewerWindow->drawDebugText(); + + LLVertexBuffer::unbind(); } - LLVertexBuffer::unbind(); - } + if (!gSnapshot) + { + set_current_modelview(saved_view); + gGL.popMatrix(); + } - if (!gSnapshot) - { - set_current_modelview(saved_view); - gGL.popMatrix(); - } + } // Tracy integration } static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap"); @@ -1435,10 +1423,7 @@ void render_ui_3d() stop_glerror(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); // Coordinate axes if (gSavedSettings.getBOOL("ShowAxes")) @@ -1478,7 +1463,6 @@ void render_ui_2d() } stop_glerror(); - //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); // render outline for HUD if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f) @@ -1568,10 +1552,7 @@ void render_ui_2d() void render_disconnected_background() { - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); gGL.color4f(1,1,1,1); if (!gDisconnectedImagep && gDisconnected) @@ -1643,11 +1624,7 @@ void render_disconnected_background() } gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } - + gUIProgram.unbind(); } void display_cleanup() diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 62d73063aa..dd03d6cfdd 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -193,6 +193,10 @@ LLFloaterOpenHandler gFloaterOpenHandler; void LLViewerFloaterReg::registerFloaters() { + if (gNonInteractive) + { + return; + } // *NOTE: Please keep these alphabetized for easier merges LLFloaterAboutUtil::registerFloater(); diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index 8a597ed7e6..fd314ed3dc 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -121,8 +121,7 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) object->mDrawable->mXform.setRotation(current_rot); gPipeline.markMoved(object->mDrawable); gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD - object->mDrawable->setState(LLDrawable::USE_BACKLIGHT); - + if(mIsHUDAttachment) { for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++) @@ -142,7 +141,6 @@ void LLViewerJointAttachment::setupDrawable(LLViewerObject *object) LLViewerObject* childp = *iter; if (childp && childp->mDrawable.notNull()) { - childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD gPipeline.markMoved(childp->mDrawable); @@ -256,7 +254,6 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) object->mDrawable->mXform.setRotation(cur_rotation); gPipeline.markMoved(object->mDrawable, TRUE); gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD - object->mDrawable->clearState(LLDrawable::USE_BACKLIGHT); if (mIsHUDAttachment) { @@ -278,7 +275,6 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) LLViewerObject* childp = *iter; if (childp && childp->mDrawable.notNull()) { - childp->mDrawable->clearState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD if (mIsHUDAttachment) { diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 63ad708e59..f3b0e82b3a 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -225,7 +225,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if (!mValid || !mMesh || !mFace || !mVisible || !mFace->getVertexBuffer() || mMesh->getNumFaces() == 0 || - (LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShaderPtr == NULL)) + LLGLSLShader::sCurBoundShaderPtr == NULL) { return 0; } @@ -246,7 +246,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) stop_glerror(); - LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny); + LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), 0.f); //---------------------------------------------------------------- // setup current texture @@ -265,7 +265,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) else { gGL.diffuseColor4f(0.7f, 0.6f, 0.3f, 1.f); - gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( !is_dummy && layerset ) @@ -328,11 +327,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) triangle_count += count; - if (mTestImageName) - { - gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT); - } - return triangle_count; } @@ -362,7 +356,6 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 //----------------------------------------------------------------------------- // updateFaceData() //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_AVATAR_FACE("Avatar Face"); void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) { @@ -383,9 +376,8 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w // since mMesh is being copied into mVertexBuffer every frame return; } - - - LL_RECORD_BLOCK_TIME(FTM_AVATAR_FACE); + + LL_PROFILE_ZONE_SCOPED; LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 54c2099ac9..0a0a3f905a 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1216,7 +1216,7 @@ LLCore::HttpHeaders::ptr_t LLViewerMedia::getHttpHeaders() ///////////////////////////////////////////////////////////////////////////////////////// void LLViewerMedia::setOpenIDCookie(const std::string& url) { - if(!mOpenIDCookie.empty()) + if(!gNonInteractive && !mOpenIDCookie.empty()) { std::string profileUrl = getProfileURL(""); @@ -1693,6 +1693,11 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) /*static*/ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) { + if (gNonInteractive) + { + return NULL; + } + std::string plugin_basename = LLMIMETypes::implType(media_type); LLPluginClassMedia* media_source = NULL; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 01a4bd587d..47f0a43884 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8370,6 +8370,7 @@ class LLViewHighlightTransparent : public view_listener_t bool handleEvent(const LLSD& userdata) { LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; + gPipeline.resetVertexBuffers(); return true; } }; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 14442c9705..22e5907b14 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2219,11 +2219,9 @@ protected: } }; -static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMPROVED_IM("Process IM"); - void process_improved_im(LLMessageSystem *msg, void **user_data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMPROVED_IM); + LL_PROFILE_ZONE_SCOPED; LLUUID from_id; BOOL from_group; @@ -2423,6 +2421,10 @@ void translateFailure(LLChat chat, LLSD toastArgs, int status, const std::string void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { + if (gNonInteractive) + { + return; + } LLChat chat; std::string mesg; std::string from_name; @@ -3263,10 +3265,9 @@ const F32 THRESHOLD_HEAD_ROT_QDOT = 0.9997f; // ~= 2.5 degrees -- if its less th const F32 MAX_HEAD_ROT_QDOT = 0.99999f; // ~= 0.5 degrees -- if its greater than this then no need to update head_rot // between these values we delay the updates (but no more than one second) -static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE_SEND("Send Message"); - void send_agent_update(BOOL force_send, BOOL send_reliable) { + LL_PROFILE_ZONE_SCOPED; if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { // We don't care if they want to send an agent update, they're not allowed to until the simulator @@ -3447,7 +3448,6 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) } */ - LL_RECORD_BLOCK_TIME(FTM_AGENT_UPDATE_SEND); // Build the message msg->newMessageFast(_PREHASH_AgentUpdate); msg->nextBlockFast(_PREHASH_AgentData); @@ -3697,11 +3697,9 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ } } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Kill Objects"); - void process_kill_object(LLMessageSystem *mesgsys, void **user_data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_OBJECTS); + LL_PROFILE_ZONE_SCOPED; LLUUID id; @@ -3984,8 +3982,8 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) F32 stat_value; msg->getU32("Stat", "StatID", stat_id, i); msg->getF32("Stat", "StatValue", stat_value, i); - LLStatViewer::SimMeasurementSampler* measurementp = LLStatViewer::SimMeasurementSampler::getInstance((ESimStatID)stat_id); - + auto measurementp = LLStatViewer::SimMeasurementSampler::getInstance((ESimStatID)stat_id); + if (measurementp ) { measurementp->sample(stat_value); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 31e80eb865..a2d3f2c0cf 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -107,6 +107,7 @@ #include "llcleanup.h" #include "llcallstack.h" #include "llmeshrepository.h" +#include "llgl.h" //#define DEBUG_UPDATE_TYPE @@ -145,21 +146,35 @@ const S32 MAX_OBJECT_BINARY_DATA_SIZE = 60 + 16; const F64 INVENTORY_UPDATE_WAIT_TIME_DESYNC = 5; // seconds const F64 INVENTORY_UPDATE_WAIT_TIME_OUTDATED = 1; -static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object"); - // static LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, S32 flags) { + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("ObjectUpdate") << "creating " << id << LL_ENDL; dumpStack("ObjectUpdateStack"); LLViewerObject *res = NULL; - LL_RECORD_BLOCK_TIME(FTM_CREATE_OBJECT); - + + if (gNonInteractive + && pcode != LL_PCODE_LEGACY_AVATAR + && pcode != LL_VO_SURFACE_PATCH + && pcode != LL_VO_WATER + && pcode != LL_VO_VOID_WATER + && pcode != LL_VO_WL_SKY + && pcode != LL_VO_SKY + && pcode != LL_VO_GROUND + && pcode != LL_VO_PART_GROUP + ) + { + return res; + } switch (pcode) { case LL_PCODE_VOLUME: - res = new LLVOVolume(id, pcode, regionp); break; + { + res = new LLVOVolume(id, pcode, regionp); break; + break; + } case LL_PCODE_LEGACY_AVATAR: { if (id == gAgentID) @@ -235,8 +250,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco } LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global) -: LLTrace::MemTrackable<LLViewerObject>("LLViewerObject"), - LLPrimitive(), +: LLPrimitive(), mChildList(), mID(id), mLocalID(0), @@ -2501,9 +2515,6 @@ void LLViewerObject::loadFlags(U32 flags) void LLViewerObject::idleUpdate(LLAgent &agent, const F64 &frame_time) { - //static LLTrace::BlockTimerStatHandle ftm("Viewer Object"); - //LL_RECORD_BLOCK_TIME(ftm); - if (!mDead) { if (!mStatic && sVelocityInterpolate && !isSelected()) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 250c4ac328..bef8e3e7e3 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -110,8 +110,7 @@ struct PotentialReturnableObject class LLViewerObject : public LLPrimitive, public LLRefCount, - public LLGLUpdate, - public LLTrace::MemTrackable<LLViewerObject> + public LLGLUpdate { protected: virtual ~LLViewerObject(); // use unref() diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 63e48d1dd0..971a355a65 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -80,6 +80,7 @@ #include "llfloaterperms.h" #include "llvocache.h" #include "llcorehttputil.h" +#include "llstartup.h" #include <algorithm> #include <iterator> @@ -168,6 +169,8 @@ U64 LLViewerObjectList::getIndex(const U32 local_id, BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) { + LL_PROFILE_ZONE_SCOPED + if(objectp && objectp->getRegion()) { U32 local_id = objectp->mLocalID; @@ -303,9 +306,11 @@ static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Objects"); LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp) { + LL_PROFILE_ZONE_SCOPED + LLDataPacker *cached_dpp = entry->getDP(); - if (!cached_dpp) + if (!cached_dpp || gNonInteractive) { return NULL; //nothing cached. } @@ -844,10 +849,10 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) LLVOAvatar::cullAvatarsByPixelArea(); } -static LLTrace::BlockTimerStatHandle FTM_IDLE_COPY("Idle Copy"); - void LLViewerObjectList::update(LLAgent &agent) { + LL_PROFILE_ZONE_SCOPED + // Update globals LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") ); LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") ); @@ -899,8 +904,6 @@ void LLViewerObjectList::update(LLAgent &agent) U32 idle_count = 0; { - LL_RECORD_BLOCK_TIME(FTM_IDLE_COPY); - for (std::vector<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) { @@ -1293,6 +1296,8 @@ void LLViewerObjectList::clearDebugText() void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { + LL_PROFILE_ZONE_SCOPED + bool new_dead_object = true; if (mDeadObjects.find(objectp->mID) != mDeadObjects.end()) { @@ -1343,11 +1348,9 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) } } -static LLTrace::BlockTimerStatHandle FTM_REMOVE_DRAWABLE("Remove Drawable"); - void LLViewerObjectList::removeDrawable(LLDrawable* drawablep) { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_DRAWABLE); + LL_PROFILE_ZONE_SCOPED; if (!drawablep) { @@ -1523,6 +1526,8 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) void LLViewerObjectList::updateActive(LLViewerObject *objectp) { + LL_PROFILE_ZONE_SCOPED + if (objectp->isDead()) { return; // We don't update dead objects! @@ -1634,12 +1639,9 @@ void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) mPendingPhysicsFlags.erase(object_id); } -static LLTrace::BlockTimerStatHandle FTM_SHIFT_OBJECTS("Shift Objects"); -static LLTrace::BlockTimerStatHandle FTM_PIPELINE_SHIFT("Pipeline Shift"); -static LLTrace::BlockTimerStatHandle FTM_REGION_SHIFT("Region Shift"); - void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { + LL_PROFILE_ZONE_SCOPED; // This is called when we shift our origin when we cross region boundaries... // We need to update many object caches, I'll document this more as I dig through the code // cleaning things out... @@ -1649,7 +1651,6 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) return; } - LL_RECORD_BLOCK_TIME(FTM_SHIFT_OBJECTS); LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) @@ -1667,16 +1668,10 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) } } - { - LL_RECORD_BLOCK_TIME(FTM_PIPELINE_SHIFT); gPipeline.shiftObjects(offset); - } - - { - LL_RECORD_BLOCK_TIME(FTM_REGION_SHIFT); + LLWorld::getInstance()->shiftRegions(offset); } -} void LLViewerObjectList::repartitionObjects() { @@ -1843,6 +1838,8 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) void LLViewerObjectList::generatePickList(LLCamera &camera) { + LL_PROFILE_ZONE_SCOPED + LLViewerObject *objectp; S32 i; // Reset all of the GL names to zero. @@ -2051,7 +2048,6 @@ LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, L LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender) { - LLUUID fullid; if (uuid == LLUUID::null) { @@ -2104,6 +2100,8 @@ LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCod S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const { + LL_PROFILE_ZONE_SCOPED + LLViewerObject *objectp; S32 num_refs = 0; @@ -2167,6 +2165,8 @@ void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) { + LL_PROFILE_ZONE_SCOPED + if (objectp->isDead()) { LL_WARNS() << "Trying to find orphans for dead obj " << objectp->mID diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 6365df09e1..b5bf4f0354 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -32,6 +32,7 @@ #include "llappviewer.h" #include "llglslshader.h" #include "llviewershadermgr.h" +#include "lldrawpoolwater.h" //----------------------------------------------------------------------------------- //static variables definitions @@ -231,8 +232,7 @@ S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LL //class LLViewerOctreeEntry definitions //----------------------------------------------------------------------------------- LLViewerOctreeEntry::LLViewerOctreeEntry() -: LLTrace::MemTrackable<LLViewerOctreeEntry, 16>("LLViewerOctreeEntry"), - mGroup(NULL), +: mGroup(NULL), mBinRadius(0.f), mBinIndex(-1), mVisible(0) @@ -458,8 +458,7 @@ LLViewerOctreeGroup::~LLViewerOctreeGroup() } LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node) -: LLTrace::MemTrackable<LLViewerOctreeGroup, 16>("LLViewerOctreeGroup"), - mOctreeNode(node), +: mOctreeNode(node), mAnyVisible(0), mState(CLEAN) { @@ -517,6 +516,7 @@ bool LLViewerOctreeGroup::removeFromGroup(LLViewerOctreeEntry* entry) //virtual void LLViewerOctreeGroup::unbound() { + LL_PROFILE_ZONE_SCOPED; if (isDirty()) { return; @@ -545,6 +545,7 @@ void LLViewerOctreeGroup::unbound() //virtual void LLViewerOctreeGroup::rebound() { + LL_PROFILE_ZONE_SCOPED; if (!isDirty()) { return; @@ -932,47 +933,53 @@ void LLOcclusionCullingGroup::releaseOcclusionQueryObjectNames() } } -void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode) -{ - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialSetOcclusionStateDiff setter(state); - setter.traverse(mOctreeNode); - } - else if (mode == STATE_MODE_BRANCH) - { - LLSpatialSetOcclusionState setter(state); - setter.traverse(mOctreeNode); - } - else - { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mOcclusionState[i] |= state; - - if ((state & DISCARD_QUERY) && mOcclusionQuery[i]) - { - releaseOcclusionQueryObjectName(mOcclusionQuery[i]); - mOcclusionQuery[i] = 0; - } - } - } - } - else - { - if (state & OCCLUDED) - { - add(sNumObjectsOccluded, 1); - } - mOcclusionState[LLViewerCamera::sCurCameraID] |= state; - if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); - mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; - } - } +void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode /* = STATE_MODE_SINGLE */ ) +{ + switch (mode) + { + case STATE_MODE_SINGLE: + if (state & OCCLUDED) + { + add(sNumObjectsOccluded, 1); + } + mOcclusionState[LLViewerCamera::sCurCameraID] |= state; + if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; + } + break; + + case STATE_MODE_DIFF: + { + LLSpatialSetOcclusionStateDiff setter(state); + setter.traverse(mOctreeNode); + } + break; + + case STATE_MODE_BRANCH: + { + LLSpatialSetOcclusionState setter(state); + setter.traverse(mOctreeNode); + } + break; + + case STATE_MODE_ALL_CAMERAS: + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionState[i] |= state; + + if ((state & DISCARD_QUERY) && mOcclusionQuery[i]) + { + releaseOcclusionQueryObjectName(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } + } + break; + + default: + break; + } } class LLSpatialClearOcclusionState : public OctreeTraveler @@ -1007,43 +1014,47 @@ public: } }; -void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode) -{ - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialClearOcclusionStateDiff clearer(state); - clearer.traverse(mOctreeNode); - } - else if (mode == STATE_MODE_BRANCH) - { - LLSpatialClearOcclusionState clearer(state); - clearer.traverse(mOctreeNode); - } - else - { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mOcclusionState[i] &= ~state; - } - } - } - else - { - if (state & OCCLUDED) - { - add(sNumObjectsUnoccluded, 1); - } - mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state; - } +void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode /* = STATE_MODE_SINGLE */) +{ + switch (mode) + { + case STATE_MODE_SINGLE: + if (state & OCCLUDED) + { + add(sNumObjectsUnoccluded, 1); + } + mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state; + break; + + case STATE_MODE_DIFF: + { + LLSpatialClearOcclusionStateDiff clearer(state); + clearer.traverse(mOctreeNode); + } + break; + + case STATE_MODE_BRANCH: + { + LLSpatialClearOcclusionState clearer(state); + clearer.traverse(mOctreeNode); + } + break; + + case STATE_MODE_ALL_CAMERAS: + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionState[i] &= ~state; + } + break; + + default: + break; + } } -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_WAIT("Occlusion Wait"); - BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera, const LLVector4a* bounds) { + LL_PROFILE_ZONE_SCOPED; if (camera->getOrigin().isExactlyZero()) { return FALSE; @@ -1092,100 +1103,82 @@ U32 LLOcclusionCullingGroup::getLastOcclusionIssuedTime() void LLOcclusionCullingGroup::checkOcclusion() { - if (LLPipeline::sUseOcclusion > 1) - { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_READBACK); - LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent(); - if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) - { //if the parent has been marked as occluded, the child is implicitly occluded - clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); - } - else if (isOcclusionState(QUERY_PENDING)) - { //otherwise, if a query is pending, read it back - - GLuint available = 0; - if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - - static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion", true); - - if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) - { //query was issued last frame, wait until it's available - S32 max_loop = 1024; - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_WAIT); - while (!available && max_loop-- > 0) - { - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - } - } - } - else - { - available = 1; - } - - if (available) - { //result is available, read it back, otherwise wait until next frame - GLuint res = 1; - if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); + if (LLPipeline::sUseOcclusion < 2) return; // 0 - NoOcclusion, 1 = ReadOnly, 2 = ModifyOcclusionState TODO: DJH 11-2021 ENUM this + + LL_PROFILE_ZONE_SCOPED; + LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent(); + if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) + { //if the parent has been marked as occluded, the child is implicitly occluded + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); + return; + } + + if (mOcclusionQuery[LLViewerCamera::sCurCameraID] && isOcclusionState(QUERY_PENDING)) + { + if (isOcclusionState(DISCARD_QUERY)) + { // delete the query to avoid holding onto hundreds of pending queries + releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; + // mark non-occluded + clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); + } + else + { + GLuint available; + { + LL_PROFILE_ZONE_NAMED("co - query available"); + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); + } + + if (available) + { + GLuint query_result; // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint) + { + LL_PROFILE_ZONE_NAMED("co - query result"); + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &query_result); + } #if LL_TRACK_PENDING_OCCLUSION_QUERIES - sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]); #endif - } - else if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { //delete the query to avoid holding onto hundreds of pending queries - releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); - mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; - } - - if (isOcclusionState(DISCARD_QUERY)) - { - res = 2; - } - if (res > 0) - { - assert_states_valid(this); - clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } - else - { - assert_states_valid(this); - - setOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); - - assert_states_valid(this); - } - - clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); - } - } - else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) - { //check occlusion has been issued for occluded node that has not had a query issued - assert_states_valid(this); - clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } - } +#if 0 // (12/2021) occasional false-negative occlusion tests produce water reflection errors, SL-16461 + // If/when water occlusion queries become 100% reliable, re-enable this optimization + + if (LLPipeline::RENDER_TYPE_WATER == mSpatialPartition->mDrawableType) + { + // Note any unoccluded water, for deciding on reflection/distortion passes + // (If occlusion is disabled, these are set within LLDrawPoolWater::render) + if (query_result > 0) + { + LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; + LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; + } + } +#endif + if (query_result > 0) + { + clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + } + else + { + setOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + } + clearOcclusionState(QUERY_PENDING); + } + } + } + else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) + { //check occlusion has been issued for occluded node that has not had a query issued + assert_states_valid(this); + clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } } -static LLTrace::BlockTimerStatHandle FTM_PUSH_OCCLUSION_VERTS("Push Occlusion"); -static LLTrace::BlockTimerStatHandle FTM_SET_OCCLUSION_STATE("Occlusion State"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_ALLOCATE("Allocate"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_BUILD("Build"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_BEGIN_QUERY("Begin Query"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_END_QUERY("End Query"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_SET_BUFFER("Set Buffer"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_DRAW_WATER("Draw Water"); -static LLTrace::BlockTimerStatHandle FTM_OCCLUSION_DRAW("Draw"); - void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* shift) { + LL_PROFILE_ZONE_SCOPED; if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) { //move mBounds to the agent space if necessary @@ -1198,7 +1191,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh } F32 OCCLUSION_FUDGE_Z = SG_OCCLUSION_FUDGE; //<-- #Solution #2 - if (LLDrawPool::POOL_WATER == mSpatialPartition->mDrawableType) + if (LLPipeline::RENDER_TYPE_VOIDWATER == mSpatialPartition->mDrawableType) { OCCLUSION_FUDGE_Z = 1.; } @@ -1206,7 +1199,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension if (earlyFail(camera, bounds)) { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_EARLY_FAIL); + LL_PROFILE_ZONE_NAMED("doOcclusion - early fail"); setOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY); assert_states_valid(this); clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); @@ -1217,11 +1210,10 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY)) { { //no query pending, or previous query to be discarded - LL_RECORD_BLOCK_TIME(FTM_RENDER_OCCLUSION); + LL_PROFILE_ZONE_NAMED("doOcclusion - render"); if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_ALLOCATE); mOcclusionQuery[LLViewerCamera::sCurCameraID] = getNewOcclusionQueryObjectName(); } @@ -1229,8 +1221,8 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh // behind the far clip plane, and in the case of edge water to avoid // it being culled while still visible. bool const use_depth_clamp = gGLManager.mHasDepthClamp && - (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || - mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); + (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER || + mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER); LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); @@ -1246,15 +1238,12 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh add(sOcclusionQueries, 1); { - LL_RECORD_BLOCK_TIME(FTM_PUSH_OCCLUSION_VERTS); + LL_PROFILE_ZONE_NAMED("doOcclusion - push"); //store which frame this query was issued on mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; - { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_BEGIN_QUERY); - glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); - } + glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; llassert(shader); @@ -1264,9 +1253,9 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh bounds[1][1]+SG_OCCLUSION_FUDGE, bounds[1][2]+OCCLUSION_FUDGE_Z); - if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) + if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER) { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_DRAW_WATER); + LL_PROFILE_ZONE_NAMED("doOcclusion - draw water"); LLGLSquashToFarClip squash; if (camera->getOrigin().isExactlyZero()) @@ -1281,7 +1270,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh } else { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_DRAW); + LL_PROFILE_ZONE_NAMED("doOcclusion - draw"); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); @@ -1292,17 +1281,13 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, bounds[0])); } } - - - { - LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_END_QUERY); - glEndQueryARB(mode); - } + + glEndQueryARB(mode); } } { - LL_RECORD_BLOCK_TIME(FTM_SET_OCCLUSION_STATE); + LL_PROFILE_ZONE_NAMED("doOcclusion - set state"); setOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING); clearOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY); } diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index 219ec7e8da..11ba7e4f1e 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -71,8 +71,9 @@ S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVe //defines data needed for octree of an entry //LL_ALIGN_PREFIX(16) -class LLViewerOctreeEntry : public LLRefCount, public LLTrace::MemTrackable<LLViewerOctreeEntry, 16> +class LLViewerOctreeEntry : public LLRefCount { + LL_ALIGN_NEW friend class LLViewerOctreeEntryData; public: @@ -178,8 +179,9 @@ protected: //defines an octree group for an octree node, which contains multiple entries. //LL_ALIGN_PREFIX(16) class LLViewerOctreeGroup -: public LLOctreeListener<LLViewerOctreeEntry>, public LLTrace::MemTrackable<LLViewerOctreeGroup, 16> +: public LLOctreeListener<LLViewerOctreeEntry> { + LL_ALIGN_NEW friend class LLViewerOctreeCull; protected: virtual ~LLViewerOctreeGroup(); @@ -201,7 +203,6 @@ public: LLViewerOctreeGroup(OctreeNode* node); LLViewerOctreeGroup(const LLViewerOctreeGroup& rhs) - : LLTrace::MemTrackable<LLViewerOctreeGroup, 16>("LLViewerOctreeGroup") { *this = rhs; } diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 7c3dd00e1a..02f7bbeed8 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -847,6 +847,7 @@ void LLViewerParcelOverlay::setDirty() void LLViewerParcelOverlay::updateGL() { + LL_PROFILE_ZONE_SCOPED updateOverlayTexture(); } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 945b51d819..c97b1d914b 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -77,6 +77,7 @@ LLGLSLShader gTransformTangentProgram; //utility shaders LLGLSLShader gOcclusionProgram; +LLGLSLShader gSkinnedOcclusionProgram; LLGLSLShader gOcclusionCubeProgram; LLGLSLShader gCustomAlphaProgram; LLGLSLShader gGlowCombineProgram; @@ -87,6 +88,7 @@ LLGLSLShader gTwoTextureCompareProgram; LLGLSLShader gOneTextureFilterProgram; LLGLSLShader gOneTextureNoColorProgram; LLGLSLShader gDebugProgram; +LLGLSLShader gSkinnedDebugProgram; LLGLSLShader gClipProgram; LLGLSLShader gDownsampleDepthProgram; LLGLSLShader gDownsampleDepthRectProgram; @@ -96,56 +98,49 @@ LLGLSLShader gBenchmarkProgram; //object shaders LLGLSLShader gObjectSimpleProgram; +LLGLSLShader gSkinnedObjectSimpleProgram; LLGLSLShader gObjectSimpleImpostorProgram; +LLGLSLShader gSkinnedObjectSimpleImpostorProgram; LLGLSLShader gObjectPreviewProgram; LLGLSLShader gObjectSimpleWaterProgram; +LLGLSLShader gSkinnedObjectSimpleWaterProgram; LLGLSLShader gObjectSimpleAlphaMaskProgram; +LLGLSLShader gSkinnedObjectSimpleAlphaMaskProgram; LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; +LLGLSLShader gSkinnedObjectSimpleWaterAlphaMaskProgram; LLGLSLShader gObjectFullbrightProgram; +LLGLSLShader gSkinnedObjectFullbrightProgram; LLGLSLShader gObjectFullbrightWaterProgram; +LLGLSLShader gSkinnedObjectFullbrightWaterProgram; LLGLSLShader gObjectEmissiveProgram; +LLGLSLShader gSkinnedObjectEmissiveProgram; LLGLSLShader gObjectEmissiveWaterProgram; +LLGLSLShader gSkinnedObjectEmissiveWaterProgram; LLGLSLShader gObjectFullbrightAlphaMaskProgram; +LLGLSLShader gSkinnedObjectFullbrightAlphaMaskProgram; LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; +LLGLSLShader gSkinnedObjectFullbrightWaterAlphaMaskProgram; LLGLSLShader gObjectFullbrightShinyProgram; +LLGLSLShader gSkinnedObjectFullbrightShinyProgram; LLGLSLShader gObjectFullbrightShinyWaterProgram; +LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; LLGLSLShader gObjectShinyProgram; +LLGLSLShader gSkinnedObjectShinyProgram; LLGLSLShader gObjectShinyWaterProgram; +LLGLSLShader gSkinnedObjectShinyWaterProgram; LLGLSLShader gObjectBumpProgram; +LLGLSLShader gSkinnedObjectBumpProgram; LLGLSLShader gTreeProgram; LLGLSLShader gTreeWaterProgram; LLGLSLShader gObjectFullbrightNoColorProgram; LLGLSLShader gObjectFullbrightNoColorWaterProgram; -LLGLSLShader gObjectSimpleNonIndexedProgram; LLGLSLShader gObjectSimpleNonIndexedTexGenProgram; LLGLSLShader gObjectSimpleNonIndexedTexGenWaterProgram; -LLGLSLShader gObjectSimpleNonIndexedWaterProgram; LLGLSLShader gObjectAlphaMaskNonIndexedProgram; LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; LLGLSLShader gObjectAlphaMaskNoColorProgram; LLGLSLShader gObjectAlphaMaskNoColorWaterProgram; -LLGLSLShader gObjectFullbrightNonIndexedProgram; -LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; -LLGLSLShader gObjectEmissiveNonIndexedProgram; -LLGLSLShader gObjectEmissiveNonIndexedWaterProgram; -LLGLSLShader gObjectFullbrightShinyNonIndexedProgram; -LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram; -LLGLSLShader gObjectShinyNonIndexedProgram; -LLGLSLShader gObjectShinyNonIndexedWaterProgram; - -//object hardware skinning shaders -LLGLSLShader gSkinnedObjectSimpleProgram; -LLGLSLShader gSkinnedObjectFullbrightProgram; -LLGLSLShader gSkinnedObjectEmissiveProgram; -LLGLSLShader gSkinnedObjectFullbrightShinyProgram; -LLGLSLShader gSkinnedObjectShinySimpleProgram; - -LLGLSLShader gSkinnedObjectSimpleWaterProgram; -LLGLSLShader gSkinnedObjectFullbrightWaterProgram; -LLGLSLShader gSkinnedObjectEmissiveWaterProgram; -LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; -LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; //environment shaders LLGLSLShader gTerrainProgram; @@ -156,6 +151,7 @@ LLGLSLShader gUnderWaterProgram; //interface shaders LLGLSLShader gHighlightProgram; +LLGLSLShader gSkinnedHighlightProgram; LLGLSLShader gHighlightNormalProgram; LLGLSLShader gHighlightSpecularProgram; @@ -191,17 +187,18 @@ LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredUnderWaterProgram; LLGLSLShader gDeferredDiffuseProgram; LLGLSLShader gDeferredDiffuseAlphaMaskProgram; +LLGLSLShader gDeferredSkinnedDiffuseAlphaMaskProgram; LLGLSLShader gDeferredNonIndexedDiffuseProgram; LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; LLGLSLShader gDeferredSkinnedDiffuseProgram; LLGLSLShader gDeferredSkinnedBumpProgram; -LLGLSLShader gDeferredSkinnedAlphaProgram; LLGLSLShader gDeferredBumpProgram; LLGLSLShader gDeferredTerrainProgram; LLGLSLShader gDeferredTerrainWaterProgram; LLGLSLShader gDeferredTreeProgram; LLGLSLShader gDeferredTreeShadowProgram; +LLGLSLShader gDeferredSkinnedTreeShadowProgram; LLGLSLShader gDeferredAvatarProgram; LLGLSLShader gDeferredAvatarAlphaProgram; LLGLSLShader gDeferredLightProgram; @@ -213,9 +210,12 @@ LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; LLGLSLShader gDeferredSoftenWaterProgram; LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredSkinnedShadowProgram; LLGLSLShader gDeferredShadowCubeProgram; LLGLSLShader gDeferredShadowAlphaMaskProgram; +LLGLSLShader gDeferredSkinnedShadowAlphaMaskProgram; LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; +LLGLSLShader gDeferredSkinnedShadowFullbrightAlphaMaskProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAvatarAlphaShadowProgram; LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; @@ -223,14 +223,20 @@ LLGLSLShader gDeferredAttachmentShadowProgram; LLGLSLShader gDeferredAttachmentAlphaShadowProgram; LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram; LLGLSLShader gDeferredAlphaProgram; +LLGLSLShader gDeferredSkinnedAlphaProgram; LLGLSLShader gDeferredAlphaImpostorProgram; +LLGLSLShader gDeferredSkinnedAlphaImpostorProgram; LLGLSLShader gDeferredAlphaWaterProgram; +LLGLSLShader gDeferredSkinnedAlphaWaterProgram; LLGLSLShader gDeferredAvatarEyesProgram; LLGLSLShader gDeferredFullbrightProgram; LLGLSLShader gDeferredFullbrightAlphaMaskProgram; LLGLSLShader gDeferredFullbrightWaterProgram; +LLGLSLShader gDeferredSkinnedFullbrightWaterProgram; LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram; +LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskWaterProgram; LLGLSLShader gDeferredEmissiveProgram; +LLGLSLShader gDeferredSkinnedEmissiveProgram; LLGLSLShader gDeferredPostProgram; LLGLSLShader gDeferredCoFProgram; LLGLSLShader gDeferredDoFCombineProgram; @@ -243,14 +249,31 @@ LLGLSLShader gDeferredWLSunProgram; LLGLSLShader gDeferredWLMoonProgram; LLGLSLShader gDeferredStarProgram; LLGLSLShader gDeferredFullbrightShinyProgram; -LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; +LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; LLGLSLShader gDeferredSkinnedFullbrightProgram; +LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskProgram; LLGLSLShader gNormalMapGenProgram; // Deferred materials shaders LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2]; +//helper for making a rigged variant of a given shader +bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) +{ + riggedShader.mName = llformat("Skinned %s", shader.mName.c_str()); + riggedShader.mFeatures = shader.mFeatures; + riggedShader.mFeatures.hasObjectSkinning = true; + riggedShader.mDefines = shader.mDefines; // NOTE: Must come before addPermutation + riggedShader.addPermutation("HAS_SKIN", "1"); + riggedShader.mShaderFiles = shader.mShaderFiles; + riggedShader.mShaderLevel = shader.mShaderLevel; + riggedShader.mShaderGroup = shader.mShaderGroup; + + shader.mRiggedVariant = &riggedShader; + return riggedShader.createShader(NULL, NULL); +} + LLViewerShaderMgr::LLViewerShaderMgr() : mShaderLevel(SHADER_COUNT, 0), mMaxAvatarShaderLevel(0) @@ -263,75 +286,77 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gWLMoonProgram); mShaderList.push_back(&gAvatarProgram); mShaderList.push_back(&gObjectShinyProgram); - mShaderList.push_back(&gObjectShinyNonIndexedProgram); + mShaderList.push_back(&gSkinnedObjectShinyProgram); mShaderList.push_back(&gWaterProgram); mShaderList.push_back(&gWaterEdgeProgram); mShaderList.push_back(&gAvatarEyeballProgram); mShaderList.push_back(&gObjectSimpleProgram); + mShaderList.push_back(&gSkinnedObjectSimpleProgram); mShaderList.push_back(&gObjectSimpleImpostorProgram); + mShaderList.push_back(&gSkinnedObjectSimpleImpostorProgram); mShaderList.push_back(&gObjectPreviewProgram); mShaderList.push_back(&gImpostorProgram); mShaderList.push_back(&gObjectFullbrightNoColorProgram); mShaderList.push_back(&gObjectFullbrightNoColorWaterProgram); mShaderList.push_back(&gObjectSimpleAlphaMaskProgram); + mShaderList.push_back(&gSkinnedObjectSimpleAlphaMaskProgram); mShaderList.push_back(&gObjectBumpProgram); + mShaderList.push_back(&gSkinnedObjectBumpProgram); mShaderList.push_back(&gObjectEmissiveProgram); + mShaderList.push_back(&gSkinnedObjectEmissiveProgram); mShaderList.push_back(&gObjectEmissiveWaterProgram); + mShaderList.push_back(&gSkinnedObjectEmissiveWaterProgram); mShaderList.push_back(&gObjectFullbrightProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightProgram); mShaderList.push_back(&gObjectFullbrightAlphaMaskProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightAlphaMaskProgram); mShaderList.push_back(&gObjectFullbrightShinyProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram); mShaderList.push_back(&gObjectFullbrightShinyWaterProgram); - mShaderList.push_back(&gObjectSimpleNonIndexedProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightShinyWaterProgram); mShaderList.push_back(&gObjectSimpleNonIndexedTexGenProgram); mShaderList.push_back(&gObjectSimpleNonIndexedTexGenWaterProgram); - mShaderList.push_back(&gObjectSimpleNonIndexedWaterProgram); mShaderList.push_back(&gObjectAlphaMaskNonIndexedProgram); mShaderList.push_back(&gObjectAlphaMaskNonIndexedWaterProgram); mShaderList.push_back(&gObjectAlphaMaskNoColorProgram); mShaderList.push_back(&gObjectAlphaMaskNoColorWaterProgram); mShaderList.push_back(&gTreeProgram); mShaderList.push_back(&gTreeWaterProgram); - mShaderList.push_back(&gObjectFullbrightNonIndexedProgram); - mShaderList.push_back(&gObjectFullbrightNonIndexedWaterProgram); - mShaderList.push_back(&gObjectEmissiveNonIndexedProgram); - mShaderList.push_back(&gObjectEmissiveNonIndexedWaterProgram); - mShaderList.push_back(&gObjectFullbrightShinyNonIndexedProgram); - mShaderList.push_back(&gObjectFullbrightShinyNonIndexedWaterProgram); - mShaderList.push_back(&gSkinnedObjectSimpleProgram); - mShaderList.push_back(&gSkinnedObjectFullbrightProgram); - mShaderList.push_back(&gSkinnedObjectEmissiveProgram); - mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram); - mShaderList.push_back(&gSkinnedObjectShinySimpleProgram); - mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram); - mShaderList.push_back(&gSkinnedObjectFullbrightWaterProgram); - mShaderList.push_back(&gSkinnedObjectEmissiveWaterProgram); - mShaderList.push_back(&gSkinnedObjectFullbrightShinyWaterProgram); - mShaderList.push_back(&gSkinnedObjectShinySimpleWaterProgram); mShaderList.push_back(&gTerrainProgram); mShaderList.push_back(&gTerrainWaterProgram); mShaderList.push_back(&gObjectSimpleWaterProgram); + mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram); mShaderList.push_back(&gObjectFullbrightWaterProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightWaterProgram); mShaderList.push_back(&gObjectSimpleWaterAlphaMaskProgram); + mShaderList.push_back(&gSkinnedObjectSimpleWaterAlphaMaskProgram); mShaderList.push_back(&gObjectFullbrightWaterAlphaMaskProgram); + mShaderList.push_back(&gSkinnedObjectFullbrightWaterAlphaMaskProgram); mShaderList.push_back(&gAvatarWaterProgram); mShaderList.push_back(&gObjectShinyWaterProgram); - mShaderList.push_back(&gObjectShinyNonIndexedWaterProgram); + mShaderList.push_back(&gSkinnedObjectShinyWaterProgram); mShaderList.push_back(&gUnderWaterProgram); mShaderList.push_back(&gDeferredSunProgram); mShaderList.push_back(&gDeferredSoftenProgram); mShaderList.push_back(&gDeferredSoftenWaterProgram); mShaderList.push_back(&gDeferredAlphaProgram); + mShaderList.push_back(&gDeferredSkinnedAlphaProgram); mShaderList.push_back(&gDeferredAlphaImpostorProgram); + mShaderList.push_back(&gDeferredSkinnedAlphaImpostorProgram); mShaderList.push_back(&gDeferredAlphaWaterProgram); - mShaderList.push_back(&gDeferredSkinnedAlphaProgram); + mShaderList.push_back(&gDeferredSkinnedAlphaWaterProgram); mShaderList.push_back(&gDeferredFullbrightProgram); mShaderList.push_back(&gDeferredFullbrightAlphaMaskProgram); mShaderList.push_back(&gDeferredFullbrightWaterProgram); - mShaderList.push_back(&gDeferredFullbrightAlphaMaskWaterProgram); + mShaderList.push_back(&gDeferredSkinnedFullbrightWaterProgram); + mShaderList.push_back(&gDeferredFullbrightAlphaMaskWaterProgram); + mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskWaterProgram); mShaderList.push_back(&gDeferredFullbrightShinyProgram); - mShaderList.push_back(&gDeferredSkinnedFullbrightShinyProgram); + mShaderList.push_back(&gDeferredSkinnedFullbrightShinyProgram); mShaderList.push_back(&gDeferredSkinnedFullbrightProgram); + mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskProgram); mShaderList.push_back(&gDeferredEmissiveProgram); + mShaderList.push_back(&gDeferredSkinnedEmissiveProgram); mShaderList.push_back(&gDeferredAvatarEyesProgram); mShaderList.push_back(&gDeferredWaterProgram); mShaderList.push_back(&gDeferredUnderWaterProgram); @@ -384,7 +409,7 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) S32 LLViewerShaderMgr::getShaderLevel(S32 type) { - return LLPipeline::sDisableShaders ? 0 : mShaderLevel[type]; + return mShaderLevel[type]; } //============================================================================ @@ -400,15 +425,6 @@ void LLViewerShaderMgr::setShaders() return; } - if (!gGLManager.mHasShaderObjects - || !gGLManager.mHasVertexShader - || !gGLManager.mHasFragmentShader) - { - // Viewer will show 'hardware requirements' warning later - LL_INFOS("ShaderLoading") << "Shaders not supported" << LL_ENDL; - return; - } - static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) max_texture_index), 1); @@ -433,7 +449,7 @@ void LLViewerShaderMgr::setShaders() initAttribsAndUniforms(); gPipeline.releaseGLBuffers(); - LLPipeline::sWaterReflections = gGLManager.mHasCubeMap; + LLPipeline::sWaterReflections = gGLManager.mHasCubeMap && LLPipeline::sRenderTransparentWater; LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); LLPipeline::updateRenderDeferred(); @@ -458,7 +474,6 @@ void LLViewerShaderMgr::setShaders() } mMaxAvatarShaderLevel = 0; - LLGLSLShader::sNoFixedFunction = false; LLVertexBuffer::unbind(); llassert((gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10)); @@ -467,10 +482,7 @@ void LLViewerShaderMgr::setShaders() bool hasWindLightShaders = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"); S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); bool doingWindLight = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders"); - bool useRenderDeferred = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP"); - - //using shaders, disable fixed function - LLGLSLShader::sNoFixedFunction = true; + bool useRenderDeferred = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred"); S32 light_class = 3; S32 interface_class = 2; @@ -543,192 +555,168 @@ void LLViewerShaderMgr::setShaders() } else { - LL_WARNS() << "Failed to load basic shaders." << LL_ENDL; + LL_ERRS() << "Unable to load basic shaders, verify graphics driver installed and current." << LL_ENDL; llassert(loaded); + reentrance = false; // For hygiene only, re-try probably helps nothing + return; } + gPipeline.mShadersLoaded = true; + + // Load all shaders to set max levels + loaded = loadShadersEnvironment(); + if (loaded) { - gPipeline.mVertexShadersEnabled = TRUE; - gPipeline.mVertexShadersLoaded = 1; - - // Load all shaders to set max levels - loaded = loadShadersEnvironment(); + LL_INFOS() << "Loaded environment shaders." << LL_ENDL; + } + else + { + LL_WARNS() << "Failed to load environment shaders." << LL_ENDL; + llassert(loaded); + } + if (loaded) + { + loaded = loadShadersWater(); if (loaded) { - LL_INFOS() << "Loaded environment shaders." << LL_ENDL; + LL_INFOS() << "Loaded water shaders." << LL_ENDL; } else { - LL_WARNS() << "Failed to load environment shaders." << LL_ENDL; + LL_WARNS() << "Failed to load water shaders." << LL_ENDL; llassert(loaded); } + } + if (loaded) + { + loaded = loadShadersWindLight(); if (loaded) { - loaded = loadShadersWater(); - if (loaded) - { - LL_INFOS() << "Loaded water shaders." << LL_ENDL; - } - else - { - LL_WARNS() << "Failed to load water shaders." << LL_ENDL; - llassert(loaded); - } + LL_INFOS() << "Loaded windlight shaders." << LL_ENDL; } - - if (loaded) + else { - loaded = loadShadersWindLight(); - if (loaded) - { - LL_INFOS() << "Loaded windlight shaders." << LL_ENDL; - } - else - { - LL_WARNS() << "Failed to load windlight shaders." << LL_ENDL; - llassert(loaded); - } + LL_WARNS() << "Failed to load windlight shaders." << LL_ENDL; + llassert(loaded); } + } + if (loaded) + { + loaded = loadShadersEffects(); if (loaded) { - loaded = loadShadersEffects(); - if (loaded) - { - LL_INFOS() << "Loaded effects shaders." << LL_ENDL; - } - else - { - LL_WARNS() << "Failed to load effects shaders." << LL_ENDL; - llassert(loaded); - } + LL_INFOS() << "Loaded effects shaders." << LL_ENDL; } - - if (loaded) + else { - loaded = loadShadersInterface(); - if (loaded) - { - LL_INFOS() << "Loaded interface shaders." << LL_ENDL; - } - else - { - LL_WARNS() << "Failed to load interface shaders." << LL_ENDL; - llassert(loaded); - } + LL_WARNS() << "Failed to load effects shaders." << LL_ENDL; + llassert(loaded); } + } + if (loaded) + { + loaded = loadShadersInterface(); if (loaded) - { - loaded = loadTransformShaders(); - if (loaded) - { - LL_INFOS() << "Loaded transform shaders." << LL_ENDL; - } - else - { - LL_WARNS() << "Failed to load transform shaders." << LL_ENDL; - llassert(loaded); - } + LL_INFOS() << "Loaded interface shaders." << LL_ENDL; } + else + { + LL_WARNS() << "Failed to load interface shaders." << LL_ENDL; + llassert(loaded); + } + } + + if (loaded) + { + loaded = loadTransformShaders(); if (loaded) { - // Load max avatar shaders to set the max level - mShaderLevel[SHADER_AVATAR] = 3; - mMaxAvatarShaderLevel = 3; + LL_INFOS() << "Loaded transform shaders." << LL_ENDL; + } + else + { + LL_WARNS() << "Failed to load transform shaders." << LL_ENDL; + llassert(loaded); + } + } + + if (loaded) + { + // Load max avatar shaders to set the max level + mShaderLevel[SHADER_AVATAR] = 3; + mMaxAvatarShaderLevel = 3; - if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) - { //hardware skinning is enabled and rigged attachment shaders loaded correctly - BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); + if (loadShadersObject()) + { //hardware skinning is enabled and rigged attachment shaders loaded correctly + BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); - // cloth is a class3 shader - S32 avatar_class = avatar_cloth ? 3 : 1; + // cloth is a class3 shader + S32 avatar_class = avatar_cloth ? 3 : 1; - // Set the actual level - mShaderLevel[SHADER_AVATAR] = avatar_class; + // Set the actual level + mShaderLevel[SHADER_AVATAR] = avatar_class; - loaded = loadShadersAvatar(); - llassert(loaded); + loaded = loadShadersAvatar(); + llassert(loaded); - if (mShaderLevel[SHADER_AVATAR] != avatar_class) + if (mShaderLevel[SHADER_AVATAR] != avatar_class) + { + if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3) { - if (mShaderLevel[SHADER_AVATAR] == 0) - { - gSavedSettings.setBOOL("RenderAvatarVP", FALSE); - } - if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3) - { - avatar_cloth = true; - } - else - { - avatar_cloth = false; - } - gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); + avatar_cloth = true; } - } - else - { //hardware skinning not possible, neither is deferred rendering - mShaderLevel[SHADER_AVATAR] = 0; - mShaderLevel[SHADER_DEFERRED] = 0; - - if (gSavedSettings.getBOOL("RenderAvatarVP")) + else { - gSavedSettings.setBOOL("RenderDeferred", FALSE); - gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); - gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + avatar_cloth = false; } - - loadShadersAvatar(); // unloads - - loaded = loadShadersObject(); - llassert(loaded); + gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth); } } + else + { //hardware skinning not possible, neither is deferred rendering + mShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_DEFERRED] = 0; - if (!loaded) - { //some shader absolutely could not load, try to fall back to a simpler setting - if (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) - { //disable windlight and try again - gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE); - LL_WARNS() << "Falling back to no windlight shaders." << LL_ENDL; - reentrance = false; - setShaders(); - return; - } - } + gSavedSettings.setBOOL("RenderDeferred", FALSE); + gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); - llassert(loaded); + loadShadersAvatar(); // unloads + + loaded = loadShadersObject(); + llassert(loaded); + } + } - if (loaded && !loadShadersDeferred()) - { //everything else succeeded but deferred failed, disable deferred and try again - gSavedSettings.setBOOL("RenderDeferred", FALSE); - LL_WARNS() << "Falling back to no deferred shaders." << LL_ENDL; + if (!loaded) + { //some shader absolutely could not load, try to fall back to a simpler setting + if (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) + { //disable windlight and try again + gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE); + LL_WARNS() << "Falling back to no windlight shaders." << LL_ENDL; reentrance = false; setShaders(); return; } + } + + llassert(loaded); + + if (loaded && !loadShadersDeferred()) + { //everything else succeeded but deferred failed, disable deferred and try again + gSavedSettings.setBOOL("RenderDeferred", FALSE); + LL_WARNS() << "Falling back to no deferred shaders." << LL_ENDL; + reentrance = false; + setShaders(); + return; } - else - { - LLGLSLShader::sNoFixedFunction = false; - gPipeline.mVertexShadersEnabled = FALSE; - gPipeline.mVertexShadersLoaded = 0; - mShaderLevel[SHADER_LIGHTING] = 0; - mShaderLevel[SHADER_INTERFACE] = 0; - mShaderLevel[SHADER_ENVIRONMENT] = 0; - mShaderLevel[SHADER_WATER] = 0; - mShaderLevel[SHADER_OBJECT] = 0; - mShaderLevel[SHADER_EFFECT] = 0; - mShaderLevel[SHADER_WINDLIGHT] = 0; - mShaderLevel[SHADER_AVATAR] = 0; - } - + if (gViewerWindow) { gViewerWindow->setCursor(UI_CURSOR_ARROW); @@ -741,8 +729,10 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { gOcclusionProgram.unload(); + gSkinnedOcclusionProgram.unload(); gOcclusionCubeProgram.unload(); gDebugProgram.unload(); + gSkinnedDebugProgram.unload(); gClipProgram.unload(); gDownsampleDepthProgram.unload(); gDownsampleDepthRectProgram.unload(); @@ -764,58 +754,50 @@ void LLViewerShaderMgr::unloadShaders() gObjectFullbrightNoColorProgram.unload(); gObjectFullbrightNoColorWaterProgram.unload(); gObjectSimpleProgram.unload(); + gSkinnedObjectSimpleProgram.unload(); gObjectSimpleImpostorProgram.unload(); + gSkinnedObjectSimpleImpostorProgram.unload(); gObjectPreviewProgram.unload(); gImpostorProgram.unload(); gObjectSimpleAlphaMaskProgram.unload(); + gSkinnedObjectSimpleAlphaMaskProgram.unload(); gObjectBumpProgram.unload(); + gSkinnedObjectBumpProgram.unload(); gObjectSimpleWaterProgram.unload(); + gSkinnedObjectSimpleWaterProgram.unload(); gObjectSimpleWaterAlphaMaskProgram.unload(); + gSkinnedObjectSimpleWaterAlphaMaskProgram.unload(); gObjectFullbrightProgram.unload(); + gSkinnedObjectFullbrightProgram.unload(); gObjectFullbrightWaterProgram.unload(); + gSkinnedObjectFullbrightWaterProgram.unload(); gObjectEmissiveProgram.unload(); + gSkinnedObjectEmissiveProgram.unload(); gObjectEmissiveWaterProgram.unload(); + gSkinnedObjectEmissiveWaterProgram.unload(); gObjectFullbrightAlphaMaskProgram.unload(); + gSkinnedObjectFullbrightAlphaMaskProgram.unload(); gObjectFullbrightWaterAlphaMaskProgram.unload(); + gSkinnedObjectFullbrightWaterAlphaMaskProgram.unload(); gObjectShinyProgram.unload(); + gSkinnedObjectShinyProgram.unload(); gObjectFullbrightShinyProgram.unload(); + gSkinnedObjectFullbrightShinyProgram.unload(); gObjectFullbrightShinyWaterProgram.unload(); + gSkinnedObjectFullbrightShinyWaterProgram.unload(); gObjectShinyWaterProgram.unload(); + gSkinnedObjectShinyWaterProgram.unload(); - gObjectSimpleNonIndexedProgram.unload(); gObjectSimpleNonIndexedTexGenProgram.unload(); gObjectSimpleNonIndexedTexGenWaterProgram.unload(); - gObjectSimpleNonIndexedWaterProgram.unload(); gObjectAlphaMaskNonIndexedProgram.unload(); gObjectAlphaMaskNonIndexedWaterProgram.unload(); gObjectAlphaMaskNoColorProgram.unload(); gObjectAlphaMaskNoColorWaterProgram.unload(); - gObjectFullbrightNonIndexedProgram.unload(); - gObjectFullbrightNonIndexedWaterProgram.unload(); - gObjectEmissiveNonIndexedProgram.unload(); - gObjectEmissiveNonIndexedWaterProgram.unload(); gTreeProgram.unload(); gTreeWaterProgram.unload(); - gObjectShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedWaterProgram.unload(); - gObjectShinyNonIndexedWaterProgram.unload(); - - gSkinnedObjectSimpleProgram.unload(); - gSkinnedObjectFullbrightProgram.unload(); - gSkinnedObjectEmissiveProgram.unload(); - gSkinnedObjectFullbrightShinyProgram.unload(); - gSkinnedObjectShinySimpleProgram.unload(); - - gSkinnedObjectSimpleWaterProgram.unload(); - gSkinnedObjectFullbrightWaterProgram.unload(); - gSkinnedObjectEmissiveWaterProgram.unload(); - gSkinnedObjectFullbrightShinyWaterProgram.unload(); - gSkinnedObjectShinySimpleWaterProgram.unload(); - - gWaterProgram.unload(); gWaterEdgeProgram.unload(); gUnderWaterProgram.unload(); @@ -828,6 +810,7 @@ void LLViewerShaderMgr::unloadShaders() gAvatarEyeballProgram.unload(); gAvatarPickProgram.unload(); gHighlightProgram.unload(); + gSkinnedHighlightProgram.unload(); gHighlightNormalProgram.unload(); gHighlightSpecularProgram.unload(); @@ -841,13 +824,13 @@ void LLViewerShaderMgr::unloadShaders() gDeferredDiffuseProgram.unload(); gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredSkinnedDiffuseAlphaMaskProgram.unload(); gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); gDeferredNonIndexedDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); gDeferredSkinnedBumpProgram.unload(); - gDeferredSkinnedAlphaProgram.unload(); - + gTransformPositionProgram.unload(); gTransformTexCoordProgram.unload(); gTransformNormalProgram.unload(); @@ -864,7 +847,7 @@ void LLViewerShaderMgr::unloadShaders() mShaderLevel[SHADER_WINDLIGHT] = 0; mShaderLevel[SHADER_TRANSFORM] = 0; - gPipeline.mVertexShadersLoaded = 0; + gPipeline.mShadersLoaded = false; } BOOL LLViewerShaderMgr::loadBasicShaders() @@ -924,7 +907,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() } shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); - boost::unordered_map<std::string, std::string> attribs; + std::unordered_map<std::string, std::string> attribs; attribs["MAX_JOINTS_PER_MESH_OBJECT"] = boost::lexical_cast<std::string>(LLSkinningUtil::getMaxJointCount()); @@ -1236,14 +1219,15 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredTreeProgram.unload(); gDeferredTreeShadowProgram.unload(); + gDeferredSkinnedTreeShadowProgram.unload(); gDeferredDiffuseProgram.unload(); gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredSkinnedDiffuseAlphaMaskProgram.unload(); gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); gDeferredNonIndexedDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); gDeferredSkinnedBumpProgram.unload(); - gDeferredSkinnedAlphaProgram.unload(); gDeferredBumpProgram.unload(); gDeferredImpostorProgram.unload(); gDeferredTerrainProgram.unload(); @@ -1260,9 +1244,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.unload(); gDeferredSoftenWaterProgram.unload(); gDeferredShadowProgram.unload(); + gDeferredSkinnedShadowProgram.unload(); gDeferredShadowCubeProgram.unload(); gDeferredShadowAlphaMaskProgram.unload(); + gDeferredSkinnedShadowAlphaMaskProgram.unload(); gDeferredShadowFullbrightAlphaMaskProgram.unload(); + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.unload(); gDeferredAvatarShadowProgram.unload(); gDeferredAvatarAlphaShadowProgram.unload(); gDeferredAvatarAlphaMaskShadowProgram.unload(); @@ -1272,12 +1259,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarProgram.unload(); gDeferredAvatarAlphaProgram.unload(); gDeferredAlphaProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); gDeferredAlphaWaterProgram.unload(); + gDeferredSkinnedAlphaWaterProgram.unload(); gDeferredFullbrightProgram.unload(); gDeferredFullbrightAlphaMaskProgram.unload(); gDeferredFullbrightWaterProgram.unload(); + gDeferredSkinnedFullbrightWaterProgram.unload(); gDeferredFullbrightAlphaMaskWaterProgram.unload(); + gDeferredSkinnedFullbrightAlphaMaskWaterProgram.unload(); gDeferredEmissiveProgram.unload(); + gDeferredSkinnedEmissiveProgram.unload(); gDeferredAvatarEyesProgram.unload(); gDeferredPostProgram.unload(); gDeferredCoFProgram.unload(); @@ -1292,8 +1284,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLMoonProgram.unload(); gDeferredStarProgram.unload(); gDeferredFullbrightShinyProgram.unload(); - gDeferredSkinnedFullbrightShinyProgram.unload(); + gDeferredSkinnedFullbrightShinyProgram.unload(); gDeferredSkinnedFullbrightProgram.unload(); + gDeferredSkinnedFullbrightAlphaMaskProgram.unload(); gDeferredHighlightProgram.unload(); gDeferredHighlightNormalProgram.unload(); @@ -1350,7 +1343,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredDiffuseProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredDiffuseProgram, gDeferredSkinnedDiffuseProgram); + success = success && gDeferredDiffuseProgram.createShader(NULL, NULL); } if (success) @@ -1362,7 +1356,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredDiffuseAlphaMaskProgram, gDeferredSkinnedDiffuseAlphaMaskProgram); + success = success && gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); } if (success) @@ -1404,94 +1399,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { - gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader"; - gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true; - gDeferredSkinnedDiffuseProgram.mFeatures.encodesNormal = true; - gDeferredSkinnedDiffuseProgram.mFeatures.hasSrgb = true; - gDeferredSkinnedDiffuseProgram.mShaderFiles.clear(); - gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; - gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; - gDeferredSkinnedBumpProgram.mFeatures.encodesNormal = true; - gDeferredSkinnedBumpProgram.mShaderFiles.clear(); - gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; - gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; - gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false; - gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false; - gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true; - gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasSrgb = true; - gDeferredSkinnedAlphaProgram.mFeatures.encodesNormal = true; - gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasTransport = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasShadows = true; - - gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); - gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - - gDeferredSkinnedAlphaProgram.clearPermutations(); - gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); - gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1"); - gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1"); - - if (use_sun_shadow) - { - gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", "1"); - } - - if (ambient_kill) - { - gDeferredSkinnedAlphaProgram.addPermutation("AMBIENT_KILL", "1"); - } - - if (sunlight_kill) - { - gDeferredSkinnedAlphaProgram.addPermutation("SUNLIGHT_KILL", "1"); - } - - if (local_light_kill) - { - gDeferredSkinnedAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1"); - } - - success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); - llassert(success); - - // Hack to include uniforms for lighting without linking in lighting file - gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; - gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; - } - - if (success) - { gDeferredBumpProgram.mName = "Deferred Bump Shader"; gDeferredBumpProgram.mFeatures.encodesNormal = true; gDeferredBumpProgram.mShaderFiles.clear(); gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredBumpProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredBumpProgram, gDeferredSkinnedBumpProgram); + success = success && gDeferredBumpProgram.createShader(NULL, NULL); llassert(success); } @@ -1579,6 +1494,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1"); gDeferredMaterialProgram[i].mFeatures.hasObjectSkinning = true; } + else + { + gDeferredMaterialProgram[i].mRiggedVariant = &gDeferredMaterialProgram[i + 0x10]; + } success = gDeferredMaterialProgram[i].createShader(NULL, NULL); llassert(success); @@ -1624,6 +1543,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN", "1"); } + else + { + gDeferredMaterialWaterProgram[i].mRiggedVariant = &(gDeferredMaterialWaterProgram[i + 0x10]); + } gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1"); if (ambient_kill) @@ -1700,10 +1623,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredTreeShadowProgram.mRiggedVariant = &gDeferredSkinnedTreeShadowProgram; success = gDeferredTreeShadowProgram.createShader(NULL, NULL); llassert(success); } + if (success) + { + gDeferredSkinnedTreeShadowProgram.mName = "Deferred Skinned Tree Shadow Shader"; + gDeferredSkinnedTreeShadowProgram.mShaderFiles.clear(); + gDeferredSkinnedTreeShadowProgram.mFeatures.isDeferred = true; + gDeferredSkinnedTreeShadowProgram.mFeatures.hasShadows = true; + gDeferredSkinnedTreeShadowProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedTreeShadowProgram.createShader(NULL, NULL); + llassert(success); + } + if (success) { gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; @@ -1892,172 +1830,235 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { - gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; - - gDeferredAlphaProgram.mFeatures.calculatesLighting = false; - gDeferredAlphaProgram.mFeatures.hasLighting = false; - gDeferredAlphaProgram.mFeatures.isAlphaLighting = true; - gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredAlphaProgram.mFeatures.hasSrgb = true; - gDeferredAlphaProgram.mFeatures.encodesNormal = true; - gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; - gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; - gDeferredAlphaProgram.mFeatures.hasGamma = true; - gDeferredAlphaProgram.mFeatures.hasTransport = true; - gDeferredAlphaProgram.mFeatures.hasShadows = use_sun_shadow; - - if (mShaderLevel[SHADER_DEFERRED] < 1) + for (int i = 0; i < 2 && success; ++i) { - gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - } - else - { //shave off some texture units for shadow maps - gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); - } - - gDeferredAlphaProgram.mShaderFiles.clear(); - gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - - gDeferredAlphaProgram.clearPermutations(); - gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1"); - gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1"); - if (use_sun_shadow) - { - gDeferredAlphaProgram.addPermutation("HAS_SHADOW", "1"); - } + LLGLSLShader* shader = nullptr; + bool rigged = i == 1; + if (!rigged) + { + shader = &gDeferredAlphaProgram; + shader->mName = "Deferred Alpha Shader"; + shader->mRiggedVariant = &gDeferredSkinnedAlphaProgram; + } + else + { + shader = &gDeferredSkinnedAlphaProgram; + shader->mName = "Skinned Deferred Alpha Shader"; + shader->mFeatures.hasObjectSkinning = true; + } - if (ambient_kill) - { - gDeferredAlphaProgram.addPermutation("AMBIENT_KILL", "1"); - } + shader->mFeatures.calculatesLighting = false; + shader->mFeatures.hasLighting = false; + shader->mFeatures.isAlphaLighting = true; + shader->mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + shader->mFeatures.hasSrgb = true; + shader->mFeatures.encodesNormal = true; + shader->mFeatures.calculatesAtmospherics = true; + shader->mFeatures.hasAtmospherics = true; + shader->mFeatures.hasGamma = true; + shader->mFeatures.hasTransport = true; + shader->mFeatures.hasShadows = use_sun_shadow; + + if (mShaderLevel[SHADER_DEFERRED] < 1) + { + shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + } + else + { //shave off some texture units for shadow maps + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); + } - if (sunlight_kill) - { - gDeferredAlphaProgram.addPermutation("SUNLIGHT_KILL", "1"); - } + shader->mShaderFiles.clear(); + shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - if (local_light_kill) - { - gDeferredAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1"); - } + shader->clearPermutations(); + shader->addPermutation("USE_VERTEX_COLOR", "1"); + shader->addPermutation("USE_INDEXED_TEX", "1"); + if (use_sun_shadow) + { + shader->addPermutation("HAS_SHADOW", "1"); + } - gDeferredAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (ambient_kill) + { + shader->addPermutation("AMBIENT_KILL", "1"); + } - success = gDeferredAlphaProgram.createShader(NULL, NULL); - llassert(success); + if (sunlight_kill) + { + shader->addPermutation("SUNLIGHT_KILL", "1"); + } + + if (local_light_kill) + { + shader->addPermutation("LOCAL_LIGHT_KILL", "1"); + } + + if (rigged) + { + shader->addPermutation("HAS_SKIN", "1"); + } + + shader->mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - // Hack - gDeferredAlphaProgram.mFeatures.calculatesLighting = true; - gDeferredAlphaProgram.mFeatures.hasLighting = true; + success = shader->createShader(NULL, NULL); + llassert(success); + + // Hack + shader->mFeatures.calculatesLighting = true; + shader->mFeatures.hasLighting = true; + } } if (success) { - gDeferredAlphaImpostorProgram.mName = "Deferred Alpha Impostor Shader"; + LLGLSLShader* shaders[] = { + &gDeferredAlphaImpostorProgram, + &gDeferredSkinnedAlphaImpostorProgram + }; -// Begin Hack - gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = false; - gDeferredAlphaImpostorProgram.mFeatures.hasLighting = false; + for (int i = 0; i < 2 && success; ++i) + { + bool rigged = i == 1; + LLGLSLShader* shader = shaders[i]; - gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true; - gDeferredAlphaImpostorProgram.mFeatures.isAlphaLighting = true; - gDeferredAlphaImpostorProgram.mFeatures.encodesNormal = true; - gDeferredAlphaImpostorProgram.mFeatures.hasShadows = use_sun_shadow; + shader->mName = rigged ? "Skinned Deferred Alpha Impostor Shader" : "Deferred Alpha Impostor Shader"; - if (mShaderLevel[SHADER_DEFERRED] < 1) - { - gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - } - else - { //shave off some texture units for shadow maps - gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); - } + // Begin Hack + shader->mFeatures.calculatesLighting = false; + shader->mFeatures.hasLighting = false; - gDeferredAlphaImpostorProgram.mShaderFiles.clear(); - gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + shader->mFeatures.hasSrgb = true; + shader->mFeatures.isAlphaLighting = true; + shader->mFeatures.encodesNormal = true; + shader->mFeatures.hasShadows = use_sun_shadow; - gDeferredAlphaImpostorProgram.clearPermutations(); - gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1"); - gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1"); - gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1"); + if (mShaderLevel[SHADER_DEFERRED] < 1) + { + shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + } + else + { //shave off some texture units for shadow maps + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); + } - if (use_sun_shadow) - { - gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", "1"); - } + shader->mShaderFiles.clear(); + shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredAlphaImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + shader->clearPermutations(); + shader->addPermutation("USE_INDEXED_TEX", "1"); + shader->addPermutation("FOR_IMPOSTOR", "1"); + shader->addPermutation("USE_VERTEX_COLOR", "1"); + if (rigged) + { + shader->mFeatures.hasObjectSkinning = true; + shader->addPermutation("HAS_SKIN", "1"); + } - success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL); - llassert(success); + if (use_sun_shadow) + { + shader->addPermutation("HAS_SHADOW", "1"); + } + + shader->mRiggedVariant = &gDeferredSkinnedAlphaImpostorProgram; + shader->mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (!rigged) + { + shader->mRiggedVariant = shaders[1]; + } + success = shader->createShader(NULL, NULL); + llassert(success); -// End Hack - gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = true; - gDeferredAlphaImpostorProgram.mFeatures.hasLighting = true; + // End Hack + shader->mFeatures.calculatesLighting = true; + shader->mFeatures.hasLighting = true; + } } - if (success) - { - gDeferredAlphaWaterProgram.mName = "Deferred Alpha Underwater Shader"; - gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = false; - gDeferredAlphaWaterProgram.mFeatures.hasLighting = false; - gDeferredAlphaWaterProgram.mFeatures.isAlphaLighting = true; - gDeferredAlphaWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredAlphaWaterProgram.mFeatures.hasWaterFog = true; - gDeferredAlphaWaterProgram.mFeatures.hasSrgb = true; - gDeferredAlphaWaterProgram.mFeatures.encodesNormal = true; - gDeferredAlphaWaterProgram.mFeatures.calculatesAtmospherics = true; - gDeferredAlphaWaterProgram.mFeatures.hasAtmospherics = true; - gDeferredAlphaWaterProgram.mFeatures.hasGamma = true; - gDeferredAlphaWaterProgram.mFeatures.hasTransport = true; - gDeferredAlphaWaterProgram.mFeatures.hasShadows = use_sun_shadow; - - if (mShaderLevel[SHADER_DEFERRED] < 1) - { - gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - } - else - { //shave off some texture units for shadow maps - gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); - } - gDeferredAlphaWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gDeferredAlphaWaterProgram.mShaderFiles.clear(); - gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); - - gDeferredAlphaWaterProgram.clearPermutations(); - gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1"); - gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1"); - gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1"); - if (use_sun_shadow) - { - gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", "1"); - } + if (success) + { + LLGLSLShader* shader[] = { + &gDeferredAlphaWaterProgram, + &gDeferredSkinnedAlphaWaterProgram + }; + + gDeferredAlphaWaterProgram.mRiggedVariant = &gDeferredSkinnedAlphaWaterProgram; + + gDeferredAlphaWaterProgram.mName = "Deferred Alpha Underwater Shader"; + gDeferredSkinnedAlphaWaterProgram.mName = "Deferred Skinned Alpha Underwater Shader"; - if (ambient_kill) + for (int i = 0; i < 2 && success; ++i) { - gDeferredAlphaWaterProgram.addPermutation("AMBIENT_KILL", "1"); - } + shader[i]->mFeatures.calculatesLighting = false; + shader[i]->mFeatures.hasLighting = false; + shader[i]->mFeatures.isAlphaLighting = true; + shader[i]->mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + shader[i]->mFeatures.hasWaterFog = true; + shader[i]->mFeatures.hasSrgb = true; + shader[i]->mFeatures.encodesNormal = true; + shader[i]->mFeatures.calculatesAtmospherics = true; + shader[i]->mFeatures.hasAtmospherics = true; + shader[i]->mFeatures.hasGamma = true; + shader[i]->mFeatures.hasTransport = true; + shader[i]->mFeatures.hasShadows = use_sun_shadow; + + if (mShaderLevel[SHADER_DEFERRED] < 1) + { + shader[i]->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + } + else + { //shave off some texture units for shadow maps + shader[i]->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1); + } + shader[i]->mShaderGroup = LLGLSLShader::SG_WATER; + shader[i]->mShaderFiles.clear(); + shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + + shader[i]->clearPermutations(); + shader[i]->addPermutation("USE_INDEXED_TEX", "1"); + shader[i]->addPermutation("WATER_FOG", "1"); + shader[i]->addPermutation("USE_VERTEX_COLOR", "1"); + if (use_sun_shadow) + { + shader[i]->addPermutation("HAS_SHADOW", "1"); + } - if (sunlight_kill) - { - gDeferredAlphaWaterProgram.addPermutation("SUNLIGHT_KILL", "1"); - } + if (ambient_kill) + { + shader[i]->addPermutation("AMBIENT_KILL", "1"); + } - if (local_light_kill) - { - gDeferredAlphaWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1"); - } - gDeferredAlphaWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (sunlight_kill) + { + shader[i]->addPermutation("SUNLIGHT_KILL", "1"); + } - success = gDeferredAlphaWaterProgram.createShader(NULL, NULL); - llassert(success); + if (local_light_kill) + { + shader[i]->addPermutation("LOCAL_LIGHT_KILL", "1"); + } - // Hack - gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = true; - gDeferredAlphaWaterProgram.mFeatures.hasLighting = true; + if (i == 1) + { // rigged variant + shader[i]->mFeatures.hasObjectSkinning = true; + shader[i]->addPermutation("HAS_SKIN", "1"); + } + else + { + shader[i]->mRiggedVariant = shader[1]; + } + shader[i]->mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + + success = shader[i]->createShader(NULL, NULL); + llassert(success); + + // Hack + shader[i]->mFeatures.calculatesLighting = true; + shader[i]->mFeatures.hasLighting = true; + } } if (success) @@ -2091,6 +2092,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = make_rigged_variant(gDeferredFullbrightProgram, gDeferredSkinnedFullbrightProgram); success = gDeferredFullbrightProgram.createShader(NULL, NULL); llassert(success); } @@ -2108,7 +2110,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1"); gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredFullbrightAlphaMaskProgram, gDeferredSkinnedFullbrightAlphaMaskProgram); + success = success && gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } @@ -2127,10 +2130,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1"); - success = gDeferredFullbrightWaterProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredFullbrightWaterProgram, gDeferredSkinnedFullbrightWaterProgram); + success = success && gDeferredFullbrightWaterProgram.createShader(NULL, NULL); llassert(success); } - + if (success) { gDeferredFullbrightAlphaMaskWaterProgram.mName = "Deferred Fullbright Underwater Alpha Masking Shader"; @@ -2147,7 +2151,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1"); gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("WATER_FOG","1"); - success = gDeferredFullbrightAlphaMaskWaterProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredFullbrightAlphaMaskWaterProgram, gDeferredSkinnedFullbrightAlphaMaskWaterProgram); + success = success && gDeferredFullbrightAlphaMaskWaterProgram.createShader(NULL, NULL); llassert(success); } @@ -2164,43 +2169,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredFullbrightShinyProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredSkinnedFullbrightProgram.mName = "Skinned Fullbright Shader"; - gDeferredSkinnedFullbrightProgram.mFeatures.calculatesAtmospherics = true; - gDeferredSkinnedFullbrightProgram.mFeatures.hasAtmospherics = true; - gDeferredSkinnedFullbrightProgram.mFeatures.hasGamma = true; - gDeferredSkinnedFullbrightProgram.mFeatures.hasTransport = true; - gDeferredSkinnedFullbrightProgram.mFeatures.hasObjectSkinning = true; - gDeferredSkinnedFullbrightProgram.mFeatures.disableTextureIndex = true; - gDeferredSkinnedFullbrightProgram.mFeatures.hasSrgb = true; - gDeferredSkinnedFullbrightProgram.mShaderFiles.clear(); - gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gDeferredSkinnedFullbrightProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredSkinnedFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasAtmospherics = true; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasGamma = true; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasTransport = true; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.disableTextureIndex = true; - gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasSrgb = true; - gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.clear(); - gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gDeferredSkinnedFullbrightShinyProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram); + success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL); llassert(success); } @@ -2215,7 +2185,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredEmissiveProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDeferredEmissiveProgram, gDeferredSkinnedEmissiveProgram); + success = success && gDeferredEmissiveProgram.createShader(NULL, NULL); llassert(success); } @@ -2358,10 +2329,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1"); } + gDeferredShadowProgram.mRiggedVariant = &gDeferredSkinnedShadowProgram; success = gDeferredShadowProgram.createShader(NULL, NULL); llassert(success); } + if (success) + { + gDeferredSkinnedShadowProgram.mName = "Deferred Skinned Shadow Shader"; + gDeferredSkinnedShadowProgram.mFeatures.isDeferred = true; + gDeferredSkinnedShadowProgram.mFeatures.hasShadows = true; + gDeferredSkinnedShadowProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedShadowProgram.mShaderFiles.clear(); + gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (gGLManager.mHasDepthClamp) + { + gDeferredSkinnedShadowProgram.addPermutation("DEPTH_CLAMP", "1"); + } + success = gDeferredSkinnedShadowProgram.createShader(NULL, NULL); + llassert(success); + } + if (success) { gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; @@ -2395,11 +2385,32 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1"); gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredShadowFullbrightAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowFullbrightAlphaMaskProgram; success = gDeferredShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } if (success) + { + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mName = "Deferred Skinned Shadow Fullbright Alpha Mask Shader"; + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.clearPermutations(); + if (gGLManager.mHasDepthClamp) + { + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1"); + } + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1"); + gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) { gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; @@ -2412,10 +2423,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1"); } gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredShadowAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowAlphaMaskProgram; success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL); llassert(success); } + if (success) + { + gDeferredSkinnedShadowAlphaMaskProgram.mName = "Deferred Skinned Shadow Alpha Mask Shader"; + gDeferredSkinnedShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredSkinnedShadowAlphaMaskProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.clear(); + gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + if (gGLManager.mHasDepthClamp) + { + gDeferredSkinnedShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1"); + } + gDeferredSkinnedShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedShadowAlphaMaskProgram.createShader(NULL, NULL); + llassert(success); + } + if (success) { gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; @@ -2791,79 +2820,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() BOOL LLViewerShaderMgr::loadShadersObject() { BOOL success = TRUE; - - if (mShaderLevel[SHADER_OBJECT] == 0) - { - gObjectShinyProgram.unload(); - gObjectFullbrightShinyProgram.unload(); - gObjectFullbrightShinyWaterProgram.unload(); - gObjectShinyWaterProgram.unload(); - gObjectFullbrightNoColorProgram.unload(); - gObjectFullbrightNoColorWaterProgram.unload(); - gObjectSimpleProgram.unload(); - gObjectSimpleImpostorProgram.unload(); - gObjectPreviewProgram.unload(); - gImpostorProgram.unload(); - gObjectSimpleAlphaMaskProgram.unload(); - gObjectBumpProgram.unload(); - gObjectSimpleWaterProgram.unload(); - gObjectSimpleWaterAlphaMaskProgram.unload(); - gObjectEmissiveProgram.unload(); - gObjectEmissiveWaterProgram.unload(); - gObjectFullbrightProgram.unload(); - gObjectFullbrightAlphaMaskProgram.unload(); - gObjectFullbrightWaterProgram.unload(); - gObjectFullbrightWaterAlphaMaskProgram.unload(); - gObjectShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedProgram.unload(); - gObjectFullbrightShinyNonIndexedWaterProgram.unload(); - gObjectShinyNonIndexedWaterProgram.unload(); - gObjectSimpleNonIndexedTexGenProgram.unload(); - gObjectSimpleNonIndexedTexGenWaterProgram.unload(); - gObjectSimpleNonIndexedWaterProgram.unload(); - gObjectAlphaMaskNonIndexedProgram.unload(); - gObjectAlphaMaskNonIndexedWaterProgram.unload(); - gObjectAlphaMaskNoColorProgram.unload(); - gObjectAlphaMaskNoColorWaterProgram.unload(); - gObjectFullbrightNonIndexedProgram.unload(); - gObjectFullbrightNonIndexedWaterProgram.unload(); - gObjectEmissiveNonIndexedProgram.unload(); - gObjectEmissiveNonIndexedWaterProgram.unload(); - gSkinnedObjectSimpleProgram.unload(); - gSkinnedObjectFullbrightProgram.unload(); - gSkinnedObjectEmissiveProgram.unload(); - gSkinnedObjectFullbrightShinyProgram.unload(); - gSkinnedObjectShinySimpleProgram.unload(); - gSkinnedObjectSimpleWaterProgram.unload(); - gSkinnedObjectFullbrightWaterProgram.unload(); - gSkinnedObjectEmissiveWaterProgram.unload(); - gSkinnedObjectFullbrightShinyWaterProgram.unload(); - gSkinnedObjectShinySimpleWaterProgram.unload(); - gTreeProgram.unload(); - gTreeWaterProgram.unload(); - - return TRUE; - } if (success) { - gObjectSimpleNonIndexedProgram.mName = "Non indexed Shader"; - gObjectSimpleNonIndexedProgram.mFeatures.calculatesLighting = true; - gObjectSimpleNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true; - gObjectSimpleNonIndexedProgram.mFeatures.hasAlphaMask = true; // Fix for MAINT-8836 - gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectSimpleNonIndexedProgram.mShaderFiles.clear(); - gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { gObjectSimpleNonIndexedTexGenProgram.mName = "Non indexed tex-gen Shader"; gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesLighting = true; gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesAtmospherics = true; @@ -2878,24 +2837,6 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL); } - - if (success) - { - gObjectSimpleNonIndexedWaterProgram.mName = "Non indexed Water Shader"; - gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesLighting = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.hasLighting = true; - gObjectSimpleNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL); - } - if (success) { gObjectSimpleNonIndexedTexGenWaterProgram.mName = "Non indexed tex-gen Water Shader"; @@ -3020,70 +2961,6 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { - gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader"; - gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true; - gObjectFullbrightNonIndexedProgram.mFeatures.hasTransport = true; - gObjectFullbrightNonIndexedProgram.mFeatures.isFullbright = true; - gObjectFullbrightNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightNonIndexedProgram.mShaderFiles.clear(); - gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightNonIndexedWaterProgram.mName = "Non Indexed Fullbright Water Shader"; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasSrgb = true; - gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectEmissiveNonIndexedProgram.mName = "Non Indexed Emissive Shader"; - gObjectEmissiveNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectEmissiveNonIndexedProgram.mFeatures.hasGamma = true; - gObjectEmissiveNonIndexedProgram.mFeatures.hasTransport = true; - gObjectEmissiveNonIndexedProgram.mFeatures.isFullbright = true; - gObjectEmissiveNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectEmissiveNonIndexedProgram.mFeatures.hasSrgb = true; - gObjectEmissiveNonIndexedProgram.mShaderFiles.clear(); - gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectEmissiveNonIndexedWaterProgram.mName = "Non Indexed Emissive Water Shader"; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.isFullbright = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasTransport = true; - gObjectEmissiveNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { gObjectFullbrightNoColorProgram.mName = "Non Indexed no color Fullbright Shader"; gObjectFullbrightNoColorProgram.mFeatures.calculatesAtmospherics = true; gObjectFullbrightNoColorProgram.mFeatures.hasGamma = true; @@ -3116,73 +2993,6 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { - gObjectShinyNonIndexedProgram.mName = "Non Indexed Shiny Shader"; - gObjectShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectShinyNonIndexedProgram.mFeatures.calculatesLighting = true; - gObjectShinyNonIndexedProgram.mFeatures.hasGamma = true; - gObjectShinyNonIndexedProgram.mFeatures.hasAtmospherics = true; - gObjectShinyNonIndexedProgram.mFeatures.isShiny = true; - gObjectShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectShinyNonIndexedProgram.mShaderFiles.clear(); - gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectShinyNonIndexedWaterProgram.mName = "Non Indexed Shiny Water Shader"; - gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesLighting = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.isShiny = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; - gObjectShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader"; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.isFullbright = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.isShiny = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasGamma = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasTransport = true; - gObjectFullbrightShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear(); - gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectFullbrightShinyNonIndexedWaterProgram.mName = "Non Indexed Fullbright Shiny Water Shader"; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isShiny = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasGamma = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasTransport = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear(); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL); - } - - if (success) - { gImpostorProgram.mName = "Impostor Shader"; gImpostorProgram.mFeatures.disableTextureIndex = true; gImpostorProgram.mFeatures.hasSrgb = true; @@ -3224,7 +3034,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectSimpleProgram, gSkinnedObjectSimpleProgram); + success = success && gObjectSimpleProgram.createShader(NULL, NULL); } if (success) @@ -3244,8 +3055,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - - success = gObjectSimpleImpostorProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectSimpleImpostorProgram, gSkinnedObjectSimpleImpostorProgram); + success = success && gObjectSimpleImpostorProgram.createShader(NULL, NULL); } if (success) @@ -3262,30 +3073,30 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + make_rigged_variant(gObjectSimpleWaterProgram, gSkinnedObjectSimpleWaterProgram); success = gObjectSimpleWaterProgram.createShader(NULL, NULL); } if (success) { gObjectBumpProgram.mName = "Bump Shader"; - /*gObjectBumpProgram.mFeatures.calculatesLighting = true; - gObjectBumpProgram.mFeatures.calculatesAtmospherics = true; - gObjectBumpProgram.mFeatures.hasGamma = true; - gObjectBumpProgram.mFeatures.hasAtmospherics = true; - gObjectBumpProgram.mFeatures.hasLighting = true; - gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/ gObjectBumpProgram.mFeatures.encodesNormal = true; gObjectBumpProgram.mShaderFiles.clear(); gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB)); gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectBumpProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectBumpProgram, gSkinnedObjectBumpProgram); + success = success && gObjectBumpProgram.createShader(NULL, NULL); if (success) { //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1 - gObjectBumpProgram.bind(); - gObjectBumpProgram.uniform1i(sTexture0, 0); - gObjectBumpProgram.uniform1i(sTexture1, 1); - gObjectBumpProgram.unbind(); + LLGLSLShader* shader[] = { &gObjectBumpProgram, &gSkinnedObjectBumpProgram }; + for (int i = 0; i < 2; ++i) + { + shader[i]->bind(); + shader[i]->uniform1i(sTexture0, 0); + shader[i]->uniform1i(sTexture1, 1); + shader[i]->unbind(); + } } } @@ -3304,7 +3115,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectSimpleAlphaMaskProgram, gSkinnedObjectSimpleAlphaMaskProgram); + success = success && gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); } if (success) @@ -3322,7 +3134,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectSimpleWaterAlphaMaskProgram, gSkinnedObjectSimpleWaterAlphaMaskProgram); + success = success && gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); } if (success) @@ -3338,7 +3151,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectFullbrightProgram, gSkinnedObjectFullbrightProgram); + success = success && gObjectFullbrightProgram.createShader(NULL, NULL); } if (success) @@ -3346,7 +3160,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterProgram.mName = "Fullbright Water Shader"; gObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; gObjectFullbrightWaterProgram.mFeatures.isFullbright = true; - gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; gObjectFullbrightWaterProgram.mFeatures.hasTransport = true; gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0; gObjectFullbrightWaterProgram.mShaderFiles.clear(); @@ -3354,7 +3168,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightWaterProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectFullbrightWaterProgram, gSkinnedObjectFullbrightWaterProgram); + success = success && gObjectFullbrightWaterProgram.createShader(NULL, NULL); } if (success) @@ -3370,7 +3185,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB)); gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectEmissiveProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectEmissiveProgram, gSkinnedObjectEmissiveProgram); + success = success && gObjectEmissiveProgram.createShader(NULL, NULL); } if (success) @@ -3386,7 +3202,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectEmissiveWaterProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectEmissiveWaterProgram, gSkinnedObjectEmissiveWaterProgram); + success = success && gObjectEmissiveWaterProgram.createShader(NULL, NULL); } if (success) @@ -3403,12 +3220,13 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectFullbrightAlphaMaskProgram, gSkinnedObjectFullbrightAlphaMaskProgram); + success = success && gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); } if (success) { - gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Shader"; + gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Alpha Mask Shader"; gObjectFullbrightWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; gObjectFullbrightWaterAlphaMaskProgram.mFeatures.isFullbright = true; gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; @@ -3420,7 +3238,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectFullbrightWaterAlphaMaskProgram, gSkinnedObjectFullbrightWaterAlphaMaskProgram); + success = success && gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); } if (success) @@ -3436,7 +3255,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectShinyProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectShinyProgram, gSkinnedObjectShinyProgram); + success = success && gObjectShinyProgram.createShader(NULL, NULL); } if (success) @@ -3453,7 +3273,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectShinyWaterProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectShinyWaterProgram, gSkinnedObjectShinyWaterProgram); + success = success && gObjectShinyWaterProgram.createShader(NULL, NULL); } if (success) @@ -3469,7 +3290,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectFullbrightShinyProgram.createShader(NULL, NULL); + success = make_rigged_variant(gObjectFullbrightShinyProgram, gSkinnedObjectFullbrightShinyProgram); + success = success && gObjectFullbrightShinyProgram.createShader(NULL, NULL); } if (success) @@ -3487,196 +3309,8 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); - } - - if (mShaderLevel[SHADER_AVATAR] > 0) - { //load hardware skinned attachment shaders - if (success) - { - gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader"; - gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true; - gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true; - gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectSimpleProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectSimpleProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectSimpleProgram.mShaderFiles.clear(); - gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; - gSkinnedObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightProgram.mFeatures.hasSrgb = true; - gSkinnedObjectFullbrightProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectEmissiveProgram.mName = "Skinned Emissive Shader"; - gSkinnedObjectEmissiveProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasGamma = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasTransport = true; - gSkinnedObjectEmissiveProgram.mFeatures.isFullbright = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectEmissiveProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectEmissiveProgram.mFeatures.hasSrgb = true; - gSkinnedObjectEmissiveProgram.mShaderFiles.clear(); - gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectEmissiveWaterProgram.mName = "Skinned Emissive Water Shader"; - gSkinnedObjectEmissiveWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasTransport = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.isFullbright = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectEmissiveWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear(); - gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectEmissiveWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; - gSkinnedObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightShinyProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; - gSkinnedObjectShinySimpleProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectShinySimpleProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasGamma = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectShinySimpleProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true; - gSkinnedObjectShinySimpleProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectShinySimpleProgram.mShaderFiles.clear(); - gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectShinySimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; - gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectSimpleWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); - gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightWaterProgram.mName = "Skinned Fullbright Water Shader"; - gSkinnedObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectFullbrightWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectFullbrightShinyWaterProgram.mName = "Skinned Fullbright Shiny Water Shader"; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); - } - - if (success) - { - gSkinnedObjectShinySimpleWaterProgram.mName = "Skinned Shiny Simple Water Shader"; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesLighting = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesAtmospherics = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasGamma = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAtmospherics = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAlphaMask = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true; - gSkinnedObjectShinySimpleWaterProgram.mFeatures.disableTextureIndex = true; - gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear(); - gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); - gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); - gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL); - } + success = make_rigged_variant(gObjectFullbrightShinyWaterProgram, gSkinnedObjectFullbrightShinyWaterProgram); + success = success && gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL); } if( !success ) @@ -3789,12 +3423,6 @@ BOOL LLViewerShaderMgr::loadShadersInterface() { BOOL success = TRUE; - if (mShaderLevel[SHADER_INTERFACE] == 0) - { - gHighlightProgram.unload(); - return TRUE; - } - if (success) { gHighlightProgram.mName = "Highlight Shader"; @@ -3802,7 +3430,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB)); gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gHighlightProgram.createShader(NULL, NULL); + success = make_rigged_variant(gHighlightProgram, gSkinnedHighlightProgram); + success = success && gHighlightProgram.createShader(NULL, NULL); } if (success) @@ -4004,9 +3633,21 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB)); gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + gOcclusionProgram.mRiggedVariant = &gSkinnedOcclusionProgram; success = gOcclusionProgram.createShader(NULL, NULL); } + if (success) + { + gSkinnedOcclusionProgram.mName = "Skinned Occlusion Shader"; + gSkinnedOcclusionProgram.mFeatures.hasObjectSkinning = true; + gSkinnedOcclusionProgram.mShaderFiles.clear(); + gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gSkinnedOcclusionProgram.createShader(NULL, NULL); + } + if (success) { gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; @@ -4023,8 +3664,10 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gDebugProgram.mShaderFiles.clear(); gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB)); gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDebugProgram.mRiggedVariant = &gSkinnedDebugProgram; gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gDebugProgram.createShader(NULL, NULL); + success = make_rigged_variant(gDebugProgram, gSkinnedDebugProgram); + success = success && gDebugProgram.createShader(NULL, NULL); } if (success) diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 081221f15b..297cfb6e68 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -184,10 +184,8 @@ extern LLGLSLShader gObjectPreviewProgram; extern LLGLSLShader gObjectSimpleAlphaMaskProgram; extern LLGLSLShader gObjectSimpleWaterProgram; extern LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; -extern LLGLSLShader gObjectSimpleNonIndexedProgram; extern LLGLSLShader gObjectSimpleNonIndexedTexGenProgram; extern LLGLSLShader gObjectSimpleNonIndexedTexGenWaterProgram; -extern LLGLSLShader gObjectSimpleNonIndexedWaterProgram; extern LLGLSLShader gObjectAlphaMaskNonIndexedProgram; extern LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; extern LLGLSLShader gObjectAlphaMaskNoColorProgram; @@ -200,8 +198,6 @@ extern LLGLSLShader gObjectEmissiveProgram; extern LLGLSLShader gObjectEmissiveWaterProgram; extern LLGLSLShader gObjectFullbrightAlphaMaskProgram; extern LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; -extern LLGLSLShader gObjectFullbrightNonIndexedProgram; -extern LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; extern LLGLSLShader gObjectEmissiveNonIndexedProgram; extern LLGLSLShader gObjectEmissiveNonIndexedWaterProgram; extern LLGLSLShader gObjectBumpProgram; @@ -213,25 +209,9 @@ extern LLGLSLShader gObjectFullbrightLODProgram; extern LLGLSLShader gObjectFullbrightShinyProgram; extern LLGLSLShader gObjectFullbrightShinyWaterProgram; -extern LLGLSLShader gObjectFullbrightShinyNonIndexedProgram; -extern LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram; extern LLGLSLShader gObjectShinyProgram; extern LLGLSLShader gObjectShinyWaterProgram; -extern LLGLSLShader gObjectShinyNonIndexedProgram; -extern LLGLSLShader gObjectShinyNonIndexedWaterProgram; - -extern LLGLSLShader gSkinnedObjectSimpleProgram; -extern LLGLSLShader gSkinnedObjectFullbrightProgram; -extern LLGLSLShader gSkinnedObjectEmissiveProgram; -extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; -extern LLGLSLShader gSkinnedObjectShinySimpleProgram; - -extern LLGLSLShader gSkinnedObjectSimpleWaterProgram; -extern LLGLSLShader gSkinnedObjectFullbrightWaterProgram; -extern LLGLSLShader gSkinnedObjectEmissiveWaterProgram; -extern LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; -extern LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; //environment shaders extern LLGLSLShader gTerrainProgram; @@ -281,9 +261,6 @@ extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseProgram; -extern LLGLSLShader gDeferredSkinnedDiffuseProgram; -extern LLGLSLShader gDeferredSkinnedBumpProgram; -extern LLGLSLShader gDeferredSkinnedAlphaProgram; extern LLGLSLShader gDeferredBumpProgram; extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTerrainWaterProgram; @@ -330,8 +307,6 @@ extern LLGLSLShader gDeferredWLSunProgram; extern LLGLSLShader gDeferredWLMoonProgram; extern LLGLSLShader gDeferredStarProgram; extern LLGLSLShader gDeferredFullbrightShinyProgram; -extern LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; -extern LLGLSLShader gDeferredSkinnedFullbrightProgram; extern LLGLSLShader gNormalMapGenProgram; // Deferred materials shaders diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 6471e89233..5ce97c086d 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -181,8 +181,9 @@ SimMeasurement<F64Kilobytes > SIM_UNACKED_BYTES("simtotalunackedbytes", "", LL_S SimMeasurement<F64Megabytes > SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL_SIM_STAT_SIMPHYSICSMEMORY); LLTrace::SampleStatHandle<F64Milliseconds > FRAMETIME_JITTER("frametimejitter", "Average delta between successive frame times"), - FRAMETIME_SLEW("frametimeslew", "Average delta between frame time and mean"), - SIM_PING("simpingstat"); + FRAMETIME_SLEW("frametimeslew", "Average delta between frame time and mean"), + FRAMETIME("frametime", "Measured frame time"), + SIM_PING("simpingstat"); LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections"); @@ -259,8 +260,11 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff) // new "stutter" meter add(LLStatViewer::FRAMETIME_DOUBLED, time_diff >= 2.0 * mLastTimeDiff ? 1 : 0); + sample(LLStatViewer::FRAMETIME, time_diff); + // old stats that were never really used - sample(LLStatViewer::FRAMETIME_JITTER, F64Milliseconds (mLastTimeDiff - time_diff)); + F64Seconds jit = (F64Seconds) std::fabs((mLastTimeDiff - time_diff)); + sample(LLStatViewer::FRAMETIME_JITTER, jit); F32Seconds average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount; sample(LLStatViewer::FRAMETIME_SLEW, F64Milliseconds (average_frametime - time_diff)); @@ -534,7 +538,7 @@ void send_viewer_stats(bool include_preferences) { shader_level = 2; } - else if (gPipeline.canUseVertexShaders()) + else if (gPipeline.shadersLoaded()) { shader_level = 1; } diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 72ce336664..1133326d4f 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -217,8 +217,8 @@ extern SimMeasurement<F64Megabytes > SIM_PHYSICS_MEM; extern LLTrace::SampleStatHandle<F64Milliseconds > FRAMETIME_JITTER, - FRAMETIME_SLEW, - SIM_PING; + FRAMETIME_SLEW, + SIM_PING; extern LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 075588d577..dcdc259b26 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -182,6 +182,7 @@ void LLViewerTextureManager::findFetchedTextures(const LLUUID& id, std::vector<L void LLViewerTextureManager::findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output) { + LL_PROFILE_ZONE_SCOPED; std::vector<LLViewerFetchedTexture*> fetched_output; gTextureList.findTexturesByID(id, fetched_output); std::vector<LLViewerFetchedTexture*>::iterator iter = fetched_output.begin(); @@ -206,6 +207,7 @@ void LLViewerTextureManager::findTextures(const LLUUID& id, std::vector<LLViewe LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id, S32 tex_type) { + LL_PROFILE_ZONE_SCOPED; return gTextureList.findImage(id, (ETexListType)tex_type); } @@ -477,11 +479,10 @@ const F32 GPU_MEMORY_CHECK_WAIT_TIME = 1.0f; F32 texmem_lower_bound_scale = 0.85f; F32 texmem_middle_bound_scale = 0.925f; -static LLTrace::BlockTimerStatHandle FTM_TEXTURE_MEMORY_CHECK("Memory Check"); - //static bool LLViewerTexture::isMemoryForTextureLow() { + LL_PROFILE_ZONE_SCOPED; // Note: we need to figure out a better source for 'min' values, // what is free for low end at minimal settings is 'nothing left' // for higher end gpus at high settings. @@ -498,6 +499,7 @@ bool LLViewerTexture::isMemoryForTextureLow() //static bool LLViewerTexture::isMemoryForTextureSuficientlyFree() { + LL_PROFILE_ZONE_SCOPED; const S32Megabytes DESIRED_FREE_TEXTURE_MEMORY(50); const S32Megabytes DESIRED_FREE_MAIN_MEMORY(200); @@ -511,6 +513,7 @@ bool LLViewerTexture::isMemoryForTextureSuficientlyFree() //static void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical) { + LL_PROFILE_ZONE_SCOPED; static LLFrameTimer timer; static S32Megabytes gpu_res = S32Megabytes(S32_MAX); static S32Megabytes physical_res = S32Megabytes(S32_MAX); @@ -523,48 +526,42 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p } timer.reset(); - LL_RECORD_BLOCK_TIME(FTM_TEXTURE_MEMORY_CHECK); - - if (gGLManager.mHasATIMemInfo) { - S32 meminfo[4]; - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - gpu_res = (S32Megabytes)meminfo[0]; + if (gGLManager.mHasATIMemInfo) + { + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + gpu_res = (S32Megabytes)meminfo[0]; - //check main memory, only works for windows. - LLMemory::updateMemoryInfo(); - physical_res = LLMemory::getAvailableMemKB(); - } - else if (gGLManager.mHasNVXMemInfo) - { - S32 free_memory; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); - gpu_res = (S32Megabytes)(free_memory / 1024); - } + //check main memory, only works for windows. + LLMemory::updateMemoryInfo(); + physical_res = LLMemory::getAvailableMemKB(); + } + else if (gGLManager.mHasNVXMemInfo) + { + S32 free_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); + gpu_res = (S32Megabytes)(free_memory / 1024); + } - gpu = gpu_res; - physical = physical_res; + gpu = gpu_res; + physical = physical_res; + } } -static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UPDATE_MEDIA("Media"); -static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UPDATE_TEST("Test"); - //static -void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity) +void LLViewerTexture::updateClass() { + LL_PROFILE_ZONE_SCOPED; sCurrentTime = gFrameTimeSeconds; LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE_TEST); tester->update(); } - { - LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE_MEDIA); - LLViewerMediaTexture::updateClass(); - } + LLViewerMediaTexture::updateClass(); sBoundTextureMemory = LLImageGL::sBoundTextureMemory; sTotalTextureMemory = LLImageGL::sGlobalTextureMemory; @@ -680,6 +677,9 @@ void LLViewerTexture::init(bool firstinit) mVolumeList[LLRender::LIGHT_TEX].clear(); mVolumeList[LLRender::SCULPT_TEX].clear(); + + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mImageQueue = LL::WorkQueue::getInstance("LLImageGL"); } //virtual @@ -701,6 +701,7 @@ void LLViewerTexture::cleanup() void LLViewerTexture::notifyAboutCreatingTexture() { + LL_PROFILE_ZONE_SCOPED; for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { for(U32 f = 0; f < mNumFaces[ch]; f++) @@ -712,6 +713,7 @@ void LLViewerTexture::notifyAboutCreatingTexture() void LLViewerTexture::notifyAboutMissingAsset() { + LL_PROFILE_ZONE_SCOPED; for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { for(U32 f = 0; f < mNumFaces[ch]; f++) @@ -724,6 +726,7 @@ void LLViewerTexture::notifyAboutMissingAsset() // virtual void LLViewerTexture::dump() { + LL_PROFILE_ZONE_SCOPED; LLGLTexture::dump(); LL_INFOS() << "LLViewerTexture" @@ -759,6 +762,7 @@ bool LLViewerTexture::isActiveFetching() bool LLViewerTexture::bindDebugImage(const S32 stage) { + LL_PROFILE_ZONE_SCOPED; if (stage < 0) return false; bool res = true; @@ -777,6 +781,7 @@ bool LLViewerTexture::bindDebugImage(const S32 stage) bool LLViewerTexture::bindDefaultImage(S32 stage) { + LL_PROFILE_ZONE_SCOPED; if (stage < 0) return false; bool res = true; @@ -819,6 +824,7 @@ void LLViewerTexture::forceImmediateUpdate() void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const { + LL_PROFILE_ZONE_SCOPED; if(needs_gltexture) { mNeedsGLTexture = TRUE; @@ -829,14 +835,14 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co { //flag to reset the values because the old values are used. resetMaxVirtualSizeResetCounter(); - mMaxVirtualSize = virtual_size; - mAdditionalDecodePriority = 0.f; + mMaxVirtualSize = virtual_size; + mAdditionalDecodePriority = 0.f; mNeedsGLTexture = needs_gltexture; } else if (virtual_size > mMaxVirtualSize) { mMaxVirtualSize = virtual_size; - } + } } void LLViewerTexture::resetTextureStats() @@ -861,6 +867,7 @@ void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) //virtual void LLViewerTexture::addFace(U32 ch, LLFace* facep) { + LL_PROFILE_ZONE_SCOPED; llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); if(mNumFaces[ch] >= mFaceList[ch].size()) @@ -876,6 +883,7 @@ void LLViewerTexture::addFace(U32 ch, LLFace* facep) //virtual void LLViewerTexture::removeFace(U32 ch, LLFace* facep) { + LL_PROFILE_ZONE_SCOPED; llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); if(mNumFaces[ch] > 1) @@ -916,6 +924,7 @@ S32 LLViewerTexture::getNumFaces(U32 ch) const //virtual void LLViewerTexture::addVolume(U32 ch, LLVOVolume* volumep) { + LL_PROFILE_ZONE_SCOPED; if (mNumVolumes[ch] >= mVolumeList[ch].size()) { mVolumeList[ch].resize(2 * mNumVolumes[ch] + 1); @@ -929,6 +938,7 @@ void LLViewerTexture::addVolume(U32 ch, LLVOVolume* volumep) //virtual void LLViewerTexture::removeVolume(U32 ch, LLVOVolume* volumep) { + LL_PROFILE_ZONE_SCOPED; if (mNumVolumes[ch] > 1) { S32 index = volumep->getIndexInTex(ch); @@ -952,6 +962,7 @@ S32 LLViewerTexture::getNumVolumes(U32 ch) const void LLViewerTexture::reorganizeFaceList() { + LL_PROFILE_ZONE_SCOPED; static const F32 MAX_WAIT_TIME = 20.f; // seconds static const U32 MAX_EXTRA_BUFFER_SIZE = 4; @@ -975,6 +986,7 @@ void LLViewerTexture::reorganizeFaceList() void LLViewerTexture::reorganizeVolumeList() { + LL_PROFILE_ZONE_SCOPED; static const F32 MAX_WAIT_TIME = 20.f; // seconds static const U32 MAX_EXTRA_BUFFER_SIZE = 4; @@ -1177,6 +1189,7 @@ FTType LLViewerFetchedTexture::getFTType() const void LLViewerFetchedTexture::cleanup() { + LL_PROFILE_ZONE_SCOPED; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -1202,6 +1215,7 @@ void LLViewerFetchedTexture::cleanup() //access the fast cache void LLViewerFetchedTexture::loadFromFastCache() { + LL_PROFILE_ZONE_SCOPED; if(!mInFastCacheList) { return; //no need to access the fast cache. @@ -1347,6 +1361,7 @@ void LLViewerFetchedTexture::dump() // ONLY called from LLViewerFetchedTextureList void LLViewerFetchedTexture::destroyTexture() { + LL_PROFILE_ZONE_SCOPED; if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory. { return ; @@ -1363,6 +1378,7 @@ void LLViewerFetchedTexture::destroyTexture() void LLViewerFetchedTexture::addToCreateTexture() { + LL_PROFILE_ZONE_SCOPED; bool force_update = false; if (getComponents() != mRawImage->getComponents()) { @@ -1404,6 +1420,7 @@ void LLViewerFetchedTexture::addToCreateTexture() } else { + LL_PROFILE_ZONE_SCOPED; #if 1 // //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, @@ -1448,99 +1465,104 @@ void LLViewerFetchedTexture::addToCreateTexture() } } #endif - mNeedsCreateTexture = TRUE; - gTextureList.mCreateTextureList.insert(this); - } + scheduleCreateTexture(); + } return; } // ONLY called from LLViewerTextureList -BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) +BOOL LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/) { - if (!mNeedsCreateTexture) - { - destroyRawImage(); - return FALSE; - } - mNeedsCreateTexture = FALSE; - if (mRawImage.isNull()) - { - LL_ERRS() << "LLViewerTexture trying to create texture with no Raw Image" << LL_ENDL; - } - if (mRawImage->isBufferInvalid()) - { - LL_WARNS() << "Can't create a texture: invalid image data" << LL_ENDL; - destroyRawImage(); - return FALSE; - } -// LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", -// mRawDiscardLevel, -// mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) -// << mID.getString() << LL_ENDL; - BOOL res = TRUE; + LL_PROFILE_ZONE_SCOPED; +#if LL_IMAGEGL_THREAD_CHECK + mGLTexturep->checkActiveThread(); +#endif - // store original size only for locally-sourced images - if (mUrl.compare(0, 7, "file://") == 0) - { - mOrigWidth = mRawImage->getWidth(); - mOrigHeight = mRawImage->getHeight(); + if (!mNeedsCreateTexture) + { + destroyRawImage(); + return FALSE; + } + mNeedsCreateTexture = FALSE; + + if (mRawImage.isNull()) + { + LL_ERRS() << "LLViewerTexture trying to create texture with no Raw Image" << LL_ENDL; + } + if (mRawImage->isBufferInvalid()) + { + LL_WARNS() << "Can't create a texture: invalid image data" << LL_ENDL; + destroyRawImage(); + return FALSE; + } + // LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", + // mRawDiscardLevel, + // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) + // << mID.getString() << LL_ENDL; + BOOL res = TRUE; + + // store original size only for locally-sourced images + if (mUrl.compare(0, 7, "file://") == 0) + { + mOrigWidth = mRawImage->getWidth(); + mOrigHeight = mRawImage->getHeight(); // This is only safe because it's a local image and fetcher doesn't use raw data // from local images, but this might become unsafe in case of changes to fetcher - if (mBoostLevel == BOOST_PREVIEW) - { - mRawImage->biasedScaleToPowerOfTwo(1024); - } - else - { // leave black border, do not scale image content - mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); - } - - mFullWidth = mRawImage->getWidth(); - mFullHeight = mRawImage->getHeight(); - setTexelsPerImage(); - } - else - { - mOrigWidth = mFullWidth; - mOrigHeight = mFullHeight; - } + if (mBoostLevel == BOOST_PREVIEW) + { + mRawImage->biasedScaleToPowerOfTwo(1024); + } + else + { // leave black border, do not scale image content + mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); + } - bool size_okay = true; + mFullWidth = mRawImage->getWidth(); + mFullHeight = mRawImage->getHeight(); + setTexelsPerImage(); + } + else + { + mOrigWidth = mFullWidth; + mOrigHeight = mFullHeight; + } - S32 discard_level = mRawDiscardLevel; - if (mRawDiscardLevel < 0) - { - LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL; - discard_level = 0; - } + bool size_okay = true; - U32 raw_width = mRawImage->getWidth() << discard_level; - U32 raw_height = mRawImage->getHeight() << discard_level; + S32 discard_level = mRawDiscardLevel; + if (mRawDiscardLevel < 0) + { + LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL; + discard_level = 0; + } - if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE ) - { - LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL; - size_okay = false; - } - - if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) - { - // A non power-of-two image was uploaded (through a non standard client) - LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL; - size_okay = false; - } - - if( !size_okay ) - { - // An inappropriately-sized image was uploaded (through a non standard client) - // We treat these images as missing assets which causes them to - // be renderd as 'missing image' and to stop requesting data - LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL; - setIsMissingAsset(); - destroyRawImage(); - return FALSE; - } + U32 raw_width = mRawImage->getWidth() << discard_level; + U32 raw_height = mRawImage->getHeight() << discard_level; + + if (raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE) + { + LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL; + size_okay = false; + } + + if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) + { + // A non power-of-two image was uploaded (through a non standard client) + LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL; + size_okay = false; + } + + if (!size_okay) + { + // An inappropriately-sized image was uploaded (through a non standard client) + // We treat these images as missing assets which causes them to + // be renderd as 'missing image' and to stop requesting data + LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL; + setIsMissingAsset(); + destroyRawImage(); + return FALSE; + } if (mGLTexturep->getHasExplicitFormat()) { @@ -1562,19 +1584,85 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) } } - res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); + return res; +} - notifyAboutCreatingTexture(); +BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) +{ + if (!mNeedsCreateTexture) + { + return FALSE; + } - setActive(); + BOOL res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); + + return res; +} - if (!needsToSaveRawImage()) - { - mNeedsAux = FALSE; - destroyRawImage(); - } +void LLViewerFetchedTexture::postCreateTexture() +{ + if (!mNeedsCreateTexture) + { + return; + } +#if LL_IMAGEGL_THREAD_CHECK + mGLTexturep->checkActiveThread(); +#endif - return res; + notifyAboutCreatingTexture(); + + setActive(); + + if (!needsToSaveRawImage()) + { + mNeedsAux = FALSE; + destroyRawImage(); + } + + mNeedsCreateTexture = FALSE; +} + +void LLViewerFetchedTexture::scheduleCreateTexture() +{ + if (!mNeedsCreateTexture) + { + ref(); + mNeedsCreateTexture = TRUE; + if (preCreateTexture()) + { + mNeedsCreateTexture = TRUE; + auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; + if (mainq) + { + mainq->postTo( + mImageQueue, + // work to be done on LLImageGL worker thread + [this]() + { +#if LL_IMAGEGL_THREAD_CHECK + mGLTexturep->mActiveThread = LLThread::currentID(); +#endif + //actually create the texture on a background thread + createTexture(); + }, + // callback to be run on main thread + [this]() + { +#if LL_IMAGEGL_THREAD_CHECK + mGLTexturep->mActiveThread = LLThread::currentID(); +#endif + //finalize on main thread + postCreateTexture(); + unref(); + }); + } + else + { + gTextureList.mCreateTextureList.insert(this); + unref(); + } + } + } } // Call with 0,0 to turn this feature off. @@ -1866,6 +1954,7 @@ void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) void LLViewerFetchedTexture::updateVirtualSize() { + LL_PROFILE_ZONE_SCOPED; if(!mMaxVirtualSizeResetCounter) { addTextureStats(0.f, FALSE);//reset @@ -1957,6 +2046,7 @@ bool LLViewerFetchedTexture::isActiveFetching() bool LLViewerFetchedTexture::updateFetch() { + LL_PROFILE_ZONE_SCOPED; static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2); static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3); @@ -2059,7 +2149,7 @@ bool LLViewerFetchedTexture::updateFetch() } else { - mIsRawImageValid = TRUE; + mIsRawImageValid = TRUE; addToCreateTexture(); } @@ -2537,6 +2627,7 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s bool LLViewerFetchedTexture::doLoadedCallbacks() { + LL_PROFILE_ZONE_SCOPED; static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds @@ -2887,7 +2978,9 @@ void LLViewerFetchedTexture::destroyRawImage() //virtual void LLViewerFetchedTexture::switchToCachedImage() { - if(mCachedRawImage.notNull()) + LL_PROFILE_ZONE_SCOPED; + if(mCachedRawImage.notNull() && + !mNeedsCreateTexture) // <--- texture creation is pending, don't step on it { mRawImage = mCachedRawImage; @@ -2898,12 +2991,12 @@ void LLViewerFetchedTexture::switchToCachedImage() mComponents = mRawImage->getComponents(); mGLTexturep->setComponents(mComponents); gTextureList.dirtyImage(this); - } + } mIsRawImageValid = TRUE; mRawDiscardLevel = mCachedRawDiscardLevel; - gTextureList.mCreateTextureList.insert(this); - mNeedsCreateTexture = TRUE; + + scheduleCreateTexture(); } } @@ -3177,6 +3270,7 @@ bool LLViewerLODTexture::isUpdateFrozen() //virtual void LLViewerLODTexture::processTextureStats() { + LL_PROFILE_ZONE_SCOPED; updateVirtualSize(); static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false); @@ -3340,6 +3434,7 @@ bool LLViewerLODTexture::scaleDown() //static void LLViewerMediaTexture::updateClass() { + LL_PROFILE_ZONE_SCOPED; static const F32 MAX_INACTIVE_TIME = 30.f; #if 0 diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 07997e02a5..03b5b7497f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -35,6 +35,7 @@ #include "llrender.h" #include "llmetricperformancetester.h" #include "httpcommon.h" +#include "workqueue.h" #include <map> #include <list> @@ -114,7 +115,7 @@ protected: public: static void initClass(); - static void updateClass(const F32 velocity, const F32 angular_velocity) ; + static void updateClass(); LLViewerTexture(BOOL usemipmaps = TRUE); LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ; @@ -213,6 +214,9 @@ protected: //do not use LLPointer here. LLViewerMediaTexture* mParcelMedia ; + LL::WorkQueue::weak_t mMainQueue; + LL::WorkQueue::weak_t mImageQueue; + static F32 sTexelPixelRatio; public: static const U32 sCurrentFileVersion; @@ -321,9 +325,13 @@ public: void addToCreateTexture(); - - // ONLY call from LLViewerTextureList + //call to determine if createTexture is necessary + BOOL preCreateTexture(S32 usename = 0); + // ONLY call from LLViewerTextureList or ImageGL background thread BOOL createTexture(S32 usename = 0); + void postCreateTexture(); + void scheduleCreateTexture(); + void destroyTexture() ; virtual void processTextureStats() ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 38fccba169..db59976be2 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -66,7 +66,6 @@ void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; S32 LLViewerTextureList::sNumImages = 0; LLViewerTextureList gTextureList; -static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMAGES("Process Images"); ETexListType get_element_type(S32 priority) { @@ -112,6 +111,7 @@ void LLViewerTextureList::init() void LLViewerTextureList::doPreloadImages() { + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("ViewerImages") << "Preloading images..." << LL_ENDL; llassert_always(mInitialized) ; @@ -203,6 +203,7 @@ static std::string get_texture_list_name() void LLViewerTextureList::doPrefetchImages() { + LL_PROFILE_ZONE_SCOPED; if (LLAppViewer::instance()->getPurgeCache()) { // cache was purged, no point @@ -256,6 +257,7 @@ LLViewerTextureList::~LLViewerTextureList() void LLViewerTextureList::shutdown() { + LL_PROFILE_ZONE_SCOPED; // clear out preloads mImagePreloads.clear(); @@ -331,6 +333,7 @@ void LLViewerTextureList::shutdown() void LLViewerTextureList::dump() { + LL_PROFILE_ZONE_SCOPED; LL_INFOS() << "LLViewerTextureList::dump()" << LL_ENDL; for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) { @@ -375,6 +378,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& LLGLenum primary_format, const LLUUID& force_id) { + LL_PROFILE_ZONE_SCOPED; if(!mInitialized) { return NULL ; @@ -402,6 +406,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& LLGLenum primary_format, const LLUUID& force_id) { + LL_PROFILE_ZONE_SCOPED; if(!mInitialized) { return NULL ; @@ -490,6 +495,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, LLGLenum primary_format, LLHost request_from_host) { + LL_PROFILE_ZONE_SCOPED; if(!mInitialized) { return NULL ; @@ -552,6 +558,7 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, LLGLenum primary_format, LLHost request_from_host) { + LL_PROFILE_ZONE_SCOPED; static LLCachedControl<bool> fast_cache_fetching_enabled(gSavedSettings, "FastCacheFetchEnabled", true); LLPointer<LLViewerFetchedTexture> imagep ; @@ -607,6 +614,7 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector<LLViewerFetchedTexture*> &output) { + LL_PROFILE_ZONE_SCOPED; LLTextureKey search_key(image_id, TEX_LIST_STANDARD); uuid_map_t::iterator iter = mUUIDMap.lower_bound(search_key); while (iter != mUUIDMap.end() && iter->first.textureId == image_id) @@ -618,6 +626,7 @@ void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector<L LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &search_key) { + LL_PROFILE_ZONE_SCOPED; uuid_map_t::iterator iter = mUUIDMap.find(search_key); if (iter == mUUIDMap.end()) return NULL; @@ -631,6 +640,7 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id, E void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image) { + LL_PROFILE_ZONE_SCOPED; assert_main_thread(); llassert_always(mInitialized) ; llassert(image); @@ -650,6 +660,7 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image) void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) { + LL_PROFILE_ZONE_SCOPED; assert_main_thread(); llassert_always(mInitialized) ; llassert(image); @@ -698,6 +709,7 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListType tex_type) { + LL_PROFILE_ZONE_SCOPED; if (!new_image) { return; @@ -721,6 +733,7 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image) { + LL_PROFILE_ZONE_SCOPED; if( image) { if (image->hasCallbacks()) @@ -745,18 +758,10 @@ void LLViewerTextureList::dirtyImage(LLViewerFetchedTexture *image) } //////////////////////////////////////////////////////////////////////////// -static LLTrace::BlockTimerStatHandle FTM_IMAGE_MARK_DIRTY("Dirty Images"); -static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE_PRIORITIES("Prioritize"); -static LLTrace::BlockTimerStatHandle FTM_IMAGE_CALLBACKS("Callbacks"); -static LLTrace::BlockTimerStatHandle FTM_IMAGE_FETCH("Fetch"); -static LLTrace::BlockTimerStatHandle FTM_FAST_CACHE_IMAGE_FETCH("Fast Cache Fetch"); -static LLTrace::BlockTimerStatHandle FTM_IMAGE_CREATE("Create"); -static LLTrace::BlockTimerStatHandle FTM_IMAGE_STATS("Stats"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_TEXTURES("Update Textures"); void LLViewerTextureList::updateImages(F32 max_time) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_TEXTURES); + LL_PROFILE_ZONE_SCOPED; static BOOL cleared = FALSE; if(gTeleportDisplay) { @@ -782,66 +787,49 @@ void LLViewerTextureList::updateImages(F32 max_time) sample(FORMATTED_MEM, F64Bytes(LLImageFormatted::sGlobalFormattedMemory)); } - { - //loading from fast cache - LL_RECORD_BLOCK_TIME(FTM_FAST_CACHE_IMAGE_FETCH); - max_time -= updateImagesLoadingFastCache(max_time); - } - - { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_UPDATE_PRIORITIES); - updateImagesDecodePriorities(); - } - - F32 total_max_time = max_time; - - { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_FETCH); - max_time -= updateImagesFetchTextures(max_time); - } + //loading from fast cache + max_time -= updateImagesLoadingFastCache(max_time); - { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_CREATE); - max_time = llmax(max_time, total_max_time*.50f); // at least 50% of max_time - max_time -= updateImagesCreateTextures(max_time); - } + updateImagesDecodePriorities(); + + F32 total_max_time = max_time; + + max_time -= updateImagesFetchTextures(max_time); + + max_time = llmax(max_time, total_max_time*.50f); // at least 50% of max_time + max_time -= updateImagesCreateTextures(max_time); if (!mDirtyTextureList.empty()) { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_MARK_DIRTY); gPipeline.dirtyPoolObjectTextures(mDirtyTextureList); mDirtyTextureList.clear(); } + bool didone = false; + for (image_list_t::iterator iter = mCallbackList.begin(); + iter != mCallbackList.end(); ) { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_CALLBACKS); - bool didone = false; - for (image_list_t::iterator iter = mCallbackList.begin(); - iter != mCallbackList.end(); ) + //trigger loaded callbacks on local textures immediately + LLViewerFetchedTexture* image = *iter++; + if (!image->getUrl().empty()) { - //trigger loaded callbacks on local textures immediately - LLViewerFetchedTexture* image = *iter++; - if (!image->getUrl().empty()) - { - // Do stuff to handle callbacks, update priorities, etc. - didone = image->doLoadedCallbacks(); - } - else if (!didone) - { - // Do stuff to handle callbacks, update priorities, etc. - didone = image->doLoadedCallbacks(); - } + // Do stuff to handle callbacks, update priorities, etc. + didone = image->doLoadedCallbacks(); + } + else if (!didone) + { + // Do stuff to handle callbacks, update priorities, etc. + didone = image->doLoadedCallbacks(); } } + - { - LL_RECORD_BLOCK_TIME(FTM_IMAGE_STATS); - updateImagesUpdateStats(); - } + updateImagesUpdateStats(); } void LLViewerTextureList::clearFetchingRequests() { + LL_PROFILE_ZONE_SCOPED; if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) { return; @@ -859,6 +847,7 @@ void LLViewerTextureList::clearFetchingRequests() void LLViewerTextureList::updateImagesDecodePriorities() { + LL_PROFILE_ZONE_SCOPED; // Update the decode priority for N images each frame { F32 lazy_flush_timeout = 30.f; // stop decoding @@ -974,6 +963,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level) { + LL_PROFILE_ZONE_SCOPED; if(!tex->setDebugFetching(debug_level)) { return; @@ -1022,6 +1012,7 @@ void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debu F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) { + LL_PROFILE_ZONE_SCOPED; if (gGLManager.mIsDisabled) return 0.0f; // @@ -1038,6 +1029,7 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) enditer = iter; LLViewerFetchedTexture *imagep = *curiter; imagep->createTexture(); + imagep->postCreateTexture(); if (create_timer.getElapsedTimeF32() > max_time) { break; @@ -1049,6 +1041,7 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time) { + LL_PROFILE_ZONE_SCOPED; if (gGLManager.mIsDisabled) return 0.0f; if(mFastCacheList.empty()) { @@ -1079,6 +1072,7 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time) void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep) { + LL_PROFILE_ZONE_SCOPED; if(!imagep) { return ; @@ -1098,6 +1092,7 @@ void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep) F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) { + LL_PROFILE_ZONE_SCOPED; LLTimer image_op_timer; // Update fetch for N images each frame @@ -1173,6 +1168,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) void LLViewerTextureList::updateImagesUpdateStats() { + LL_PROFILE_ZONE_SCOPED; if (mForceResetTextureStats) { for (image_priority_list_t::iterator iter = mImageList.begin(); @@ -1187,6 +1183,7 @@ void LLViewerTextureList::updateImagesUpdateStats() void LLViewerTextureList::decodeAllImages(F32 max_time) { + LL_PROFILE_ZONE_SCOPED; LLTimer timer; //loading from fast cache @@ -1256,6 +1253,7 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec) { + LL_PROFILE_ZONE_SCOPED; // Load the image LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); if (image.isNull()) @@ -1309,6 +1307,7 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename, // note: modifies the argument raw_image!!!! LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image) { + LL_PROFILE_ZONE_SCOPED; raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C(); @@ -1342,6 +1341,7 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage // Returns min setting for TextureMemory (in MB) S32Megabytes LLViewerTextureList::getMinVideoRamSetting() { + LL_PROFILE_ZONE_SCOPED; U32Megabytes system_ram = gSysMemory.getPhysicalMemoryKB(); //min texture mem sets to 64M if total physical mem is more than 1.5GB return (system_ram > U32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ; @@ -1351,6 +1351,7 @@ S32Megabytes LLViewerTextureList::getMinVideoRamSetting() // Returns max setting for TextureMemory (in MB) S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier) { + LL_PROFILE_ZONE_SCOPED; S32Megabytes max_texmem; if (gGLManager.mVRAM != 0) { @@ -1358,7 +1359,7 @@ S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, fl // - it's going to be swapping constantly regardless S32Megabytes max_vram(gGLManager.mVRAM); - if(gGLManager.mIsATI) + if(gGLManager.mIsAMD) { //shrink the availabe vram for ATI cards because some of them do not handel texture swapping well. max_vram = max_vram * 0.75f; @@ -1404,6 +1405,7 @@ const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12); const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512); void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) { + LL_PROFILE_ZONE_SCOPED; // Initialize the image pipeline VRAM settings S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory")); F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); @@ -1466,8 +1468,8 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d { static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; - LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMAGES); - + LL_PROFILE_ZONE_SCOPED; + // Receive image header, copy into image object and decompresses // if this is a one-packet image. @@ -1538,7 +1540,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d { static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; - LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMAGES); + LL_PROFILE_ZONE_SCOPED; // Receives image packet, copy into image object, // checks if all packets received, decompresses if so. @@ -1611,7 +1613,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d // static void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data) { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMAGES); + LL_PROFILE_ZONE_SCOPED; LLUUID image_id; msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id); @@ -1644,6 +1646,7 @@ void LLUIImageList::cleanUp() LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority) { + LL_PROFILE_ZONE_SCOPED; // use id as image name std::string image_name = image_id.asString(); @@ -1662,6 +1665,7 @@ LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority) LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priority) { + LL_PROFILE_ZONE_SCOPED; // look for existing image uuid_ui_image_map_t::iterator found_it = mUIImages.find(image_name); if (found_it != mUIImages.end()) @@ -1679,6 +1683,7 @@ LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority, LLUIImage::EScaleStyle scale_style) { + LL_PROFILE_ZONE_SCOPED; if (boost_priority == LLGLTexture::BOOST_NONE) { boost_priority = LLGLTexture::BOOST_UI; @@ -1691,6 +1696,7 @@ LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority, LLUIImage::EScaleStyle scale_style) { + LL_PROFILE_ZONE_SCOPED; if (boost_priority == LLGLTexture::BOOST_NONE) { boost_priority = LLGLTexture::BOOST_UI; @@ -1702,6 +1708,7 @@ LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLUIImage::EScaleStyle scale_style) { + LL_PROFILE_ZONE_SCOPED; if (!imagep) return NULL; imagep->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -1739,6 +1746,7 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLUIImage::EScaleStyle scale_style) { + LL_PROFILE_ZONE_SCOPED; // look for existing image uuid_ui_image_map_t::iterator found_it = mUIImages.find(name); if (found_it != mUIImages.end()) @@ -1753,6 +1761,7 @@ LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::s //static void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* user_data ) { + LL_PROFILE_ZONE_SCOPED; if(!success || !user_data) { return; @@ -1854,6 +1863,7 @@ struct UIImageDeclarations : public LLInitParam::Block<UIImageDeclarations> bool LLUIImageList::initFromFile() { + LL_PROFILE_ZONE_SCOPED; // Look for textures.xml in all the right places. Pass // constraint=LLDir::ALL_SKINS because we want to overlay textures.xml // from all the skins directories. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 92e8f8026d..8d749c41cc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -608,12 +608,6 @@ public: { LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); - if (gPipeline.getUseVertexShaders() == 0) - { - addText(xpos, ypos, "Shaders Disabled"); - ypos += y_inc; - } - if (gGLManager.mHasATIMemInfo) { S32 meminfo[4]; @@ -1518,8 +1512,15 @@ BOOL LLViewerWindow::handleCloseRequest(LLWindow *window) void LLViewerWindow::handleQuit(LLWindow *window) { - LL_INFOS() << "Window forced quit" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); + if (gNonInteractive) + { + LLAppViewer::instance()->requestQuit(); + } + else + { + LL_INFOS() << "Window forced quit" << LL_ENDL; + LLAppViewer::instance()->forceQuit(); + } } void LLViewerWindow::handleResize(LLWindow *window, S32 width, S32 height) @@ -1766,6 +1767,7 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data) BOOL LLViewerWindow::handleTimerEvent(LLWindow *window) { + //TODO: just call this every frame from gatherInput instead of using a convoluted 30fps timer callback if (LLViewerJoystick::getInstance()->getOverrideCamera()) { LLViewerJoystick::getInstance()->updateStatus(); @@ -1906,7 +1908,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) p.title, p.name, p.x, p.y, p.width, p.height, 0, p.fullscreen, gHeadlessClient, - gSavedSettings.getBOOL("DisableVerticalSync"), + gSavedSettings.getBOOL("RenderVSyncEnable"), !gHeadlessClient, p.ignore_pixel_depth, gSavedSettings.getBOOL("RenderDeferred") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled @@ -1973,6 +1975,13 @@ LLViewerWindow::LLViewerWindow(const Params& p) } LLFontManager::initClass(); + // Init font system, load default fonts and generate basic glyphs + // currently it takes aprox. 0.5 sec and we would load these fonts anyway + // before login screen. + LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), + mDisplayScale.mV[VX], + mDisplayScale.mV[VY], + gDirUtilp->getAppRODataDir()); // // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off @@ -2014,19 +2023,11 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. - LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ; + LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreaded")); gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); - // Init font system, but don't actually load the fonts yet - // because our window isn't onscreen and they take several - // seconds to parse. - LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), - mDisplayScale.mV[VX], - mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir()); - // Create container for all sub-views LLView::Params rvp; rvp.name("root"); @@ -2059,20 +2060,6 @@ void LLViewerWindow::initGLDefaults() { gGL.setSceneBlendType(LLRender::BT_ALPHA); - if (!LLGLSLShader::sNoFixedFunction) - { //initialize fixed function state - glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); - - glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,LLColor4::black.mV); - glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,LLColor4::white.mV); - - // lights for objects - glShadeModel( GL_SMOOTH ); - - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } - glPixelStorei(GL_PACK_ALIGNMENT,1); glPixelStorei(GL_UNPACK_ALIGNMENT,1); @@ -2112,6 +2099,8 @@ void LLViewerWindow::initBase() LL_DEBUGS("AppInit") << "initializing edit menu" << LL_ENDL; initialize_edit_menu(); + LLFontGL::loadCommonFonts(); + // Create the floater view at the start so that other views can add children to it. // (But wait to add it as a child of the root view so that it will be in front of the // other views.) @@ -2198,6 +2187,14 @@ void LLViewerWindow::initBase() void LLViewerWindow::initWorldUI() { + if (gNonInteractive) + { + gIMMgr = LLIMMgr::getInstance(); + LLNavigationBar::getInstance(); + gFloaterView->pushVisibleAll(FALSE); + return; + } + S32 height = mRootView->getRect().getHeight(); S32 width = mRootView->getRect().getWidth(); LLRect full_window(0, height, width, 0); @@ -2208,12 +2205,15 @@ void LLViewerWindow::initWorldUI() //getRootView()->sendChildToFront(gFloaterView); //getRootView()->sendChildToFront(gSnapshotFloaterView); - LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container"); - LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); - chiclet_bar->setShape(chiclet_container->getLocalRect()); - chiclet_bar->setFollowsAll(); - chiclet_container->addChild(chiclet_bar); - chiclet_container->setVisible(TRUE); + if (!gNonInteractive) + { + LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container"); + LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); + chiclet_bar->setShape(chiclet_container->getLocalRect()); + chiclet_bar->setFollowsAll(); + chiclet_container->addChild(chiclet_bar); + chiclet_container->setVisible(TRUE); + } LLRect morph_view_rect = full_window; morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); @@ -2302,21 +2302,24 @@ void LLViewerWindow::initWorldUI() gToolBarView->setVisible(TRUE); } - LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); - if (destinations) + if (!gNonInteractive) { - destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("DestinationGuideURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); - if (avatar_picker) - { - avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("AvatarPickerURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); + if (destinations) + { + destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("DestinationGuideURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } + LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); + if (avatar_picker) + { + avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("AvatarPickerURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } } } @@ -2560,7 +2563,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) mWindow->setMinSize(min_window_width, min_window_height); LLCoordScreen window_rect; - if (mWindow->getSize(&window_rect)) + if (!gNonInteractive && mWindow->getSize(&window_rect)) { // Only save size if not maximized gSavedSettings.setU32("WindowWidth", window_rect.mX); @@ -2672,10 +2675,7 @@ void LLViewerWindow::drawDebugText() gGL.color4f(1,1,1,1); gGL.pushMatrix(); gGL.pushUIMatrix(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); { // scale view by UI global scale factor and aspect ratio correction factor gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); @@ -2685,10 +2685,7 @@ void LLViewerWindow::drawDebugText() gGL.popMatrix(); gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } + gUIProgram.unbind(); } void LLViewerWindow::draw() @@ -2734,10 +2731,7 @@ void LLViewerWindow::draw() // Draw all nested UI views. // No translation needed, this view is glued to 0,0 - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); gGL.pushMatrix(); LLUI::pushMatrix(); @@ -2813,14 +2807,9 @@ void LLViewerWindow::draw() LLUI::popMatrix(); gGL.popMatrix(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } + gUIProgram.unbind(); -//#if LL_DEBUG LLView::sIsDrawing = FALSE; -//#endif } // Takes a single keyup event, usually when UI is visible @@ -3790,8 +3779,15 @@ void LLViewerWindow::updateLayout() void LLViewerWindow::updateMouseDelta() { +#if LL_WINDOWS + LLCoordCommon delta; + mWindow->getCursorDelta(&delta); + S32 dx = delta.mX; + S32 dy = delta.mY; +#else S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); +#endif //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; @@ -5388,6 +5384,7 @@ void LLViewerWindow::setup3DRender() void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset) { + LL_PROFILE_ZONE_SCOPED gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset; gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset; gGLViewport[2] = mWorldViewRectRaw.getWidth(); @@ -5606,8 +5603,6 @@ void LLViewerWindow::initFonts(F32 zoom_factor) mDisplayScale.mV[VX] * zoom_factor, mDisplayScale.mV[VY] * zoom_factor, gDirUtilp->getAppRODataDir()); - // Force font reloads, which can be very slow - LLFontGL::loadDefaultFonts(); } void LLViewerWindow::requestResolutionUpdate() @@ -5649,7 +5644,7 @@ void LLViewerWindow::restartDisplay(BOOL show_progress_bar) } } -BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar) +BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar) { //BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized"); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 713cc51bf7..979a560508 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -427,7 +427,7 @@ public: void requestResolutionUpdate(); void checkSettings(); void restartDisplay(BOOL show_progress_bar); - BOOL changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar); + BOOL changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar); BOOL getIgnoreDestroyWindow() { return mIgnoreActivate; } F32 getWorldViewAspectRatio() const; const LLVector2& getDisplayScale() const { return mDisplayScale; } diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index c63c5f6b23..46beac8255 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -254,6 +254,7 @@ BOOL LLVLComposition::generateComposition() BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, const F32 width, const F32 height) { + LL_PROFILE_ZONE_SCOPED llassert(mSurfacep); llassert(x >= 0.f); llassert(y >= 0.f); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 5d994058c2..c8c85d404d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -111,6 +111,7 @@ #include "llsdserialize.h" #include "llcallstack.h" #include "llrendersphere.h" +#include "llskinningutil.h" #include <boost/lexical_cast.hpp> @@ -126,6 +127,9 @@ const F32 MIN_HOVER_Z = -2.0; const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f; const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f; +const F32 FIRST_APPEARANCE_CLOUD_MIN_DELAY = 3.f; // seconds +const F32 FIRST_APPEARANCE_CLOUD_MAX_DELAY = 45.f; + using namespace LLAvatarAppearanceDefines; //----------------------------------------------------------------------------- @@ -328,6 +332,7 @@ public: // must return FALSE when the motion is completed. virtual BOOL onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; F32 nx[2]; nx[0]=time*TORSO_NOISE_SPEED; nx[1]=0.0f; @@ -448,6 +453,7 @@ public: // must return FALSE when the motion is completed. virtual BOOL onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; mBreatheRate = 1.f; F32 breathe_amt = (sinf(mBreatheRate * time) * BREATHE_ROT_MOTION_STRENGTH); @@ -549,6 +555,7 @@ public: // must return FALSE when the motion is completed. virtual BOOL onUpdate(F32 time, U8* joint_mask) { + LL_PROFILE_ZONE_SCOPED; mPelvisState->setPosition(LLVector3::zero); return TRUE; @@ -664,6 +671,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisuallyMuteSetting(AV_RENDER_NORMALLY), mMutedAVColor(LLColor4::white /* used for "uninitialize" */), mFirstFullyVisible(TRUE), + mFirstUseDelaySeconds(FIRST_APPEARANCE_CLOUD_MIN_DELAY), mFullyLoaded(FALSE), mPreviousFullyLoaded(FALSE), mFullyLoadedInitialized(FALSE), @@ -738,7 +746,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mCurrentGesticulationLevel = 0; - + mFirstSeenTimer.reset(); mRuthTimer.reset(); mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); @@ -1317,11 +1325,9 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) } -static LLTrace::BlockTimerStatHandle FTM_AVATAR_EXTENT_UPDATE("Av Upd Extent"); - void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { - LL_RECORD_BLOCK_TIME(FTM_AVATAR_EXTENT_UPDATE); + LL_PROFILE_ZONE_SCOPED; S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity"); if (getOverallAppearance() != AOA_NORMAL) @@ -1424,7 +1430,7 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) continue; } LLDrawable* drawable = attached_object->mDrawable; - if (drawable && !drawable->isState(LLDrawable::RIGGED)) + if (drawable && !drawable->isState(LLDrawable::RIGGED | LLDrawable::RIGGED_CHILD)) // <-- don't extend bounding box if any rigged objects are present { LLSpatialBridge* bridge = drawable->getSpatialBridge(); if (bridge) @@ -2490,10 +2496,6 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) return setTETextureCore(te, image); } -static LLTrace::BlockTimerStatHandle FTM_AVATAR_UPDATE("Avatar Update"); -static LLTrace::BlockTimerStatHandle FTM_AVATAR_UPDATE_COMPLEXITY("Avatar Update Complexity"); -static LLTrace::BlockTimerStatHandle FTM_JOINT_UPDATE("Update Joints"); - //------------------------------------------------------------------------ // LLVOAvatar::dumpAnimationState() //------------------------------------------------------------------------ @@ -2526,7 +2528,7 @@ void LLVOAvatar::dumpAnimationState() //------------------------------------------------------------------------ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) { - LL_RECORD_BLOCK_TIME(FTM_AVATAR_UPDATE); + LL_PROFILE_ZONE_SCOPED; if (isDead()) { @@ -2562,8 +2564,6 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) // force asynchronous drawable update if(mDrawable.notNull()) { - LL_RECORD_BLOCK_TIME(FTM_JOINT_UPDATE); - if (isSitting() && getParent()) { LLViewerObject *root_object = (LLViewerObject*)getRoot(); @@ -2663,9 +2663,8 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) if ((LLFrameTimer::getFrameCount() + mID.mData[0]) % compl_upd_freq == 0) { - LL_RECORD_BLOCK_TIME(FTM_AVATAR_UPDATE_COMPLEXITY); - idleUpdateRenderComplexity(); -} + idleUpdateRenderComplexity(); + } idleUpdateDebugInfo(); } @@ -2778,10 +2777,17 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) }//if ( voiceEnabled ) } -static LLTrace::BlockTimerStatHandle FTM_ATTACHMENT_UPDATE("Update Attachments"); +static void override_bbox(LLDrawable* drawable, LLVector4a* extents) +{ + LL_PROFILE_ZONE_SCOPED; + drawable->setSpatialExtents(extents[0], extents[1]); + drawable->setPositionGroup(LLVector4a(0, 0, 0)); + drawable->movePartition(); +} void LLVOAvatar::idleUpdateMisc(bool detailed_update) { + LL_PROFILE_ZONE_SCOPED; if (LLVOAvatar::sJointDebug) { LL_INFOS() << getFullname() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << LL_ENDL; @@ -2795,7 +2801,6 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) // update attachments positions if (detailed_update) { - LL_RECORD_BLOCK_TIME(FTM_ATTACHMENT_UPDATE); for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -2813,21 +2818,34 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid()) { - // if selecting any attachments, update all of them as non-damped - if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment()) - { - gPipeline.updateMoveNormalAsync(attached_object->mDrawable); - } - else - { - gPipeline.updateMoveDampedAsync(attached_object->mDrawable); - } - - LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge(); - if (bridge) - { - gPipeline.updateMoveNormalAsync(bridge); - } + + //override rigged attachments' octree spatial extents with this avatar's bounding box + LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge(); + bool rigged = false; + if (bridge) + { + //transform avatar bounding box into attachment's coordinate frame + LLVector4a extents[2]; + bridge->transformExtents(mDrawable->getSpatialExtents(), extents); + + if (attached_object->mDrawable->isState(LLDrawable::RIGGED | LLDrawable::RIGGED_CHILD)) + { + rigged = true; + override_bbox(attached_object->mDrawable, extents); + } + } + + + attached_object->mDrawable->makeActive(); + attached_object->mDrawable->updateXform(TRUE); + + if (!rigged) + { + if (bridge) + { + gPipeline.updateMoveNormalAsync(bridge); + } + } attached_object->updateText(); } } @@ -3135,6 +3153,8 @@ void LLVOAvatar::idleUpdateWindEffect() void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) { + LL_PROFILE_ZONE_SCOPED; + // update chat bubble //-------------------------------------------------------------------- // draw text label over character's head @@ -4883,6 +4903,8 @@ bool LLVOAvatar::shouldAlphaMask() //----------------------------------------------------------------------------- U32 LLVOAvatar::renderSkinned() { + LL_PROFILE_ZONE_SCOPED; + U32 num_indices = 0; if (!mIsBuilt) @@ -5051,11 +5073,6 @@ U32 LLVOAvatar::renderSkinned() bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - } - BOOL first_pass = TRUE; if (!LLDrawPoolAvatar::sSkipOpaque) { @@ -5102,11 +5119,6 @@ U32 LLVOAvatar::renderSkinned() } } - if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) - { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - } - if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { LLGLState blend(GL_BLEND, !mIsDummy); @@ -5122,21 +5134,21 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) U32 num_indices = 0; if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (isUIAvatar() || isTextureVisible(TEX_SKIRT_BAKED)) ) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); + gGL.flush(); LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); if (skirt_mesh) { num_indices += skirt_mesh->render(mAdjustedPixelArea, FALSE); } first_pass = FALSE; - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); } if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { if (LLPipeline::sImpostorRender) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + gGL.flush(); } if (isTextureVisible(TEX_HEAD_BAKED)) @@ -5159,7 +5171,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) } if (LLPipeline::sImpostorRender) { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); } } @@ -5191,11 +5203,6 @@ U32 LLVOAvatar::renderRigid() bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - } - if (isTextureVisible(TEX_EYES_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) { LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); @@ -5210,11 +5217,6 @@ U32 LLVOAvatar::renderRigid() } } - if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) - { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - } - return num_indices; } @@ -5265,7 +5267,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) } { LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); + gGL.flush(); gGL.color4ubv(color.mV); gGL.getTexUnit(diffuse_channel)->bind(&mImpostor); @@ -6157,27 +6159,29 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) LLJoint *LLVOAvatar::getJoint( S32 joint_num ) { LLJoint *pJoint = NULL; - S32 collision_start = mNumBones; - S32 attachment_start = mNumBones + mNumCollisionVolumes; - if (joint_num>=attachment_start) + if (joint_num >= 0) { - // Attachment IDs start at 1 - S32 attachment_id = joint_num - attachment_start + 1; - attachment_map_t::iterator iter = mAttachmentPoints.find(attachment_id); - if (iter != mAttachmentPoints.end()) + if (joint_num < mNumBones) { - pJoint = iter->second; + pJoint = mSkeleton[joint_num]; + } + else if (joint_num < mNumBones + mNumCollisionVolumes) + { + S32 collision_id = joint_num - mNumBones; + pJoint = &mCollisionVolumes[collision_id]; + } + else + { + // Attachment IDs start at 1 + S32 attachment_id = joint_num - (mNumBones + mNumCollisionVolumes) + 1; + attachment_map_t::iterator iter = mAttachmentPoints.find(attachment_id); + if (iter != mAttachmentPoints.end()) + { + pJoint = iter->second; + } } } - else if (joint_num>=collision_start) - { - S32 collision_id = joint_num-collision_start; - pJoint = &mCollisionVolumes[collision_id]; - } - else if (joint_num>=0) - { - pJoint = mSkeleton[joint_num]; - } + llassert(!pJoint || pJoint->getJointNum() == joint_num); return pJoint; } @@ -6512,7 +6516,7 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LL LLJoint* pJoint = getJoint( lookingForJoint ); if (pJoint) { - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + const LLVector3& jointPos = LLVector3(pSkinData->mAlternateBindMatrix[i].getTranslation()); if (pJoint->aboveJointPosThreshold(jointPos)) { bool override_changed; @@ -7116,6 +7120,7 @@ void LLVOAvatar::updateGL() { if (mMeshTexturesDirty) { + LL_PROFILE_ZONE_SCOPED updateMeshTextures(); mMeshTexturesDirty = FALSE; } @@ -7124,10 +7129,9 @@ void LLVOAvatar::updateGL() //----------------------------------------------------------------------------- // updateGeometry() //----------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_UPDATE_AVATAR("Update Avatar"); BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_AVATAR); + LL_PROFILE_ZONE_SCOPED; if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))) { return TRUE; @@ -7861,6 +7865,8 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color) // Do rigged mesh attachments display with this av? bool LLVOAvatar::shouldRenderRigged() const { + LL_PROFILE_ZONE_SCOPED; + if (getOverallAppearance() == AOA_NORMAL) { return true; @@ -8125,16 +8131,35 @@ void LLVOAvatar::updateRuthTimer(bool loading) BOOL LLVOAvatar::processFullyLoadedChange(bool loading) { // We wait a little bit before giving the 'all clear', to let things to - // settle down (models to snap into place, textures to get first packets) + // settle down (models to snap into place, textures to get first packets). + // And if viewer isn't aware of some parts yet, this gives them a chance + // to arrive. const F32 LOADED_DELAY = 1.f; - const F32 FIRST_USE_DELAY = 3.f; - if (loading) - mFullyLoadedTimer.reset(); + if (loading) + { + mFullyLoadedTimer.reset(); + } if (mFirstFullyVisible) { - mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > FIRST_USE_DELAY); + if (!isSelf() && loading) + { + // Note that textures can causes 60s delay on thier own + // so this delay might end up on top of textures' delay + mFirstUseDelaySeconds = llclamp( + mFirstSeenTimer.getElapsedTimeF32(), + FIRST_APPEARANCE_CLOUD_MIN_DELAY, + FIRST_APPEARANCE_CLOUD_MAX_DELAY); + + if (shouldImpostor()) + { + // Impostors are less of a priority, + // let them stay cloud longer + mFirstUseDelaySeconds *= 1.25; + } + } + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > mFirstUseDelaySeconds); } else { @@ -8352,6 +8377,7 @@ void LLVOAvatar::updateMeshVisibility() // virtual void LLVOAvatar::updateMeshTextures() { + LL_PROFILE_ZONE_SCOPED static S32 update_counter = 0; mBakedTextureDebugText.clear(); @@ -9420,6 +9446,54 @@ LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te) } +const LLVOAvatar::MatrixPaletteCache& LLVOAvatar::updateSkinInfoMatrixPalette(const LLMeshSkinInfo* skin) +{ + U64 hash = skin->mHash; + MatrixPaletteCache& entry = mMatrixPaletteCache[hash]; + + if (entry.mFrame != gFrameCount) + { + LL_PROFILE_ZONE_SCOPED; + + entry.mFrame = gFrameCount; + + //build matrix palette + U32 count = LLSkinningUtil::getMeshJointCount(skin); + entry.mMatrixPalette.resize(count); + LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, this); + + const LLMatrix4a* mat = &(entry.mMatrixPalette[0]); + + entry.mGLMp.resize(count * 12); + + F32* mp = &(entry.mGLMp[0]); + + for (U32 i = 0; i < count; ++i) + { + F32* m = (F32*)mat[i].mMatrix[0].getF32ptr(); + + U32 idx = i * 12; + + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; + + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; + + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + } + + return entry; +} + // static void LLVOAvatar::getAnimLabels( std::vector<std::string>* labels ) { @@ -10183,6 +10257,7 @@ void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32& void LLVOAvatar::getAssociatedVolumes(std::vector<LLVOVolume*>& volumes) { + LL_PROFILE_ZONE_SCOPED; for ( LLVOAvatar::attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) { LLViewerJointAttachment* attachment = iter->second; @@ -10240,27 +10315,19 @@ void LLVOAvatar::getAssociatedVolumes(std::vector<LLVOVolume*>& volumes) } } -static LLTrace::BlockTimerStatHandle FTM_AVATAR_RIGGING_INFO_UPDATE("Av Upd Rig Info"); -static LLTrace::BlockTimerStatHandle FTM_AVATAR_RIGGING_KEY_UPDATE("Av Upd Rig Key"); -static LLTrace::BlockTimerStatHandle FTM_AVATAR_RIGGING_AVOL_UPDATE("Av Upd Avol"); - // virtual void LLVOAvatar::updateRiggingInfo() { - LL_RECORD_BLOCK_TIME(FTM_AVATAR_RIGGING_INFO_UPDATE); + LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("RigSpammish") << getFullname() << " updating rig tab" << LL_ENDL; std::vector<LLVOVolume*> volumes; - { - LL_RECORD_BLOCK_TIME(FTM_AVATAR_RIGGING_AVOL_UPDATE); - getAssociatedVolumes(volumes); - } + getAssociatedVolumes(volumes); std::map<LLUUID,S32> curr_rigging_info_key; { - LL_RECORD_BLOCK_TIME(FTM_AVATAR_RIGGING_KEY_UPDATE); // Get current rigging info key for (std::vector<LLVOVolume*>::iterator it = volumes.begin(); it != volumes.end(); ++it) { @@ -10422,6 +10489,7 @@ void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue) void LLVOAvatar::idleUpdateRenderComplexity() { + LL_PROFILE_ZONE_SCOPED; if (isControlAvatar()) { LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this); @@ -10949,6 +11017,7 @@ void LLVOAvatar::updateOverallAppearanceAnimations() // Based on isVisuallyMuted(), but has 3 possible results. LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const { + LL_PROFILE_ZONE_SCOPED; AvatarOverallAppearance result = AOA_NORMAL; // Priority order (highest priority first) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 74ef589ca4..ab2a2daf49 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -53,6 +53,7 @@ #include "llviewerstats.h" #include "llvovolume.h" #include "llavatarrendernotifier.h" +#include "llmodel.h" extern const LLUUID ANIM_AGENT_BODY_NOISE; extern const LLUUID ANIM_AGENT_BREATHE_ROT; @@ -77,6 +78,7 @@ class LLViewerJointMesh; const F32 MAX_AVATAR_LOD_FACTOR = 1.0f; +extern U32 gFrameCount; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -87,6 +89,7 @@ class LLVOAvatar : public LLViewerObject, public boost::signals2::trackable { + LL_ALIGN_NEW; LOG_CLASS(LLVOAvatar); public: @@ -99,16 +102,6 @@ public: **/ public: - void* operator new(size_t size) - { - return LLTrace::MemTrackable<LLViewerObject>::aligned_new<16>(size); - } - - void operator delete(void* ptr, size_t size) - { - LLTrace::MemTrackable<LLViewerObject>::aligned_delete<16>(ptr, size); - } - LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual void markDead(); static void initClass(); // Initialize data that's only init'd once per class. @@ -209,6 +202,11 @@ public: virtual LLJoint* getJoint(const std::string &name); LLJoint* getJoint(S32 num); + //if you KNOW joint_num is a valid animated joint index, use getSkeletonJoint for efficiency + inline LLJoint* getSkeletonJoint(S32 joint_num) { return mSkeleton[joint_num]; } + inline size_t getSkeletonJointCount() const { return mSkeleton.size(); } + + void addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LLUUID>* meshes_seen = NULL, bool recursive = true); void removeAttachmentOverridesForObject(const LLUUID& mesh_id); void removeAttachmentOverridesForObject(LLViewerObject *vo); @@ -380,6 +378,9 @@ protected: private: BOOL mFirstFullyVisible; + F32 mFirstUseDelaySeconds; + LLFrameTimer mFirstSeenTimer; + BOOL mFullyLoaded; BOOL mPreviousFullyLoaded; BOOL mFullyLoadedInitialized; @@ -747,6 +748,34 @@ public: void updateMeshVisibility(); LLViewerTexture* getBakedTexture(const U8 te); + // Matrix palette cache entry + class alignas(16) MatrixPaletteCache + { + public: + // Last frame this entry was updated + U32 mFrame; + + // List of Matrix4a's for this entry + LLMeshSkinInfo::matrix_list_t mMatrixPalette; + + // Float array ready to be sent to GL + std::vector<F32> mGLMp; + + MatrixPaletteCache() : + mFrame(gFrameCount - 1) + { + } + }; + + // Accessor for Matrix Palette Cache + // Will do a map lookup for the entry associated with the given MeshSkinInfo + // Will update said entry if it hasn't been updated yet this frame + const MatrixPaletteCache& updateSkinInfoMatrixPalette(const LLMeshSkinInfo* skinInfo); + + // Map of LLMeshSkinInfo::mHash to MatrixPaletteCache + typedef std::unordered_map<U64, MatrixPaletteCache> matrix_palette_cache_t; + matrix_palette_cache_t mMatrixPaletteCache; + protected: void releaseMeshData(); virtual void restoreMeshData(); diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 5ebc65405f..e10a9f9bcb 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -63,8 +63,7 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) //--------------------------------------------------------------------------- LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) -: LLTrace::MemTrackable<LLVOCacheEntry, 16>("LLVOCacheEntry"), - LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), +: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(local_id), mCRC(crc), mUpdateFlags(-1), @@ -83,8 +82,7 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer & } LLVOCacheEntry::LLVOCacheEntry() -: LLTrace::MemTrackable<LLVOCacheEntry, 16>("LLVOCacheEntry"), - LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), +: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(0), mCRC(0), mUpdateFlags(-1), @@ -102,8 +100,7 @@ LLVOCacheEntry::LLVOCacheEntry() } LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) -: LLTrace::MemTrackable<LLVOCacheEntry, 16>("LLVOCacheEntry"), - LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), +: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mBuffer(NULL), mUpdateFlags(-1), mState(INACTIVE), @@ -619,7 +616,6 @@ void LLVOCacheGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c } LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) -: LLTrace::MemTrackable<LLVOCachePartition>("LLVOCachePartition") { mLODPeriod = 16; mRegionp = regionp; diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index dd6afd6b85..c510ff77fc 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -38,9 +38,9 @@ class LLCamera; class LLVOCacheEntry -: public LLViewerOctreeEntryData, - public LLTrace::MemTrackable<LLVOCacheEntry, 16> +: public LLViewerOctreeEntryData { + LL_ALIGN_NEW public: enum { @@ -185,7 +185,7 @@ protected: virtual ~LLVOCacheGroup(); }; -class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTrackable<LLVOCachePartition> +class LLVOCachePartition : public LLViewerOctreePartition { public: LLVOCachePartition(LLViewerRegion* regionp); diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 345e87eea8..9a41eedb54 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -661,11 +661,9 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count } } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_GRASS_VB("Grass VB"); - void LLGrassPartition::getGeometry(LLSpatialGroup* group) { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_GRASS_VB); + LL_PROFILE_ZONE_SCOPED; std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index c7a544f8eb..3d503638e0 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5560,7 +5560,9 @@ void LLVivoxVoiceClient::setVoiceEnabled(bool enabled) bool LLVivoxVoiceClient::voiceEnabled() { - return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice"); + return gSavedSettings.getBOOL("EnableVoiceChat") && + !gSavedSettings.getBOOL("CmdLineDisableVoice") && + !gNonInteractive; } void LLVivoxVoiceClient::setLipSyncEnabled(BOOL enabled) diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index b31afca61d..068e8a131d 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -306,10 +306,9 @@ LLVector3 LLVOPartGroup::getCameraPosition() const return gAgentCamera.getCameraPositionAgent(); } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_PARTICLES("Update Particles"); BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_PARTICLES); + LL_PROFILE_ZONE_SCOPED; dirtySpatialGroup(); @@ -754,10 +753,9 @@ LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp) : mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_PARTICLE_VBO("Particle VBO"); - void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) { + LL_PROFILE_ZONE_SCOPED; if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { return; @@ -769,8 +767,6 @@ void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; } - LL_RECORD_BLOCK_TIME(FTM_REBUILD_PARTICLE_VBO); - group->clearDrawMap(); //get geometry count @@ -843,11 +839,9 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_PARTICLE_GEOM("Particle Geom"); - void LLParticlePartition::getGeometry(LLSpatialGroup* group) { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_PARTICLE_GEOM); + LL_PROFILE_ZONE_SCOPED; std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 878d7287ed..72ec8390a4 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvosky.cpp * @brief LLVOSky class implementation * * $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$ */ @@ -64,7 +64,9 @@ namespace const S32 NUM_TILES_X = 8; const S32 NUM_TILES_Y = 4; const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y; - const S32 NUM_CUBEMAP_FACES = 6; + const S32 NUM_CUBEMAP_FACES = 6; // See SKYTEX_RESOLUTION for face dimensions + const S32 TOTAL_TILES = NUM_CUBEMAP_FACES * NUM_TILES; + const S32 MAX_TILES = TOTAL_TILES + 1; // Heavenly body constants const F32 SUN_DISK_RADIUS = 0.5f; @@ -77,11 +79,6 @@ namespace const LLVector2 TEX10 = LLVector2(1.f, 0.f); const LLVector2 TEX11 = LLVector2(1.f, 1.f); - LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATETIMER("VOSky Update Timer Tick"); - LLTrace::BlockTimerStatHandle FTM_VOSKY_CALC("VOSky Update Calculations"); - LLTrace::BlockTimerStatHandle FTM_VOSKY_CREATETEXTURES("VOSky Update Textures"); - LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATEFORCED("VOSky Update Forced"); - F32Seconds UPDATE_EXPRY(0.25f); const F32 UPDATE_MIN_DELTA_THRESHOLD = 0.0005f; @@ -90,8 +87,6 @@ namespace SkyTex ***************************************/ -S32 LLSkyTex::sComponents = 4; -S32 LLSkyTex::sResolution = 64; S32 LLSkyTex::sCurrent = 0; @@ -105,15 +100,15 @@ LLSkyTex::LLSkyTex() : void LLSkyTex::init(bool isShiny) { mIsShiny = isShiny; - mSkyData = new LLColor4[sResolution * sResolution]; - mSkyDirs = new LLVector3[sResolution * sResolution]; + mSkyData = new LLColor4[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION]; + mSkyDirs = new LLVector3[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION]; for (S32 i = 0; i < 2; ++i) { mTexture[i] = LLViewerTextureManager::getLocalTexture(FALSE); mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP); - mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents); - + mImageRaw[i] = new LLImageRaw(SKYTEX_RESOLUTION, SKYTEX_RESOLUTION, SKYTEX_COMPONENTS); + initEmpty(i); } } @@ -144,7 +139,7 @@ LLSkyTex::~LLSkyTex() S32 LLSkyTex::getResolution() { - return sResolution; + return SKYTEX_RESOLUTION; } S32 LLSkyTex::getCurrent() @@ -172,12 +167,12 @@ S32 LLSkyTex::getWhich(const BOOL curr) void LLSkyTex::initEmpty(const S32 tex) { U8* data = mImageRaw[tex]->getData(); - for (S32 i = 0; i < sResolution; ++i) + for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i) { - for (S32 j = 0; j < sResolution; ++j) + for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j) { - const S32 basic_offset = (i * sResolution + j); - S32 offset = basic_offset * sComponents; + const S32 basic_offset = (i * SKYTEX_RESOLUTION + j); + S32 offset = basic_offset * SKYTEX_COMPONENTS; data[offset] = 0; data[offset+1] = 0; data[offset+2] = 0; @@ -193,12 +188,12 @@ void LLSkyTex::initEmpty(const S32 tex) void LLSkyTex::create() { U8* data = mImageRaw[sCurrent]->getData(); - for (S32 i = 0; i < sResolution; ++i) + for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i) { - for (S32 j = 0; j < sResolution; ++j) + for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j) { - const S32 basic_offset = (i * sResolution + j); - S32 offset = basic_offset * sComponents; + const S32 basic_offset = (i * SKYTEX_RESOLUTION + j); + S32 offset = basic_offset * SKYTEX_COMPONENTS; U32* pix = (U32*)(data + offset); LLColor4U temp = LLColor4U(mSkyData[basic_offset]); *pix = temp.asRGBA(); @@ -208,7 +203,7 @@ void LLSkyTex::create() } void LLSkyTex::createGLImage(S32 which) -{ +{ mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA); mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -395,10 +390,8 @@ const LLVector3* LLHeavenBody::corners() const Sky ***************************************/ - -S32 LLVOSky::sResolution = LLSkyTex::getResolution(); -S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X; -S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y; +const S32 SKYTEX_TILE_RES_X = SKYTEX_RESOLUTION / NUM_TILES_X; +const S32 SKYTEX_TILE_RES_Y = SKYTEX_RESOLUTION / NUM_TILES_Y; LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLStaticViewerObject(id, pcode, regionp, TRUE), @@ -433,7 +426,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) { mFace[i] = NULL; } - + mCameraPosAgent = gAgentCamera.getCameraPositionAgent(); mAtmHeight = ATM_HEIGHT; mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS); @@ -461,30 +454,12 @@ void LLVOSky::init() llassert(!mInitialized); // Update sky at least once to get correct initial sun/moon directions and lighting calcs performed - LLEnvironment::instance().getCurrentSky()->update(); - - updateDirections(); - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + psky->update(); - // invariants across whole sky tex process... - m_atmosphericsVars.blue_density = psky->getBlueDensity(); - m_atmosphericsVars.blue_horizon = psky->getBlueHorizon(); - m_atmosphericsVars.haze_density = psky->getHazeDensity(); - m_atmosphericsVars.haze_horizon = psky->getHazeHorizon(); - m_atmosphericsVars.density_multiplier = psky->getDensityMultiplier(); - m_atmosphericsVars.max_y = psky->getMaxY(); - m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm(); - m_atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor(); - m_atmosphericsVars.ambient = psky->getAmbientColor(); - m_atmosphericsVars.glow = psky->getGlow(); - m_atmosphericsVars.cloud_shadow = psky->getCloudShadow(); - m_atmosphericsVars.dome_radius = psky->getDomeRadius(); - m_atmosphericsVars.dome_offset = psky->getDomeOffset(); - m_atmosphericsVars.light_atten = psky->getLightAttenuation(m_atmosphericsVars.max_y); - m_atmosphericsVars.light_transmittance = psky->getLightTransmittance(m_atmosphericsVars.max_y); - m_atmosphericsVars.total_density = psky->getTotalDensity(); - m_atmosphericsVars.gamma = psky->getGamma(); + updateDirections(psky); + + cacheEnvironment(psky,m_atmosphericsVars); // Initialize the cached normalized direction vectors for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side) @@ -492,7 +467,7 @@ void LLVOSky::init() for (S32 tile = 0; tile < NUM_TILES; ++tile) { initSkyTextureDirs(side, tile); - createSkyTexture(m_atmosphericsVars, side, tile); + createSkyTexture(psky, m_atmosphericsVars, side, tile); } mSkyTex[side].create(); mShinyTex[side].create(); @@ -509,28 +484,35 @@ void LLVOSky::init() } +void LLVOSky::cacheEnvironment(LLSettingsSky::ptr_t psky,AtmosphericsVars& atmosphericsVars) +{ + // NOTE: Also see: LLAtmospherics::updateFog() + // invariants across whole sky tex process... + atmosphericsVars.blue_density = psky->getBlueDensity(); + atmosphericsVars.blue_horizon = psky->getBlueHorizon(); + atmosphericsVars.haze_density = psky->getHazeDensity(); + atmosphericsVars.haze_horizon = psky->getHazeHorizon(); + atmosphericsVars.density_multiplier = psky->getDensityMultiplier(); + atmosphericsVars.distance_multiplier = psky->getDistanceMultiplier(); + atmosphericsVars.max_y = psky->getMaxY(); + atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm(); + atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor(); + atmosphericsVars.ambient = psky->getAmbientColor(); + atmosphericsVars.glow = psky->getGlow(); + atmosphericsVars.cloud_shadow = psky->getCloudShadow(); + atmosphericsVars.dome_radius = psky->getDomeRadius(); + atmosphericsVars.dome_offset = psky->getDomeOffset(); + atmosphericsVars.light_atten = psky->getLightAttenuation(atmosphericsVars.max_y); + atmosphericsVars.light_transmittance = psky->getLightTransmittance(atmosphericsVars.max_y); + atmosphericsVars.total_density = psky->getTotalDensity(); + atmosphericsVars.gamma = psky->getGamma(); +} + void LLVOSky::calc() { + LL_PROFILE_ZONE_SCOPED; LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - - // invariants across whole sky tex process... - m_atmosphericsVars.blue_density = psky->getBlueDensity(); - m_atmosphericsVars.blue_horizon = psky->getBlueHorizon(); - m_atmosphericsVars.haze_density = psky->getHazeDensity(); - m_atmosphericsVars.haze_horizon = psky->getHazeHorizon(); - m_atmosphericsVars.density_multiplier = psky->getDensityMultiplier(); - m_atmosphericsVars.distance_multiplier = psky->getDistanceMultiplier(); - m_atmosphericsVars.max_y = psky->getMaxY(); - m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm(); - m_atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor(); - m_atmosphericsVars.ambient = psky->getAmbientColor(); - m_atmosphericsVars.glow = psky->getGlow(); - m_atmosphericsVars.cloud_shadow = psky->getCloudShadow(); - m_atmosphericsVars.dome_radius = psky->getDomeRadius(); - m_atmosphericsVars.dome_offset = psky->getDomeOffset(); - m_atmosphericsVars.light_atten = psky->getLightAttenuation(m_atmosphericsVars.max_y); - m_atmosphericsVars.light_transmittance = psky->getLightTransmittance(m_atmosphericsVars.max_y); - m_atmosphericsVars.gamma = psky->getGamma(); + cacheEnvironment(psky,m_atmosphericsVars); mSun.setColor(psky->getSunDiffuse()); mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f)); @@ -541,14 +523,14 @@ void LLVOSky::calc() mMoon.renewColor(); } -void LLVOSky::initCubeMap() +void LLVOSky::initCubeMap() { std::vector<LLPointer<LLImageRaw> > images; for (S32 side = 0; side < NUM_CUBEMAP_FACES; side++) { images.push_back(mShinyTex[side].getImageRaw()); } - + if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { mCubeMap = new LLCubeMap(false); @@ -592,12 +574,12 @@ void LLVOSky::restoreGL() setMoonTextures(psky->getMoonTextureId(), psky->getNextMoonTextureId()); } - updateDirections(); + updateDirections(psky); if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) - { + { initCubeMap(); - } + } forceSkyUpdate(); @@ -613,8 +595,8 @@ void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) S32 tile_x = tile % NUM_TILES_X; S32 tile_y = tile / NUM_TILES_X; - S32 tile_x_pos = tile_x * sTileResX; - S32 tile_y_pos = tile_y * sTileResY; + S32 tile_x_pos = tile_x * SKYTEX_TILE_RES_X; + S32 tile_y_pos = tile_y * SKYTEX_TILE_RES_Y; F32 coeff[3] = {0, 0, 0}; const S32 curr_coef = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X @@ -624,11 +606,11 @@ void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) coeff[curr_coef] = (F32)side_dir; - F32 inv_res = 1.f/sResolution; + F32 inv_res = 1.f/SKYTEX_RESOLUTION; S32 x, y; - for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y) + for (y = tile_y_pos; y < (tile_y_pos + SKYTEX_TILE_RES_Y); ++y) { - for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x) + for (x = tile_x_pos; x < (tile_x_pos + SKYTEX_TILE_RES_X); ++x) { coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f; coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f; @@ -640,37 +622,35 @@ void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile) } } -void LLVOSky::createSkyTexture(AtmosphericsVars& vars, const S32 side, const S32 tile) +void LLVOSky::createSkyTexture(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const S32 side, const S32 tile) { - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + const bool low_end = !gPipeline.canUseWindLightShaders(); S32 tile_x = tile % NUM_TILES_X; S32 tile_y = tile / NUM_TILES_X; - S32 tile_x_pos = tile_x * sTileResX; - S32 tile_y_pos = tile_y * sTileResY; + S32 tile_x_pos = tile_x * SKYTEX_TILE_RES_X; + S32 tile_y_pos = tile_y * SKYTEX_TILE_RES_Y; S32 x, y; - for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y) + for (y = tile_y_pos; y < (tile_y_pos + SKYTEX_TILE_RES_Y); ++y) { - for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x) + for (x = tile_x_pos; x < (tile_x_pos + SKYTEX_TILE_RES_X); ++x) { - mSkyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mSkyTex[side].getDir(x, y), false), x, y); - mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mShinyTex[side].getDir(x, y), true), x, y); + mSkyTex [side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mSkyTex [side].getDir(x, y), false, low_end), x, y); + mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mShinyTex[side].getDir(x, y), true , low_end), x, y); } } } -void LLVOSky::updateDirections(void) +void LLVOSky::updateDirections(LLSettingsSky::ptr_t psky) { - LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - mSun.setDirection(psky->getSunDirection()); - mMoon.setDirection(psky->getMoonDirection()); + mMoon.setDirection(psky->getMoonDirection()); mSun.setRotation(psky->getSunRotation()); - mMoon.setRotation(psky->getMoonRotation()); - mSun.renewDirection(); - mMoon.renewDirection(); + mMoon.setRotation(psky->getMoonRotation()); + mSun.renewDirection(); + mMoon.renewDirection(); } void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time) @@ -692,11 +672,6 @@ bool LLVOSky::updateSky() if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))) { - return TRUE; - } - - if (mDead) - { // It's dead. Don't update it. return TRUE; } @@ -706,18 +681,18 @@ bool LLVOSky::updateSky() return TRUE; } + LL_PROFILE_ZONE_SCOPED; + static S32 next_frame = 0; - const S32 total_no_tiles = NUM_CUBEMAP_FACES * NUM_TILES; - const S32 cycle_frame_no = total_no_tiles + 1; - + mNeedUpdate = mForceUpdate; ++next_frame; - next_frame = next_frame % cycle_frame_no; + next_frame = next_frame % MAX_TILES; - mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no; + mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / MAX_TILES; LLHeavenBody::setInterpVal( mInterpVal ); - updateDirections(); + updateDirections(psky); if (!mCubeMap) { @@ -725,10 +700,9 @@ bool LLVOSky::updateSky() mForceUpdate = FALSE; return TRUE; } - + if (mCubeMapUpdateStage < 0) { - LL_RECORD_BLOCK_TIME(FTM_VOSKY_CALC); calc(); bool same_atmospherics = approximatelyEqual(m_lastAtmosphericsVars, m_atmosphericsVars, UPDATE_MIN_DELTA_THRESHOLD); @@ -745,7 +719,7 @@ bool LLVOSky::updateSky() } else if (mCubeMapUpdateStage == NUM_CUBEMAP_FACES) { - LL_RECORD_BLOCK_TIME(FTM_VOSKY_UPDATEFORCED); + LL_PROFILE_ZONE_NAMED("updateSky - forced"); LLSkyTex::stepCurrent(); bool is_alm_wl_sky = gPipeline.canUseWindLightShaders(); @@ -805,8 +779,8 @@ bool LLVOSky::updateSky() } // run 0 to 5 faces, each face in own frame else if (mCubeMapUpdateStage >= 0 && mCubeMapUpdateStage < NUM_CUBEMAP_FACES) - { - LL_RECORD_BLOCK_TIME(FTM_VOSKY_CREATETEXTURES); + { + LL_PROFILE_ZONE_NAMED("updateSky - create"); S32 side = mCubeMapUpdateStage; // CPU hungry part, createSkyTexture() is math heavy // Prior to EEP it was mostly per tile, but since EPP it is per face. @@ -815,7 +789,7 @@ bool LLVOSky::updateSky() // instead of executing per face, or may be can be moved to shaders) for (S32 tile = 0; tile < NUM_TILES; tile++) { - createSkyTexture(m_atmosphericsVars, side, tile); + createSkyTexture(psky, m_atmosphericsVars, side, tile); } mCubeMapUpdateStage++; } @@ -889,10 +863,10 @@ void LLVOSky::setSunScale(F32 sun_scale) void LLVOSky::setMoonScale(F32 moon_scale) { mMoonScale = moon_scale; - } - +} + void LLVOSky::setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next) - { +{ // We test the UUIDs here because we explicitly do not want the default image returned by getFetchedTexture in that case... mSunTexturep[0] = sun_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mSunTexturep[1] = sun_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); @@ -910,32 +884,32 @@ void LLVOSky::setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_textur LLViewerTexture* current_tex1 = mFace[FACE_SUN]->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP); if (current_tex0 && (mSunTexturep[0] != current_tex0) && current_tex0->isViewerMediaTexture()) - { + { static_cast<LLViewerMediaTexture*>(current_tex0)->removeMediaFromFace(mFace[FACE_SUN]); } if (current_tex1 && (mSunTexturep[1] != current_tex1) && current_tex1->isViewerMediaTexture()) - { + { static_cast<LLViewerMediaTexture*>(current_tex1)->removeMediaFromFace(mFace[FACE_SUN]); - } + } mFace[FACE_SUN]->setTexture(LLRender::DIFFUSE_MAP, mSunTexturep[0]); if (can_use_wl) { if (mSunTexturep[1]) - { - mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); - } + { + mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); + } mFace[FACE_SUN]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mSunTexturep[1]); - } - } - } + } + } +} void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next) - { +{ LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - + bool can_use_wl = gPipeline.canUseWindLightShaders(); mMoonTexturep[0] = moon_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); @@ -944,17 +918,17 @@ void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_tex if (mFace[FACE_MOON]) { if (mMoonTexturep[0]) - { - mMoonTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - } + { + mMoonTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); + } mFace[FACE_MOON]->setTexture(LLRender::DIFFUSE_MAP, mMoonTexturep[0]); if (mMoonTexturep[1] && can_use_wl) - { - mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); + { + mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); mFace[FACE_MOON]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mMoonTexturep[1]); - } - } + } + } } void LLVOSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next) @@ -963,7 +937,7 @@ void LLVOSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLU mCloudNoiseTexturep[0] = cloud_noise_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mCloudNoiseTexturep[1] = cloud_noise_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); - + if (mCloudNoiseTexturep[0]) { mCloudNoiseTexturep[0]->setAddressMode(LLTexUnit::TAM_WRAP); @@ -986,21 +960,19 @@ void LLVOSky::setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_ mBloomTexturep[1] = bloom_tex_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); if (mBloomTexturep[0]) -{ - mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); + { + mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP); } if (mBloomTexturep[1]) - { - mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); + { + mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP); } - } - -static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Sky Geometry"); +} BOOL LLVOSky::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_GEO_SKY); + LL_PROFILE_ZONE_SCOPED; if (mFace[FACE_REFLECTION] == NULL) { LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); @@ -1029,11 +1001,11 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) LLStrider<LLVector2> texCoordsp; LLStrider<U16> indicesp; U16 index_offset; - LLFace *face; + LLFace *face; for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side) { - face = mFace[FACE_SIDE0 + side]; + face = mFace[FACE_SIDE0 + side]; if (!face->getVertexBuffer()) { @@ -1045,7 +1017,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) face->setVertexBuffer(buff); index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - + S32 vtx = 0; S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X S32 side_dir = side & 1; // even - 0, odd - 1 @@ -1164,11 +1136,11 @@ bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const hb.setVisible(TRUE); - facep = mFace[f]; + facep = mFace[f]; if (!facep->getVertexBuffer()) { - facep->setSize(4, 6); + facep->setSize(4, 6); LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); if (!buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE)) { @@ -1402,7 +1374,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, dt_clip = -0.1f; } - LLFace *face = mFace[FACE_REFLECTION]; + LLFace *face = mFace[FACE_REFLECTION]; if (face) { @@ -1420,13 +1392,13 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, face->setGeomIndex(0); face->setVertexBuffer(buff); } - + LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> texCoordsp; LLStrider<U16> indicesp; S32 index_offset; - + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { @@ -1444,7 +1416,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, LLColor4 hb_refl_col = (1 - attenuation) * hb_col + attenuation * getSkyFogColor(); face->setFaceColor(hb_refl_col); - + LLVector3 v_far[2]; v_far[0] = v_refl_corner[1]; v_far[1] = v_refl_corner[3]; @@ -1568,52 +1540,53 @@ void LLVOSky::updateFog(const F32 distance) } void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLVector3 &moon_dir_cfr) - { - mSun.setDirection(sun_dir_cfr); - mMoon.setDirection(moon_dir_cfr); +{ + mSun.setDirection(sun_dir_cfr); + mMoon.setDirection(moon_dir_cfr); - // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping - // on the upward facing faces of cubes. - { - // Same as dot product with the up direction + clamp. - F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]); - sunDot *= sunDot; - - // Create normalized vector that has the sunDir pushed south about an hour and change. - LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; - - // Blend between normal sun dir and adjusted sun dir based on how close we are - // to having the sun overhead. - mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot); - mBumpSunDir.normalize(); - } - updateDirections(); - } + // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping + // on the upward facing faces of cubes. + // Same as dot product with the up direction + clamp. + F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]); + sunDot *= sunDot; + + // Create normalized vector that has the sunDir pushed south about an hour and change. + LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; + + // Blend between normal sun dir and adjusted sun dir based on how close we are + // to having the sun overhead. + mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot); + mBumpSunDir.normalize(); + + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + updateDirections(psky); +} void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr) - { - mSun.setDirection(sun_dir_cfr); +{ + mSun.setDirection(sun_dir_cfr); - // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping - // on the upward facing faces of cubes. - { - // Same as dot product with the up direction + clamp. - F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]); - sunDot *= sunDot; + // Push the sun "South" as it approaches directly overhead so that we can always see bump mapping + // on the upward facing faces of cubes. + // Same as dot product with the up direction + clamp. + F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]); + sunDot *= sunDot; - // Create normalized vector that has the sunDir pushed south about an hour and change. - LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; + // Create normalized vector that has the sunDir pushed south about an hour and change. + LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f; - // Blend between normal sun dir and adjusted sun dir based on how close we are - // to having the sun overhead. - mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot); - mBumpSunDir.normalize(); - } - updateDirections(); + // Blend between normal sun dir and adjusted sun dir based on how close we are + // to having the sun overhead. + mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot); + mBumpSunDir.normalize(); + + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + updateDirections(psky); } void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr) { - mMoon.setDirection(moon_dir_cfr); - updateDirections(); + mMoon.setDirection(moon_dir_cfr); + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); + updateDirections(psky); } diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index 39e42bbb24..5941ab6e3b 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -43,6 +43,9 @@ const F32 HEAVENLY_BODY_DIST = HORIZON_DIST - 20.f; const F32 HEAVENLY_BODY_FACTOR = 0.1f; const F32 HEAVENLY_BODY_SCALE = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR; +const F32 SKYTEX_COMPONENTS = 4; +const F32 SKYTEX_RESOLUTION = 64; + class LLFace; class LLHaze; @@ -50,8 +53,6 @@ class LLSkyTex { friend class LLVOSky; private: - static S32 sResolution; - static S32 sComponents; LLPointer<LLViewerTexture> mTexture[2]; LLPointer<LLImageRaw> mImageRaw[2]; LLColor4 *mSkyData; @@ -82,25 +83,25 @@ protected: void setDir(const LLVector3 &dir, const S32 i, const S32 j) { - S32 offset = i * sResolution + j; + S32 offset = i * SKYTEX_RESOLUTION + j; mSkyDirs[offset] = dir; } const LLVector3 &getDir(const S32 i, const S32 j) const { - S32 offset = i * sResolution + j; + S32 offset = i * SKYTEX_RESOLUTION + j; return mSkyDirs[offset]; } void setPixel(const LLColor4 &col, const S32 i, const S32 j) { - S32 offset = i * sResolution + j; + S32 offset = i * SKYTEX_RESOLUTION + j; mSkyData[offset] = col; } void setPixel(const LLColor4U &col, const S32 i, const S32 j) { - S32 offset = (i * sResolution + j) * sComponents; + S32 offset = (i * SKYTEX_RESOLUTION + j) * SKYTEX_COMPONENTS; U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]); *pix = col.asRGBA(); } @@ -108,7 +109,7 @@ protected: LLColor4U getPixel(const S32 i, const S32 j) { LLColor4U col; - S32 offset = (i * sResolution + j) * sComponents; + S32 offset = (i * SKYTEX_RESOLUTION + j) * SKYTEX_COMPONENTS; U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]); col.fromRGBA( *pix ); return col; @@ -214,12 +215,12 @@ public: // Initialize/delete data that's only inited once per class. void init(); void initCubeMap(); - void initEmpty(); void cleanupGL(); void restoreGL(); void calc(); + void cacheEnvironment(LLSettingsSky::ptr_t psky, AtmosphericsVars& atmosphericsVars); /*virtual*/ void idleUpdate(LLAgent &agent, const F64 &time); bool updateSky(); @@ -253,8 +254,6 @@ public: LLColor4 getSkyFogColor() const { return m_legacyAtmospherics.getFogColor(); } LLColor4 getGLFogColor() const { return m_legacyAtmospherics.getGLFogColor(); } - LLColor4U getFadeColor() const; - void setCloudDensity(F32 cloud_density) { mCloudDensity = cloud_density; } void setWind ( const LLVector3& wind ) { mWind = wind.length(); } @@ -299,10 +298,10 @@ public: protected: ~LLVOSky(); - void updateDirections(void); + void updateDirections(LLSettingsSky::ptr_t psky); void initSkyTextureDirs(const S32 side, const S32 tile); - void createSkyTexture(AtmosphericsVars& vars, const S32 side, const S32 tile); + void createSkyTexture(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const S32 side, const S32 tile); LLPointer<LLViewerFetchedTexture> mSunTexturep[2]; LLPointer<LLViewerFetchedTexture> mMoonTexturep[2]; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 897bace4e1..b0af565867 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -59,63 +59,7 @@ public: // virtual void setupVertexBuffer(U32 data_mask) { - if (LLGLSLShader::sNoFixedFunction) - { //just use default if shaders are in play - LLVertexBuffer::setupVertexBuffer(data_mask & ~(MAP_TEXCOORD2 | MAP_TEXCOORD3)); - return; - } - - volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; - - //assume tex coords 2 and 3 are present - U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3; - - if ((data_mask & type_mask) != data_mask) - { - LL_ERRS() << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << LL_ENDL; - } - - if (data_mask & MAP_NORMAL) - { - glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); - } - if (data_mask & MAP_TEXCOORD3) - { //substitute tex coord 1 for tex coord 3 - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TEXCOORD2) - { //substitute tex coord 0 for tex coord 2 - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TEXCOORD1) - { - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TANGENT) - { - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TANGENT], (void*)(base + mOffsets[TYPE_TANGENT])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - if (data_mask & MAP_TEXCOORD0) - { - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); - } - if (data_mask & MAP_COLOR) - { - glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); - } - - if (data_mask & MAP_VERTEX) - { - glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); - } + LLVertexBuffer::setupVertexBuffer(data_mask & ~(MAP_TEXCOORD2 | MAP_TEXCOORD3)); } }; @@ -212,19 +156,19 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) return mDrawable; } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_TERRAIN("Update Terrain"); void LLVOSurfacePatch::updateGL() { if (mPatchp) { + LL_PROFILE_ZONE_SCOPED mPatchp->updateGL(); } } BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_TERRAIN); + LL_PROFILE_ZONE_SCOPED; dirtySpatialGroup(TRUE); @@ -1070,10 +1014,9 @@ LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage) return new LLVertexBufferTerrain(); } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_TERRAIN_VB("Terrain VB"); void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_TERRAIN_VB); + LL_PROFILE_ZONE_SCOPED; LLVertexBuffer* buffer = group->mVertexBuffer; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 41099cb570..493162b47b 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -493,11 +493,9 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) const S32 LEAF_INDICES = 24; const S32 LEAF_VERTICES = 16; -static LLTrace::BlockTimerStatHandle FTM_UPDATE_TREE("Update Tree"); - BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_TREE); + LL_PROFILE_ZONE_SCOPED; if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index ca5305b169..c49ac895ca 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -103,10 +103,6 @@ S32 LLVOVolume::mRenderComplexity_current = 0; LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL; LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL; -static LLTrace::BlockTimerStatHandle FTM_GEN_TRIANGLES("Generate Triangles"); -static LLTrace::BlockTimerStatHandle FTM_GEN_VOLUME("Generate Volumes"); -static LLTrace::BlockTimerStatHandle FTM_VOLUME_TEXTURES("Volume Textures"); - extern BOOL gGLDebugLoggingEnabled; // Implementation class of LLMediaDataClientObject. See llmediadataclient.h @@ -716,7 +712,7 @@ BOOL LLVOVolume::isVisible() const void LLVOVolume::updateTextureVirtualSize(bool forced) { - LL_RECORD_BLOCK_TIME(FTM_VOLUME_TEXTURES); + LL_PROFILE_ZONE_SCOPED; // Update the pixel area of all faces if (mDrawable.isNull()) @@ -995,6 +991,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) { + LL_PROFILE_ZONE_SCOPED; LLVolumeParams volume_params = params_in; S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; @@ -1622,6 +1619,7 @@ BOOL LLVOVolume::setParent(LLViewerObject* parent) // NOTE: regenFaces() MUST be followed by genTriangles()! void LLVOVolume::regenFaces() { + LL_PROFILE_ZONE_SCOPED; // remove existing faces BOOL count_changed = mNumFaces != getNumTEs(); @@ -1669,14 +1667,15 @@ void LLVOVolume::regenFaces() BOOL LLVOVolume::genBBoxes(BOOL force_global) { - BOOL res = TRUE; + LL_PROFILE_ZONE_SCOPED; + BOOL res = TRUE; - LLVector4a min,max; + LLVector4a min, max; - min.clear(); - max.clear(); + min.clear(); + max.clear(); - BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); + BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED); if (getRiggedVolume()) { @@ -1687,74 +1686,112 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) // Without the flag, this will remove unused rigged volumes, which we are not currently very aggressive about. updateRiggedVolume(); } - - LLVolume* volume = mRiggedVolume; - if (!volume) - { - volume = getVolume(); - } + + LLVolume* volume = mRiggedVolume; + if (!volume) + { + volume = getVolume(); + } bool any_valid_boxes = false; - + if (getRiggedVolume()) { LL_DEBUGS("RiggedBox") << "rebuilding box, volume face count " << getVolume()->getNumVolumeFaces() << " drawable face count " << mDrawable->getNumFaces() << LL_ENDL; } + // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() - for (S32 i = 0; - i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); - i++) - { - LLFace *face = mDrawable->getFace(i); - if (!face) - { - continue; - } + for (S32 i = 0; + i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs(); + i++) + { + LLFace* face = mDrawable->getFace(i); + if (!face) + { + continue; + } BOOL face_res = face->genVolumeBBoxes(*volume, i, - mRelativeXform, - (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); + mRelativeXform, + (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); res &= face_res; // note that this result is never used - + // MAINT-8264 - ignore bboxes of ill-formed faces. if (!face_res) { continue; } - if (rebuild) - { + if (rebuild) + { if (getRiggedVolume()) { LL_DEBUGS("RiggedBox") << "rebuilding box, face " << i << " extents " << face->mExtents[0] << ", " << face->mExtents[1] << LL_ENDL; } - if (!any_valid_boxes) - { - min = face->mExtents[0]; - max = face->mExtents[1]; + if (!any_valid_boxes) + { + min = face->mExtents[0]; + max = face->mExtents[1]; any_valid_boxes = true; - } - else - { - min.setMin(min, face->mExtents[0]); - max.setMax(max, face->mExtents[1]); - } - } - } + } + else + { + min.setMin(min, face->mExtents[0]); + max.setMax(max, face->mExtents[1]); + } + } + } + + bool rigged = false; + + if (!isAnimatedObject()) + { + rigged = isRiggedMesh() && isAttachment(); + } + else + { + rigged = isRiggedMesh() && getControlAvatar() && getControlAvatar()->mPlaying; + } if (any_valid_boxes) { if (rebuild) { - if (getRiggedVolume()) + //get the Avatar associated with this object if it's rigged + LLVOAvatar* avatar = nullptr; + if (isRiggedMesh()) { - LL_DEBUGS("RiggedBox") << "rebuilding got extents " << min << ", " << max << LL_ENDL; + if (!isAnimatedObject()) + { + if (isAttachment()) + { + avatar = getAvatar(); + } + } + else + { + LLControlAvatar* controlAvatar = getControlAvatar(); + if (controlAvatar && controlAvatar->mPlaying) + { + avatar = controlAvatar; + } + } } - mDrawable->setSpatialExtents(min,max); - min.add(max); - min.mul(0.5f); - mDrawable->setPositionGroup(min); - } + mDrawable->setSpatialExtents(min, max); + + if (avatar) + { + // put all rigged drawables in the same octree node for better batching + mDrawable->setPositionGroup(LLVector4a(0, 0, 0)); + } + else + { + min.add(max); + min.mul(0.5f); + mDrawable->setPositionGroup(min); + } + } + updateRadius(); mDrawable->movePartition(); } @@ -1762,8 +1799,8 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) { LL_DEBUGS("RiggedBox") << "genBBoxes failed to find any valid face boxes" << LL_ENDL; } - - return res; + + return res; } void LLVOVolume::preRebuild() @@ -1879,12 +1916,9 @@ void LLVOVolume::updateRelativeXform(bool force_identity) } } -static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); - bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) { + LL_PROFILE_ZONE_SCOPED; bool regen_faces = false; LLVolume *old_volumep, *new_volumep; @@ -1897,7 +1931,6 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) old_volumep = NULL; { - LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); const LLVolumeParams &volume_params = getVolume()->getParams(); setVolume(volume_params, 0); } @@ -1925,7 +1958,6 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); if (regen_faces) { @@ -1950,14 +1982,11 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); + LL_PROFILE_ZONE_SCOPED; if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) { - { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_RIGGED_VOLUME); - updateRiggedVolume(); - } + updateRiggedVolume(); genBBoxes(FALSE); mDrawable->clearState(LLDrawable::REBUILD_RIGGED); } @@ -1966,7 +1995,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { BOOL res; { - LL_RECORD_BLOCK_TIME(FTM_GEN_FLEX); res = mVolumeImpl->doUpdateGeometry(drawable); } updateFaceFlags(); @@ -2006,7 +2034,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) } if (!was_regen_faces) { - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); regenFaces(); } @@ -2029,7 +2056,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { compiled = TRUE; // All it did was move or we changed the texture coordinate offset - LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); genBBoxes(FALSE); } @@ -3579,7 +3605,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const { if (getVolume()) { - return gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); + return gMeshRepo.getSkinInfo(getMeshID(), this); } else { @@ -3741,11 +3767,9 @@ void LLVOVolume::afterReparent() } //---------------------------------------------------------------------------- -static LLTrace::BlockTimerStatHandle FTM_VOVOL_RIGGING_INFO("VOVol Rigging Info"); - void LLVOVolume::updateRiggingInfo() { - LL_RECORD_BLOCK_TIME(FTM_VOVOL_RIGGING_INFO); + LL_PROFILE_ZONE_SCOPED; if (isRiggedMesh()) { const LLMeshSkinInfo* skin = getSkinInfo(); @@ -4355,6 +4379,7 @@ void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) F32 LLVOVolume::getBinRadius() { + LL_PROFILE_ZONE_SCOPED; F32 radius; F32 scale = 1.f; @@ -4750,6 +4775,7 @@ void LLVOVolume::clearRiggedVolume() void LLVOVolume::updateRiggedVolume(bool force_update) { + LL_PROFILE_ZONE_SCOPED; //Update mRiggedVolume to match current animation frame of avatar. //Also update position/size in octree. @@ -4785,11 +4811,9 @@ void LLVOVolume::updateRiggedVolume(bool force_update) mRiggedVolume->update(skin, avatar, volume); } -static LLTrace::BlockTimerStatHandle FTM_SKIN_RIGGED("Skin"); -static LLTrace::BlockTimerStatHandle FTM_RIGGED_OCTREE("Octree"); - void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) { + LL_PROFILE_ZONE_SCOPED; bool copy = false; if (volume->getNumVolumeFaces() != getNumVolumeFaces()) { @@ -4810,7 +4834,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons if (copy) { - copyVolumeFaces(volume); + copyVolumeFaces(volume); } else { @@ -4831,7 +4855,8 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons LLMatrix4a mat[kMaxJoints]; U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); - LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); + LLSkinningUtil::initSkinningMatrixPalette(mat, maxJoints, skin, avatar); + const LLMatrix4a bind_shape_matrix = skin->mBindShapeMatrix; S32 rigged_vert_count = 0; S32 rigged_face_count = 0; @@ -4847,15 +4872,11 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons if ( weight ) { LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); - LLMatrix4a bind_shape_matrix; - bind_shape_matrix.loadu(skin->mBindShapeMatrix); LLVector4a* pos = dst_face.mPositions; if (pos && dst_face.mExtents) { - LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); - U32 max_joints = LLSkinningUtil::getMaxJointCount(); rigged_vert_count += dst_face.mNumVertices; rigged_face_count++; @@ -4926,8 +4947,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons } { - LL_RECORD_BLOCK_TIME(FTM_RIGGED_OCTREE); - delete dst_face.mOctree; + delete dst_face.mOctree; dst_face.mOctree = NULL; LLVector4a size; @@ -5029,13 +5049,13 @@ bool can_batch_texture(LLFace* facep) const static U32 MAX_FACE_COUNT = 4096U; int32_t LLVolumeGeometryManager::sInstanceCount = 0; -LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL; -LLFace** LLVolumeGeometryManager::sBumpFaces = NULL; -LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL; -LLFace** LLVolumeGeometryManager::sNormFaces = NULL; -LLFace** LLVolumeGeometryManager::sSpecFaces = NULL; -LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL; -LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL; +LLFace** LLVolumeGeometryManager::sFullbrightFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sBumpFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sSimpleFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sNormFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sSpecFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sNormSpecFaces[2] = { NULL }; +LLFace** LLVolumeGeometryManager::sAlphaFaces[2] = { NULL }; LLVolumeGeometryManager::LLVolumeGeometryManager() : LLGeometryManager() @@ -5063,39 +5083,43 @@ LLVolumeGeometryManager::~LLVolumeGeometryManager() void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) { - sFullbrightFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sBumpFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sSimpleFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sNormFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sNormSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); - sAlphaFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + for (int i = 0; i < 2; ++i) + { + sFullbrightFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sBumpFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sSimpleFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sNormFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sNormSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + sAlphaFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*))); + } } void LLVolumeGeometryManager::freeFaces() { - ll_aligned_free<64>(sFullbrightFaces); - ll_aligned_free<64>(sBumpFaces); - ll_aligned_free<64>(sSimpleFaces); - ll_aligned_free<64>(sNormFaces); - ll_aligned_free<64>(sSpecFaces); - ll_aligned_free<64>(sNormSpecFaces); - ll_aligned_free<64>(sAlphaFaces); - - sFullbrightFaces = NULL; - sBumpFaces = NULL; - sSimpleFaces = NULL; - sNormFaces = NULL; - sSpecFaces = NULL; - sNormSpecFaces = NULL; - sAlphaFaces = NULL; + for (int i = 0; i < 2; ++i) + { + ll_aligned_free<64>(sFullbrightFaces[i]); + ll_aligned_free<64>(sBumpFaces[i]); + ll_aligned_free<64>(sSimpleFaces[i]); + ll_aligned_free<64>(sNormFaces[i]); + ll_aligned_free<64>(sSpecFaces[i]); + ll_aligned_free<64>(sNormSpecFaces[i]); + ll_aligned_free<64>(sAlphaFaces[i]); + + sFullbrightFaces[i] = NULL; + sBumpFaces[i] = NULL; + sSimpleFaces[i] = NULL; + sNormFaces[i] = NULL; + sSpecFaces[i] = NULL; + sNormSpecFaces[i] = NULL; + sAlphaFaces[i] = NULL; + } } -static LLTrace::BlockTimerStatHandle FTM_REGISTER_FACE("Register Face"); - void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { - LL_RECORD_BLOCK_TIME(FTM_REGISTER_FACE); + LL_PROFILE_ZONE_SCOPED; if ( type == LLRenderPass::PASS_ALPHA && facep->getTextureEntry()->getMaterialParams().notNull() && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT) @@ -5111,8 +5135,18 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, return; } + U32 passType = type; + + bool rigged = facep->isState(LLFace::RIGGED); + + if (rigged && type != LLRenderPass::PASS_ALPHA) + { + // hacky, should probably clean up -- if this face is rigged, put it in "type + 1" + // See LLRenderPass PASS_foo enum + passType += 1; + } //add face to drawmap - LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type]; + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[passType]; S32 idx = draw_vec.size()-1; @@ -5138,7 +5172,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LLDrawable* drawable = facep->getDrawable(); - if (drawable->isState(LLDrawable::ANIMATED_CHILD)) + if (rigged) + { + // rigged meshes ignore their model matrix + model_mat = nullptr; + } + else if (drawable->isState(LLDrawable::ANIMATED_CHILD)) { model_mat = &drawable->getWorldMatrix(); } @@ -5179,6 +5218,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, } } + F32 vsize = facep->getVirtualSize(); //TODO -- adjust by texture scale? if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0) { @@ -5192,10 +5232,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, { batchable = true; draw_vec[idx]->mTextureList[index] = tex; + draw_vec[idx]->mTextureListVSize[index] = vsize; } else if (draw_vec[idx]->mTextureList[index] == tex) { //this face's texture index can be used with this batch batchable = true; + draw_vec[idx]->mTextureListVSize[index] = llmax(vsize, draw_vec[idx]->mTextureListVSize[index]); } } else @@ -5212,7 +5254,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && #endif - draw_vec[idx]->mMaterial == mat && + //draw_vec[idx]->mMaterial == mat && draw_vec[idx]->mMaterialID == mat_id && draw_vec[idx]->mFullbright == fullbright && draw_vec[idx]->mBump == bump && @@ -5220,16 +5262,20 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mTextureMatrix == tex_mat && draw_vec[idx]->mModelMatrix == model_mat && draw_vec[idx]->mShaderMask == shader_mask && - draw_vec[idx]->mSelected == selected) + draw_vec[idx]->mSelected == selected && + draw_vec[idx]->mAvatar == facep->mAvatar && + draw_vec[idx]->getSkinHash() == facep->getSkinHash()) { draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); - draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= draw_vec[idx]->mTextureList.size()) { draw_vec[idx]->mTextureList.resize(index+1); draw_vec[idx]->mTextureList[index] = tex; + draw_vec[idx]->mTextureListVSize.resize(index + 1); + 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]); @@ -5244,7 +5290,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex, facep->getVertexBuffer(), selected, fullbright, bump); draw_info->mGroup = group; - draw_info->mVSize = facep->getVirtualSize(); + draw_info->mVSize = vsize; draw_vec.push_back(draw_info); draw_info->mTextureMatrix = tex_mat; draw_info->mModelMatrix = model_mat; @@ -5266,6 +5312,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mSpecularMap = NULL; draw_info->mMaterial = mat; draw_info->mShaderMask = shader_mask; + draw_info->mAvatar = facep->mAvatar; + draw_info->mSkinInfo = facep->mSkinInfo; if (mat) { @@ -5317,6 +5365,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, { //initialize texture list for texture batching draw_info->mTextureList.resize(index+1); draw_info->mTextureList[index] = tex; + draw_info->mTextureListVSize.resize(index + 1); + draw_info->mTextureListVSize[index] = vsize; } draw_info->validate(); } @@ -5327,38 +5377,6 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_VB("Volume VB"); -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_FACE_LIST("Build Face List"); -static LLTrace::BlockTimerStatHandle FTM_REBUILD_VOLUME_GEN_DRAW_INFO("Gen Draw Info"); - -static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) -{ - LLVOAvatar* avatar = vobj->getAvatar(); - - if (avatar) - { - LLDrawable* drawable = avatar->mDrawable; - if (drawable && drawable->getNumFaces() > 0) - { - LLFace* face = drawable->getFace(0); - if (face) - { - LLDrawPool* drawpool = face->getPool(); - if (drawpool) - { - if (drawpool->getType() == LLDrawPool::POOL_AVATAR - || drawpool->getType() == LLDrawPool::POOL_CONTROL_AV) - { - return (LLDrawPoolAvatar*) drawpool; - } - } - } - } - } - - return NULL; -} - void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) { static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); @@ -5434,8 +5452,29 @@ void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value) } } +// add a face pointer to a list of face pointers without going over MAX_COUNT faces +template<typename T> +static inline void add_face(T*** list, U32* count, T* face) +{ + if (face->isState(LLFace::RIGGED)) + { + if (count[1] < MAX_FACE_COUNT) + { + list[1][count[1]++] = face; + } + } + else + { + if (count[0] < MAX_FACE_COUNT) + { + list[0][count[0]++] = face; + } + } +} + void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { + LL_PROFILE_ZONE_SCOPED; if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -5452,8 +5491,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) return; } - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); - group->mBuilt = 1.f; LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); @@ -5481,14 +5518,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) mFaceList.clear(); - U32 fullbright_count = 0; - U32 bump_count = 0; - U32 simple_count = 0; - U32 alpha_count = 0; - U32 norm_count = 0; - U32 spec_count = 0; - U32 normspec_count = 0; - + U32 fullbright_count[2] = { 0 }; + U32 bump_count[2] = { 0 }; + U32 simple_count[2] = { 0 }; + U32 alpha_count[2] = { 0 }; + U32 norm_count[2] = { 0 }; + U32 spec_count[2] = { 0 }; + U32 normspec_count[2] = { 0 }; U32 useage = group->getSpatialPartition()->mBufferUsage; @@ -5510,7 +5546,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) #endif { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); + LL_PROFILE_ZONE_NAMED("rebuildGeom - face list"); //get all the faces into a list for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); @@ -5537,7 +5573,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) std::string vobj_name = llformat("Vol%p", vobj); - if (vobj->isMesh() && + bool is_mesh = vobj->isMesh(); + if (is_mesh && ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) { continue; @@ -5550,7 +5587,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); } - bool is_mesh = vobj->isMesh(); + F32 est_tris = vobj->getEstTrianglesMax(); vobj->updateControlAvatar(); @@ -5574,15 +5611,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) drawablep->clearState(LLDrawable::HAS_ALPHA); - if (vobj->isRiggedMesh() && - ((vobj->isAnimatedObject() && vobj->getControlAvatar()) || - (!vobj->isAnimatedObject() && vobj->getAvatar()))) + LLVOAvatar* avatar = nullptr; + const LLMeshSkinInfo* skinInfo = nullptr; + if (is_mesh) + { + skinInfo = vobj->getSkinInfo(); + } + + if (skinInfo) { - vobj->getAvatar()->addAttachmentOverridesForObject(vobj, NULL, false); + if (vobj->isAnimatedObject()) + { + avatar = vobj->getControlAvatar(); + } + else + { + avatar = vobj->getAvatar(); + } + } + + if (avatar != nullptr) + { + avatar->addAttachmentOverridesForObject(vobj, NULL, false); } // Standard rigged mesh attachments: - bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->isAttachment(); + bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to // exclude static objects in animated object linksets. rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && @@ -5606,183 +5660,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //sum up face verts and indices drawablep->updateFaceSize(i); - - if (rigged) - { - if (!facep->isState(LLFace::RIGGED)) - { //completely reset vertex buffer - facep->clearVertexBuffer(); - } - - facep->setState(LLFace::RIGGED); - any_rigged_face = true; - - //get drawpool of avatar with rigged face - LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - if (pool) - { - const LLTextureEntry* te = facep->getTextureEntry(); - - //remove face from old pool if it exists - LLDrawPool* old_pool = facep->getPool(); - if (old_pool - && (old_pool->getType() == LLDrawPool::POOL_AVATAR || old_pool->getType() == LLDrawPool::POOL_CONTROL_AV)) - { - ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); - } - - //add face to new pool - LLViewerTexture* tex = facep->getTexture(); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); - - F32 te_alpha = te->getColor().mV[3]; - - if (te->getGlow()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); - } - - LLMaterial* mat = te->getMaterialParams().get(); - bool fullbright = te->getFullbright(); - - if (mat && LLPipeline::sRenderDeferred) - { - U8 alpha_mode = mat->getDiffuseAlphaMode(); - - bool is_alpha = type == LLDrawPool::POOL_ALPHA && - (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND || - te_alpha < 0.999f); - if (is_alpha) - { //this face needs alpha blending, override alpha mode - alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - - if (fullbright && (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE)) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else if (!is_alpha || te_alpha > 0.f) // //only add the face if it will actually be visible - { - U32 mask = mat->getShaderMask(alpha_mode); - pool->addRiggedFace(facep, mask); - } - - if(vobj->isAnimatedObject() && vobj->isRiggedMesh()) - { - pool->updateRiggedVertexBuffers(vobj->getAvatar()); - } - } - else if (mat) - { - bool is_alpha = type == LLDrawPool::POOL_ALPHA; - U8 mode = mat->getDiffuseAlphaMode(); - bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE || - mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE; - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else if (is_alpha || (te->getColor().mV[3] < 0.999f)) - { - if (te->getColor().mV[3] > 0.f) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - else if (gPipeline.canUseVertexShaders() - && LLPipeline::sRenderBump - && te->getShiny() - && can_be_shiny) - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY); - } - else - { - pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - else - { - if (type == LLDrawPool::POOL_ALPHA) - { - if (te->getColor().mV[3] > 0.f) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); - } - } - } - else if (te->getShiny()) - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); - } - else - { - if (LLPipeline::sRenderDeferred) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); - } - } - } - else - { - if (te->getFullbright()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); - } - } - - - if (LLPipeline::sRenderDeferred) - { - if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) - { - if (te->getBumpmap()) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); - } - else - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); - } - } - } - } - } - - continue; - } - else - { - if (facep->isState(LLFace::RIGGED)) - { //face is not rigged but used to be, remove from rigged face pool - LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); - if (pool) - { - pool->removeRiggedFace(facep); - } - facep->clearState(LLFace::RIGGED); - } - } + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } + facep->setState(LLFace::RIGGED); + facep->mSkinInfo = (LLMeshSkinInfo*) skinInfo; // TODO -- fix ugly de-consting here + facep->mAvatar = avatar; + any_rigged_face = true; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { + //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeFace(facep); + } + facep->clearState(LLFace::RIGGED); + } + } if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { @@ -5792,7 +5695,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) cur_total += facep->getGeomCount(); - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) + if (facep->hasGeometry() && + (rigged || // <-- HACK FIXME -- getPixelArea might be incorrect for rigged objects + facep->getPixelArea() > FORCE_CULL_AREA)) // <-- don't render tiny faces { const LLTextureEntry* te = facep->getTextureEntry(); LLViewerTexture* tex = facep->getTexture(); @@ -5851,21 +5756,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (facep->canRenderAsMask()) { //can be treated as alpha mask - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } + add_face(sSimpleFaces, simple_count, facep); } else { - if (te->getColor().mV[3] > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - } - if (alpha_count < MAX_FACE_COUNT) - { - sAlphaFaces[alpha_count++] = facep; - } + if (te->getColor().mV[3] > 0.f || te->getGlow() > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + add_face(sAlphaFaces, alpha_count, facep); + } + else if (LLDrawPoolAlpha::sShowDebugAlpha) + { + add_face(sAlphaFaces, alpha_count, facep); + } } } else @@ -5885,81 +5788,51 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (mat->getSpecularID().notNull()) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - if (normspec_count < MAX_FACE_COUNT) - { - sNormSpecFaces[normspec_count++] = facep; - } + add_face(sNormSpecFaces, normspec_count, facep); } else { //has normal map (needs texcoord1 and tangent) - if (norm_count < MAX_FACE_COUNT) - { - sNormFaces[norm_count++] = facep; - } + add_face(sNormFaces, norm_count, facep); } } else if (mat->getSpecularID().notNull()) { //has specular map but no normal map, needs texcoord2 - if (spec_count < MAX_FACE_COUNT) - { - sSpecFaces[spec_count++] = facep; - } + add_face(sSpecFaces, spec_count, facep); } else { //has neither specular map nor normal map, only needs texcoord0 - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } + add_face(sSimpleFaces, simple_count, facep); } } else if (te->getBumpmap()) { //needs normal + tangent - if (bump_count < MAX_FACE_COUNT) - { - sBumpFaces[bump_count++] = facep; - } + add_face(sBumpFaces, bump_count, facep); } else if (te->getShiny() || !te->getFullbright()) { //needs normal - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } + add_face(sSimpleFaces, simple_count, facep); } else { //doesn't need normal facep->setState(LLFace::FULLBRIGHT); - if (fullbright_count < MAX_FACE_COUNT) - { - sFullbrightFaces[fullbright_count++] = facep; - } + add_face(sFullbrightFaces, fullbright_count, facep); } } else { if (te->getBumpmap() && LLPipeline::sRenderBump) { //needs normal + tangent - if (bump_count < MAX_FACE_COUNT) - { - sBumpFaces[bump_count++] = facep; - } + add_face(sBumpFaces, bump_count, facep); } else if ((te->getShiny() && LLPipeline::sRenderBump) || !(te->getFullbright() || bake_sunlight)) { //needs normal - if (simple_count < MAX_FACE_COUNT) - { - sSimpleFaces[simple_count++] = facep; - } + add_face(sSimpleFaces, simple_count, facep); } else { //doesn't need normal facep->setState(LLFace::FULLBRIGHT); - if (fullbright_count < MAX_FACE_COUNT) - { - sFullbrightFaces[fullbright_count++] = facep; - } + add_face(sFullbrightFaces, fullbright_count, facep); } } } @@ -5975,6 +5848,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (!drawablep->isState(LLDrawable::RIGGED)) { drawablep->setState(LLDrawable::RIGGED); + LLDrawable* root = drawablep->getRoot(); + if (root != drawablep) + { + root->setState(LLDrawable::RIGGED_CHILD); + } //first time this is drawable is being marked as rigged, // do another LoD update to use avatar bounding box @@ -6014,6 +5892,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; + // add extra vertex data for deferred rendering (not necessarily for batching textures) if (batch_textures) { bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; @@ -6026,13 +5905,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) U32 geometryBytes = 0; - geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); - geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); - geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); - geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); - geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); + U32 extra_mask = LLVertexBuffer::MAP_TEXTURE_INDEX; + geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[0], simple_count[0], FALSE, batch_textures); + geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[0], fullbright_count[0], FALSE, batch_textures); + geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[0], alpha_count[0], TRUE, batch_textures); + geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[0], bump_count[0], FALSE, FALSE); + geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[0], norm_count[0], FALSE, FALSE); + geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[0], spec_count[0], FALSE, FALSE); + geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[0], normspec_count[0], FALSE, FALSE); + + extra_mask |= LLVertexBuffer::MAP_WEIGHT4; + geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[1], simple_count[1], FALSE, batch_textures, TRUE); + geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[1], fullbright_count[1], FALSE, batch_textures, TRUE); + geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[1], alpha_count[1], TRUE, batch_textures, TRUE); + geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[1], bump_count[1], FALSE, TRUE); + geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[1], norm_count[1], FALSE, TRUE); + geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[1], spec_count[1], FALSE, TRUE); + geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[1], normspec_count[1], FALSE, TRUE); group->mGeometryBytes = geometryBytes; @@ -6061,133 +5950,130 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) mFaceList.clear(); } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_MESH_FLUSH("Flush Mesh"); - void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { + LL_PROFILE_ZONE_SCOPED; llassert(group); if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_VB); - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers + { + LL_PROFILE_ZONE_NAMED("rebuildMesh - gen draw info"); - group->mBuilt = 1.f; + group->mBuilt = 1.f; - S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; + S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; - const U32 MAX_BUFFER_COUNT = 4096; - LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; - - U32 buffer_count = 0; + const U32 MAX_BUFFER_COUNT = 4096; + LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + U32 buffer_count = 0; - if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLVOVolume* vobj = drawablep->getVOVolume(); - if (debugLoggingEnabled("AnimatedObjectsLinkset")) - { - if (vobj->isAnimatedObject() && vobj->isRiggedMesh()) - { - std::string vobj_name = llformat("Vol%p", vobj); - F32 est_tris = vobj->getEstTrianglesMax(); - LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; - } - } - if (vobj->isNoLOD()) continue; - - vobj->preRebuild(); - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - LLVolume* volume = vobj->getVolume(); - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) { - LLFace* face = drawablep->getFace(i); - if (face) + LLVOVolume* vobj = drawablep->getVOVolume(); + if (debugLoggingEnabled("AnimatedObjectsLinkset")) { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) + if (vobj->isAnimatedObject() && vobj->isRiggedMesh()) { - llassert(!face->isState(LLFace::RIGGED)); + std::string vobj_name = llformat("Vol%p", vobj); + F32 est_tris = vobj->getEstTrianglesMax(); + LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuildMesh, tris " << est_tris << LL_ENDL; + } + } + if (vobj->isNoLOD()) continue; - if (!face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) - { //something's gone wrong with the vertex buffer accounting, rebuild this group - group->dirtyGeom(); - gPipeline.markRebuild(group, TRUE); - } + vobj->preRebuild(); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } - if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT) + LLVolume* volume = vobj->getVolume(); + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) { - locked_buffer[buffer_count++] = buff; + llassert(!face->isState(LLFace::RIGGED)); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + + + if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT) + { + locked_buffer[buffer_count++] = buff; + } } } } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } + + drawablep->clearState(LLDrawable::REBUILD_ALL); } + } - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + LL_PROFILE_ZONE_NAMED("rebuildMesh - flush"); + for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) { - vobj->updateRelativeXform(); + (*iter)->flush(); } - - drawablep->clearState(LLDrawable::REBUILD_ALL); + // don't forget alpha + if(group != NULL && + !group->mVertexBuffer.isNull() && + group->mVertexBuffer->isLocked()) + { + group->mVertexBuffer->flush(); + } } - } - - { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_MESH_FLUSH); - for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) - { - (*iter)->flush(); - } - - // don't forget alpha - if(group != NULL && - !group->mVertexBuffer.isNull() && - group->mVertexBuffer->isLocked()) - { - group->mVertexBuffer->flush(); - } - } - //if not all buffers are unmapped - if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) - { - LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + //if not all buffers are unmapped + if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount) { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if(!drawablep) - { - continue; - } - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + LL_WARNS() << "Not all mapped vertex buffers are unmapped!" << LL_ENDL ; + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLFace* face = drawablep->getFace(i); - if (face) + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(!drawablep) { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff && buff->isLocked()) + continue; + } + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) { - buff->flush(); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff && buff->isLocked()) + { + buff->flush(); + } } } } - } - } - - group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } + } -// llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } } struct CompareBatchBreakerModified @@ -6197,7 +6083,7 @@ struct CompareBatchBreakerModified const LLTextureEntry* lte = lhs->getTextureEntry(); const LLTextureEntry* rte = rhs->getTextureEntry(); - if (lte->getBumpmap() != rte->getBumpmap()) + if (lte->getBumpmap() != rte->getBumpmap()) { return lte->getBumpmap() < rte->getBumpmap(); } @@ -6220,19 +6106,45 @@ struct CompareBatchBreakerModified } }; -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_SORT("Draw Info Face Sort"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FACE_SIZE("Face Sizing"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_ALLOCATE("Allocate VB"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_FIND_VB("Find VB"); -static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); - - +struct CompareBatchBreakerRigged +{ + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + const LLTextureEntry* lte = lhs->getTextureEntry(); + const LLTextureEntry* rte = rhs->getTextureEntry(); + if (lhs->mAvatar != rhs->mAvatar) + { + return lhs->mAvatar < rhs->mAvatar; + } + else if (lhs->mSkinInfo->mHash != rhs->mSkinInfo->mHash) + { + return lhs->mSkinInfo->mHash < rhs->mSkinInfo->mHash; + } + else if (lhs->getTexture() != rhs->getTexture()) + { + return lhs->getTexture() < rhs->getTexture(); + } + else if (lte->getBumpmap() != rte->getBumpmap()) + { + return lte->getBumpmap() < rte->getBumpmap(); + } + else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID()) + { + return lte->getMaterialID() < rte->getMaterialID(); + } + else // if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny())) + { + return lte->getShiny() < rte->getShiny(); + } + + } +}; -U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) +U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL rigged) { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); + LL_PROFILE_ZONE_SCOPED; U32 geometryBytes = 0; U32 buffer_usage = group->mBufferUsage; @@ -6264,12 +6176,18 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace max_vertices = llmin(max_vertices, (U32) 65535); { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_SORT); - if (!distance_sort) - { - //sort faces by things that break batches - std::sort(faces, faces+face_count, CompareBatchBreakerModified()); - } + LL_PROFILE_ZONE_NAMED("genDrawInfo - sort"); + + if (rigged) + { + //sort faces by things that break batches, including avatar and mesh id + std::sort(faces, faces + face_count, CompareBatchBreakerRigged()); + } + else if (!distance_sort) + { + //sort faces by things that break batches, not including avatar and mesh id + std::sort(faces, faces + face_count, CompareBatchBreakerModified()); + } else { //sort faces by distance @@ -6286,11 +6204,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace LLViewerTexture* last_tex = NULL; S32 buffer_index = 0; - if (distance_sort) - { - buffer_index = -1; - } - S32 texture_index_channels = 1; if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) @@ -6302,6 +6215,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; } + + if (rigged) + { //don't attempt distance sorting on rigged meshes, not likely to succeed and breaks batches + distance_sort = FALSE; + } + + if (distance_sort) + { + buffer_index = -1; + } static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); texture_index_channels = llmin(texture_index_channels, (S32) max_texture_index); @@ -6316,7 +6239,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace //pull off next face LLFace* facep = *face_iter; LLViewerTexture* tex = facep->getTexture(); - LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams(); + const LLTextureEntry* te = facep->getTextureEntry(); + LLMaterialPtr mat = te->getMaterialParams(); + LLMaterialID matId = te->getMaterialID(); if (distance_sort) { @@ -6350,7 +6275,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace U32 texture_count = 0; { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_FACE_SIZE); + LL_PROFILE_ZONE_NAMED("genDrawInfo - face size"); if (batch_textures) { U8 cur_tex = 0; @@ -6439,11 +6364,14 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace while (i != end_faces && (LLPipeline::sTextureBindTest || (distance_sort || - ((*i)->getTexture() == tex && - ((*i)->getTextureEntry()->getMaterialParams() == mat))))) + ((*i)->getTexture() == tex)))) { facep = *i; - + const LLTextureEntry* nextTe = facep->getTextureEntry(); + if (nextTe->getMaterialID() != matId) + { + break; + } //face has no texture index facep->mDrawInfo = NULL; @@ -6473,7 +6401,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace LLPointer<LLVertexBuffer> buffer; { - LL_RECORD_BLOCK_TIME(FTM_GEN_DRAW_INFO_ALLOCATE); + LL_PROFILE_ZONE_NAMED("genDrawInfo - allocate"); buffer = createVertexBuffer(mask, buffer_usage); if(!buffer->allocateBuffer(geom_count, index_count, TRUE)) { @@ -6533,8 +6461,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace U32 te_idx = facep->getTEOffset(); - llassert(!facep->isState(LLFace::RIGGED)); - if (!facep->getGeometryVolume(*volume, te_idx, vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) { @@ -6631,10 +6557,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } } } - else if (no_materials) - { - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } else if (transparent) { registerFace(group, facep, LLRenderPass::PASS_ALPHA); @@ -6699,7 +6621,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_ALPHA); } - else if (gPipeline.canUseVertexShaders() + else if (gPipeline.shadersLoaded() && LLPipeline::sRenderBump && te->getShiny() && can_be_shiny) @@ -6734,7 +6656,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace registerFace(group, facep, LLRenderPass::PASS_ALPHA); } } - else if (gPipeline.canUseVertexShaders() + else if (gPipeline.shadersLoaded() && LLPipeline::sRenderBump && te->getShiny() && can_be_shiny) @@ -6815,7 +6737,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } - if (!gPipeline.canUseVertexShaders() && + if (!gPipeline.shadersLoaded() && !is_alpha && te->getShiny() && LLPipeline::sRenderBump) @@ -6861,6 +6783,8 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) { + LL_PROFILE_ZONE_SCOPED; + //initialize to default usage for this partition U32 usage = group->getSpatialPartition()->mBufferUsage; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 73eeec813c..d158044f5d 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -295,6 +295,9 @@ public: BOOL setIsFlexible(BOOL is_flexible); const LLMeshSkinInfo* getSkinInfo() const; + + //convenience accessor for mesh ID (which is stored in sculpt id for legacy reasons) + const LLUUID& getMeshID() const { return getVolume()->getParams().getSculptID(); } // Extended Mesh Properties U32 getExtendedMeshFlags() const; diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 12def24a0d..089a7712c0 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -114,11 +114,9 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline) return mDrawable; } -static LLTrace::BlockTimerStatHandle FTM_UPDATE_WATER("Update Water"); - BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_WATER); + LL_PROFILE_ZONE_SCOPED; LLFace *face; if (drawable->getNumFaces() < 1) @@ -145,7 +143,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) static const unsigned int vertices_per_quad = 4; static const unsigned int indices_per_quad = 6; - const S32 size = LLPipeline::sRenderTransparentWater && LLGLSLShader::sNoFixedFunction ? 16 : 1; + const S32 size = LLPipeline::sRenderTransparentWater ? 16 : 1; const S32 num_quads = size * size; face->setSize(vertices_per_quad * num_quads, diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index d428cb1568..d1f584cbca 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -36,8 +36,8 @@ #include "llenvironment.h" #include "llsettingssky.h" -static const U32 MIN_SKY_DETAIL = 8; -static const U32 MAX_SKY_DETAIL = 180; +constexpr U32 MIN_SKY_DETAIL = 8; +constexpr U32 MAX_SKY_DETAIL = 180; inline U32 LLVOWLSky::getNumStacks(void) { @@ -97,13 +97,14 @@ LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline) return mDrawable; } -inline F32 LLVOWLSky::calcPhi(U32 i) +// a tiny helper function for controlling the sky dome tesselation. +inline F32 calcPhi(const U32 &i, const F32 &reciprocal_num_stacks) { // Calc: PI/8 * 1-((1-t^4)*(1-t^4)) { 0<t<1 } // Demos: \pi/8*\left(1-((1-x^{4})*(1-x^{4}))\right)\ \left\{0<x\le1\right\} // i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f] - F32 t = float(i) / float(getNumStacks()); + F32 t = float(i) * reciprocal_num_stacks; //SL-16127: remove: / float(getNumStacks()); // ^4 the parameter of the tesselation to bias things toward 0 (the dome's apex) t *= t; @@ -141,11 +142,9 @@ void LLVOWLSky::restoreGL() gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } -static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Windlight Sky Geometry"); - BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { - LL_RECORD_BLOCK_TIME(FTM_GEO_SKY); + LL_PROFILE_ZONE_SCOPED; LLStrider<LLVector3> vertices; LLStrider<LLVector2> texCoords; LLStrider<U16> indices; @@ -189,6 +188,8 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) } { + const F32 dome_radius = LLEnvironment::instance().getCurrentSky()->getDomeRadius(); + const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024; const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask); @@ -204,12 +205,14 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) // round up to a whole number of segments const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg; - LL_INFOS() << "WL Skydome strips in " << strips_segments << " batches." << LL_ENDL; - mStripsVerts.resize(strips_segments, NULL); +#if RELEASE_SHOW_DEBUG + LL_INFOS() << "WL Skydome strips in " << strips_segments << " batches." << LL_ENDL; + LLTimer timer; timer.start(); +#endif for (U32 i = 0; i < strips_segments ;++i) { @@ -234,34 +237,42 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack); llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes); - if (!segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE)) + bool allocated = segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE); +#if RELEASE_SHOW_WARNS + if( !allocated ) { LL_WARNS() << "Failed to allocate Vertex Buffer on update to " << num_verts_this_seg << " vertices and " << num_indices_this_seg << " indices" << LL_ENDL; } +#else + (void) allocated; +#endif // lock the buffer BOOL success = segment->getVertexStrider(vertices) && segment->getTexCoord0Strider(texCoords) && segment->getIndexStrider(indices); - if(!success) +#if RELEASE_SHOW_DEBUG + if(!success) { LL_ERRS() << "Failed updating WindLight sky geometry." << LL_ENDL; } - - U32 vertex_count = 0; - U32 index_count = 0; +#else + (void) success; +#endif // fill it - buildStripsBuffer(begin_stack, end_stack, vertex_count, index_count, vertices, texCoords, indices); + buildStripsBuffer(begin_stack, end_stack, vertices, texCoords, indices, dome_radius, verts_per_stack, total_stacks); // and unlock the buffer segment->flush(); } +#if RELEASE_SHOW_DEBUG LL_INFOS() << "completed in " << llformat("%.2f", timer.getElapsedTimeF32().value()) << "seconds" << LL_ENDL; +#endif } updateStarColors(); @@ -366,23 +377,16 @@ void LLVOWLSky::initStars() void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack, - U32& vertex_count, - U32& index_count, - LLStrider<LLVector3> & vertices, - LLStrider<LLVector2> & texCoords, - LLStrider<U16> & indices) + LLStrider<LLVector3> & vertices, + LLStrider<LLVector2> & texCoords, + LLStrider<U16> & indices, + const F32 dome_radius, + const U32& num_slices, + const U32& num_stacks) { - const F32 RADIUS = LLEnvironment::instance().getCurrentSky()->getDomeRadius(); - - U32 i, j, num_slices, num_stacks; + U32 i, j; F32 phi0, theta, x0, y0, z0; - - // paranoia checking for SL-55986/SL-55833 - U32 count_verts = 0; - U32 count_indices = 0; - - num_slices = getNumSlices(); - num_stacks = getNumStacks(); + const F32 reciprocal_num_stacks = 1.f / num_stacks; llassert(end_stack <= num_stacks); @@ -393,7 +397,7 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, for(i = begin_stack + 1; i <= end_stack+1; ++i) #endif { - phi0 = calcPhi(i); + phi0 = calcPhi(i, reciprocal_num_stacks); for(j = 0; j < num_slices; ++j) { @@ -406,24 +410,22 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, z0 = sin(phi0) * sin(theta); #if NEW_TESS - *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS); + *vertices++ = LLVector3(x0 * dome_radius, y0 * dome_radius, z0 * dome_radius); #else if (i == num_stacks-2) { - *vertices++ = LLVector3(x0*RADIUS, y0*RADIUS-1024.f*2.f, z0*RADIUS); + *vertices++ = LLVector3(x0*dome_radius, y0*dome_radius-1024.f*2.f, z0*dome_radius); } else if (i == num_stacks-1) { - *vertices++ = LLVector3(0, y0*RADIUS-1024.f*2.f, 0); + *vertices++ = LLVector3(0, y0*dome_radius-1024.f*2.f, 0); } else { - *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS); + *vertices++ = LLVector3(x0 * dome_radius, y0 * dome_radius, z0 * dome_radius); } #endif - ++count_verts; - // generate planar uv coordinates // note: x and z are transposed in order for things to animate // correctly in the global coordinate system where +x is east and @@ -434,12 +436,11 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, //build triangle strip... *indices++ = 0 ; - count_indices++ ; + S32 k = 0 ; for(i = 1; i <= end_stack - begin_stack; ++i) { *indices++ = i * num_slices + k ; - count_indices++ ; k = (k+1) % num_slices ; for(j = 0; j < num_slices ; ++j) @@ -447,8 +448,6 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, *indices++ = (i-1) * num_slices + k ; *indices++ = i * num_slices + k ; - count_indices += 2 ; - k = (k+1) % num_slices ; } @@ -458,11 +457,7 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, } *indices++ = i * num_slices + k ; - count_indices++ ; } - - vertex_count = count_verts; - index_count = count_indices; } void LLVOWLSky::updateStarColors() diff --git a/indra/newview/llvowlsky.h b/indra/newview/llvowlsky.h index 2b7ebe75dd..3853dd2c70 100644 --- a/indra/newview/llvowlsky.h +++ b/indra/newview/llvowlsky.h @@ -55,8 +55,6 @@ public: void restoreGL(); private: - // a tiny helper function for controlling the sky dome tesselation. - static F32 calcPhi(U32 i); // helper function for initializing the stars. void initStars(); @@ -66,11 +64,12 @@ private: // begin_stack is the first stack to be included, end_stack is the first // stack not to be included. static void buildStripsBuffer(U32 begin_stack, U32 end_stack, - U32& vertex_count, - U32& index_count, - LLStrider<LLVector3> & vertices, - LLStrider<LLVector2> & texCoords, - LLStrider<U16> & indices); + LLStrider<LLVector3> & vertices, + LLStrider<LLVector2> & texCoords, + LLStrider<U16> & indices, + const F32 RADIUS, + const U32& num_slices, + const U32& num_stacks); // helper function for updating the stars colors. void updateStarColors(); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index fb3fc55a94..d7f16713d2 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -135,6 +135,7 @@ void LLWorld::destroyClass() LLDrawable::incrementVisible(); LLSceneMonitor::deleteSingleton(); + LLWorld::deleteSingleton(); } @@ -884,6 +885,7 @@ void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_heigh void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool include_void_water) { + LL_PROFILE_ZONE_SCOPED; if (!gAgent.getRegion()) { return; @@ -1077,6 +1079,7 @@ void LLWorld::updateWaterObjects() void LLWorld::shiftRegions(const LLVector3& offset) { + LL_PROFILE_ZONE_SCOPED; for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i) { LLViewerRegion* region = *i; @@ -1147,11 +1150,9 @@ void LLWorld::disconnectRegions() } } -static LLTrace::BlockTimerStatHandle FTM_ENABLE_SIMULATOR("Enable Sim"); - void process_enable_simulator(LLMessageSystem *msg, void **user_data) { - LL_RECORD_BLOCK_TIME(FTM_ENABLE_SIMULATOR); + LL_PROFILE_ZONE_SCOPED; // enable the appropriate circuit for this simulator and // add its values into the gSimulator structure U64 handle; @@ -1222,12 +1223,11 @@ public: } }; -static LLTrace::BlockTimerStatHandle FTM_DISABLE_REGION("Disable Region"); // disable the circuit to this simulator // Called in response to "DisableSimulator" message. void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) { - LL_RECORD_BLOCK_TIME(FTM_DISABLE_REGION); + LL_PROFILE_ZONE_SCOPED; LLHost host = mesgsys->getSender(); @@ -1289,6 +1289,7 @@ void send_agent_pause() void send_agent_resume() { + LL_PROFILE_ZONE_SCOPED // Note: used to check for LLWorld initialization before it became a singleton. // Rather than just remove this check I'm changing it to assure that the message // system has been initialized. -MG diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index 98552bc4d1..69f2df4203 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -59,11 +59,12 @@ class LLVOAvatar; // as simulators are connected to, viewer_regions are popped off the stack and connected as required // as simulators are removed, they are pushed back onto the stack -class LLWorld : public LLSingleton<LLWorld> +class LLWorld : public LLSimpleton<LLWorld> { - LLSINGLETON(LLWorld); public: - void destroyClass(); + LLWorld(); + + void destroyClass(); LLViewerRegion* addRegion(const U64 ®ion_handle, const LLHost &host); // safe to call if already present, does the "right thing" if diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp index 8be340de4c..e4a9f9afdb 100644 --- a/indra/newview/llworldmapmessage.cpp +++ b/indra/newview/llworldmapmessage.cpp @@ -150,6 +150,10 @@ void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 // public static void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**) { + if (gNonInteractive) + { + return; + } U32 agent_flags; msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index a6df079223..59ac4554d7 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -321,22 +321,19 @@ void LLWorldMapView::draw() // Clear the background alpha to 0 gGL.flush(); gGL.setColorMask(false, true); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); + gGL.flush(); gGL.setSceneBlendType(LLRender::BT_REPLACE); gGL.color4f(0.0f, 0.0f, 0.0f, 0.0f); gl_rect_2d(0, height, width, 0); } gGL.flush(); - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); // Draw the image tiles drawMipmap(width, height); gGL.flush(); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setColorMask(true, true); // Draw per sim overlayed information (names, mature, offline...) @@ -480,13 +477,13 @@ void LLWorldMapView::draw() LLGLSUIDefault gls_ui; { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); + gGL.flush(); gGL.blendFunc(LLRender::BF_ONE_MINUS_DEST_ALPHA, LLRender::BF_DEST_ALPHA); gGL.color4fv( mBackgroundColor.mV ); gl_rect_2d(0, height, width, 0); } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gGL.flush(); gGL.setSceneBlendType(LLRender::BT_ALPHA); // Draw item infos if we're not zoomed out too much and there's something to draw diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index cd1b9c7c69..d5f9772b85 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -142,7 +142,6 @@ bool gShiftFrame = false; //cached settings -bool LLPipeline::RenderAvatarVP; bool LLPipeline::WindLightUseAtmosShaders; bool LLPipeline::RenderDeferred; F32 LLPipeline::RenderDeferredSunWash; @@ -238,7 +237,6 @@ const LLMatrix4* gGLLastMatrix = NULL; LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY("Render Geometry"); LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS("Grass"); LLTrace::BlockTimerStatHandle FTM_RENDER_INVISIBLE("Invisible"); -LLTrace::BlockTimerStatHandle FTM_RENDER_OCCLUSION("Occlusion"); LLTrace::BlockTimerStatHandle FTM_RENDER_SHINY("Shiny"); LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE("Simple"); LLTrace::BlockTimerStatHandle FTM_RENDER_TERRAIN("Terrain"); @@ -253,14 +251,12 @@ LLTrace::BlockTimerStatHandle FTM_RENDER_MATERIALS("Render Materials"); LLTrace::BlockTimerStatHandle FTM_RENDER_FULLBRIGHT("Fullbright"); LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW("Glow"); LLTrace::BlockTimerStatHandle FTM_GEO_UPDATE("Geo Update"); -LLTrace::BlockTimerStatHandle FTM_PIPELINE_CREATE("Pipeline Create"); LLTrace::BlockTimerStatHandle FTM_POOLRENDER("RenderPool"); LLTrace::BlockTimerStatHandle FTM_POOLS("Pools"); LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLRENDER("RenderPool (Deferred)"); LLTrace::BlockTimerStatHandle FTM_DEFERRED_POOLS("Pools (Deferred)"); LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLRENDER("RenderPool (Post)"); LLTrace::BlockTimerStatHandle FTM_POST_DEFERRED_POOLS("Pools (Post)"); -LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM_FBO("First FBO"); LLTrace::BlockTimerStatHandle FTM_STATESORT("Sort Draw State"); LLTrace::BlockTimerStatHandle FTM_PIPELINE("Pipeline"); LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY("Client Copy"); @@ -269,11 +265,8 @@ LLTrace::BlockTimerStatHandle FTM_RENDER_DEFERRED("Deferred Shading"); LLTrace::BlockTimerStatHandle FTM_RENDER_UI_HUD("HUD"); LLTrace::BlockTimerStatHandle FTM_RENDER_UI_3D("3D"); LLTrace::BlockTimerStatHandle FTM_RENDER_UI_2D("2D"); -LLTrace::BlockTimerStatHandle FTM_RENDER_UI_DEBUG_TEXT("Debug Text"); -LLTrace::BlockTimerStatHandle FTM_RENDER_UI_SCENE_MON("Scene Mon"); static LLTrace::BlockTimerStatHandle FTM_STATESORT_DRAWABLE("Sort Drawables"); -static LLTrace::BlockTimerStatHandle FTM_STATESORT_POSTSORT("Post Sort"); static LLStaticHashedString sTint("tint"); static LLStaticHashedString sAmbiance("ambiance"); @@ -338,7 +331,6 @@ S32 LLPipeline::sUseOcclusion = 0; bool LLPipeline::sDelayVBUpdate = true; bool LLPipeline::sAutoMaskAlphaDeferred = true; bool LLPipeline::sAutoMaskAlphaNonDeferred = false; -bool LLPipeline::sDisableShaders = false; bool LLPipeline::sRenderTransparentWater = true; bool LLPipeline::sRenderBump = true; bool LLPipeline::sBakeSunlight = false; @@ -359,7 +351,6 @@ bool LLPipeline::sRenderAttachedLights = true; bool LLPipeline::sRenderAttachedParticles = true; bool LLPipeline::sRenderDeferred = false; S32 LLPipeline::sVisibleLightCount = 0; -F32 LLPipeline::sMinRenderSize = 0.f; bool LLPipeline::sRenderingHUDs; F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f; @@ -385,8 +376,7 @@ LLPipeline::LLPipeline() : mNumVisibleFaces(0), mInitialized(false), - mVertexShadersEnabled(false), - mVertexShadersLoaded(0), + mShadersLoaded(false), mTransformFeedbackPrimitives(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), @@ -487,6 +477,10 @@ void LLPipeline::init() { clearAllRenderTypes(); } + else if (gNonInteractive) + { + clearAllRenderTypes(); + } else { setAllRenderTypes(); // By default, all rendering types start enabled @@ -541,7 +535,6 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors"); connectRefreshCachedSettingsSafe("RenderDelayVBUpdate"); connectRefreshCachedSettingsSafe("UseOcclusion"); - connectRefreshCachedSettingsSafe("RenderAvatarVP"); connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); connectRefreshCachedSettingsSafe("RenderDeferred"); connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); @@ -725,8 +718,6 @@ void LLPipeline::destroyGL() } } -static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture"); - void LLPipeline::requestResizeScreenTexture() { gResizeScreenTexture = TRUE; @@ -746,8 +737,7 @@ void LLPipeline::resizeShadowTexture() void LLPipeline::resizeScreenTexture() { - LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE); - if (gPipeline.canUseVertexShaders() && assertInitialized()) + if (gPipeline.shadersLoaded()) { GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resY = gViewerWindow->getWorldViewHeightRaw(); @@ -758,8 +748,8 @@ void LLPipeline::resizeScreenTexture() releaseShadowTargets(); allocateScreenBuffer(resX,resY); gResizeScreenTexture = FALSE; - } - } + } + } } void LLPipeline::allocatePhysicsBuffer() @@ -900,7 +890,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (!addDeferredAttachments(mDeferredScreen)) return false; GLuint screenFormat = GL_RGBA16; - if (gGLManager.mIsATI) + if (gGLManager.mIsAMD) { screenFormat = GL_RGBA12; } @@ -1054,8 +1044,6 @@ void LLPipeline::updateRenderDeferred() RenderDeferred && LLRenderTarget::sUseFBO && LLPipeline::sRenderBump && - LLPipeline::sRenderTransparentWater && - RenderAvatarVP && WindLightUseAtmosShaders && (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); } @@ -1072,12 +1060,10 @@ void LLPipeline::refreshCachedSettings() LLPipeline::sUseOcclusion = (!gUseWireframe - && LLGLSLShader::sNoFixedFunction && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; - RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP"); WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); RenderDeferred = gSavedSettings.getBOOL("RenderDeferred"); RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); @@ -1153,6 +1139,12 @@ void LLPipeline::refreshCachedSettings() RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); RenderSpotLight = nullptr; updateRenderDeferred(); + + if (gNonInteractive) + { + LLVOAvatar::sMaxNonImpostors = 1; + LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); + } } void LLPipeline::releaseGLBuffers() @@ -1232,7 +1224,8 @@ void LLPipeline::releaseShadowTargets() void LLPipeline::createGLBuffers() { - stop_glerror(); + LL_PROFILE_ZONE_SCOPED; + stop_glerror(); assertInitialized(); updateRenderDeferred(); @@ -1370,10 +1363,7 @@ void LLPipeline::restoreGL() { assertInitialized(); - if (mVertexShadersEnabled) - { - LLViewerShaderMgr::instance()->setShaders(); - } + LLViewerShaderMgr::instance()->setShaders(); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -1385,31 +1375,19 @@ void LLPipeline::restoreGL() if (part) { part->restoreGL(); - } + } } } } - -bool LLPipeline::canUseVertexShaders() +bool LLPipeline::shadersLoaded() { - if (sDisableShaders || - !gGLManager.mHasVertexShader || - !gGLManager.mHasFragmentShader || - (assertInitialized() && mVertexShadersLoaded != 1) ) - { - return false; - } - else - { - return true; - } + return (assertInitialized() && mShadersLoaded); } bool LLPipeline::canUseWindLightShaders() const { - return (!LLPipeline::sDisableShaders && - gWLSkyProgram.mProgramObject != 0 && + return (gWLSkyProgram.mProgramObject != 0 && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1); } @@ -1427,8 +1405,7 @@ bool LLPipeline::canUseAntiAliasing() const void LLPipeline::unloadShaders() { LLViewerShaderMgr::instance()->unloadShaders(); - - mVertexShadersLoaded = 0; + mShadersLoaded = false; } void LLPipeline::assertInitializedDoError() @@ -1514,6 +1491,7 @@ public: // Called when a texture changes # of channels (causes faces to move to alpha pool) void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures) { + LL_PROFILE_ZONE_SCOPED; assertInitialized(); // *TODO: This is inefficient and causes frame spikes; need a better way to do this @@ -1725,15 +1703,9 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj) } -static LLTrace::BlockTimerStatHandle FTM_UNLINK("Unlink"); -static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_MOVE_LIST("Movelist"); -static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition"); -static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_LIGHT_SET("Light Set"); -static LLTrace::BlockTimerStatHandle FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set"); - void LLPipeline::unlinkDrawable(LLDrawable *drawable) { - LL_RECORD_BLOCK_TIME(FTM_UNLINK); + LL_PROFILE_ZONE_SCOPED; assertInitialized(); @@ -1742,7 +1714,6 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) // Based on flags, remove the drawable from the queues that it's on. if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_MOVE_LIST); LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); if (iter != mMovedList.end()) { @@ -1752,7 +1723,6 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) if (drawablep->getSpatialGroup()) { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_SPATIAL_PARTITION); if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) { #ifdef LL_RELEASE_FOR_DOWNLOAD @@ -1763,30 +1733,24 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) } } - { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); - mLights.erase(drawablep); + mLights.erase(drawablep); - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + if (iter->drawable == drawablep) { - if (iter->drawable == drawablep) - { - mNearbyLights.erase(iter); - break; - } + mNearbyLights.erase(iter); + break; } } - { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_HIGHLIGHT_SET); - HighlightItem item(drawablep); - mHighlightSet.erase(item); + HighlightItem item(drawablep); + mHighlightSet.erase(item); - if (mHighlightObject == drawablep) - { - mHighlightObject = NULL; - } + if (mHighlightObject == drawablep) + { + mHighlightObject = NULL; } for (U32 i = 0; i < 2; ++i) @@ -1801,14 +1765,12 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) mTargetShadowSpotLight[i] = NULL; } } - - } //static void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) { - LL_RECORD_BLOCK_TIME(FTM_REMOVE_FROM_LIGHT_SET); + LL_PROFILE_ZONE_SCOPED; for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); iter != gPipeline.mNearbyLights.end(); iter++) { @@ -1836,7 +1798,7 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::createObjects(F32 max_dtime) { - LL_RECORD_BLOCK_TIME(FTM_PIPELINE_CREATE); + LL_PROFILE_ZONE_SCOPED; LLTimer update_timer; @@ -1860,6 +1822,7 @@ void LLPipeline::createObjects(F32 max_dtime) void LLPipeline::createObject(LLViewerObject* vobj) { + LL_PROFILE_ZONE_SCOPED; LLDrawable* drawablep = vobj->mDrawable; if (!drawablep) @@ -1897,6 +1860,7 @@ void LLPipeline::createObject(LLViewerObject* vobj) void LLPipeline::resetFrameStats() { + LL_PROFILE_ZONE_SCOPED assertInitialized(); sCompiles = 0; @@ -1912,6 +1876,7 @@ void LLPipeline::resetFrameStats() //external functions for asynchronous updating void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) { + LL_PROFILE_ZONE_SCOPED; if (FreezeTime) { return; @@ -1942,6 +1907,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) { + LL_PROFILE_ZONE_SCOPED; if (FreezeTime) { return; @@ -1972,6 +1938,7 @@ void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) { + LL_PROFILE_ZONE_SCOPED; for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin(); iter != moved_list.end(); ) { @@ -2005,14 +1972,9 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) } } -static LLTrace::BlockTimerStatHandle FTM_OCTREE_BALANCE("Balance Octree"); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_MOVE("Update Move"); -static LLTrace::BlockTimerStatHandle FTM_RETEXTURE("Retexture"); -static LLTrace::BlockTimerStatHandle FTM_MOVED_LIST("Moved List"); - void LLPipeline::updateMove() { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_MOVE); + LL_PROFILE_ZONE_SCOPED; if (FreezeTime) { @@ -2021,49 +1983,38 @@ void LLPipeline::updateMove() assertInitialized(); + for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); + iter != mRetexturedList.end(); ++iter) { - LL_RECORD_BLOCK_TIME(FTM_RETEXTURE); - - for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); - iter != mRetexturedList.end(); ++iter) + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) - { - drawablep->updateTexture(); - } + drawablep->updateTexture(); } - mRetexturedList.clear(); } + mRetexturedList.clear(); - { - LL_RECORD_BLOCK_TIME(FTM_MOVED_LIST); - updateMovedList(mMovedList); - } + updateMovedList(mMovedList); //balance octrees + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { - LL_RECORD_BLOCK_TIME(FTM_OCTREE_BALANCE); - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->mOctree->balance(); - } + part->mOctree->balance(); } + } - //balance the VO Cache tree - LLVOCachePartition* vo_part = region->getVOCachePartition(); - if(vo_part) - { - vo_part->mOctree->balance(); - } + //balance the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->mOctree->balance(); } } } @@ -2125,6 +2076,7 @@ void LLPipeline::grabReferences(LLCullResult& result) void LLPipeline::clearReferences() { + LL_PROFILE_ZONE_SCOPED sCull = NULL; mGroupSaveQ1.clear(); } @@ -2372,20 +2324,28 @@ bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); -void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep) +void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* planep) { static LLCachedControl<bool> use_occlusion(gSavedSettings,"UseOcclusion"); - static bool can_use_occlusion = LLGLSLShader::sNoFixedFunction - && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") + static bool can_use_occlusion = LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gGLManager.mHasOcclusionQuery; LL_RECORD_BLOCK_TIME(FTM_CULL); + if (planep != nullptr) + { + camera.setUserClipPlane(*planep); + } + else + { + camera.disableUserClipPlane(); + } + grabReferences(result); sCull->clear(); - bool to_texture = LLPipeline::sUseOcclusion > 1 && gPipeline.canUseVertexShaders(); + bool to_texture = LLPipeline::sUseOcclusion > 1 && gPipeline.shadersLoaded(); if (to_texture) { @@ -2419,7 +2379,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDepthTest depth(GL_TRUE, GL_FALSE); bool bound_shader = false; - if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0) + 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; @@ -2435,11 +2395,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); } - if (!sReflectionRender) - { - camera.disableUserClipPlane(); - } - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -2461,8 +2416,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLVOCachePartition* vo_part = region->getVOCachePartition(); if(vo_part) { - bool do_occlusion_cull = can_use_occlusion && use_occlusion && !gUseWireframe && 0 > water_clip /* && !gViewerWindow->getProgressView()->getVisible()*/; - do_occlusion_cull &= !sReflectionRender; + bool do_occlusion_cull = can_use_occlusion && use_occlusion && !gUseWireframe; vo_part->cull(camera, do_occlusion_cull); } } @@ -2553,13 +2507,6 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) return; } - const LLVector4a* bounds = group->getBounds(); - if (sMinRenderSize > 0.f && - llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) - { - return; - } - assertInitialized(); if (!group->getSpatialPartition()->mRenderByGroup) @@ -2669,7 +2616,8 @@ void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderT void LLPipeline::doOcclusion(LLCamera& camera) { - if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested && + LL_PROFILE_ZONE_SCOPED; + if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) { LLVertexBuffer::unbind(); @@ -2690,7 +2638,7 @@ void LLPipeline::doOcclusion(LLCamera& camera) LLGLDisable cull(GL_CULL_FACE); - bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0; + bool bind_shader = (LLGLSLShader::sCurBoundShader == 0); if (bind_shader) { if (LLPipeline::sShadowRender) @@ -2753,14 +2701,10 @@ bool LLPipeline::updateDrawableGeom(LLDrawable* drawablep, bool priority) return update_complete; } -static LLTrace::BlockTimerStatHandle FTM_SEED_VBO_POOLS("Seed VBO Pool"); - -static LLTrace::BlockTimerStatHandle FTM_UPDATE_GL("Update GL"); - void LLPipeline::updateGL() { + LL_PROFILE_ZONE_SCOPED; { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_GL); while (!LLGLUpdate::sGLQ.empty()) { LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); @@ -2771,15 +2715,13 @@ void LLPipeline::updateGL() } { //seed VBO Pools - LL_RECORD_BLOCK_TIME(FTM_SEED_VBO_POOLS); LLVertexBuffer::seedPools(); } } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_PRIORITY_GROUPS("Rebuild Priority Groups"); - void LLPipeline::clearRebuildGroups() { + LL_PROFILE_ZONE_SCOPED; LLSpatialGroup::sg_vector_t hudGroups; mGroupQ1Locked = true; @@ -2884,7 +2826,7 @@ void LLPipeline::clearRebuildDrawables() void LLPipeline::rebuildPriorityGroups() { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_PRIORITY_GROUPS); + LL_PROFILE_ZONE_SCOPED; LLTimer update_timer; assertInitialized(); @@ -2906,8 +2848,6 @@ void LLPipeline::rebuildPriorityGroups() } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_GROUPS("Rebuild Groups"); - void LLPipeline::rebuildGroups() { if (mGroupQ2.empty()) @@ -2915,7 +2855,7 @@ void LLPipeline::rebuildGroups() return; } - LL_RECORD_BLOCK_TIME(FTM_REBUILD_GROUPS); + LL_PROFILE_ZONE_SCOPED; mGroupQ2Locked = true; // Iterate through some drawables on the non-priority build queue S32 size = (S32) mGroupQ2.size(); @@ -3161,12 +3101,9 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } -static LLTrace::BlockTimerStatHandle FTM_SHIFT_DRAWABLE("Shift Drawable"); -static LLTrace::BlockTimerStatHandle FTM_SHIFT_OCTREE("Shift Octree"); -static LLTrace::BlockTimerStatHandle FTM_SHIFT_HUD("Shift HUD"); - void LLPipeline::shiftObjects(const LLVector3 &offset) { + LL_PROFILE_ZONE_SCOPED; assertInitialized(); glClear(GL_DEPTH_BUFFER_BIT); @@ -3175,46 +3112,36 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) LLVector4a offseta; offseta.load3(offset.mV); + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); + iter != mShiftList.end(); iter++) { - LL_RECORD_BLOCK_TIME(FTM_SHIFT_DRAWABLE); - - for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); - iter != mShiftList.end(); iter++) + LLDrawable *drawablep = *iter; + if (drawablep->isDead()) { - LLDrawable *drawablep = *iter; - if (drawablep->isDead()) - { - continue; - } - drawablep->shiftPos(offseta); - drawablep->clearState(LLDrawable::ON_SHIFT_LIST); - } - mShiftList.resize(0); + continue; + } + drawablep->shiftPos(offseta); + drawablep->clearState(LLDrawable::ON_SHIFT_LIST); } - + mShiftList.resize(0); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { - LL_RECORD_BLOCK_TIME(FTM_SHIFT_OCTREE); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { - LLViewerRegion* region = *iter; - for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) { - LLSpatialPartition* part = region->getSpatialPartition(i); - if (part) - { - part->shift(offseta); - } + part->shift(offseta); } } } - { - LL_RECORD_BLOCK_TIME(FTM_SHIFT_HUD); - LLHUDText::shiftAll(offset); - LLHUDNameTag::shiftAll(offset); - } + LLHUDText::shiftAll(offset); + LLHUDNameTag::shiftAll(offset); + display_update_camera(); } @@ -3245,10 +3172,9 @@ void LLPipeline::markPartitionMove(LLDrawable* drawable) } } -static LLTrace::BlockTimerStatHandle FTM_PROCESS_PARTITIONQ("PartitionQ"); void LLPipeline::processPartitionQ() { - LL_RECORD_BLOCK_TIME(FTM_PROCESS_PARTITIONQ); + LL_PROFILE_ZONE_SCOPED; for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) { LLDrawable* drawable = *iter; @@ -3348,8 +3274,6 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f } } -static LLTrace::BlockTimerStatHandle FTM_RESET_DRAWORDER("Reset Draw Order"); - void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, @@ -3363,7 +3287,6 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) LLPipeline::END_RENDER_TYPES)) { //clear faces from face pools - LL_RECORD_BLOCK_TIME(FTM_RESET_DRAWORDER); gPipeline.resetDrawOrders(); } @@ -3483,12 +3406,12 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) group->mLastUpdateDistance = group->mDistance; } } - } void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed) { - if (bridge->getSpatialGroup()->changeLOD() || fov_changed) + LL_PROFILE_ZONE_SCOPED; + if (bridge->getSpatialGroup()->changeLOD() || fov_changed) { bool force_update = false; bridge->updateDistance(camera, force_update); @@ -3497,7 +3420,8 @@ void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_c void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) { - if (!drawablep + LL_PROFILE_ZONE_SCOPED; + if (!drawablep || drawablep->isDead() || !hasRenderType(drawablep->getRenderType())) { @@ -3790,9 +3714,36 @@ void renderSoundHighlights(LLDrawable* drawablep) } } +void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize) +{ + if (tex) + { + LLImageGL* gl_tex = tex->getGLTexture(); + if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory)) + { + tex->setActive(); + tex->addTextureStats(vsize); + } + } + + +} +void LLPipeline::touchTextures(LLDrawInfo* info) +{ + LL_PROFILE_ZONE_SCOPED; + for (int i = 0; i < info->mTextureList.size(); ++i) + { + touchTexture(info->mTextureList[i], info->mTextureListVSize[i]); + } + + touchTexture(info->mTexture, info->mVSize); + touchTexture(info->mSpecularMap, info->mVSize); + touchTexture(info->mNormalMap, info->mVSize); +} + void LLPipeline::postSort(LLCamera& camera) { - LL_RECORD_BLOCK_TIME(FTM_STATESORT_POSTSORT); + LL_PROFILE_ZONE_SCOPED; assertInitialized(); @@ -3842,20 +3793,14 @@ void LLPipeline::postSort(LLCamera& camera) for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k) { - if (sMinRenderSize > 0.f) - { - LLVector4a bounds; - bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]); - - if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize) - { - sCull->pushDrawInfo(j->first, *k); - } - } - else - { - sCull->pushDrawInfo(j->first, *k); - } + LLDrawInfo* info = *k; + + sCull->pushDrawInfo(j->first, info); + if (!sShadowRender && !sReflectionRender) + { + touchTextures(info); + addTrianglesDrawn(info->mCount, info->mDrawMode); + } } } @@ -3994,7 +3939,10 @@ void LLPipeline::postSort(LLCamera& camera) { mSelectedFaces.clear(); - LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + if (!gNonInteractive) + { + LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + } // Draw face highlights for selected faces. if (LLSelectMgr::getInstance()->getTEMode()) @@ -4038,10 +3986,7 @@ void render_hud_elements() gGL.color4f(1,1,1,1); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); LLGLDepthTest depth(GL_TRUE, GL_FALSE); if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) @@ -4052,8 +3997,11 @@ void render_hud_elements() // Draw the tracking overlays LLTracker::render3D(); - // Show the property lines - LLWorld::getInstance()->renderPropertyLines(); + if (LLWorld::instanceExists()) + { + // Show the property lines + LLWorld::getInstance()->renderPropertyLines(); + } LLViewerParcelMgr::getInstance()->render(); LLViewerParcelMgr::getInstance()->renderParcelCollision(); @@ -4070,10 +4018,7 @@ void render_hud_elements() LLHUDText::renderAllHUD(); } - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } + gUIProgram.unbind(); gGL.flush(); } @@ -4105,10 +4050,7 @@ void LLPipeline::renderHighlights() gGL.setColorMask(false, false); - if (LLGLSLShader::sNoFixedFunction) - { - gHighlightProgram.bind(); - } + gHighlightProgram.bind(); for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter) { @@ -4340,7 +4282,6 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate) // Do verification of GL state LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); if (mRenderDebugMask & RENDER_DEBUG_VERIFY) { if (!verify()) @@ -4564,92 +4505,98 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); + { + // SL-15709 -- NOTE: Tracy only allows one ZoneScoped per function. + // Solutions are: + // 1. Use a new scope + // 2. Use named zones + // 3. Use transient zones + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); - LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS); + LLGLEnable cull(GL_CULL_FACE); - LLGLEnable cull(GL_CULL_FACE); - - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (hasRenderType(poolp->getType())) + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { - poolp->prerender(); + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } } - } - LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); - U32 cur_type = 0; + U32 cur_type = 0; - gGL.setColorMask(true, true); + gGL.setColorMask(true, true); - pool_set_t::iterator iter1 = mPools.begin(); + pool_set_t::iterator iter1 = mPools.begin(); - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; - cur_type = poolp->getType(); + cur_type = poolp->getType(); - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) - { - LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) + { + LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLRENDER); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); - for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) - { - LLVertexBuffer::unbind(); - poolp->beginDeferredPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) + for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) + LLVertexBuffer::unbind(); + poolp->beginDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) { - break; + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); } } - - if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); } - } - poolp->endDeferredPass(i); - LLVertexBuffer::unbind(); + poolp->endDeferredPass(i); + LLVertexBuffer::unbind(); - if (gDebugGL || gDebugPipeline) - { - LLGLState::checkStates(); + if (gDebugGL || gDebugPipeline) + { + LLGLState::checkStates(); + } } } - } - else - { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) + else { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) { - break; + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } } } + iter1 = iter2; + stop_glerror(); } - iter1 = iter2; - stop_glerror(); - } - gGLLastMatrix = NULL; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(gGLModelView); - gGL.setColorMask(true, false); + gGL.setColorMask(true, false); + + } // Tracy ZoneScoped } void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) @@ -4749,7 +4696,8 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion) void LLPipeline::renderGeomShadow(LLCamera& camera) { - U32 cur_type = 0; + LL_PROFILE_ZONE_SCOPED; + U32 cur_type = 0; LLGLEnable cull(GL_CULL_FACE); @@ -4814,6 +4762,7 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type) { + LL_PROFILE_ZONE_SCOPED; assertInitialized(); S32 count = 0; if (render_type == LLRender::TRIANGLE_STRIP) @@ -4853,10 +4802,7 @@ void LLPipeline::renderPhysicsDisplay() gGL.setColorMask(true, false); - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } + gDebugProgram.bind(); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -4877,11 +4823,7 @@ void LLPipeline::renderPhysicsDisplay() gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.unbind(); - } - + gDebugProgram.unbind(); mPhysicsDisplay.flush(); } @@ -4908,13 +4850,10 @@ void LLPipeline::renderDebug() if ( pathfindingCharacter->getVisible() || gAgentCamera.cameraMouselook() ) { - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingProgram.bind(); - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - } + gPathfindingProgram.bind(); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); //Requried character physics capsule render parameters LLUUID id; @@ -4923,21 +4862,14 @@ void LLPipeline::renderDebug() if ( pathfindingCharacter->isPhysicsCapsuleEnabled( id, pos, rot ) ) { - if (LLGLSLShader::sNoFixedFunction) - { - //remove blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - gGL.setColorMask(true, false); - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - } + //remove blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + gGL.setColorMask(true, false); + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + gPathfindingProgram.bind(); } } } @@ -4953,14 +4885,11 @@ void LLPipeline::renderDebug() { F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingProgram.bind(); + gPathfindingProgram.bind(); - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - } + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); if ( !pathfindingConsole->isRenderWorld() ) { @@ -4992,18 +4921,11 @@ void LLPipeline::renderDebug() } //render edges - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); - gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); - llPathingLibInstance->renderNavMeshEdges(); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderNavMeshEdges(); - } + gPathfindingNoNormalsProgram.bind(); + gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); + llPathingLibInstance->renderNavMeshEdges(); + gPathfindingProgram.bind(); gGL.flush(); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); @@ -5014,53 +4936,31 @@ void LLPipeline::renderDebug() if ( LLPathfindingPathTool::getInstance()->isRenderPath() ) { //The path - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - llPathingLibInstance->renderPath(); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderPath(); - } - //The bookends - if (LLGLSLShader::sNoFixedFunction) - { - //remove blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + gUIProgram.bind(); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + llPathingLibInstance->renderPath(); + gPathfindingProgram.bind(); + + //The bookends + //remove blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - gGL.setColorMask(true, false); - //render the bookends - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - } - + gGL.setColorMask(true, false); + //render the bookends + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + gPathfindingProgram.bind(); } if ( pathfindingConsole->isRenderWaterPlane() ) { - if (LLGLSLShader::sNoFixedFunction) - { - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); - } - else - { - llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); - } + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); } //physics/exclusion shapes if ( pathfindingConsole->isRenderAnyShapes() ) @@ -5191,18 +5091,11 @@ void LLPipeline::renderDebug() } //render edges - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - llPathingLibInstance->renderNavMeshEdges(); - gPathfindingProgram.bind(); - } - else - { - llPathingLibInstance->renderNavMeshEdges(); - } + gPathfindingNoNormalsProgram.bind(); + gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + llPathingLibInstance->renderNavMeshEdges(); + gPathfindingProgram.bind(); gGL.flush(); glLineWidth(1.0f); @@ -5211,10 +5104,7 @@ void LLPipeline::renderDebug() glPolygonOffset(0.f, 0.f); gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gPathfindingProgram.unbind(); - } + gPathfindingProgram.unbind(); } } } @@ -5229,10 +5119,7 @@ void LLPipeline::renderDebug() if (!hud_only && !mDebugBlips.empty()) { //render debug blips - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); @@ -5296,7 +5183,7 @@ void LLPipeline::renderDebug() } } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && LLGLSLShader::sNoFixedFunction) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { //render visible selected group occlusion geometry gDebugProgram.bind(); LLGLDepthTest depth(GL_TRUE, GL_FALSE); @@ -5318,44 +5205,38 @@ void LLPipeline::renderDebug() visible_selected_groups.clear(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only) { //draw crosshairs on particle intersection if (gDebugRaycastParticle) { - if (LLGLSLShader::sNoFixedFunction) - { //this debug display requires shaders - gDebugProgram.bind(); + gDebugProgram.bind(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); - LLVector3 size(0.1f, 0.1f, 0.1f); + LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); + LLVector3 size(0.1f, 0.1f, 0.1f); - LLVector3 p[6]; + LLVector3 p[6]; - p[0] = center + size.scaledVec(LLVector3(1,0,0)); - p[1] = center + size.scaledVec(LLVector3(-1,0,0)); - p[2] = center + size.scaledVec(LLVector3(0,1,0)); - p[3] = center + size.scaledVec(LLVector3(0,-1,0)); - p[4] = center + size.scaledVec(LLVector3(0,0,1)); - p[5] = center + size.scaledVec(LLVector3(0,0,-1)); + p[0] = center + size.scaledVec(LLVector3(1,0,0)); + p[1] = center + size.scaledVec(LLVector3(-1,0,0)); + p[2] = center + size.scaledVec(LLVector3(0,1,0)); + p[3] = center + size.scaledVec(LLVector3(0,-1,0)); + p[4] = center + size.scaledVec(LLVector3(0,0,1)); + p[5] = center + size.scaledVec(LLVector3(0,0,-1)); - gGL.begin(LLRender::LINES); - gGL.diffuseColor3f(1.f, 1.f, 0.f); - for (U32 i = 0; i < 6; i++) - { - gGL.vertex3fv(p[i].mV); - } - gGL.end(); - gGL.flush(); - - gDebugProgram.unbind(); + gGL.begin(LLRender::LINES); + gGL.diffuseColor3f(1.f, 1.f, 0.f); + for (U32 i = 0; i < 6; i++) + { + gGL.vertex3fv(p[i].mV); } + gGL.end(); + gGL.flush(); + + gDebugProgram.unbind(); } } @@ -5588,17 +5469,12 @@ void LLPipeline::renderDebug() } gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } + gUIProgram.unbind(); } -static LLTrace::BlockTimerStatHandle FTM_REBUILD_POOLS("Rebuild Pools"); - void LLPipeline::rebuildPools() { - LL_RECORD_BLOCK_TIME(FTM_REBUILD_POOLS); + LL_PROFILE_ZONE_SCOPED; assertInitialized(); @@ -5942,6 +5818,7 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) void LLPipeline::resetDrawOrders() { + LL_PROFILE_ZONE_SCOPED; assertInitialized(); // Iterate through all of the draw pools and rebuild them. for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) @@ -6261,11 +6138,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLEnvironment& environment = LLEnvironment::instance(); LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - if (!LLGLSLShader::sNoFixedFunction) - { - gGL.syncMatrices(); - } - // Ambient LLColor4 ambient = psky->getTotalAmbient(); gGL.setAmbientLightColor(ambient); @@ -6387,21 +6259,19 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) continue; } - LLVector3 light_pos(light->getRenderPosition()); - LLVector4 light_pos_gl(light_pos, 1.0f); - - F32 light_radius = llmax(light->getLightRadius(), 0.001f); - F32 size = light_radius * (sRenderDeferred ? 1.5f : 1.0f); + LLVector3 light_pos(light->getRenderPosition()); + LLVector4 light_pos_gl(light_pos, 1.0f); - if (size <= 0.001f) + F32 adjusted_radius = light->getLightRadius() * (sRenderDeferred ? 1.5f : 1.0f); + if (adjusted_radius <= 0.001f) { continue; } - F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior. - F32 linatten = x / (light_radius); // % of brightness at radius + F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior. + F32 linatten = x / adjusted_radius; // % of brightness at radius - mHWLightColors[cur_light] = light_color; + mHWLightColors[cur_light] = light_color; LLLightState* light_state = gGL.getLight(cur_light); light_state->setPosition(light_pos_gl); @@ -6410,7 +6280,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) light_state->setConstantAttenuation(0.f); if (sRenderDeferred) { - light_state->setLinearAttenuation(size); + light_state->setLinearAttenuation(linatten); light_state->setQuadraticAttenuation(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF) + 1.f); // get falloff to match for forward deferred rendering lights } else @@ -6466,11 +6336,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) // prev site of forward (non-deferred) character light injection, removed by SL-13522 09/20 // Init GL state - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } - for (S32 i = 0; i < 8; ++i) { gGL.getLight(i)->disable(); @@ -6489,13 +6354,6 @@ void LLPipeline::enableLights(U32 mask) if (mLightMask != mask) { stop_glerror(); - if (!mLightMask) - { - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - } - } if (mask) { stop_glerror(); @@ -6515,13 +6373,6 @@ void LLPipeline::enableLights(U32 mask) } stop_glerror(); } - else - { - if (!LLGLSLShader::sNoFixedFunction) - { - glDisable(GL_LIGHTING); - } - } mLightMask = mask; stop_glerror(); } @@ -6572,11 +6423,6 @@ void LLPipeline::enableLightsPreview() { disableLights(); - if (!LLGLSLShader::sNoFixedFunction) - { - glEnable(GL_LIGHTING); - } - LLColor4 ambient = PreviewAmbientColor; gGL.setAmbientLightColor(ambient); @@ -7357,8 +7203,6 @@ void LLPipeline::resetVertexBuffers() mResetVertexBuffers = true; } -static LLTrace::BlockTimerStatHandle FTM_RESET_VB("Reset VB"); - void LLPipeline::doResetVertexBuffers(bool forced) { if (!mResetVertexBuffers) @@ -7380,7 +7224,7 @@ void LLPipeline::doResetVertexBuffers(bool forced) } } - LL_RECORD_BLOCK_TIME(FTM_RESET_VB); + LL_PROFILE_ZONE_SCOPED; mResetVertexBuffers = false; mCubeVB = NULL; @@ -7450,32 +7294,91 @@ void LLPipeline::doResetVertexBuffers(bool forced) LLVOPartGroup::restoreGL(); } -void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture) +void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged) { assertInitialized(); gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; - mSimplePool->pushBatches(type, mask, texture, batch_texture); + if (rigged) + { + mSimplePool->pushRiggedBatches(type + 1, mask, texture, batch_texture); + } + else + { + mSimplePool->pushBatches(type, mask, texture, batch_texture); + } gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; } -void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture) +void LLPipeline::renderAlphaObjects(U32 mask, bool texture, bool batch_texture, bool rigged) +{ + LL_PROFILE_ZONE_SCOPED; + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + U32 type = LLRenderPass::PASS_ALPHA; + LLVOAvatar* lastAvatar = nullptr; + U64 lastMeshId = 0; + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + { + 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; + } + + 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; +} + +void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged) { assertInitialized(); gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; - mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + if (rigged) + { + mAlphaMaskPool->pushRiggedMaskBatches(type+1, mask, texture, batch_texture); + } + else + { + mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + } gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; } -void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture) +void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged) { assertInitialized(); gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; - mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + if (rigged) + { + mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, mask, texture, batch_texture); + } + else + { + mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture); + } gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; } @@ -7580,11 +7483,8 @@ void LLPipeline::renderFinalize() if (sRenderGlow) { - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); - mGlow[2].bindTarget(); - mGlow[2].clear(); - } + mGlow[2].bindTarget(); + mGlow[2].clear(); gGlowExtractProgram.bind(); F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f); @@ -7650,11 +7550,8 @@ void LLPipeline::renderFinalize() for (S32 i = 0; i < kernel; i++) { - { - LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO); - mGlow[i % 2].bindTarget(); - mGlow[i % 2].clear(); - } + mGlow[i % 2].bindTarget(); + mGlow[i % 2].clear(); if (i == 0) { @@ -8079,18 +7976,7 @@ void LLPipeline::renderFinalize() LLGLDisable blend(GL_BLEND); - if (LLGLSLShader::sNoFixedFunction) - { - gGlowCombineProgram.bind(); - } - else - { - // tex unit 0 - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - // tex unit 1 - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, - LLTexUnit::TBS_PREV_COLOR); - } + gGlowCombineProgram.bind(); gGL.getTexUnit(0)->bind(&mGlow[1]); gGL.getTexUnit(1)->bind(&mScreen); @@ -8100,28 +7986,14 @@ void LLPipeline::renderFinalize() buff->setBuffer(mask); buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); - if (LLGLSLShader::sNoFixedFunction) - { - gGlowCombineProgram.unbind(); - } - else - { - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - } + gGlowCombineProgram.unbind(); } gGL.setSceneBlendType(LLRender::BT_ALPHA); if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) { - if (LLGLSLShader::sNoFixedFunction) - { - gSplatTextureRectProgram.bind(); - } + gSplatTextureRectProgram.bind(); gGL.setColorMask(true, false); @@ -8147,10 +8019,7 @@ void LLPipeline::renderFinalize() gGL.end(); gGL.flush(); - if (LLGLSLShader::sNoFixedFunction) - { - gSplatTextureRectProgram.unbind(); - } + gSplatTextureRectProgram.unbind(); } if (LLRenderTarget::sUseFBO) @@ -8171,11 +8040,9 @@ void LLPipeline::renderFinalize() LLGLState::checkTextureChannels(); } -static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred"); - void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target) { - LL_RECORD_BLOCK_TIME(FTM_BIND_DEFERRED); + LL_PROFILE_ZONE_SCOPED; LLRenderTarget* deferred_target = &mDeferredScreen; LLRenderTarget* deferred_depth_target = &mDeferredDepth; @@ -8417,8 +8284,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ LLEnvironment& environment = LLEnvironment::instance(); LLSettingsSky::ptr_t sky = environment.getCurrentSky(); - - static_cast<LLSettingsVOSky*>(sky.get())->updateShader(&shader); } LLColor3 pow3f(LLColor3 v, F32 f) @@ -8437,19 +8302,9 @@ LLVector4 pow4fsrgb(LLVector4 v, F32 f) return v; } -static LLTrace::BlockTimerStatHandle FTM_GI_TRACE("Trace"); -static LLTrace::BlockTimerStatHandle FTM_GI_GATHER("Gather"); -static LLTrace::BlockTimerStatHandle FTM_SUN_SHADOW("Shadow Map"); -static LLTrace::BlockTimerStatHandle FTM_SOFTEN_SHADOW("Shadow Soften"); -static LLTrace::BlockTimerStatHandle FTM_EDGE_DETECTION("Find Edges"); -static LLTrace::BlockTimerStatHandle FTM_LOCAL_LIGHTS("Local Lights"); -static LLTrace::BlockTimerStatHandle FTM_ATMOSPHERICS("Atmospherics"); -static LLTrace::BlockTimerStatHandle FTM_FULLSCREEN_LIGHTS("Fullscreen Lights"); -static LLTrace::BlockTimerStatHandle FTM_PROJECTORS("Projectors"); -static LLTrace::BlockTimerStatHandle FTM_POST("Post"); - void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) { + LL_PROFILE_ZONE_SCOPED; if (!sCull) { return; @@ -8526,7 +8381,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) { deferred_light_target->bindTarget(); { // paint shadow/SSAO light map (direct lighting lightmap) - LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW); + LL_PROFILE_ZONE_NAMED("renderDeferredLighting - sun shadow"); bindDeferredShader(gDeferredSunProgram, deferred_light_target); mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX); glClearColor(1, 1, 1, 1); @@ -8572,7 +8427,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) if (RenderDeferredSSAO) { // soften direct lighting lightmap - LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW); + LL_PROFILE_ZONE_NAMED("renderDeferredLighting - soften shadow"); // blur lightmap screen_target->bindTarget(); glClearColor(1, 1, 1, 1); @@ -8650,7 +8505,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) { // apply sunlight contribution LLGLSLShader &soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram; - LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS); + LL_PROFILE_ZONE_NAMED("renderDeferredLighting - atmospherics"); bindDeferredShader(soften_shader); LLEnvironment &environment = LLEnvironment::instance(); @@ -8716,6 +8571,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) LLVertexBuffer::unbind(); { + LL_PROFILE_ZONE_NAMED("renderDeferredLighting - local lights"); bindDeferredShader(gDeferredLightProgram); if (mCubeVB.isNull()) @@ -8786,7 +8642,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) continue; } - LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS); gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c); gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s); gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV); @@ -8822,6 +8677,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) if (!spot_lights.empty()) { + LL_PROFILE_ZONE_NAMED("renderDeferredLighting - projectors"); LLGLDepthTest depth(GL_TRUE, GL_FALSE); bindDeferredShader(gDeferredSpotLightProgram); @@ -8831,7 +8687,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) { - LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable *drawablep = *iter; LLVOVolume *volume = drawablep->getVOVolume(); @@ -8867,6 +8722,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) vert[2].set(3, 1, 0); { + LL_PROFILE_ZONE_NAMED("renderDeferredLighting - fullscreen lights"); LLGLDepthTest depth(GL_FALSE); // full screen blit @@ -8886,7 +8742,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) while (!fullscreen_lights.empty()) { - LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS); light[count] = fullscreen_lights.front(); fullscreen_lights.pop_front(); col[count] = light_colors.front(); @@ -8918,7 +8773,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) { - LL_RECORD_BLOCK_TIME(FTM_PROJECTORS); LLDrawable *drawablep = *iter; LLVOVolume *volume = drawablep->getVOVolume(); LLVector3 center = drawablep->getPositionAgent(); @@ -9262,8 +9116,19 @@ inline float sgn(float a) void LLPipeline::generateWaterReflection(LLCamera& camera_in) { - if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate) + LL_PROFILE_ZONE_SCOPED; + + if (!assertInitialized()) + { + return; + } + + if (LLPipeline::sWaterReflections && LLDrawPoolWater::sNeedsReflectionUpdate) { + //disable occlusion culling for reflection/refraction passes (save setting to restore later) + S32 occlude = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 0; + bool skip_avatar_update = false; if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) { @@ -9300,26 +9165,19 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) //plane params LLPlane plane; LLVector3 pnorm; - S32 water_clip = 0; - if (!camera_is_underwater) + + if (camera_is_underwater) { - //camera is above water, clip plane points up - pnorm.setVec(0,0,1); - plane.setVec(pnorm, -water_height); - water_clip = 1; + //camera is below water, cull above water + pnorm.setVec(0, 0, 1); } else { - //camera is below water, clip plane points down - pnorm = LLVector3(0,0,-1); - plane.setVec(pnorm, water_height); - water_clip = -1; + //camera is above water, cull below water + pnorm = LLVector3(0, 0, -1); } - S32 occlusion = LLPipeline::sUseOcclusion; - - //disable occlusion culling for reflection map for now - LLPipeline::sUseOcclusion = 0; + plane.setVec(LLVector3(0, 0, water_height), pnorm); if (!camera_is_underwater) { @@ -9418,7 +9276,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLUserClipPlane clip_plane(plane, mReflectionModelView, saved_projection); LLGLDisable cull(GL_CULL_FACE); - updateCull(camera, mReflectedObjects, -water_clip, &plane); + updateCull(camera, mReflectedObjects, &plane); stateSort(camera, mReflectedObjects); renderGeom(camera); } @@ -9436,8 +9294,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) set_current_modelview(saved_modelview); } - //LLPipeline::sUseOcclusion = occlusion; - camera.setOrigin(camera_in.getOrigin()); //render distortion map static bool last_update = true; @@ -9485,41 +9341,47 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) mWaterDis.clear(); gGL.setColorMask(true, false); - F32 water_dist = water_height * LLPipeline::sDistortionWaterClipPlaneMargin; + F32 water_dist = water_height; //clip out geometry on the same side of water as the camera w/ enough margin to not include the water geo itself, // but not so much as to clip out parts of avatars that should be seen under the water in the distortion map - LLPlane plane(-pnorm, water_dist); + LLPlane plane; + + if (camera_is_underwater) + { + //nudge clip plane below water to avoid visible holes in objects intersecting water surface + water_dist /= LLPipeline::sDistortionWaterClipPlaneMargin; + //camera is below water, clip plane points up + pnorm.setVec(0, 0, -1); + } + else + { + //nudge clip plane above water to avoid visible holes in objects intersecting water surface + water_dist *= LLPipeline::sDistortionWaterClipPlaneMargin; + //camera is above water, clip plane points down + pnorm = LLVector3(0, 0, 1); + } + + plane.setVec(LLVector3(0, 0, water_dist), pnorm); + LLGLUserClipPlane clip_plane(plane, saved_modelview, saved_projection); gGL.setColorMask(true, true); mWaterDis.clear(); gGL.setColorMask(true, false); - // ignore clip plane if we're underwater and viewing distortion map of objects above waterline - if (camera_is_underwater) - { - clip_plane.disable(); - } - if (reflection_detail >= WATER_REFLECT_NONE_WATER_TRANSPARENT) { - updateCull(camera, mRefractedObjects, water_clip, &plane); + updateCull(camera, mRefractedObjects, &plane); stateSort(camera, mRefractedObjects); renderGeom(camera); } - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } + gUIProgram.bind(); LLWorld::getInstance()->renderPropertyLines(); - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.unbind(); - } + gUIProgram.unbind(); mWaterDis.flush(); } @@ -9532,7 +9394,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.popRenderTypeMask(); - LLPipeline::sUseOcclusion = occlusion; LLPipeline::sUnderWaterRender = false; LLPipeline::sReflectionRender = false; @@ -9554,6 +9415,32 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + + // restore occlusion culling + LLPipeline::sUseOcclusion = occlude; + } + else + { + // Initial sky pass is still needed even if water reflection is not rendering + bool camera_is_underwater = LLViewerCamera::getInstance()->cameraUnderWater(); + if (!camera_is_underwater) + { + gPipeline.pushRenderTypeMask(); + { + gPipeline.andRenderTypeMask( + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::END_RENDER_TYPES); + + LLCamera camera = camera_in; + camera.setFar(camera_in.getFar() * 0.75f); + + updateCull(camera, mSky); + stateSort(camera, mSky); + renderGeom(camera, TRUE); + } + gPipeline.popRenderTypeMask(); + } } } @@ -9634,204 +9521,212 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass"); static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked"); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, bool use_shader, bool use_occlusion, U32 target_width) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width) { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); + LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); - //clip out geometry on the same side of water as the camera - S32 occlude = LLPipeline::sUseOcclusion; - if (!use_occlusion) - { - LLPipeline::sUseOcclusion = 0; - } - LLPipeline::sShadowRender = true; - - static const U32 types[] = { - LLRenderPass::PASS_SIMPLE, - LLRenderPass::PASS_FULLBRIGHT, - LLRenderPass::PASS_SHINY, - LLRenderPass::PASS_BUMP, - LLRenderPass::PASS_FULLBRIGHT_SHINY , - LLRenderPass::PASS_MATERIAL, - LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - LLRenderPass::PASS_SPECMAP, - LLRenderPass::PASS_SPECMAP_EMISSIVE, - LLRenderPass::PASS_NORMMAP, - LLRenderPass::PASS_NORMMAP_EMISSIVE, - LLRenderPass::PASS_NORMSPEC, - LLRenderPass::PASS_NORMSPEC_EMISSIVE, - }; + //disable occlusion culling for shadow passes (save setting to restore later) + S32 occlude = LLPipeline::sUseOcclusion; + if (!use_occlusion) + { + LLPipeline::sUseOcclusion = 0; + } + LLPipeline::sShadowRender = true; + + static const U32 types[] = { + LLRenderPass::PASS_SIMPLE, + LLRenderPass::PASS_FULLBRIGHT, + LLRenderPass::PASS_SHINY, + LLRenderPass::PASS_BUMP, + LLRenderPass::PASS_FULLBRIGHT_SHINY , + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, + }; + + LLGLEnable cull(GL_CULL_FACE); + + //enable depth clamping if available + LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); + + if (use_shader) + { + gDeferredShadowCubeProgram.bind(); + } - LLGLEnable cull(GL_CULL_FACE); + LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID - 1]; - //enable depth clamping if available - LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0); + occlusion_target.bindTarget(); + updateCull(shadow_cam, result); + occlusion_target.flush(); - if (use_shader) - { - gDeferredShadowCubeProgram.bind(); - } + stateSort(shadow_cam, result); - LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1]; - occlusion_target.bindTarget(); - updateCull(shadow_cam, result); - occlusion_target.flush(); + //generate shadow map + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(proj.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadMatrix(view.m); - stateSort(shadow_cam, result); - - - //generate shadow map - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadMatrix(proj.m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadMatrix(view.m); + stop_glerror(); + gGLLastMatrix = NULL; - stop_glerror(); - gGLLastMatrix = NULL; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - stop_glerror(); - LLEnvironment& environment = LLEnvironment::instance(); - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - { - if (!use_shader) - { //occlusion program is general purpose depth-only no-textures - gOcclusionProgram.bind(); - } - else - { - gDeferredShadowProgram.bind(); - gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - } + 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); + } - gGL.diffuseColor4f(1,1,1,1); + gGL.diffuseColor4f(1, 1, 1, 1); S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); // if not using VSM, disable color writes if (shadow_detail <= 2) { - gGL.setColorMask(false, false); + gGL.setColorMask(false, false); } - - LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); - - gGL.getTexUnit(0)->disable(); - for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) - { - renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); - } - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - if (!use_shader) - { - gOcclusionProgram.unbind(); - } - } - - if (use_shader) - { + + LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); + + gGL.getTexUnit(0)->disable(); + for (U32 i = 0; i < sizeof(types) / sizeof(U32); ++i) + { + renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE, FALSE, rigged); + } + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + if (!use_shader) + { + gOcclusionProgram.unbind(); + } + + + } + + if (use_shader) + { LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM); - gDeferredShadowProgram.unbind(); - renderGeomShadow(shadow_cam); - gDeferredShadowProgram.bind(); + gDeferredShadowProgram.unbind(); + renderGeomShadow(shadow_cam); + gDeferredShadowProgram.bind(); gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - } - else - { + } + else + { LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM); - renderGeomShadow(shadow_cam); - } + renderGeomShadow(shadow_cam); + } - { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA); + { + LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA); - gDeferredShadowAlphaMaskProgram.bind(); - gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); - gDeferredShadowAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); + for (int i = 0; i < 2; ++i) + { + bool rigged = i == 1; - U32 mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_TEXTURE_INDEX; + gDeferredShadowAlphaMaskProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED); - renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE); - } + U32 mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TEXTURE_INDEX; - { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_BLEND); - gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f); - renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE); - } + { + LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED); + renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE, rigged); + } - { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED); - gDeferredShadowFullbrightAlphaMaskProgram.bind(); - gDeferredShadowFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); - gDeferredShadowFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE); - } + { + LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_BLEND); + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f); + renderAlphaObjects(mask, TRUE, TRUE, rigged); + } - mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX; - { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_TREE); - gDeferredTreeShadowProgram.bind(); - gDeferredTreeShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, mask); - renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, mask); - renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, mask); - renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, mask); + { + LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED); + gDeferredShadowFullbrightAlphaMaskProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); + renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE, rigged); + } + + + { + LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_GRASS); + gDeferredTreeShadowProgram.bind(rigged); + if (i == 0) + { + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f); + renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); + } + + U32 no_idx_mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX; + renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, no_idx_mask, true, false, rigged); + renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, no_idx_mask, true, false, rigged); + renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, no_idx_mask, true, false, rigged); + renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, no_idx_mask, true, false, rigged); + } } - - { - LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_GRASS); - gDeferredTreeShadowProgram.setMinimumAlpha(0.598f); - renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); - } } - //glCullFace(GL_BACK); + //glCullFace(GL_BACK); - gDeferredShadowCubeProgram.bind(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); + gDeferredShadowCubeProgram.bind(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); - LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID-1]; + LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID - 1]; - doOcclusion(shadow_cam, occlusion_source, occlusion_target); + doOcclusion(shadow_cam, occlusion_source, occlusion_target); - if (use_shader) - { - gDeferredShadowProgram.unbind(); - } - - gGL.setColorMask(true, true); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - gGLLastMatrix = NULL; + if (use_shader) + { + gDeferredShadowProgram.unbind(); + } + + gGL.setColorMask(true, true); - LLPipeline::sUseOcclusion = occlude; - LLPipeline::sShadowRender = false; + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + gGLLastMatrix = NULL; + + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = false; } -static LLTrace::BlockTimerStatHandle FTM_VISIBLE_CLOUD("Visible Cloud"); bool LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir) { - LL_RECORD_BLOCK_TIME(FTM_VISIBLE_CLOUD); + LL_PROFILE_ZONE_SCOPED; //get point cloud of intersection of frust and min, max if (getVisibleExtents(camera, min, max)) @@ -10043,10 +9938,7 @@ void LLPipeline::generateHighlight(LLCamera& camera) gGL.setColorMask(true, true); mHighlight.clear(); - if (LLGLSLShader::sNoFixedFunction) - { - gHighlightProgram.bind(); - } + gHighlightProgram.bind(); gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ) @@ -10088,9 +9980,6 @@ LLRenderTarget* LLPipeline::getShadowTarget(U32 i) } static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); -static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SETUP("Sun Shadow Setup"); -static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_RENDER_DIRECTIONAL("Render Dir"); -static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_SETUP("Spot Shadow Setup"); static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render"); void LLPipeline::generateSunShadow(LLCamera& camera) @@ -10160,6 +10049,29 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND, LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK, LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SIMPLE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_BUMP_RIGGED, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SHINY_RIGGED, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED, END_RENDER_TYPES); gGL.setColorMask(false, false); @@ -10886,17 +10798,28 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool textu } } -static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_MARK_VISIBLE("Impostor Mark Visible"); -static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_SETUP("Impostor Setup"); -static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_BACKGROUND("Impostor Background"); -static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_ALLOCATE("Impostor Allocate"); -static LLTrace::BlockTimerStatHandle FTM_IMPOSTOR_RESIZE("Impostor Resize"); +void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture) +{ + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + { + LLSpatialGroup* group = *i; + if (!group->isDead() && + (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && + gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && + group->mDrawMap.find(type) != group->mDrawMap.end()) + { + pass->renderRiggedGroup(group, type, mask, texture); + } + } +} + +static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor"); void LLPipeline::generateImpostor(LLVOAvatar* avatar) { + LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR); LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); static LLCullResult result; result.clear(); @@ -10924,37 +10847,31 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (visually_muted || too_complex) { + // only show jelly doll geometry andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, END_RENDER_TYPES); } else { - andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA, - LLPipeline::RENDER_TYPE_FULLBRIGHT, - LLPipeline::RENDER_TYPE_VOLUME, - LLPipeline::RENDER_TYPE_GLOW, - LLPipeline::RENDER_TYPE_BUMP, - LLPipeline::RENDER_TYPE_PASS_SIMPLE, - LLPipeline::RENDER_TYPE_PASS_ALPHA, - LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_BUMP, - LLPipeline::RENDER_TYPE_PASS_POST_BUMP, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, - LLPipeline::RENDER_TYPE_PASS_GLOW, - LLPipeline::RENDER_TYPE_PASS_GRASS, - LLPipeline::RENDER_TYPE_PASS_SHINY, - LLPipeline::RENDER_TYPE_PASS_INVISIBLE, - LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY, - LLPipeline::RENDER_TYPE_AVATAR, - LLPipeline::RENDER_TYPE_CONTROL_AV, - LLPipeline::RENDER_TYPE_ALPHA_MASK, - LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_INVISIBLE, - LLPipeline::RENDER_TYPE_SIMPLE, - END_RENDER_TYPES); + //hide world geometry + clearRenderTypeMask( + RENDER_TYPE_SKY, + RENDER_TYPE_WL_SKY, + RENDER_TYPE_GROUND, + RENDER_TYPE_TERRAIN, + RENDER_TYPE_GRASS, + RENDER_TYPE_CONTROL_AV, // Animesh + RENDER_TYPE_TREE, + RENDER_TYPE_VOIDWATER, + RENDER_TYPE_WATER, + RENDER_TYPE_PASS_GRASS, + RENDER_TYPE_HUD, + RENDER_TYPE_PARTICLES, + RENDER_TYPE_CLOUDS, + RENDER_TYPE_HUD_PARTICLES, + END_RENDER_TYPES + ); } S32 occlusion = sUseOcclusion; @@ -10968,7 +10885,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_MARK_VISIBLE); markVisible(avatar->mDrawable, *viewer_camera); LLVOAvatar::attachment_map_t::iterator iter; @@ -10997,7 +10913,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) U32 resX = 0; { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_SETUP); const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); @@ -11054,9 +10969,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete()) { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_ALLOCATE); - - if (LLPipeline::sRenderDeferred) { avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE); @@ -11073,7 +10985,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) } else if(resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_RESIZE); avatar->mImpostor.resize(resX,resY); } @@ -11135,10 +11046,10 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLDrawPoolAvatar::sMinimumAlpha = old_alpha; { //create alpha mask based on depth buffer (grey out if muted) - LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_BACKGROUND); if (LLPipeline::sRenderDeferred) { GLuint buff = GL_COLOR_ATTACHMENT0; + LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x8000FF ); glDrawBuffersARB(1, &buff); } @@ -11167,11 +11078,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) static const F32 clip_plane = 0.99999f; - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.bind(); - } - + gDebugProgram.bind(); if (visually_muted) { // Visually muted avatar @@ -11185,7 +11092,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.diffuseColor4fv(LLColor4::pink.mV ); } - { gGL.begin(LLRender::QUADS); gGL.vertex3f(-1, -1, clip_plane); gGL.vertex3f(1, -1, clip_plane); @@ -11193,12 +11099,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.vertex3f(-1, 1, clip_plane); gGL.end(); gGL.flush(); - } - if (LLGLSLShader::sNoFixedFunction) - { - gDebugProgram.unbind(); - } + gDebugProgram.unbind(); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -11227,7 +11129,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); } bool LLPipeline::hasRenderBatches(const U32 type) const diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 0eaa6b141d..fdc3738472 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -66,7 +66,6 @@ bool setup_hud_matrices(const LLRect& screen_region); // specify portion of scre extern LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY; extern LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS; extern LLTrace::BlockTimerStatHandle FTM_RENDER_INVISIBLE; -extern LLTrace::BlockTimerStatHandle FTM_RENDER_OCCLUSION; extern LLTrace::BlockTimerStatHandle FTM_RENDER_SHINY; extern LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE; extern LLTrace::BlockTimerStatHandle FTM_RENDER_TERRAIN; @@ -87,8 +86,6 @@ extern LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY; extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_HUD; extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_3D; extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_2D; -extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_DEBUG_TEXT; -extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_SCENE_MON; class LLPipeline { @@ -228,9 +225,7 @@ public: S32 getLightingDetail() const { return mLightingDetail; } S32 getMaxLightingDetail() const; - void setUseVertexShaders(bool use_shaders); - bool getUseVertexShaders() const { return mVertexShadersEnabled; } - bool canUseVertexShaders(); + bool shadersLoaded(); bool canUseWindLightShaders() const; bool canUseWindLightShadersOnObjects() const; bool canUseAntiAliasing() const; @@ -245,7 +240,7 @@ public: bool visibleObjectsInFrustum(LLCamera& camera); bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0)); - void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane + void updateCull(LLCamera& camera, LLCullResult& result, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void processPartitionQ(); @@ -265,13 +260,20 @@ public: void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE); void stateSort(LLDrawable* drawablep, LLCamera& camera); void postSort(LLCamera& camera); + + //update stats for textures in given DrawInfo + void touchTextures(LLDrawInfo* info); + void touchTexture(LLViewerTexture* tex, F32 vsize); + void forAllVisibleDrawables(void (*func)(LLDrawable*)); - void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); - void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); - void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false); + void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false); + 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); void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture); + void renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture); void grabReferences(LLCullResult& result); void clearReferences(); @@ -458,34 +460,61 @@ public: RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, + RENDER_TYPE_PASS_SIMPLE_RIGGED = LLRenderPass::PASS_SIMPLE_RIGGED, RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, + RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT, RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, + RENDER_TYPE_PASS_INVISIBLE_RIGGED = LLRenderPass::PASS_INVISIBLE_RIGGED, RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, + RENDER_TYPE_PASS_INVISI_SHINY_RIGGED = LLRenderPass::PASS_INVISI_SHINY_RIGGED, RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, + RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED = LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, + RENDER_TYPE_PASS_SHINY_RIGGED = LLRenderPass::PASS_SHINY_RIGGED, RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, + RENDER_TYPE_PASS_BUMP_RIGGED = LLRenderPass::PASS_BUMP_RIGGED, RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP, + RENDER_TYPE_PASS_POST_BUMP_RIGGED = LLRenderPass::PASS_POST_BUMP_RIGGED, RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, + RENDER_TYPE_PASS_GLOW_RIGGED = LLRenderPass::PASS_GLOW_RIGGED, RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, + RENDER_TYPE_PASS_ALPHA_MASK_RIGGED = LLRenderPass::PASS_ALPHA_MASK_RIGGED, RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL, + RENDER_TYPE_PASS_MATERIAL_RIGGED = LLRenderPass::PASS_MATERIAL_RIGGED, RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA, + RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_RIGGED, RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP, + RENDER_TYPE_PASS_SPECMAP_RIGGED = LLRenderPass::PASS_SPECMAP_RIGGED, RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND, + RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED = LLRenderPass::PASS_SPECMAP_BLEND_RIGGED, RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK, + RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED = LLRenderPass::PASS_SPECMAP_MASK_RIGGED, RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE, + RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED = LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP, + RENDER_TYPE_PASS_NORMMAP_RIGGED = LLRenderPass::PASS_NORMMAP_RIGGED, RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND, + RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED = LLRenderPass::PASS_NORMMAP_BLEND_RIGGED, RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK, + RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED = LLRenderPass::PASS_NORMMAP_MASK_RIGGED, RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE, + RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC, + RENDER_TYPE_PASS_NORMSPEC_RIGGED = LLRenderPass::PASS_NORMSPEC_RIGGED, RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND, + RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED = LLRenderPass::PASS_NORMSPEC_BLEND_RIGGED, RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK, + RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED = LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, + RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, // Following are object types (only used in drawable mRenderType) RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, RENDER_TYPE_VOLUME, @@ -574,7 +603,6 @@ public: static bool sDelayVBUpdate; static bool sAutoMaskAlphaDeferred; static bool sAutoMaskAlphaNonDeferred; - static bool sDisableShaders; // if true, rendering will be done without shaders static bool sRenderTransparentWater; static bool sRenderBump; static bool sBakeSunlight; @@ -597,7 +625,6 @@ public: static bool sRenderAttachedParticles; static bool sRenderDeferred; static S32 sVisibleLightCount; - static F32 sMinRenderSize; static bool sRenderingHUDs; static F32 sDistortionWaterClipPlaneMargin; @@ -676,8 +703,7 @@ public: LLVector4 mTransformedMoonDir; bool mInitialized; - bool mVertexShadersEnabled; - S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed + bool mShadersLoaded; U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback protected: @@ -878,7 +904,6 @@ public: //cached settings static bool WindLightUseAtmosShaders; - static bool RenderAvatarVP; static bool RenderDeferred; static F32 RenderDeferredSunWash; static U32 RenderFSAASamples; diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index 7654f0dcd6..b322e67bb7 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -60,7 +60,6 @@ DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 20 expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). GL Copyright (C) 1999-2004 Brian Paul. -GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index 42e23b2089..b2708f7141 100644 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -19,7 +19,6 @@ mit Open-Source-Beiträgen von:</text> expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm und Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University sowie David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW). diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 7786ba8a1c..d1e167df64 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -102,6 +102,18 @@ Low </text> + <check_box + control_name="RenderVSyncEnable" + height="16" + initial_value="true" + label="Enable VSync" + layout="topleft" + left="30" + top_delta="16" + name="vsync" + tool_tip="Synchronizes the frame rate to the refresh rate of the monitor, which results in smooth performance." + width="315" /> + <text type="string" length="1" @@ -334,18 +346,6 @@ width="256" /> <check_box - control_name="RenderVBOEnable" - height="16" - initial_value="true" - label="Enable OpenGL Vertex Buffer Objects" - layout="topleft" - left="30" - top_delta="16" - name="vbo" - tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled." - width="315" /> - - <check_box control_name="RenderCompressTextures" height="16" initial_value="true" @@ -661,20 +661,6 @@ </text> <check_box - control_name="RenderAvatarVP" - height="16" - initial_value="true" - label="Avatar Hardware skinning" - layout="topleft" - left="440" - name="AvatarVertexProgram" - top_delta="16" - width="280"> - <check_box.commit_callback - function="Pref.RenderOptionUpdate" /> - </check_box> - - <check_box control_name="RenderAvatarCloth" height="16" initial_value="true" @@ -885,7 +871,7 @@ layout="topleft" left="13" name="horiz_border" - top_pad="5" + top_pad="21" top_delta="5" width="774"/> <button diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index f9d44b2c69..b9ca0108b6 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -35,6 +35,25 @@ decimal_digits="1" show_bar="true" show_history="true"/> + <stat_bar name="frame_mean" + label="frame (mean)" + unit_label="ms" + stat="frametime" + decimal_digits="1" + show_bar="false" + show_history="false"/> + <stat_bar name="frame_median" + label="frame (median)" + unit_label="ms" + stat="frametime" + show_median="true" + decimal_digits="1" + show_bar="false" + show_history="false"/> + <stat_bar name="framet_jitter" + label="jitter" + decimal_digits="1" + stat="frametimejitter"/> <stat_bar name="bandwidth" label="UDP Data Received" stat="activemessagedatareceived" diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index 8f143cf072..f59f534908 100644 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -19,7 +19,6 @@ con contribuciones de código abierto de:</text> expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm y Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University y David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index 1e2a14ab3e..df6b61e293 100644 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -19,7 +19,6 @@ avec les contributions Open Source de :</text> expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm et Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University, et David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index 9603238b66..edb334e13e 100644 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -19,7 +19,6 @@ con contributi open source da:</text> expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm e Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University e David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index cf5e97bd8d..6a39d057e2 100644 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -19,7 +19,6 @@ DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 20 expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. -GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 65c457f822..3c0ca332ac 100644 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -19,7 +19,6 @@ com contribuições de código aberto de:</text> expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University e David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml index ee9f82847d..44216e0430 100644 --- a/indra/newview/skins/default/xui/ru/floater_about.xml +++ b/indra/newview/skins/default/xui/ru/floater_about.xml @@ -19,7 +19,6 @@ expat (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType (C) 1996-2002, 2006 David Turner, Robert Wilhelm и Werner Lemberg. GL (C) 1999-2004 Brian Paul. - GLOD (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Университет Джона Гопкинса и David Luebke, Brenden Schubert, Университет Вирджинии. google-perftools (c) 2005, Google Inc. Havok.com(TM) (C) 1999-2001, Telekinesys Research Limited. jpeg2000 (C) 2001, David Taubman, Университет Нового Южного Уэльса (UNSW) diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml index b91575954b..faa504a996 100644 --- a/indra/newview/skins/default/xui/tr/floater_about.xml +++ b/indra/newview/skins/default/xui/tr/floater_about.xml @@ -19,7 +19,6 @@ açık kaynak kod katkısında bulunanlar şunlardır:</text> expat Telif Hakkı (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Telif Hakkı (C) 1996-2002, 2006 David Turner, Robert Wilhelm ve Werner Lemberg. GL Telif Hakkı (C) 1999-2004 Brian Paul. - GLOD Telif Hakkı (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University ve David Luebke, Brenden Schubert, University of Virginia. google-perftools Telif Hakkı (c) 2005, Google Inc. Havok.com(TM) Telif Hakkı (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Telif Hakkı (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml index 9f6b4421a9..d7d2a52750 100644 --- a/indra/newview/skins/default/xui/zh/floater_about.xml +++ b/indra/newview/skins/default/xui/zh/floater_about.xml @@ -19,7 +19,6 @@ expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia. google-perftools Copyright (c) 2005, Google Inc. Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) diff --git a/indra/newview/slplugin.entitlements b/indra/newview/slplugin.entitlements index a72c6bc82c..aea8dbfd15 100644 --- a/indra/newview/slplugin.entitlements +++ b/indra/newview/slplugin.entitlements @@ -12,5 +12,7 @@ <true/> <key>com.apple.security.cs.allow-dyld-environment-variables</key> <true/> + <key>com.apple.security.device.audio-input</key> + <true/> </dict> </plist> diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 87c4a8d8a3..bb48216b2b 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -112,6 +112,7 @@ public: virtual void recordMessage(LLError::ELevel level, const std::string& message) { + LL_PROFILE_ZONE_SCOPED mFile << message << std::endl; } |