summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt2
-rw-r--r--indra/llwindow/llwindow.h3
-rw-r--r--indra/llwindow/llwindowheadless.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp136
-rw-r--r--indra/llwindow/llwindowwin32.h4
5 files changed, 146 insertions, 1 deletions
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();