Как получить размер памяти видеокарты?
Столкнулся с проблемой чтения объёма памяти видеокарты средствами Win32-API. Может кто знает способы? На запрос WMI вида wmic.exe PATH Win32_videocontroller GET AdapterRAM система возвращает размер памяти графической карты, но с ограничением в 4Gb. Этот-же самый порог определяется и в реестре. Но сейчас есть карты с памятью в 8 и более гигов, поэтому вариант не подходит. И вообще желательно на чистом WinAPI.
Ответы (1 шт):
После долгих поисков нашёл всё-таки решение вопроса при помощи функции D3DKMTQueryAdapterInfo(). Чтобы получить размер памяти видео свыше 4 Gb, нужно проделать следующие шаги:
CM_Get_Device_Interface_List()из setupapi.dll, чтобы получить системное имя адаптера. Во-втором параметре передаём ей константу "GUID_DISPLAY_DEVICE_ARRIVAL", а в последнем - флаг "CM_GET_DEVICE_INTERFACE_LIST_PRESENT" =0. Так мы получим имя только активного адаптера, а не всех когда-либо установленных.MultiByteToWideChar()преобразует полученное имя из ANSI в Unicode, т.к. сл.функции требуется именно Unicode.Теперь это имя передаём функции
D3DKMTOpenAdapterFromDeviceName(), чтобы получить дескриптор видеоадаптера. В качестве параметра функция ожидает следующую структуру, и в неё-же возвращает дескриптор и LUID:
struct D3DKMT_OPENADAPTERFROMDEVICENAME
pDeviceName dd 0 ;// In. линк на Unicode-имя адаптера
hAdapter dd 0 ;// Out. "D3DKMT_HANDLE"
AdapterLuid dq 0 ;// Out. LUID
ends
D3DKMTQueryAdapterInfo()указав ей тип запроса "KMTQAITYPE_GETSEGMENTSIZE" =3. В единственном параметре функция так-же ожидает указатель на структуру, все поля которой мы должны предварительно заполнить:
struct D3DKMT_QUERYADAPTERINFO
hAdapter dd 0 ;// In. D3DKMT_HANDLE (Дескриптор адаптера, о котором извлекается информация)
Type dd 0 ;// In. KMTQUERYADAPTERINFOTYPE (тип информации, которую нужно получить)
pPrivateDriverData dd 0 ;// In.Out. указатель на приёмный буфер
PrivateDriverDataSize dd 0 ;// In. размер буфера в байтах
ends
Обратите внимание, что данная функция может возвращать 47 типов информации об адаптере, который указывается в параметре "Type" структуры. От запрашиваемого типа зависит и возврат функции, поэтому в последнем параметре "PrivateDriverDataSize" нужно указывать строго валидный размер ожидаемых на выходе данных, иначе функция будет возвращать ошибку "Invalid Parameter" 0xC000000d.
В данном случае я запрашиваю тип информации "KMTQAITYPE_GETSEGMENTSIZE" и получаю структуру "D3DKMT_SEGMENTSIZEINFO" с тремя 8-байтными членами, поэтому передаю размер буфера = 8*3.
struct D3DKMT_SEGMENTSIZEINFO
DedicatedVideoMemorySize dq 0 ;// Out. размер памяти, выделенной из видеоадаптера
DedicatedSystemMemorySize dq 0 ;// Out. размер апертуры, выделенной из ОЗУ для графики
SharedSystemMemorySize dq 0 ;// Out. общая доступная видео-память
ends
Как-правило, в первом члене LONGLONG лежит размер памяти видеокарты, а чтобы получить общий, выделенный для графических нужд ресурс, нужно сложить все/эти три значения. Как показала практика, запрос WMI выше возвращает именно сумму данной структуры.
Что-же касается чтения версии DirectX, то в сети встречаются достаточно громоздкие варианты, чуть-ли не в сотню сишных строк. Меня это никак не вдохновило, поэтому я пошёл иным путём.
Если заглянуть в системную папку system32, можно обнаружить в ней файлы типа: d3d9.dll, d3d10.dll, d3d11.dll, d3d12.dll. Каждая из этих библиотек поставляется вместе с соответствующей версией DirectX, так-что начиная с 12 я просто через LoadLibrary() в цикле пытаюсь загрузить эти либы в своё пространство и если ошибка, то перехожу к следующей 11 и т.д. Вариант "топорный" и не позволяет получить версию-минор типа v11.1, но мне это и не нужно было - достаточно лишь мажор. Алго работает от Win7(х32), до Win10(x64).