Разделение буфера DMA
Точки разделения используются диспетчером видеопамяти для разделения большого рабочего элемента, отправленного драйвером мини-порта дисплея, на небольшие рабочие элементы, для выполнения которых требуется меньше ресурсов GPU. Например, большой буфер DMA может ссылаться на набор выделений, которые, возможно, не помещаются в локальную видеопамять или нелокальную память. Единственный способ обработки такого рабочего элемента — разделить его на несколько небольших рабочих элементов, требующих меньше ресурсов GPU.
Примечание Разделение буфера DMA и вытеснение буфера DMA — это разные независимые понятия. Драйвер мини-порта дисплея всегда должен поддерживать разделение буфера DMA даже в системе с GPU, где вытеснение буфера DMA невозможно. В системе с GPU, где сохранение и восстановление контекста невозможно, планировщик GPU планирует разделение частей буфера DMA обратно в обратно, гарантируя, что разделенные части не чередуются с другим буфером DMA из другого контекста GPU. Однако буфер подкачки следует отправлять между частями разделенного буфера DMA, так как операции разбиения по страницам требуются между разделенными частями буфера DMA. Каждая точка разбиения, используемая драйвером для создания потока DMA приложения, используется диспетчером видеопамятки. Отправленный буфер DMA должен перепрограммировать достаточное состояние GPU после каждой точки разделения, чтобы учитывать потенциальный буфер подкачки, который может быть вставлен в это расположение.
Чтобы указать точки разбиения, драйвер мини-порта отображения задает значения в элементах SplitOffset и SlotId структуры D3DDDI_PATCHLOCATIONLIST для каждого выделения, на которое ссылается член AllocationIndex D3DDDI_PATCHLOCATIONLIST. Для отслеживания использования выделения в определенном буфере DMA диспетчер видеопамяти создает необходимые измерения массива с помощью элемента MaxAllocationListSlotIdструктуры DXGK_DRIVERCAPS , предоставленной драйвером посредством вызова функции DxgkDdiQueryAdapterInfo . Этот массив инициализируется с нулевым значением и заполняется при обработке разделенных записей в списке расположений исправлений. Элемент SlotIdD3DDDI_PATCHLOCATIONLIST для расположения исправления указывает, какая строка таблицы ресурсов должна быть обновлена, а элемент SplitOffset указывает смещение в буфере DMA, где требуется выделение. Буфер DMA можно запустить до точки, указанной splitOffset , без доступа к ресурсу GPU. Аналогичным образом, если новая запись разделенной части с расположением исправлений ссылается на тот же SlotId, предыдущее выделение заменяется новым выделением, и предыдущее выделение больше не требуется (то есть предыдущее выделение может быть разбиение по страницам).
При разбиении на страницы в ресурсах, необходимых буферу DMA, диспетчер видеопамяти обрабатывает список расположений исправлений, начиная с первого элемента и перемещаясь вниз к последнему элементу. Элементы D3DDDI_PATCHLOCATIONLIST , заполненные драйвером, должны содержать значения в своих членах SplitOffset ; элементы строго увеличиваются (то есть выделения должны отображаться в том порядке, в котором они используются в потоке). Страницы диспетчера видеопамяти в выделениях, на которые ссылается список расположений исправлений в порядке их предоставления. Когда достигается точка, в которой диспетчер видеопамяти больше не может встраивать выделение из-за нехватки памяти, диспетчер видеопамяти отправляет текущую часть буфера DMA, подготавливаемую планировщику GPU для выполнения. Буфер DMA выполняется от начала предыдущей точки разбиения до значения SplitOffset , указанного для выделения, которое не может быть включено. После отправки диспетчер видеопамятки определяет список необходимых выделений по текущему смещению разделения в потоке DMA с помощью таблицы ресурсов. Все выделения в таблице хранятся в текущем физическом расположении, в то время как другие выделения, которые больше не используются, могут быть исключены. Затем диспетчер видеопамяли продолжает обрабатывать список расположений исправлений, потенциально повторно разделяя их несколько раз.
Драйвер должен указывать точки разбиения каждый раз, когда выделение привязано или несвязано. Чтобы указать, что выделение является несвязанным, драйвер может указать маркер выделения NULL в элементе hDeviceSpecificAllocation структуры DXGK_ALLOCATIONLIST с соответствующим значением в элементе SlotId связанного D3DDDI_PATCHLOCATIONLIST. Драйвер должен отменить привязку больших ресурсов, чтобы увеличить вероятность того, что диспетчер видеопамяли сможет решить сложные проблемы с размещением памяти.
Аналогичным образом драйвер должен перепрограммировать большие ресурсы в каждой точке разделения. При использовании точки разделения диспетчер видеопамяти вынужден оставить ранее привязанное выделение к предыдущему выделению. Это приводит к фрагментации памяти, что может привести к сбою при решении сложных проблем с размещением памяти, которые могли бы быть решены, если бы не ограничение ранее связанного выделения. При вычислении состояния в точке разделения диспетчер видеопамяти определяет, какой идентификатор слота (SlotId) перепрограммируется в этой точке разбиения (т. е. каждый элемент списка размещения исправлений, который использует одно и то же значение SplitOffset с другими элементами), и игнорирует ограничение размещения для этой точки разделения. Например, если драйвер использует текстуру размером 64 МБ, перепрограммирование текстуры в каждой точке разделения дает диспетчеру видеопамяти возможность перемещать эту текстуру в памяти между точками разделения, если это необходимо.