meow-7.2.2
Ansariel 2022-08-26 19:39:16 +02:00
commit c100236f39
5 changed files with 171 additions and 37 deletions

View File

@ -54,7 +54,6 @@ const F32 MIN_TEXTURE_LIFETIME = 10.f;
U32 wpo2(U32 i);
#if LL_DARWIN
// texture memory accounting (for OS X)
static LLMutex sTexMemMutex;
static std::unordered_map<U32, U32> sTextureAllocs;
@ -119,22 +118,6 @@ U64 LLImageGL::getTextureBytesAllocated()
return sTextureBytes;
}
#else
#define alloc_tex_image(width, height, pixformat) (void) width; (void) height; (void) pixformat;
#define free_tex_image(texName) (void) texName;
#define free_tex_images(count, texNames) (void) count; (void) texNames;
#define free_cur_tex_image()
// static
U64 LLImageGL::getTextureBytesAllocated()
{
// UNIMPLEMENTED OUTSIDE OF OS X, DO NOT CALL
llassert(false);
return 0;
}
#endif
//statics
U32 LLImageGL::sUniqueCount = 0;

View File

@ -53,7 +53,10 @@ class LLImageGL : public LLRefCount
friend class LLTexUnit;
public:
// For OS X use only -- get an estimate of how many bytes have been allocated in vram for textures
// Get an estimate of how many bytes have been allocated in vram for textures.
// Does not include mipmaps.
// NOTE: multiplying this number by two gives a good estimate for total
// video memory usage based on testing in lagland against an NVIDIA GPU.
static U64 getTextureBytesAllocated();
// These 2 functions replace glGenTextures() and glDeleteTextures()

View File

@ -48,6 +48,8 @@
#include "llthreadsafequeue.h"
#include "stringize.h"
#include "llframetimer.h"
#include "commoncontrol.h" // TODO: Remove after testing
#include "llsd.h" // TODO: Remove after testing
// System includes
#include <commdlg.h>
@ -414,9 +416,12 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
HWND mWindowHandle = NULL;
HDC mhDC = 0;
// best guess at available video memory in MB
std::atomic<U32> mAvailableVRAM;
bool mTryUseDXGIAdapter; // TODO: Remove after testing
IDXGIAdapter3* mDXGIAdapter = nullptr;
bool mTryUseD3DDevice; // TODO: Remove after testing
LPDIRECT3D9 mD3D = nullptr;
LPDIRECT3DDEVICE9 mD3DDevice = nullptr;
};
@ -4675,6 +4680,14 @@ void LLWindowWin32::getWindowChrome( U32 &aChromeW, U32 &aChromeH )
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
: ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE)
{
const LLSD skipDXGI{ LL::CommonControl::get("Global", "DisablePrimaryGraphicsMemoryAccounting") }; // TODO: Remove after testing
LL_WARNS() << "DisablePrimaryGraphicsMemoryAccounting: " << skipDXGI << ", as boolean: " << skipDXGI.asBoolean() << LL_ENDL;
mTryUseDXGIAdapter = !skipDXGI.asBoolean();
LL_WARNS() << "mTryUseDXGIAdapter: " << mTryUseDXGIAdapter << LL_ENDL;
const LLSD skipD3D{ LL::CommonControl::get("Global", "DisableSecondaryGraphicsMemoryAccounting") }; // TODO: Remove after testing
LL_WARNS() << "DisableSecondaryGraphicsMemoryAccounting: " << skipD3D << ", as boolean: " << skipD3D.asBoolean() << LL_ENDL;
mTryUseD3DDevice = !skipD3D.asBoolean();
LL_WARNS() << "mTryUseD3DDevice: " << mTryUseD3DDevice << LL_ENDL;
ThreadPool::start();
}
@ -4724,10 +4737,77 @@ private:
std::string mPrev;
};
// Print hardware debug info about available graphics adapters in ordinal order
void debugEnumerateGraphicsAdapters()
{
LL_INFOS("Window") << "Enumerating graphics adapters..." << LL_ENDL;
IDXGIFactory1* factory;
HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory);
if (FAILED(res) || !factory)
{
LL_WARNS() << "CreateDXGIFactory1 failed: 0x" << std::hex << res << LL_ENDL;
}
else
{
UINT graphics_adapter_index = 0;
IDXGIAdapter3* dxgi_adapter;
while (true)
{
res = factory->EnumAdapters(graphics_adapter_index, reinterpret_cast<IDXGIAdapter**>(&dxgi_adapter));
if (FAILED(res))
{
if (graphics_adapter_index == 0)
{
LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL;
}
else
{
LL_INFOS("Window") << "Done enumerating graphics adapters" << LL_ENDL;
}
}
else
{
DXGI_ADAPTER_DESC desc;
dxgi_adapter->GetDesc(&desc);
std::wstring description_w((wchar_t*)desc.Description);
std::string description(description_w.begin(), description_w.end());
LL_INFOS("Window") << "Graphics adapter index: " << graphics_adapter_index << ", "
<< "Description: " << description << ", "
<< "DeviceId: " << desc.DeviceId << ", "
<< "SubSysId: " << desc.SubSysId << ", "
<< "AdapterLuid: " << desc.AdapterLuid.HighPart << "_" << desc.AdapterLuid.LowPart << ", "
<< "DedicatedVideoMemory: " << desc.DedicatedVideoMemory / 1024 / 1024 << ", "
<< "DedicatedSystemMemory: " << desc.DedicatedSystemMemory / 1024 / 1024 << ", "
<< "SharedSystemMemory: " << desc.SharedSystemMemory / 1024 / 1024 << LL_ENDL;
}
if (dxgi_adapter)
{
dxgi_adapter->Release();
dxgi_adapter = NULL;
}
else
{
break;
}
graphics_adapter_index++;
}
}
if (factory)
{
factory->Release();
}
}
void LLWindowWin32::LLWindowWin32Thread::initDX()
{
if (mDXGIAdapter == NULL)
if (mDXGIAdapter == NULL && mTryUseDXGIAdapter)
{
debugEnumerateGraphicsAdapters();
IDXGIFactory4* pFactory = nullptr;
HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory);
@ -4743,15 +4823,22 @@ void LLWindowWin32::LLWindowWin32Thread::initDX()
{
LL_WARNS() << "EnumAdapters failed: 0x" << std::hex << res << LL_ENDL;
}
else
{
LL_INFOS() << "EnumAdapters success" << LL_ENDL;
}
}
pFactory->Release();
if (pFactory)
{
pFactory->Release();
}
}
}
void LLWindowWin32::LLWindowWin32Thread::initD3D()
{
if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandle != 0)
if (mDXGIAdapter == NULL && mD3DDevice == NULL && mTryUseD3DDevice && mWindowHandle != 0)
{
mD3D = Direct3DCreate9(D3D_SDK_VERSION);
@ -4761,7 +4848,16 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D()
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice);
HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice);
if (FAILED(res))
{
LL_WARNS() << "(fallback) CreateDevice failed: 0x" << std::hex << res << LL_ENDL;
}
else
{
LL_INFOS() << "(fallback) CreateDevice success" << LL_ENDL;
}
}
}
@ -4770,44 +4866,68 @@ void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage()
LL_PROFILE_ZONE_SCOPED;
if (mDXGIAdapter != nullptr)
{
// NOTE: what lies below is hand wavy math based on compatibility testing and observation against a variety of hardware
// It doesn't make sense, but please don't refactor it to make sense. -- davep
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.Budget / 1024 / 1024;
#if 0 // debug 0 budget and 0 CU
info.Budget = 0;
info.CurrentUsage = 0;
#endif
// EXPERIMENTAL
// Trying to zero in on a good target usage, code here should be tuned against observed behavior
// of various hardware.
if (target > 4096) // if 4GB are installed, try to leave 2GB free
U32 budget_mb = info.Budget / 1024 / 1024;
U32 afr_mb = info.AvailableForReservation / 1024 / 1024;
// correct for systems that misreport budget
if (budget_mb == 0)
{
// fall back to available for reservation clamped between 512MB and 2GB
budget_mb = llclamp(afr_mb, (U32) 512, (U32) 2048);
}
U32 cu_mb = info.CurrentUsage / 1024 / 1024;
// get an estimated usage based on texture bytes allocated
U32 eu_mb = LLImageGL::getTextureBytesAllocated() * 2 / 1024 / 1024;
if (cu_mb == 0)
{ // current usage is sometimes unreliable on Intel GPUs, fall back to estimated usage
cu_mb = llmax((U32)1, eu_mb);
}
F32 eu_error = (F32)((S32)eu_mb - (S32)cu_mb) / (F32)cu_mb;
U32 target_mb = info.Budget / 1024 / 1024;
if (target_mb > 4096) // if 4GB are installed, try to leave 2GB free
{
target -= 2048;
target_mb -= 2048;
}
else // if less than 4GB are installed, try not to use more than half of it
{
target /= 2;
target_mb /= 2;
}
U32 used_vram = info.CurrentUsage / 1024 / 1024;
mAvailableVRAM = used_vram < target ? target - used_vram : 0;
mAvailableVRAM = cu_mb < target_mb ? target_mb - cu_mb : 0;
LL_INFOS("Window") << "\nLocal\nAFR: " << info.AvailableForReservation / 1024 / 1024
<< "\nBudget: " << info.Budget / 1024 / 1024
<< "\nCR: " << info.CurrentReservation / 1024 / 1024
<< "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;
<< "\nCU: " << info.CurrentUsage / 1024 / 1024
<< "\nEU: " << eu_mb << llformat(" (%.2f)", eu_error)
<< "\nTU: " << target_mb
<< "\nAM: " << mAvailableVRAM << LL_ENDL;
mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info);
/*mDXGIAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &info);
LL_INFOS("Window") << "\nNon-Local\nAFR: " << info.AvailableForReservation / 1024 / 1024
<< "\nBudget: " << info.Budget / 1024 / 1024
<< "\nCR: " << info.CurrentReservation / 1024 / 1024
<< "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;
<< "\nCU: " << info.CurrentUsage / 1024 / 1024 << LL_ENDL;*/
}
else if (mD3DDevice != NULL)
{ // fallback to D3D9
mAvailableVRAM = mD3DDevice->GetAvailableTextureMem() / 1024 / 1024;
}
}
void LLWindowWin32::LLWindowWin32Thread::run()
@ -4824,6 +4944,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
if (mWindowHandle != 0)
{
// lazily call initD3D inside this loop to catch when mWindowHandle has been set
// *TODO: Shutdown if this fails when mWindowHandle exists
initD3D();
MSG msg;

View File

@ -5481,6 +5481,29 @@
<key>Backup</key>
<integer>0</integer>
</map>
<!-- TODO: Remove settings keys DisablePrimaryGraphicsMemoryAccounting and DisableSecondaryGraphicsMemoryAccounting after testing, and code that references them -->
<key>DisablePrimaryGraphicsMemoryAccounting</key>
<map>
<key>Comment</key>
<string>Disable the first method used to detect GPU memory use</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DisableSecondaryGraphicsMemoryAccounting</key>
<map>
<key>Comment</key>
<string>Disable the second method used to detect GPU memory use, used as a fallback when the first method fails</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DisableTextHyperlinkActions</key>
<map>
<key>Comment</key>

View File

@ -462,6 +462,7 @@ void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name)
void LLPipeline::init()
{
LL_WARNS() << "Begin pipeline initialization" << LL_ENDL; // TODO: Remove after testing
refreshCachedSettings();
gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
@ -490,6 +491,7 @@ void LLPipeline::init()
mInitialized = true;
stop_glerror();
LL_WARNS() << "No GL errors yet. Pipeline initialization will continue." << LL_ENDL; // TODO: Remove after testing
//create render pass pools
getPool(LLDrawPool::POOL_ALPHA);
@ -552,7 +554,9 @@ void LLPipeline::init()
// Enable features
LL_WARNS() << "Shader initialization start" << LL_ENDL; // TODO: Remove after testing
LLViewerShaderMgr::instance()->setShaders();
LL_WARNS() << "Shader initialization end" << LL_ENDL; // TODO: Remove after testing
stop_glerror();