diff options
| author | Dave Parks <davep@lindenlab.com> | 2022-03-29 15:41:00 -0500 | 
|---|---|---|
| committer | Dave Parks <davep@lindenlab.com> | 2022-03-29 15:41:00 -0500 | 
| commit | e60024f0afecb6f92e383221084f1a7af02f8542 (patch) | |
| tree | 4d61ab23da7bb316903185622ee2abc7fd398b5b | |
| parent | 180989f28e69600a3bc198b8b62101ec25374bee (diff) | |
SL-17005 WIP - Use D3D/DXGI to query for available VRAM on Windows
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 52 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.h | 8 | ||||
| -rw-r--r-- | indra/llwindow/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llwindow/llwindow.h | 3 | ||||
| -rw-r--r-- | indra/llwindow/llwindowheadless.h | 2 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 136 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.h | 4 | ||||
| -rw-r--r-- | indra/newview/lltextureview.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llviewerdisplay.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.cpp | 4 | 
10 files changed, 153 insertions, 66 deletions
| diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c171f7051f..0a5d258b3a 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1615,51 +1615,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_      return TRUE;  } -void LLImageGLThread::updateClass() -{ -    LL_PROFILE_ZONE_SCOPED; - -    // update available vram one per second -    static LLFrameTimer sTimer; - -    if (sTimer.getElapsedSeconds() < 1.f) -    { -        return; -    } -     -    sTimer.reset(); - -    auto func = []() -    { -        if (gGLManager.mHasATIMemInfo) -        { -            S32 meminfo[4]; -            glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); -            LLImageGLThread::sFreeVRAMMegabytes = meminfo[0]; - -        } -        else if (gGLManager.mHasNVXMemInfo) -        { -            S32 free_memory; -            glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); -            LLImageGLThread::sFreeVRAMMegabytes = free_memory / 1024; -        } -    }; - -     -    // post update to background thread if available, otherwise execute immediately -    auto queue = LL::WorkQueue::getInstance("LLImageGL"); -    if (sEnabled) -    { -        queue->post(func); -    } -    else -    { -        llassert(queue == nullptr); -        func(); -    } -} -  void LLImageGL::syncToMainThread(LLGLuint new_tex_name)  {      LL_PROFILE_ZONE_SCOPED; @@ -2389,8 +2344,6 @@ void LLImageGL::checkActiveThread()  		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,  nummips);  */   -std::atomic<S32> LLImageGLThread::sFreeVRAMMegabytes(4096); //if free vram is unknown, default to 4GB -  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() @@ -2418,8 +2371,3 @@ void LLImageGLThread::run()      mWindow->destroySharedContext(mContext);  } -S32 LLImageGLThread::getFreeVRAMMegabytes() -{ -    return sFreeVRAMMegabytes; -} - diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index ae4ab7c9c3..1716338c0b 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -321,12 +321,6 @@ public:      // follows gSavedSettings "RenderGLMultiThreaded"      static bool sEnabled; -    // app should call this function periodically -    static void updateClass(); - -    // free video memory in megabytes -    static std::atomic<S32> sFreeVRAMMegabytes; -      LLImageGLThread(LLWindow* window);      // post a function to be executed on the LLImageGL background thread @@ -338,8 +332,6 @@ public:      void run() override; -    static S32 getFreeVRAMMegabytes(); -  private:      LLWindow* mWindow;      void* mContext = nullptr; diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 70eb99c86c..32f0fa14c4 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -145,6 +145,8 @@ if (WINDOWS)    list(APPEND llwindow_LINK_LIBRARIES         comdlg32     # Common Dialogs for ChooseColor         ole32 +       dxgi +       d3d9         )  endif (WINDOWS) diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0edf39f6ef..507e6076d6 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -163,6 +163,9 @@ public:  	virtual F32 getPixelAspectRatio() = 0;  	virtual void setNativeAspectRatio(F32 aspect) = 0; +    // query VRAM usage +    virtual U32 getAvailableVRAMMegabytes() = 0; +  	virtual void beforeDialog() {};	// prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)  	virtual void afterDialog() {};	// undo whatever was done in beforeDialog() diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 410da79623..0e1f603db7 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -96,6 +96,8 @@ public:  	/*virtual*/ F32 getPixelAspectRatio() { return 1.0f; };  	/*virtual*/ void setNativeAspectRatio(F32 ratio) {} +    U32 getAvailableVRAMMegabytes() override { return 4096; } +  	/*virtual*/ void *getPlatformWindow() { return 0; };  	/*virtual*/ void bringToFront() {}; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 9feccd7874..3afb78d1d2 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -47,6 +47,7 @@  #include "llglslshader.h"  #include "llthreadsafequeue.h"  #include "stringize.h" +#include "llframetimer.h"  // System includes  #include <commdlg.h> @@ -61,6 +62,10 @@  #include <sstream>  #include <utility>                  // std::pair +#include <d3d9.h> +#include <dxgi1_4.h> + +  // Require DirectInput version 8  #define DIRECTINPUT_VERSION 0x0800 @@ -347,6 +352,20 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool      void run() override; +    // initialzie DXGI adapter (for querying available VRAM) +    void initDX(); +     +    // initialize D3D (if DXGI cannot be used) +    void initD3D(); + +    // call periodically to update available VRAM +    void updateVRAMUsage(); + +    U32 getAvailableVRAMMegabytes() +    { +        return mAvailableVRAM; +    } +      /// called by main thread to post work to this window thread      template <typename CALLABLE>      void post(CALLABLE&& func) @@ -395,6 +414,12 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool      void gatherInput();      HWND mWindowHandle = NULL;      HDC mhDC = 0; + +    std::atomic<U32> mAvailableVRAM; + +    IDXGIAdapter3* mDXGIAdapter = nullptr; +    LPDIRECT3D9 mD3D = nullptr; +    LPDIRECT3DDEVICE9 mD3DDevice = nullptr;  }; @@ -4507,6 +4532,10 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()  	return std::vector<std::string>();  } +U32 LLWindowWin32::getAvailableVRAMMegabytes() +{ +    return mWindowThread ? mWindowThread->getAvailableVRAMMegabytes() : 0; +}  #endif // LL_WINDOWS @@ -4562,17 +4591,97 @@ private:      std::string mPrev;  }; +void LLWindowWin32::LLWindowWin32Thread::initDX() +{ +    if (mDXGIAdapter == NULL) +    { +        IDXGIFactory4* pFactory = nullptr; + +        HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory); + +        if (FAILED(res)) +        { +            LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL; +        } +        else +        { +            res = pFactory->EnumAdapters(0, reinterpret_cast<IDXGIAdapter**>(&mDXGIAdapter)); +            if (FAILED(res)) +            { +                LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL; +            } +        } + +        pFactory->Release(); +    } +} + +void LLWindowWin32::LLWindowWin32Thread::initD3D() +{ +    if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandle != 0) +    { +        mD3D = Direct3DCreate9(D3D_SDK_VERSION); +         +        D3DPRESENT_PARAMETERS d3dpp; + +        ZeroMemory(&d3dpp, sizeof(d3dpp)); +        d3dpp.Windowed = TRUE; +        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + +        mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice); +    } +} + +void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() +{ +    LL_PROFILE_ZONE_SCOPED; +    if (mDXGIAdapter != nullptr) +    { +        DXGI_QUERY_VIDEO_MEMORY_INFO info; +        mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &info); + +        // try to use no more than the available reserve minus 10% +        U32 target = info.AvailableForReservation / 1024 / 1024; +        target -= target / 10; + +        U32 used_vram = info.CurrentUsage / 1024 / 1024; + +        mAvailableVRAM = used_vram < target ? target - used_vram : 0; + +        /*LL_INFOS() << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024 +            << "\nBudget: " << info.Budget / 1024 / 1024 +            << "\nCR: " << info.CurrentReservation / 1024 / 1024 +            << "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL; + +        mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info); +        LL_INFOS() << "\nNon-Local\nAFR: " << info.AvailableForReservation / 1024 / 1024 +            << "\nBudget: " << info.Budget / 1024 / 1024 +            << "\nCR: " << info.CurrentReservation / 1024 / 1024 +            << "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;*/ +    } +    else if (mD3DDevice != NULL) +    { // fallback to D3D9 +        mAvailableVRAM = mD3DDevice->GetAvailableTextureMem() / 1024 / 1024; +    } + +} +  void LLWindowWin32::LLWindowWin32Thread::run()  {      sWindowThreadId = std::this_thread::get_id();      LogChange logger("Window"); +    initDX(); +      while (! getQueue().done())      {          LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;          if (mWindowHandle != 0)          { +            // lazily call initD3D inside this loop to catch when mWindowHandle has been set +            initD3D(); +              MSG msg;              BOOL status;              if (mhDC == 0) @@ -4605,6 +4714,13 @@ void LLWindowWin32::LLWindowWin32Thread::run()              getQueue().runPending();          } +        // update available vram once every 3 seconds +        static LLFrameTimer vramTimer; +        if (vramTimer.getElapsedTimeF32() > 3.f) +        { +            updateVRAMUsage(); +            vramTimer.reset(); +        }  #if 0          {              LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Sleep"); @@ -4613,6 +4729,26 @@ void LLWindowWin32::LLWindowWin32Thread::run()          }  #endif      } + +    //clean up DXGI/D3D resources +    if (mDXGIAdapter) +    { +        mDXGIAdapter->Release(); +        mDXGIAdapter = nullptr; +    } + +    if (mD3DDevice) +    { +        mD3DDevice->Release(); +        mD3DDevice = nullptr; +    } + +    if (mD3D) +    { +        mD3D->Release(); +        mD3D = nullptr; +    } +  }  void LLWindowWin32::post(const std::function<void()>& func) diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index b391acc12d..bd53b3e92a 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -108,7 +108,9 @@ public:  	/*virtual*/ F32 getPixelAspectRatio();  	/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } -	/*virtual*/	BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b ); +    U32 getAvailableVRAMMegabytes() override; +	 +    /*virtual*/	BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );  	/*virtual*/ void *getPlatformWindow();  	/*virtual*/ void bringToFront(); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index b58070526c..99ab854293 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -49,6 +49,8 @@  #include "llviewerobjectlist.h"  #include "llviewertexture.h"  #include "llviewertexturelist.h" +#include "llviewerwindow.h" +#include "llwindow.h"  #include "llvovolume.h"  #include "llviewerstats.h"  #include "llworld.h" @@ -545,8 +547,8 @@ void LLGLTexMemBar::draw()      U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);      U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f); -	text = llformat("GL Free: %d Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", -                    LLImageGLThread::getFreeVRAMMegabytes(), +    text = llformat("GL Free: %d Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", +                    gViewerWindow->getWindow()->getAvailableVRAMMegabytes(),                      LLMemory::getAvailableMemKB()/1024,  					LLRenderTarget::sBytesAllocated/(1024*1024),  					discard_bias, diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6a2b06d9b5..4fc1bdbec3 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -788,8 +788,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  				LLViewerTexture::updateClass();  			} -            LLImageGLThread::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. diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index be7ee3660e..ac6c86d9c6 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -58,6 +58,8 @@  #include "llvovolume.h"  #include "llviewermedia.h"  #include "lltexturecache.h" +#include "llviewerwindow.h" +#include "llwindow.h"  ///////////////////////////////////////////////////////////////////////////////  // extern @@ -523,7 +525,7 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p      timer.reset();      { -        gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes(); +        gpu_res = (S32Megabytes)gViewerWindow->getWindow()->getAvailableVRAMMegabytes();          //check main memory, only works for windows.          LLMemory::updateMemoryInfo(); | 
