Поделиться через


Отслеживание использования распределения

После удаления списка выделения диспетчер видеопамяти (VidMm) больше не будет видеть выделения, на которые ссылается определенный буфер команд. В результате VidMm больше не может отслеживать использование выделения и обрабатывать связанную синхронизацию. Теперь эта ответственность ложится на драйвер пользовательского режима (UMD). В частности, UMD должен обрабатывать синхронизацию в отношении прямого доступа ЦП к выделению и переименованию.

VidMm асинхронно откладывает удаление выделения безопасным способом, который является как неблокирующей для вызывающего потока, так и для производительности. Таким образом, UMD не должен беспокоиться о том, что придется отложить уничтожение выделения. Когда VidMm получает запрос на удаление выделения, по умолчанию предполагается, что команды, поставленные в очередь до запроса на уничтожение, могут потенциально получить доступ к уничтожаемому выделению. Таким образом, VidMm откладывает операцию уничтожения до завершения выполнения команд в очереди. Если UMD знает, что ожидающие команды не имеют доступа к уничтожаемой выделению, он может указать VidMm обработать запрос без ожидания, установив флаг AssumeNotInUse при вызове Deallocate2 или DestroyAllocation2.

Lock2

UMD отвечает за правильную синхронизацию с прямым доступом к ЦП. В частности, UMD требуется для выполнения:

  1. Поддержка семантики блокировки без перезаписи и отмены, что означает, что UMD должен реализовать собственную схему переименования.

  2. Для операций сопоставления, требующих синхронизации (т. е. не указанного выше без перезаписи или отмены):

    • Верните WasStillDrawing, если предпринята попытка получить доступ к выделению, которое в настоящее время занято, и вызывающий объект запросил, чтобы операция блокировки не блокировала вызывающий поток (D3D11_MAP_FLAG_DO_NOT_WAIT).
    • Или, если флаг D3D11_MAP_FLAG_DO_NOT_WAIT не установлен, дождитесь, пока выделение станет доступным для доступа к ЦП. UMD должен реализовать неполующий режим ожидания. UMD будет использовать новый механизм мониторинга контекста.

На данный момент UMD по-прежнему требуется вызвать LockCb/UnlockCb , чтобы попросить VidMm настроить выделение для доступа к ЦП. В большинстве случаев UMD может поддерживать сопоставление выделения на протяжении всего времени существования. Однако в будущем LockCb и UnlockCb будут объявлены нерекомендуемой в пользу новых вызовов Lock2Cb и Unlock2Cb . Цель этих новых обратных вызовов — обеспечить новую чистую реализацию с новым набором аргументов и флагов.

Диапазоны swizzling удаляются из WDDM версии 2. Разработчик драйверов отвечает за удаление зависимости от диапазонов свертывания от вызовов LockCb по мере их перехода к реализации, основанной на Lock2Cb.

Lock2Cb предоставляется как простой метод для получения виртуального адреса для выделения. Существует несколько ограничений, основанных на типе выделения и текущем сегменте, в который он в настоящее время проживает.

Драйвер указывает, доступен ли сегмент ЦП с помощью флага CpuVisible , который находится в элементе Flags структуры DXGK_SEGMENTDESCRIPTOR .

Для выделения ресурсов, доступных для ЦП:

  • Кэшированные выделения, доступные для ЦП, должны находиться в сегменте диафрагмы или не быть резидентными, чтобы быть заблокированными. Мы не можем гарантировать согласованность кэша между ЦП и сегментом памяти на графическом процессоре (GPU).
  • Выделения, доступные ЦП, расположенные в полностью доступном для ЦП сегменте памяти (размер с помощью изменяемой bar-панели), гарантированно блокируются и могут возвращать виртуальный адрес. В этом сценарии никаких особых ограничений не требуется.
  • Выделения, доступные ЦП, расположенные в сегменте памяти, недоступном для ЦП (с доступом к CpuHostAperture или без нее), могут быть не сопоставлены с виртуальным адресом ЦП по различным причинам. Если cpuHostAperture не имеет доступного пространства или выделение не указывает сегмент диафрагмы, получить виртуальный адрес невозможно. По этой причине все доступные ЦП выделения в сегментах памяти, не доступных ЦП, должны содержать сегмент диафрагмы в поддерживаемом наборе сегментов. Это требование гарантирует, что VidMm сможет разместить выделение в системной памяти и предоставить виртуальный адрес.
  • Ресурсы, доступные для ЦП, уже расположенные в системной памяти (и (или) сопоставленные с сегментом диафрагмы, гарантированно будут работать.

Для выделений, не доступных для ЦП:

  • Выделения, доступные ЦП, поддерживаются объектами разделов, которые не могут указывать непосредственно на буфер кадров GPU. Чтобы заблокировать выделение, недоступное для ЦП, выделение должно поддерживать сегмент диафрагмы в поддерживаемом наборе сегментов или уже находиться в системной памяти (не должно находиться на устройстве).

Если выделение успешно заблокировано, а выделение не размещено на устройстве, но не поддерживает сегмент диафрагмы, выделение не должно быть зафиксировано в сегменте памяти на время блокировки.

Lock2 в настоящее время не содержит флагов, а все разряды зарезервированных флагов должны иметь значение 0.

CpuHostAperture

Для лучшей поддержки блокировки с сегментами памяти, не доступными для ЦП, при сбое изменения размера BAR в апертуре PCI предоставляется CpuHostAperture . CpuHostAperture ведет себя как менеджер на основе страниц, который затем может быть сопоставлен непосредственно с областями видеопамяти с помощью функции DxgkDdiMapCpuHostAperture(DDI). Затем VidMm может сопоставить диапазон виртуального адресного пространства непосредственно с несмежным диапазоном CpuHostAperture, а затем сопоставить CpuHostAperture с видеопамяти без необходимости в зависаемых диапазонах.

Максимальный объем блокируемой памяти, на которую может ссылаться ЦП в сегментах памяти, недоступных ЦП, ограничен размером CpuHostAperture. Сведения о предоставлении cpuHostAperture графическому ядру DirectX можно найти в разделе Диафрагма узла ЦП.

Когерентность ввода-вывода

На сегодняшний день в x86/x64 все GPU должны поддерживать когерентность ввода-вывода по сравнению с PCIe, чтобы позволить GPU читать или записывать данные в кэшируемую область системной памяти и поддерживать когерентность с ЦП. Если поверхность сопоставляется как кэш, согласованный с точки зрения GPU, GPU должен подслевать кэши ЦП при доступе к поверхности. Эта форма когерентности обычно используется для ресурсов, с которыми ЦП должен считывать данные, например для некоторых промежуточных поверхностей.

На некоторых платформах Arm когерентность ввода-вывода не поддерживается непосредственно в оборудовании. На этих платформах необходимо эмулировать когерентность ввода-вывода путем ручной отмены иерархии кэша ЦП. VidMm делает это путем отслеживания операций выделения, поступающих из GPU (операция чтения и записи списка выделения) и ЦП (операция сопоставления, чтение и запись). VidMm выдает недействительное значение кэша, когда определяет, что кэш может содержать:

  • Данные, которые необходимо записать обратно (запись ЦП, чтение GPU)
  • Устаревшие данные, которые необходимо сделать недействительными (запись в GPU, операции чтения ЦП).

На платформе без когерентности ввода-вывода ответственность за отслеживание доступа КП и GPU к выделениям ложится на UMD. Графическое ядро предоставляет новый недопустимый DDI кэша, который UMD может использовать для обратной записи и отмены диапазона виртуальных адресов, связанного с кэшируемым выделением. На платформах, которые не поддерживают когерентность ввода-вывода, UMD требуется для вызова этой функции после записи ЦП и перед чтением GPU, а также после записи и перед чтением ЦП. Последнее может показаться нелогичным на первый взгляд. Но так как ЦП может спекулятивно считывать данные до записи GPU в память, необходимо сделать недействительными все кэши ЦП, чтобы ЦП повторно считывал данные из ОЗУ.