Устройство Direct3D10 и Direct3D11 - SIISII/DirectX GitHub Wiki
Устройство Direct3D является, по сути, программным интерфейсом, позволяющим управлять работой видеоадаптера. В Direct3D10 оно обеспечивает создание различных ресурсов и выполнение собственно рендеринга. В Direct3D11 эти функции разделены: устройство Direct3D обеспечивает создание ресурсов и определение поддерживаемых оборудованием возможностей Direct3D, а собственно рендеринг выполняется с помощью так называемых контекстов устройства.
Возможно создание нескольких устройств — как правило, чтобы обеспечить вывод изображения в различные окна одновременно. Объекты, созданные с помощью некоторого устройства, могут использоваться только с этим устройством. Это касается и разделяемых объектов: они позволяют разным устройствам совместно использовать некоторые данные, однако собственно разделяемые объекты, обеспечивающие доступ к этим данным, всё равно должны использоваться только со своими устройствами.
Создание устройства
Создание устройства в зависимости от используемой версии Direct3D выполняется одной из следующих функций:
-
для Direct3D10 — D3D10CreateDevice либо D3D10CreateDeviceAndSwapChain;
-
для Direct3D10.1 — D3D10CreateDevice1 либо D3D10CreateDeviceAndSwapChain1;
-
для Direct3D11 и его подверсий — D3D11CreateDevice либо D3D11CreateDeviceAndSwapChain.
В каждой из этих пар функций первая функция создаёт лишь само устройство Direct3D, а вторая функция — и устройство Direct3D, и связанную с ним цепочку переключения буферов. Последняя может быть создана отдельно с помощью соответствующей функции фабрики DXGI, причём обычно такой вариант является более предпочтительным (в современных программах она большинстве случаев создаётся вызовом метода IDXGIFactory2::CreateSwapChainForHwnd).
Из всех перечисленных функций наиболее полный набор параметров имеет D3D11CreateDeviceAndSwapChain
, чей прототип выглядит следующим образом:
HRESULT D3D11CreateDeviceAndSwapChain(
IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
IDXGISwapChain* *ppSwapChain,
ID3D11Device* *ppDevice,
D3D_FEATURE_LEVEL *pFeatureLevel,
ID3D11DeviceContext* *ppImmediateContext);
-
pAdapter
— указатель на интерфейс адаптера, для которого следует создать устройство. Если указанnullptr
, устройство создаётся для первого из адаптеров, возвращаемых при их перечислении. Какая именно из потенциально доступных функций перечисления имеется в виду, не совсем ясно: документация говорит о функцииIDXGIFactory1::EnumAdapters
, однако эта функция изначально определена в интерфейсе IDXGIFactory, появившимся в составе DirectX 10, а не в IDXGIFactory1 из DirectX 11, где определена функция IDXGIFactory1::EnumAdapters1. Скорей всего, эти функции первым всегда возвращают один и тот же адаптер (к которому подключён монитор, считающийся в системе основным); это всегда так для систем, начиная с Windows 8 (в них обе функции перечисляют адаптеры в одинаковом порядке). -
DriverType
— тип адаптера, задаваемый одной из следующих констант:-
D3D_DRIVER_TYPE_HARDWARE
(D3D10_DRIVER_TYPE_HARDWARE
для функций создания устройства Direct3D10 или Direct3D10.1) — реальное аппаратное устройство. Во всех обычных случаях используется только этот тип; -
D3D_DRIVER_TYPE_REFERENCE
(D3D10_DRIVER_TYPE_REFERENCE
) — эталонное программное устройство. Осуществляет рендеринг чисто программными средствами на центральном процессоре; может использоваться для получения изображения, каким оно должно быть в соответствии с правилами Direct3D (например, для отладки драйверов аппаратуры). Всегда поддерживает все функциональные возможности Direct3D соответствующей версии; -
D3D_DRIVER_TYPE_NULL
(D3D10_DRIVER_TYPE_NULL
) — пустое программное устройство, не способное осуществлять рендеринг вообще; используется для отладки вызовов API, не связанных с рендерингом; -
D3D_DRIVER_TYPE_SOFTWARE
(D3D10_DRIVER_TYPE_SOFTWARE
) — чисто программное устройство; в Direct3D10 объявлено, но не используется. Данное устройство, в отличие от эталонного и WARP-устройств, реализовано в динамически загружаемой библиотеке (DLL), явно указываемой приложением с помощью параметраSoftware
; -
D3D_DRIVER_TYPE_WARP
(D3D10_DRIVER_TYPE_WARP
) — программное устройство, выполняющее сравнительно быстрый рендеринг, используя только центральный процессор (см. Windows Advanced Rasterization Platform. Этот тип устройства в Direct3D10 может использоваться лишь в случае, если ОС поддерживает Direct3D11.
-
-
Software
— хэндл динамически загружаемой библиотеки, реализующей программный рендеринг для устройства типаD3D_DRIVER_TYPE_SOFTWARE
. При использовании устройств любых других типов должен быть равен нулю. -
Flags
— битовая маска, которая может включать следующие флаги.-
D3D11_CREATE_DEVICE_SINGLETHREADED
(D3D10_CREATE_DEVICE_SINGLETHREADED
) — вызовы устройства Direct3D будут осуществляться только из одного потока, поэтому внутренняя блокировка для упорядочивания доступов использоваться не должна; её отсутствие слегка повышает производительность. По всей видимости, функции устройства можно вызывать из разных потоков и при наличии этого флага, но при этом необходимо гарантировать, чтобы в любой момент времени выполняется лишь один вызов. -
D3D11_CREATE_DEVICE_DEBUG
(D3D10_CREATE_DEVICE_DEBUG
) — устройство Direct3D создаётся с отладочным слоем. -
D3D10_CREATE_DEVICE_SWITCH_TO_REF
— одновременное создание аппаратного и эталонного программного устройств Direct3D10, что позволяет переключаться между ними с целью отладки (см. интерфейс ID3D10SwitchToRef). В Direct3D11 флагD3D11_CREATE_DEVICE_SWITCH_TO_REF
объявлен, но сама эта возможность не поддерживается. -
D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
(D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
) — запрет использования многопоточности внутри самого Direct3D (во всяком случае, для WARP-устройства), что в некоторых случаях может упростить отладку или профилирование. -
D3D11_CREATE_DEVICE_BGRA_SUPPORT
(D3D10_CREATE_DEVICE_BGRA_SUPPORT
) — запрет создания устройства, если оно не способно поддерживать форматы данных с обратным порядком цветов (группа форматовDXGI_FORMAT_B8G8R8A8_xxx
). Заметим, что данные форматы могут быть доступны и без этого флага, его наличие лишь гарантирует, что устройство их поддерживает.Этот флаг доступен, начиная с Windows 7 и обновлённой Windows Vista. Он не может указываться в функциях
D3D10CreateDevice
иD3D10CreateDeviceAndSwapChain
, хотя при указании в последующих версиях этих функций его применение возможно и для аппаратуры, поддерживающей лишь DirectX 10, но не 10.1 или последующие версии. Его наличие необходимо для взаимодействия Direct2D с ресурсами Direct3D. -
D3D10_CREATE_DEVICE_ALLOW_NULL_FROM_MAP
— при обнаружении нехватки памяти некоторые функции вместо выдачи исключения должны возвращатьnullptr
.Этот флаг можно использовать только в Windows 7. Он отсутствует в Direct3D11.
-
D3D10_CREATE_DEVICE_STRICT_VALIDATION
— этот флаг объявлен зарезервированным и не должен использоваться; в Direct3D11 он отсутствует. -
D3D11_CREATE_DEVICE_DEBUGGABLE
(D3D10_CREATE_DEVICE_DEBUGGABLE
) — сохранение информации, полезной для отладки шейдеров. Какая именно информация сохраняется, зависит от драйвера. Этот флаг поддерживается, начиная с Direct3D11.1 (неясно, идёт ли речь лишь о необходимости поддержки Direct3D11.1 на уровне ОС, т. е., по сути, о подходящей версии системы и обновлений на неё, или же о принципиальной невозможности использования с Direct3D11). -
D3D11_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY
(D3D10_CREATE_DEVICE_PREVENT_ALTERING_LAYER_SETTINGS_FROM_REGISTRY
) — запрещает подключение отладочного слоя устройства извне программы, т. е. с помощью параметров реестра, через DirectX Control Panel или из Visual Studio.Обычно этот флаг устанавливается в версиях программы, предназначенных для распространения среди конечных пользователей. Он не предотвращает возможность подключения отладочного слоя из поздних версий Visual Studio, работающих под Windows 8.1 или позднейшими версиями ОС; для этой цели в них следует использовать метод ID3D11DeviceContext2::IsAnnotationEnabled (доступен только для Direct3D11).
Этот флаг доступен лишь при наличии поддержки Direct3D11.1 (неясно, можно ли его использовать с Direct3D11.0, хотя с Direct3D10 он допустим). Он автоматически подключает отладочный слой.
-
D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT
— запрещает обнаружение таймаута графического процессора, что позволяет выполнять на нём вычисления, требующие более двух секунд времени (при его отсутствии ОС обнаруживает отсутствие ответа ГП и выполняет его сброс).Этот флаг поддерживается, начиная с Direct3D11.1 (неясно, идёт речь именно о Direct3D или о поддержке в ОС).
-
D3D11_CREATE_DEVICE_VIDEO_SUPPORT
— запрещает создание устройства, если его драйвер не соответствует драйверной модели WDDM 1.2, появившейся в Windows 8, что каким-то образом связано с возможностями воспроизведения видео.Этот флаг поддерживается, начиная с Direct3D11.1 (неясно, идёт речь именно о Direct3D или о поддержке в ОС).
-
-
pFeatureLevels
— указатель на массив значений типа D3D_FEATURE_LEVEL, задающих в порядке убывания предпочтительности требуемый уровень функциональных возможностей создаваемого устройства. Если этот указатель равенnullptr
, то предполагается, что уровни понижаются отD3D_FEATURE_LEVEL_11_0
доD3D_FEATURE_LEVEL_9_1
включительно.Для создания устройства уровня Direct3D11.1 этот параметр должен указывать на массив, первый элемент которого содержит значение
D3D_FEATURE_LEVEL_11_1
. Однако следует учитывать, что, если аппаратура не поддерживает данный уровень, функция создания устройства завершится неудачно с кодомE_INVALIDARG
независимо от того, была ли в массиве указана какая-либо альтернатива. Соответственно, если программа способна работать и с Direct3D11.1, и с более ранними версиями, ей может потребоваться вызывать функцию дважды: сначала при попытке создать устройство Direct3D11.1, а при её неудачном завершении — для создания устройства более низкого уровня.Функции, создающие устройство Direct3D10, не имеют аналогичного по назначению параметра; они всегда создают устройство уровня
D3D10_FEATURE_LEVEL_10_0
. Функции создания устройства Direct3D10.1 имеют параметрHardwareLevel
, который задаёт требуемый уровень функциональности и должен быть равен одной из констант типа D3D10_FEATURE_LEVEL1. Если приложение, использующее Direct3D10.1, способно работать с более низкими уровнями функциональности, оно должно несколько раз вызывать функцию создания устройства, постепенно понижая требования к функциональности, до тех пор, пока устройство не будет успешно создано. -
FeatureLevels
— число элементов в массиве, заданном предыдущим параметром. -
SDKVersion
— версия используемого SDK, должна быть равнаD3D11_SDK_VERSION
(в функциях создания устройства Direct3D10 или Direct3D10.1 соответствующий параметр равенD3D10_SDK_VERSION
илиD3D10_1_SDK_VERSION
соответственно). -
pSwapChainDesc
— адрес структуры типа DXGI_SWAP_CHAIN_DESC, задающей характеристики цепочки переключения буферов (см. описание работы с цепочками, где приведены в том числе сведения о создании цепочки с использованием функции IDXGIFactory2::CreateSwapChainForHwnd и структуры DXGI_SWAP_CHAIN_DESC1, являющейся расширенным вариантомDXGI_SWAP_CHAIN_DESC
). -
ppSwapChain
— адрес переменной, в которую будет помещён указатель на интерфейс созданной цепочки переключения буферов. -
ppDevice
— адрес переменной, в которую будет помещён указатель на интерфейс созданного устройства типа ID3D11Device. В функциях, создающих устройства Direct3D10 или Direct3D10.1, имеется такой же параметр, но тип интерфейса будет соответствовать версии Direct3D API.Заметим, что тип интерфейса устройства не связан с функциональным уровнем: и для Direct3D11.1, и для Direct3D9.1, и для любых уровней функциональности между этими двумя значениями будет возвращён один и тот же интерфейс устройства типа
ID3D11Device
. Последующие версии интерфейса могут быть получены обычным вызовом метода IUnknown::QueryInterface. -
pFeatureLevel
— адрес переменной, в которой будет сохранено значение типаD3D_FEATURE_LEVEL
, показывающее функциональный уровень созданного устройства. Этот параметр может быть равенnullptr
, если программа не нуждается в информации о фактически поддерживаемом функциональном уровне. -
ppImmediateContext
— адрес переменной, в которой сохраняется указатель на интерфейс немедленного контекста устройства Direct3D11 типа ID3D11DeviceContext. Немедленный контекст используется для собственно выполнения рендеринга.У функций создания устройства Direct3D10 или Direct3D10.1 аналогичного параметра нет, поскольку там все операции рендеринга осуществляются через само устройство, а не через его немедленный контекст.
Уничтожение устройства
Как и любой другой COM-интерфейс, устройство Direct3D автоматически уничтожается, когда счётчик ссылок на него снижается до нуля. Поэтому для его уничтожения необходимо сначала уничтожить все интерфейсы, порождённые через данное устройство, а потом освободить сам интерфейс устройства обычной метода IUnknown::Release.
Поддерживаемые функциональные возможности
Основной набор функциональных устройств, поддерживаемых устройством, определяется установленным уровнем функциональности, который сохраняется функциями D3D11CreateDevice
и D3D11CreateDeviceAndSwapChain
в переменной, адрес которой задан параметром pFeatureLevel
(если программа указывала только один допустимый уровень при вызове функции создания устройства и последняя завершилась успешно, нужды сохранять уровень нет, так как будет установлен именно он).
Некоторые возможности являются необязательными. Чтобы определить, поддерживаются ли они конкретным устройством, следует использовать методы ID3D11Device::CheckFeatureSupport и ID3D11Device::CheckFormatSupport.
Direct3D10 и 10.1 не имеют средств для проверки дополнительных функциональных возможностей. В Direct3D10 можно лишь проверить поддержку тех или иных форматов данных с помощью метода ID3D10Device::CheckFormatSupport; Direct3D10.1 добавляет возможность проверки используемого уровня средств (метод ID3D10Device1::GetFeatureLevel).
Объекты-дети устройства
Ряд объектов, создаваемых методами устройства (например объекты состояний, шейдеры, контексты), называется детьми этого устройства. В случае устройства Direct3D10 или Direct3D10.1 они являются наследниками интерфейса ID3D10DeviceChild, порождённого прямо от IUnknown
и определяющего следующие методы.
В случае устройства Direct3D11 дети являются наследниками интерфейса ID3D11DeviceChild, также порождённого прямо от IUnknown
и определяющего аналогичные методы:
Интерфейс устройства
Для работы с устройствами Direct3D предусмотрены интерфейсы устройств Direct3D10 и Direct3D11.