Как получить размер памяти видеокарты?

Столкнулся с проблемой чтения объёма памяти видеокарты средствами Win32-API. Может кто знает способы? На запрос WMI вида wmic.exe PATH Win32_videocontroller GET AdapterRAM система возвращает размер памяти графической карты, но с ограничением в 4Gb. Этот-же самый порог определяется и в реестре. Но сейчас есть карты с памятью в 8 и более гигов, поэтому вариант не подходит. И вообще желательно на чистом WinAPI.


Ответы (1 шт):

Автор решения: PRODIGY

После долгих поисков нашёл всё-таки решение вопроса при помощи функции D3DKMTQueryAdapterInfo(). Чтобы получить размер памяти видео свыше 4 Gb, нужно проделать следующие шаги:

  1. CM_Get_Device_Interface_List() из setupapi.dll, чтобы получить системное имя адаптера. Во-втором параметре передаём ей константу "GUID_DISPLAY_DEVICE_ARRIVAL", а в последнем - флаг "CM_GET_DEVICE_INTERFACE_LIST_PRESENT" =0. Так мы получим имя только активного адаптера, а не всех когда-либо установленных.

  2. MultiByteToWideChar() преобразует полученное имя из ANSI в Unicode, т.к. сл.функции требуется именно Unicode.

  3. Теперь это имя передаём функции D3DKMTOpenAdapterFromDeviceName(), чтобы получить дескриптор видеоадаптера. В качестве параметра функция ожидает следующую структуру, и в неё-же возвращает дескриптор и LUID:

struct D3DKMT_OPENADAPTERFROMDEVICENAME
  pDeviceName               dd  0  ;// In. линк на Unicode-имя адаптера
  hAdapter                  dd  0  ;// Out. "D3DKMT_HANDLE"
  AdapterLuid               dq  0  ;// Out. LUID
ends
  1. 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).

→ Ссылка