функция обратного вызова DXGKDDI_BUILDPAGINGBUFFER (d3dkmddi.h)
Функция DxgkDdiBuildPagingBuffer создает буферы разбиения по страницам для операций с памятью.
Синтаксис
DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;
NTSTATUS DxgkddiBuildpagingbuffer(
[in] IN_CONST_HANDLE hAdapter,
[in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}
Параметры
[in] hAdapter
Дескриптор к блоку контекста, связанному с адаптером отображения. Драйвер минипорта отображения ранее предоставил этот дескриптор подсистеме ядра графики Microsoft DirectX в MiniportDeviceContext выходном параметре функции DxgkDdiAddDevice.
[in/out] pBuildPagingBuffer
Указатель на структуру DXGKARG_BUILDPAGINGBUFFER, содержащую сведения о создании буфера разбиения по страницам.
Возвращаемое значение
DxgkDdiBuildPagingBuffer возвращает одно из следующих значений:
код возврата | описание |
---|---|
STATUS_SUCCESS | DxgkDdiBuildPagingBuffersuccesfully построил буфер разбиения по страницам. |
STATUS_GRAPHICS_ALLOCATION_BUSY | В настоящее время GPU использует выделение для буфера разбиения по страницам. |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER | Больше места требуется в буфере разбиения по страницам (т. е. в элементе pDmaBuffer структуры DXGKARG_BUILDPAGINGBUFFER, на которую указывает параметр pBuildPagingBuffer). |
Замечания
Функция DxgkDdiBuildPagingBuffer вызывается для создания буферов специального прямого доступа к памяти (DMA), которые называются буферами разбиения по страницам. Буфер разбиения на страницы содержит операцию, которая перемещает содержимое частей выделения:
- В сегменте выделения.
- Между сегментами выделения.
- Из сегмента выделения в системную память.
- Из системной памяти в сегмент выделения.
Минипорт-драйвер дисплея должен написать соответствующую инструкцию графической обработки (GPU) в предоставленном буфере разбиения по страницам (в pDmaBuffer член DXGKARG_BUILDPAGINGBUFFER) в соответствии с запрошенной операцией разбиения по страницам; затем драйвер должен вернуть буфер разбиения на страницы в диспетчер памяти видео (который входит в Dxgkrnl.sys). Планировщик GPU (который также является частью Dxgkrnl.sys) впоследствии вызывает функцию драйвера DxgkDdiSubmitCommand, чтобы запросить, чтобы драйвер отправил буфер разбиения по страницам в качестве обычного буфера DMA в GPU.
Если DxgkDdiBuildPagingBuffer определяет, что для операции разбиения по страницам требуется несколько буферов разбиения по страницам, драйвер может указать сведения в MultipassOffset члена DXGKARG_BUILDPAGINGBUFFER и использовать эти сведения в нескольких итерациях операции разбиения по страницам. Диспетчер памяти видео инициализирует сведения в MultipassOffset до нуля до первого запроса операции разбиения на страницы и не изменяет сведения в MultipassOffset между итерациями. Поэтому драйвер может использовать MultipassOffset для сохранения хода выполнения между итерациями. Например, драйвер может хранить номер страницы, который последний раз был передан для передачи на основе страниц.
Буфер разбиения по страницам в настоящее время создается для следующих типов операций:
-
Перенос
Операция передачи перемещает содержимое выделения из одного расположения в другое. Эта операция является наиболее распространенным типом операции памяти.
Выделение всегда полностью передается из одного расположения в другое. Однако из-за ограничений памяти передача выделения может быть разделена на несколько вложенных передач (т. е. часть выделения перемещается из расположения A в B, а затем перемещается следующая часть и т. д., пока не будет передано все выделение). Первый вложенный перенос выделения помечается флагом TransferStart битового поля в элементе Flags члена Transfer DXGKARG_BUILDPAGINGBUFFER; Последняя подпередача выделения помечается флагом TransferEnd битового поля. Драйвер гарантированно получит конец ожидающей передачи (т. е. последняя подпереработка), прежде чем водитель получит начало новой передачи.
Для каждой подпередачи может потребоваться несколько вызовов DxgkDdiBuildPagingBuffer (например, драйвер может выйти из буфера DMA). Поэтому драйвер может получить флаг TransferStart в нескольких вызовах DxgkDdiBuildPagingBuffer, пока драйвер не получит флаг TransferEnd в вызове DxgkDdiBuildPagingBuffer. Получение флага transferStart несколько раз не указывает на начало нескольких новых передач; Он указывает, что вложенные передачи для выделения требуют нескольких итераций (например, если драйвер не был выделен буфера DMA). Драйвер может использовать MultipassOffset члена DXGKARG_BUILDPAGINGBUFFER для отслеживания хода выполнения определенной подпередачки в нескольких итерациях DxgkDdiBuildPagingBuffer.
Как правило, передача выполняется в одной операции. В этой ситуации задаются флаги TransferStart TransferStart и TransferEnd битового поля.
В некоторых сценариях драйвер может потребоваться для настройки аппаратных ресурсов, когда определенные выделения отображаются в памяти или вне памяти. По умолчанию GPU может использовать выделение, на которое ссылается во время вызова DxgkDdiBuildPagingBuffer. В этих сценариях драйвер может потребовать простоя выделения, прежде чем драйвер программирует необходимые аппаратные ресурсы (т. е. программирование аппаратных ресурсов невозможно в очереди в предоставленном буфере DMA). В таких сценариях драйвер может завершить вызов DxgkDdiBuildPagingBuffer с STATUS_GRAPHICS_ALLOCATION_BUSY.
Если драйвер возвращает STATUS_GRAPHICS_ALLOCATION_BUSY, диспетчер памяти видео ожидает завершения работы GPU с любой ссылкой на текущее выделение, а затем снова вызывает функцию dxgkDdiBuildPuffer. Во втором вызове dxgkDdiBuildPagingBufferBufferдиспетчер памяти видео задает флаг AllocationIsIdle битового поля в элементе Flags элемента Transfer элемента DXGKARG_BUILDPAGINGBUFFER, чтобы указать, что выделение, на которое ссылается ссылка, неактивно. Если флаг простоя не задан, драйвер всегда должен определить, что выделение в настоящее время занято или вскоре может быть занято. Если установлен флаг простоя, диспетчер памяти видео гарантирует, что выделение, на которое ссылается ссылка, остается бездействующим в течение времени вызова DxgkDdiBuildPagingBuffer.
Если элемент DXGKARG_BUILDPAGINGBUFFER hAllocation hAllocation null, драйвер должен скопировать данные в источник в место назначения, не выполняя никаких ветвей или навесок.
-
Заполнять
Операция заполнения заполняет выделение указанным шаблоном. Операция заполнения используется для настройки начального содержимого выделения. Когда содержимое выделения заполнено, выделение гарантированно будет бездействующим (т. е. не используется GPU). Операция заполнения может выполняться только в сегменте памяти. Диспетчер памяти видео никогда не запрашивает, чтобы драйвер мини-порта дисплея заполнял сегмент диафрагмы.
-
Удаление содержимого
Операция отмены содержимого уведомляет драйвер о том, что выделение удаляется из текущего расположения выделения в сегменте памяти. То есть выделение вытеснится и не копируется обратно в системную память.
В некоторых сценариях драйвер может потребоваться для настройки аппаратных ресурсов, когда определенные выделения отображаются в памяти или вне памяти. По умолчанию GPU может использовать выделение, на которое ссылается во время вызова DxgkDdiBuildPagingBuffer. В этих сценариях драйвер может потребовать простоя выделения, прежде чем драйвер программирует необходимые аппаратные ресурсы (т. е. программирование аппаратных ресурсов невозможно в очереди в предоставленном буфере DMA). В таких сценариях драйвер может завершить вызов DxgkDdiBuildPagingBuffer с STATUS_GRAPHICS_ALLOCATION_BUSY.
Если драйвер возвращает STATUS_GRAPHICS_ALLOCATION_BUSY, диспетчер памяти видео ожидает завершения работы GPU с любой ссылкой на текущее выделение, а затем снова вызывает функцию dxgkDdiBuildPuffer. Во втором вызове DxgkDdiBuildPagingBufferдиспетчер памяти видео задает флаг AllocationIsIdle битовое поле в элементе флагов Флаги элемента Отменаcontent элемента структуры DXGKARG_BUILDPAGINGBUFFER, чтобы указать, что выделение, на которое ссылается ссылка, неактивен. Если флаг простоя не задан, драйвер всегда должен определить, что выделение в настоящее время занято или вскоре может быть занято. Если установлен флаг простоя, диспетчер памяти видео гарантирует, что выделение, на которое ссылается ссылка, остается бездействующим в течение времени вызова DxgkDdiBuildPagingBuffer.
-
Чтение физического
Операция чтения с физической нагрузкой считывается из указанного адреса физической памяти. Драйвер запрашивается для программирования GPU для операции. Размер физической памяти для доступа к чтению может составлять от 1 байта до 8 байтов. Так как данные, которые считываются, не имеют значения, DxgkDdiBuildPagingBuffer не требуется для возврата данных. Однако в сценариях, когда ЦП пытается считывать из памяти AGP после записи GPU в эту память AGP, физическая операция чтения критически важна для обеспечения совместного использования памяти.
-
Запись физического кода
Операция записи на физический адрес записывается в указанный физический адрес. Драйвер запрашивается для программирования GPU для операции. Размер физической памяти для доступа к операции записи может составлять от 1 байта до 8 байтов. Так как записанные данные не имеют значения, DxgkDdiBuildPagingBuffer может записывать в память любые данные. Однако в сценариях, когда ЦП пытается считывать из памяти AGP после записи GPU в эту память AGP, физическая операция записи критически важна для обеспечения совместного использования памяти.
-
Сегмент диафрагмы карты
Операция map-aperture-segment сопоставляет указанный список дескриптора памяти (MDL) в указанный сегмент диафрагмы с заданным смещением сегмента для указанного количества страниц. Если флаг CacheCoherent битовое поле задан в элементе флагов элемента MapApertureSegment структуры DXGKARG_BUILDPAGINGBUFFER, драйвер должен убедиться, что на страницах, сопоставленных с ней, применяется когерентность кэша; В противном случае для страниц, сопоставленных с ней, не требуется совместное кэширование.
ПримечаниеФлаг кэша КэшCoherent битового поля задается только в том случае, если кэшируемая память сопоставляется с сегментом диафрагмы, согласованным в кэше, и никогда не устанавливается в сегменте не кэшируемой диафрагмы или в объединенном выделении, сопоставленном с кэшем. -
Сегмент распакуемой диаграммы
Операция unmap-aperture-segment распакует ранее сопоставленный диапазон указанного сегмента диафрагмы. Драйвер должен сопоставить диапазон, не сопоставленный с фиктивной страницей, которая DummyPage член UnmapApertureSegment член структуры DXGKARG_BUILDPAGINGBUFFER.
Примечание Если драйвер не отображается на фиктивной странице, драйвер должен включить доступ к GPU через указанный диапазон диафрагмы, чтобы подсистема ядра графики DirectX может обнаруживать проблемы с повреждением. Тесты соответствия существуют для проверки этой ситуации.Драйвер может дополнительно использовать MMIO для настройки сегмента диафрагмы. Gpu не будет получать доступ к диапазону диафрагмы во время настройки. Однако эта конфигурация диафрагмы не должна препятствовать выполнению GPU. GPU не будет бездействующим, если DxgkDdiBuildPagingBuffer вызывается с набором типов операций DXGK_OPERATION_UNMAP_APERTURE_SEGMENT, и GPU может быть занят доступом к другим частям сегмента диафрагмы, который перенастраивается.
-
Передача специальных блокировок
Операция специальной передачи блокировки аналогична обычной операции передачи. Однако вместо передачи содержимого выделения из или в регулярное хранилище резервной копии выделения специальная операция блокировки передает содержимое выделения из или в альтернативный виртуальный адрес, настроенный для выделения, когда функция pfnLockCb была вызвана с набором флагов UseAlternateVA битового поля.
Операция специальной передачи блокировки выполняется только в одном из следующих сценариев:
- Выделение в настоящее время доступно для ЦП с альтернативным виртуальным адресом и вытесняется.
- Выделение, которое было вытеснило ранее, например ситуацию, описанную в предыдущем маркере, выстраиваются обратно.
В некоторых сценариях драйвер может потребоваться для настройки аппаратных ресурсов, когда определенные выделения отображаются в памяти или вне памяти. По умолчанию GPU может использовать выделение, на которое ссылается во время вызова DxgkDdiBuildPagingBuffer. В этих сценариях драйвер может потребовать простоя выделения, прежде чем драйвер программирует необходимые аппаратные ресурсы (т. е. программирование аппаратных ресурсов невозможно в очереди в предоставленном буфере DMA). В таких сценариях драйвер может завершить вызов DxgkDdiBuildPagingBuffer с STATUS_GRAPHICS_ALLOCATION_BUSY.
Если драйвер возвращает STATUS_GRAPHICS_ALLOCATION_BUSY, диспетчер памяти видео ожидает завершения работы GPU с любой ссылкой на текущее выделение, а затем снова вызывает функцию dxgkDdiBuildPuffer. Во втором вызове DxgkDdiBuildPufferBufferдиспетчер памяти видео задает флаг AllocationIsIdle битового поля в элементе Flags элемента SpecialLockTransfer член структуры DXGKARG_BUILDPAGINGBUFFER, чтобы указать, что выделение, на которое ссылается ссылка, неактивен. Если флаг простоя не задан, драйвер всегда должен определить, что выделение в настоящее время занято или вскоре может быть занято. Если установлен флаг простоя, диспетчер памяти видео гарантирует, что выделение, на которое ссылается ссылка, остается бездействующим в течение времени вызова DxgkDdiBuildPagingBuffer.
Диспетчер памяти системы гарантирует, что передача невидима для приложения. Тем не менее, поскольку выделение находится в системной памяти, а виртуальный адрес выделения больше не может проходить через аппаратное отверстие, драйвер должен обеспечить порядок байтов в системной памяти, что было видно через диафрагму.
DxgkDdiBuildPagingBuffer должен быть создан на страницу.
Примеры
В следующем примере кода показано, как использовать DxgkDdiBuildPagingBuffer.
NTSTATUS ntStatus;
DXGKARG_BUILDPAGINGBUFFER param;
// The driver receives the following paging operation to build:
//
param.Flags = 0;
param.pDmaBuffer= CurrentPagingBuffer;
param.DmaSize = CurrentPagingBufferSizeLeft;
param.pDmaBufferPrivateData = CurrentPagingBufferPrivateData;
param.DmaBufferPrivateDataSize = CurrentPagingBufferPrivateDataSizeLeft;
param.Operation = DXGK_OPERATION_TRANSFER;
param.Transfer.Flags = 0;
param.Transfer.TransferOffset = CurrentOffsetInAllocationBeingTransfered;
param.Transfer.hAllocation = DriverContextForAllocationBeingMoved;
param.Transfer.Source.SegmentId = 0; // Source is an MDL.
param.Transfer.Source.pMdl = MDLDescribingPagesForAllocationBeingMoved;
param.Transfer.Destination.SegmentId = 1; // Source to segment #1.
param.Transfer.Destination.SegmentAddress = 0; // Source to offset 0 of segment #1.
// The driver receives MultipassOffset when it is initialized to zero
// and uses it for multiple iterations of the paging operation.
//
param.MultipassOffset = 0;
do {
// Call the driver's BuildPagingBuffer function to build a paging buffer.
//
ntStatus = BuildPagingBuffer(hAdapter, ¶m);
// BuildPagingBuffer updates the size that is left in the
// paging buffer with the amount of bytes that were written.
//
if (NT_SUCCESS(ntStatus)) {
//
// If STATUS_SUCCESS, batch the paging buffer to the
// scheduler after multiple paging operations are batched.
}
else if (ntStatus == STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER) {
//
// If STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, submit the current paging buffer to the scheduler to let
// the GPU start working on a partial transfer.
VidSchSubmitPagingBuffer(CurrentPagingBuffer, CurrentPagingBufferSizeLeft);
// Acquire a new paging buffer to complete the transfer.
//
VidMmAcquirePagingBuffer(&CurrentPagingBuffer, &CurrentPagingBufferSizeLeft);
}
else {
//
// A critical failure occurred, so bugcheck the system.
// This situation should never occur because the driver can
// fail the call only if it requires more DMA buffer space.
}
} while(!NT_SUCCESS(ntStatus))
Требования
Требование | Ценность |
---|---|
минимальные поддерживаемые клиентские | Windows Vista |
целевая платформа | Настольный |
заголовка | d3dkmddi.h |
IRQL | PASSIVE_LEVEL |