From 24f8745914f7cec320d707f36895ac393575b861 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 19 Mar 2014 17:57:00 -0500 Subject: MAINT-3131 Use benchmark to determine GPU class instead of GPU table. --- indra/llrender/llglslshader.cpp | 58 +++++++++++++++++++++++------------ indra/llrender/llglslshader.h | 4 ++- indra/llrender/llrendertarget.cpp | 1 + indra/llrender/llshadermgr.cpp | 6 +++- indra/newview/llfeaturemanager.cpp | 63 +++++++++++++++++++++++++++++++++++--- indra/newview/llglsandbox.cpp | 31 ++++++++++++++++--- indra/newview/llviewermenu.cpp | 2 +- 7 files changed, 133 insertions(+), 32 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 1c50a51d02..b99435f39e 100755 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -87,6 +87,7 @@ LLShaderFeatures::LLShaderFeatures() , mIndexedTextureChannels(0) , disableTextureIndex(false) , hasAlphaMask(false) + , attachNothing(false) { } @@ -119,28 +120,31 @@ struct LLGLSLShaderCompareTimeElapsed }; //static -void LLGLSLShader::finishProfile() +void LLGLSLShader::finishProfile(bool emit_report) { sProfileEnabled = false; - std::vector sorted; - - for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + if (emit_report) { - sorted.push_back(*iter); - } + std::vector sorted; - std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + sorted.push_back(*iter); + } - for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) - { - (*iter)->dumpStats(); - } + std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); - llinfos << "-----------------------------------" << llendl; - llinfos << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << llendl; - llinfos << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << llendl; - llinfos << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << llendl; + for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + { + (*iter)->dumpStats(); + } + + llinfos << "-----------------------------------" << llendl; + llinfos << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << llendl; + llinfos << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << llendl; + llinfos << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << llendl; + } } void LLGLSLShader::clearStats() @@ -175,7 +179,7 @@ void LLGLSLShader::dumpStats() } } llinfos << "=============================================" << llendl; - + F32 ms = mTimeElapsed/1000000.f; F32 seconds = ms/1000.f; @@ -221,6 +225,7 @@ void LLGLSLShader::placeProfileQuery() #if !LL_DARWIN if (mTimerQuery == 0) { + glGenQueriesARB(1, &mSamplesQuery); glGenQueriesARB(1, &mTimerQuery); } @@ -257,7 +262,7 @@ void LLGLSLShader::placeProfileQuery() } - glBeginQueryARB(GL_SAMPLES_PASSED, 1); + glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery); glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery); #endif } @@ -272,7 +277,7 @@ void LLGLSLShader::readProfileQuery(U32 count, U32 mode) glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); U64 samples_passed = 0; - glGetQueryObjectui64v(1, GL_QUERY_RESULT, &samples_passed); + glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); sTotalTimeElapsed += time_elapsed; mTimeElapsed += time_elapsed; @@ -307,14 +312,15 @@ LLGLSLShader::LLGLSLShader() mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE), - mTimerQuery(0) + mTimerQuery(0), + mSamplesQuery(0) + { } LLGLSLShader::~LLGLSLShader() { - } void LLGLSLShader::unload() @@ -349,6 +355,18 @@ void LLGLSLShader::unload() mProgramObject = 0; } + if (mTimerQuery) + { + glDeleteQueriesARB(1, &mTimerQuery); + mTimerQuery = 0; + } + + if (mSamplesQuery) + { + glDeleteQueriesARB(1, &mSamplesQuery); + mSamplesQuery = 0; + } + //hack to make apple not complain glGetError(); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 7b2f5f04c2..5abddf274b 100755 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -51,6 +51,7 @@ public: S32 mIndexedTextureChannels; bool disableTextureIndex; bool hasAlphaMask; + bool attachNothing; // char numLights; @@ -80,7 +81,7 @@ public: static bool sNoFixedFunction; static void initProfile(); - static void finishProfile(); + static void finishProfile(bool emit_report = true); static void startProfile(); static void stopProfile(U32 count, U32 mode); @@ -184,6 +185,7 @@ public: //statistcis for profiling shader performance U32 mTimerQuery; + U32 mSamplesQuery; U64 mTimeElapsed; static U64 sTotalTimeElapsed; U32 mTrianglesDrawn; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index fe8110904d..33ef831cb4 100755 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -388,6 +388,7 @@ void LLRenderTarget::release() // if (mFBO && (mTex.size() > 1)) { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); S32 z; for (z = mTex.size() - 1; z >= 1; z--) { diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 6e04fc82df..b81ae9af09 100755 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -73,7 +73,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { llassert_always(shader != NULL); LLShaderFeatures *features = & shader->mFeatures; - + + if (features->attachNothing) + { + return TRUE; + } ////////////////////////////////////// // Attach Vertex Shader Features First ////////////////////////////////////// diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index ba6f26d3ef..938ea707f9 100755 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -417,13 +417,67 @@ bool LLFeatureManager::parseFeatureTable(std::string filename) return parse_ok; } +F32 gpu_benchmark(); + bool LLFeatureManager::loadGPUClass() { + //get memory bandwidth from benchmark + F32 gbps = gpu_benchmark(); + + if (gbps < -1.f) + { //couldn't bench, use GLVersion + + if (gGLManager.mGLVersion < 2.f) + { + mGPUClass = GPU_CLASS_0; + } + else if (gGLManager.mGLVersion < 3.f) + { + mGPUClass = GPU_CLASS_1; + } + else if (gGLManager.mGLVersion < 3.3f) + { + mGPUClass = GPU_CLASS_2; + } + else if (gGLManager.mGLVersion < 4.f) + { + mGPUClass = GPU_CLASS_3; + } + else + { + mGPUClass = GPU_CLASS_4; + } + } + else if (gbps < 5.f) + { + mGPUClass = GPU_CLASS_0; + } + else if (gbps < 10.f) + { + mGPUClass = GPU_CLASS_1; + } + else if (gbps < 20.f) + { + mGPUClass = GPU_CLASS_2; + } + else if (gbps < 40.f) + { + mGPUClass = GPU_CLASS_3; + } + else if (gbps < 80.f) + { + mGPUClass = GPU_CLASS_4; + } + else + { + mGPUClass = GPU_CLASS_5; + } + // defaults - mGPUClass = GPU_CLASS_UNKNOWN; mGPUString = gGLManager.getRawGLString(); - mGPUSupported = FALSE; + mGPUSupported = TRUE; +#if 0 // first table is in the app dir std::string app_path = gDirUtilp->getAppRODataDir(); app_path += gDirUtilp->getDirDelimiter(); @@ -451,8 +505,8 @@ bool LLFeatureManager::loadGPUClass() { parse_ok = parseGPUTable(app_path); } - - return parse_ok; // indicates that the file parsed correctly, not that the gpu was recognized +#endif + return true; // indicates that the file parsed correctly, not that the gpu was recognized } @@ -719,6 +773,7 @@ void LLFeatureManager::init() void LLFeatureManager::applyRecommendedSettings() { + loadGPUClass(); // apply saved settings // cap the level at 2 (high) U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index c4c1827266..92553e875d 100755 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -878,13 +878,32 @@ void LLViewerObjectList::renderObjectBeacons() } -void gpu_benchmark() +F32 gpu_benchmark() { - if (!LLGLSLShader::sNoFixedFunction) - { //don't bother benchmarking the fixed function - return; + if (!gGLManager.mHasShaderObjects || !gGLManager.mHasTimerQuery) + { //don't bother benchmarking the fixed function or using CPU timers + return -1.f; } + + if (gBenchmarkProgram.mProgramObject == 0) + { + LLViewerShaderMgr::instance()->initAttribsAndUniforms(); + + gBenchmarkProgram.mName = "Benchmark Shader"; + gBenchmarkProgram.mFeatures.attachNothing = true; + gBenchmarkProgram.mShaderFiles.clear(); + gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB)); + gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB)); + gBenchmarkProgram.mShaderLevel = 1; + if (!gBenchmarkProgram.createShader(NULL, NULL)) + { + return -1.f; + } + } + + LLGLDisable blend(GL_BLEND); + //measure memory bandwidth by: // - allocating a batch of textures and render targets // - rendering those textures to those render targets @@ -981,7 +1000,7 @@ void gpu_benchmark() gBenchmarkProgram.unbind(); - LLGLSLShader::finishProfile(); + LLGLSLShader::finishProfile(false); LLImageGL::deleteTextures(count, source); @@ -1007,5 +1026,7 @@ void gpu_benchmark() { llinfos << "ARB_timer_query unavailable." << llendl; } + + return gbps; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c7c8da27f3..d5acec7c9a 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7197,7 +7197,7 @@ class LLAdvancedClickRenderProfile: public view_listener_t } }; -void gpu_benchmark(); +F32 gpu_benchmark(); class LLAdvancedClickRenderBenchmark: public view_listener_t { -- cgit v1.2.3 From 7defa95f6778778d850aa1aba3ea8cb16396d0dd Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 21 Mar 2014 14:30:14 -0500 Subject: MAINT-3131 fallback to CPU timers for return value of benchmark if ARB_timer_query is unavailable. --- indra/newview/llglsandbox.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 92553e875d..f620bf19fb 100755 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -880,8 +880,8 @@ void LLViewerObjectList::renderObjectBeacons() F32 gpu_benchmark() { - if (!gGLManager.mHasShaderObjects || !gGLManager.mHasTimerQuery) - { //don't bother benchmarking the fixed function or using CPU timers + if (!gGLManager.mHasShaderObjects) + { //don't bother benchmarking the fixed function return -1.f; } @@ -1011,15 +1011,15 @@ F32 gpu_benchmark() llinfos << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to CPU timers" << llendl; - F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; - - F64 samples_drawn = res*res*count*samples; - F32 samples_sec = (samples_drawn/1000000000.0)/seconds; - gbps = samples_sec*8; - if (gGLManager.mHasTimerQuery) { + F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; + F32 seconds = ms/1000.f; + + F64 samples_drawn = res*res*count*samples; + F32 samples_sec = (samples_drawn/1000000000.0)/seconds; + gbps = samples_sec*8; + llinfos << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query" << llendl; } else -- cgit v1.2.3 From c142696f9dd18dcebee903444225026caf08e6e3 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 21 Mar 2014 14:33:46 -0500 Subject: MAINT-3131 Actually fallback to GL version guess instead of treating error value from gpu_benchmark as actual memory bandwidth. --- indra/newview/llfeaturemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 938ea707f9..5f37c0ea73 100755 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -424,7 +424,7 @@ bool LLFeatureManager::loadGPUClass() //get memory bandwidth from benchmark F32 gbps = gpu_benchmark(); - if (gbps < -1.f) + if (gbps < 0.f) { //couldn't bench, use GLVersion if (gGLManager.mGLVersion < 2.f) -- cgit v1.2.3 From e43f43b4d9dbcaeb20884772b3fcba6df5e9a62c Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 24 Mar 2014 11:56:02 -0500 Subject: MAINT-3131 Attempt to work around drivers that lack timer query and ignore glFinish calls. --- indra/newview/llglsandbox.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index f620bf19fb..0a423e6785 100755 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -969,6 +969,8 @@ F32 gpu_benchmark() //wait for any previoius GL commands to finish glFinish(); + bool busted_finish = false; + for (S32 c = -1; c < samples; ++c) { LLTimer timer; @@ -983,7 +985,18 @@ F32 gpu_benchmark() } //wait for current batch of copies to finish - glFinish(); + if (busted_finish) + { + //read a pixel off the last target since some drivers seem to ignore glFinish + dest[count-1].bindTarget(); + U32 pixel = 0; + glReadPixels(0,0,1,1,GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + dest[count-1].flush(); + } + else + { + glFinish(); + } F32 time = timer.getElapsedTimeF32(); @@ -994,7 +1007,14 @@ F32 gpu_benchmark() F32 gbps = gb/time; - results.push_back(gbps); + if (!gGLManager.mHasTimerQuery && !busted_finish && gbps > 128.f) + { //unrealistically high bandwidth for a card without timer queries, glFinish is probably ignored + busted_finish = true; + } + else + { + results.push_back(gbps); + } } } -- cgit v1.2.3