diff options
author | Dave Parks <davep@lindenlab.com> | 2022-02-17 22:52:23 +0000 |
---|---|---|
committer | Dave Parks <davep@lindenlab.com> | 2022-02-17 22:52:23 +0000 |
commit | 0d6aa3c0fe184ae00899304cb3f71315f5c73314 (patch) | |
tree | 88196dfd88c70728132cd05b5b7d5d4e630dd50a /indra/newview | |
parent | 892f7d98d5da2c329472a7075a88e010277b86b0 (diff) |
SL-16815 Remove frame stalls from occlusion queries, bumpmap updates, and querying for available video memory.
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 203 | ||||
-rw-r--r-- | indra/newview/lldrawpoolbump.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewerdisplay.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llviewermedia.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llvieweroctree.cpp | 93 | ||||
-rw-r--r-- | indra/newview/llviewertexture.cpp | 24 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 5 |
7 files changed, 205 insertions, 132 deletions
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 471b0e2c48..20287a7777 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -54,6 +54,8 @@ // static LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; +LL::WorkQueue::weak_t LLBumpImageList::sMainQueue; +LL::WorkQueue::weak_t LLBumpImageList::sTexUpdateQueue; // static U32 LLStandardBumpmap::sStandardBumpmapCount = 0; @@ -761,6 +763,8 @@ void LLBumpImageList::init() LLStandardBumpmap::init(); LLStandardBumpmap::restoreGL(); + sMainQueue = LL::WorkQueue::getInstance("mainloop"); + sTexUpdateQueue = LL::WorkQueue::getInstance("LLImageGL"); // Share work queue with tex loader. } void LLBumpImageList::clear() @@ -909,10 +913,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText } else { - LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1); - raw->clear(0x77, 0x77, 0xFF, 0xFF); - - (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE); + (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( TRUE ); bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image } @@ -1043,10 +1044,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI iter->second->getWidth() != src->getWidth() || iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution { //make sure an entry exists for this image - LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1); - raw->clear(0x77, 0x77, 0xFF, 0xFF); - - entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE); + entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture(TRUE); iter = entries_list.find(src_vi->getID()); } } @@ -1166,108 +1164,161 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } //--------------------------------------------------- - // immediately assign bump to a global smart pointer in case some local smart pointer + // immediately assign bump to a smart pointer in case some local smart pointer // accidentally releases it. - LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE ); + LLPointer<LLViewerTexture> bump = iter->second; if (!LLPipeline::sRenderDeferred) { bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - bump->createGLTexture(0, dst_image); + + auto tex_queue = LLImageGLThread::sEnabled ? sTexUpdateQueue.lock() : nullptr; + + if (tex_queue) + { //dispatch creation to background thread + LLImageRaw* dst_ptr = dst_image; + LLViewerTexture* bump_ptr = bump; + dst_ptr->ref(); + bump_ptr->ref(); + tex_queue->post( + [=]() + { + LL_PROFILE_ZONE_NAMED("bil - create texture"); + bump_ptr->createGLTexture(0, dst_ptr); + bump_ptr->unref(); + dst_ptr->unref(); + }); + } + else + { + bump->createGLTexture(0, dst_image); + } } else { //convert to normal map //disable compression on normal maps to prevent errors below bump->getGLTexture()->setAllowCompression(false); + bump->getGLTexture()->setUseMipMaps(TRUE); - { - bump->setExplicitFormat(GL_RGBA8, GL_ALPHA); - bump->createGLTexture(0, dst_image); - } + auto* bump_ptr = bump.get(); + auto* dst_ptr = dst_image.get(); - { - gPipeline.mScreen.bindTarget(); - - LLGLDepthTest depth(GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - gGL.setColorMask(TRUE, TRUE); - gNormalMapGenProgram.bind(); + bump_ptr->ref(); + dst_ptr->ref(); - static LLStaticHashedString sNormScale("norm_scale"); - static LLStaticHashedString sStepX("stepX"); - static LLStaticHashedString sStepY("stepY"); + bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA); - gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale")); - gNormalMapGenProgram.uniform1f(sStepX, 1.f/bump->getWidth()); - gNormalMapGenProgram.uniform1f(sStepY, 1.f/bump->getHeight()); + auto create_texture = [bump_ptr, dst_ptr]() + { + LL_PROFILE_ZONE_NAMED("bil - create texture deferred"); + bump_ptr->createGLTexture(0, dst_ptr); + }; - LLVector2 v((F32) bump->getWidth()/gPipeline.mScreen.getWidth(), - (F32) bump->getHeight()/gPipeline.mScreen.getHeight()); + auto gen_normal_map = [bump_ptr, dst_ptr]() + { + LL_PROFILE_ZONE_NAMED("bil - generate normal map"); + gPipeline.mScreen.bindTarget(); - gGL.getTexUnit(0)->bind(bump); - - S32 width = bump->getWidth(); - S32 height = bump->getHeight(); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + gGL.setColorMask(TRUE, TRUE); + gNormalMapGenProgram.bind(); - S32 screen_width = gPipeline.mScreen.getWidth(); - S32 screen_height = gPipeline.mScreen.getHeight(); + static LLStaticHashedString sNormScale("norm_scale"); + static LLStaticHashedString sStepX("stepX"); + static LLStaticHashedString sStepY("stepY"); - glViewport(0, 0, screen_width, screen_height); + gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale")); + gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth()); + gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight()); - for (S32 left = 0; left < width; left += screen_width) - { - S32 right = left + screen_width; - right = llmin(right, width); - - F32 left_tc = (F32) left/ width; - F32 right_tc = (F32) right/width; + LLVector2 v((F32)bump_ptr->getWidth() / gPipeline.mScreen.getWidth(), + (F32)bump_ptr->getHeight() / gPipeline.mScreen.getHeight()); - for (S32 bottom = 0; bottom < height; bottom += screen_height) - { - S32 top = bottom+screen_height; - top = llmin(top, height); + gGL.getTexUnit(0)->bind(bump_ptr); - F32 bottom_tc = (F32) bottom/height; - F32 top_tc = (F32)(bottom+screen_height)/height; - top_tc = llmin(top_tc, 1.f); + S32 width = bump_ptr->getWidth(); + S32 height = bump_ptr->getHeight(); - F32 screen_right = (F32) (right-left)/screen_width; - F32 screen_top = (F32) (top-bottom)/screen_height; + S32 screen_width = gPipeline.mScreen.getWidth(); + S32 screen_height = gPipeline.mScreen.getHeight(); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.texCoord2f(left_tc, bottom_tc); - gGL.vertex2f(0, 0); + glViewport(0, 0, screen_width, screen_height); - gGL.texCoord2f(left_tc, top_tc); - gGL.vertex2f(0, screen_top); + for (S32 left = 0; left < width; left += screen_width) + { + S32 right = left + screen_width; + right = llmin(right, width); - gGL.texCoord2f(right_tc, bottom_tc); - gGL.vertex2f(screen_right, 0); + F32 left_tc = (F32)left / width; + F32 right_tc = (F32)right / width; - gGL.texCoord2f(right_tc, top_tc); - gGL.vertex2f(screen_right, screen_top); + for (S32 bottom = 0; bottom < height; bottom += screen_height) + { + S32 top = bottom + screen_height; + top = llmin(top, height); - gGL.end(); + F32 bottom_tc = (F32)bottom / height; + F32 top_tc = (F32)(bottom + screen_height) / height; + top_tc = llmin(top_tc, 1.f); - gGL.flush(); + F32 screen_right = (F32)(right - left) / screen_width; + F32 screen_top = (F32)(top - bottom) / screen_height; - S32 w = right-left; - S32 h = top-bottom; + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(left_tc, bottom_tc); + gGL.vertex2f(0, 0); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h); - } - } + gGL.texCoord2f(left_tc, top_tc); + gGL.vertex2f(0, screen_top); - glGenerateMipmap(GL_TEXTURE_2D); + gGL.texCoord2f(right_tc, bottom_tc); + gGL.vertex2f(screen_right, 0); - gPipeline.mScreen.flush(); + gGL.texCoord2f(right_tc, top_tc); + gGL.vertex2f(screen_right, screen_top); - gNormalMapGenProgram.unbind(); - - //generateNormalMapFromAlpha(dst_image, nrm_image); - } + gGL.end(); + + gGL.flush(); + + S32 w = right - left; + S32 h = top - bottom; + + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h); + } + } + + glGenerateMipmap(GL_TEXTURE_2D); + + gPipeline.mScreen.flush(); + + gNormalMapGenProgram.unbind(); + + //generateNormalMapFromAlpha(dst_image, nrm_image); + + bump_ptr->unref(); + dst_ptr->unref(); + }; + + auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr; + + if (main_queue) + { //dispatch creation to background thread + LLImageRaw* dst_ptr = dst_image; + LLViewerTexture* bump_ptr = bump; + dst_ptr->ref(); + bump_ptr->ref(); + + main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map); + } + else + { + create_texture(); + gen_normal_map(); + } } iter->second = bump; // derefs (and deletes) old image diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 38744a7d98..6e21859738 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -161,6 +161,8 @@ private: typedef std::unordered_map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t; bump_image_map_t mBrightnessEntries; bump_image_map_t mDarknessEntries; + static LL::WorkQueue::weak_t sMainQueue; + static LL::WorkQueue::weak_t sTexUpdateQueue; }; extern LLBumpImageList gBumpImageList; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index b5d3dc5d30..4fc1bdbec3 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -649,9 +649,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); } - //upkeep gl name pools - LLGLNamePool::upkeepPools(); - stop_glerror(); display_update_camera(); stop_glerror(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index bd60b9f1e2..42bd5d8367 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2986,11 +2986,12 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da LLPointer<LLImageRaw> raw = new LLImageRaw(data, media_tex->getWidth(), media_tex->getHeight(), media_tex->getComponents(), true); // Allocate GL texture based on LLImageRaw but do NOT copy to GL - media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true); + LLGLuint tex_name = 0; + media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true, &tex_name); // copy just the subimage covered by the image raw to GL - media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, sync); - media_tex->getGLTexture()->syncToMainThread(); + media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, tex_name); + media_tex->getGLTexture()->syncToMainThread(tex_name); // release the data pointer before freeing raw so LLImageRaw destructor doesn't // free memory at data pointer diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 3cdef0ebff..65e9fa533d 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -787,42 +787,73 @@ void LLViewerOctreeGroup::checkStates() //occulsion culling functions and classes //------------------------------------------------------------------------------------------- std::set<U32> LLOcclusionCullingGroup::sPendingQueries; -class LLOcclusionQueryPool : public LLGLNamePool + +static std::queue<GLuint> sFreeQueries; + +U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() { -public: - LLOcclusionQueryPool() - { - } + LL_PROFILE_ZONE_SCOPED; + // TODO: refactor this to a general purpose name pool + static GLuint occlusion_queries[2][1024]; + static std::atomic<S32> query_count[2]; + static S32 query_page = -1; + + //reuse any query names that have been freed + if (!sFreeQueries.empty()) + { + GLuint ret = sFreeQueries.front(); + sFreeQueries.pop(); + return ret; + } -protected: + // first call, immediately fill entire name pool + if (query_page == -1) + { + glGenQueriesARB(1024, occlusion_queries[0]); + glGenQueriesARB(1024, occlusion_queries[1]); + query_page = 0; + query_count[0] = 1024; + query_count[1] = 1024; + } - virtual GLuint allocateName() - { - GLuint ret = 0; + if (query_count[query_page] == 0) //this page is empty + { + //check the other page + query_page = (query_page + 1) % 2; - glGenQueriesARB(1, &ret); - - return ret; - } + if (query_count[query_page] == 0) + { + //the other page is also empty, generate immediately and return + GLuint ret; + glGenQueriesARB(1, &ret); + return ret; + } + } - virtual void releaseName(GLuint name) - { -#if LL_TRACK_PENDING_OCCLUSION_QUERIES - LLOcclusionCullingGroup::sPendingQueries.erase(name); -#endif - glDeleteQueriesARB(1, &name); - } -}; + GLuint ret = occlusion_queries[query_page][--query_count[query_page]]; -static LLOcclusionQueryPool sQueryPool; -U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() -{ - return sQueryPool.allocate(); + if (query_count[query_page] == 0) + { //exhausted this page, replenish on background thread + S32 page = query_page; + LL::WorkQueue::postMaybe(LL::WorkQueue::getInstance("LLImageGL"), + [=]() + { + LL_PROFILE_ZONE_NAMED("glGenQueries bg"); + if (query_count[page] == 0) // <-- protect against redundant attempts to replenish + { + glGenQueriesARB(1024, occlusion_queries[page]); + query_count[page] = 1024; + glFlush(); + } + }); + } + + return ret; } void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(GLuint name) { - sQueryPool.release(name); + sFreeQueries.push(name); } //===================================== @@ -1243,7 +1274,10 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh //store which frame this query was issued on mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; - glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); + { + LL_PROFILE_ZONE_NAMED("glBeginQuery"); + glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); + } LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; llassert(shader); @@ -1282,7 +1316,10 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh } } - glEndQueryARB(mode); + { + LL_PROFILE_ZONE_NAMED("glEndQuery"); + glEndQueryARB(mode); + } } } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5fed46f437..fa2c070ea0 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -515,9 +515,10 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLFrameTimer timer; + static S32Megabytes gpu_res = S32Megabytes(S32_MAX); static S32Megabytes physical_res = S32Megabytes(S32_MAX); - + if (timer.getElapsedTimeF32() < GPU_MEMORY_CHECK_WAIT_TIME) //call this once per second. { gpu = gpu_res; @@ -527,22 +528,11 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p timer.reset(); { - 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); - } + gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes(); + + //check main memory, only works for windows. + LLMemory::updateMemoryInfo(); + physical_res = LLMemory::getAvailableMemKB(); gpu = gpu_res; physical = physical_res; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 8d45e64bf8..ac242c2bf7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7267,11 +7267,6 @@ void LLPipeline::doResetVertexBuffers(bool forced) SUBSYSTEM_CLEANUP(LLVertexBuffer); - //delete all name pool caches - LLGLNamePool::cleanupPools(); - - - if (LLVertexBuffer::sGLCount > 0) { LL_WARNS() << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << LL_ENDL; |